blob: a8ef5c2a73b5724c2f47505a3aabfbe9a8ceb69f [file] [log] [blame]
/*
* Copyright 2022 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_SCREENCAST_PORTAL_H_
#define MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_SCREENCAST_PORTAL_H_
#include <gio/gio.h>
#define typeof __typeof__
#include <string>
#include "absl/types/optional.h"
namespace webrtc {
class ScreenCastPortal {
public:
// Values are set based on source type property in
// xdg-desktop-portal/screencast
// https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml
enum class CaptureSourceType : uint32_t {
kScreen = 0b01,
kWindow = 0b10,
kAnyScreenContent = kScreen | kWindow
};
// Values are set based on cursor mode property in
// xdg-desktop-portal/screencast
// https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml
enum class CursorMode : uint32_t {
// Mouse cursor will not be included in any form
kHidden = 0b01,
// Mouse cursor will be part of the screen content
kEmbedded = 0b10,
// Mouse cursor information will be send separately in form of metadata
kMetadata = 0b100
};
// Interface that must be implemented by the ScreenCastPortal consumers.
enum class RequestResponse {
// Success, the request is carried out.
kSuccess,
// The user cancelled the interaction.
kUserCancelled,
// The user interaction was ended in some other way.
kError,
kMaxValue = kError
};
class PortalNotifier {
public:
virtual void OnScreenCastRequestResult(RequestResponse result,
uint32_t stream_node_id,
int fd) = 0;
virtual void OnScreenCastSessionClosed() = 0;
protected:
PortalNotifier() = default;
virtual ~PortalNotifier() = default;
};
explicit ScreenCastPortal(CaptureSourceType source_type,
PortalNotifier* notifier);
~ScreenCastPortal();
// Initialize ScreenCastPortal with series of DBus calls where we try to
// obtain all the required information, like PipeWire file descriptor and
// PipeWire stream node ID.
//
// The observer will return whether the communication with xdg-desktop-portal
// was successful and only then you will be able to get all the required
// information in order to continue working with PipeWire.
void Start();
private:
PortalNotifier* notifier_;
// A PipeWire stream ID of stream we will be connecting to
uint32_t pw_stream_node_id_ = 0;
// A file descriptor of PipeWire socket
int pw_fd_ = -1;
CaptureSourceType capture_source_type_ =
ScreenCastPortal::CaptureSourceType::kScreen;
CursorMode cursor_mode_ = ScreenCastPortal::CursorMode::kEmbedded;
GDBusConnection* connection_ = nullptr;
GDBusProxy* proxy_ = nullptr;
GCancellable* cancellable_ = nullptr;
std::string portal_handle_;
std::string session_handle_;
std::string sources_handle_;
std::string start_handle_;
guint session_request_signal_id_ = 0;
guint sources_request_signal_id_ = 0;
guint start_request_signal_id_ = 0;
guint session_closed_signal_id_ = 0;
void PortalFailed(RequestResponse result);
uint32_t SetupRequestResponseSignal(const char* object_path,
GDBusSignalCallback callback);
static void OnProxyRequested(GObject* object,
GAsyncResult* result,
gpointer user_data);
static std::string PrepareSignalHandle(GDBusConnection* connection,
const char* token);
void SessionRequest();
static void OnSessionRequested(GDBusProxy* proxy,
GAsyncResult* result,
gpointer user_data);
static void OnSessionRequestResponseSignal(GDBusConnection* connection,
const char* sender_name,
const char* object_path,
const char* interface_name,
const char* signal_name,
GVariant* parameters,
gpointer user_data);
static void OnSessionClosedSignal(GDBusConnection* connection,
const char* sender_name,
const char* object_path,
const char* interface_name,
const char* signal_name,
GVariant* parameters,
gpointer user_data);
void SourcesRequest();
static void OnSourcesRequested(GDBusProxy* proxy,
GAsyncResult* result,
gpointer user_data);
static void OnSourcesRequestResponseSignal(GDBusConnection* connection,
const char* sender_name,
const char* object_path,
const char* interface_name,
const char* signal_name,
GVariant* parameters,
gpointer user_data);
void StartRequest();
static void OnStartRequested(GDBusProxy* proxy,
GAsyncResult* result,
gpointer user_data);
static void OnStartRequestResponseSignal(GDBusConnection* connection,
const char* sender_name,
const char* object_path,
const char* interface_name,
const char* signal_name,
GVariant* parameters,
gpointer user_data);
void OpenPipeWireRemote();
static void OnOpenPipeWireRemoteRequested(GDBusProxy* proxy,
GAsyncResult* result,
gpointer user_data);
};
} // namespace webrtc
#endif // MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_SCREENCAST_PORTAL_H_