UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
ScreenCastPortal_impl Class Reference
Collaboration diagram for ScreenCastPortal_impl:
Collaboration graph

Public Member Functions

 ScreenCastPortal_impl ()
 
 ~ScreenCastPortal_impl ()
 
GDBusConnection * dbus_connection () const
 
std::future< std::string > get_future ()
 
int get_pw_fd ()
 
uint32_t get_pw_node ()
 
GDBusProxy * proxy ()
 
void quit_loop ()
 
void run (std::string restore_file, bool show_cursor)
 
void run_loop ()
 
const std::string & sender_name () const
 
const std::string & session_path () const
 
const std::string & session_token () const
 

Static Public Attributes

static constexpr uint32_t REQUEST_RESPONSE_CANCELLED_BY_USER = 1
 
static constexpr uint32_t REQUEST_RESPONSE_OK = 0
 
static constexpr uint32_t REQUEST_RESPONSE_OTHER_ERROR = 2
 

Private Member Functions

template<auto callback>
void call_with_request (const char *method_name, std::initializer_list< GVariant * > arguments, GVariantBuilder &params_builder)
 

Static Private Member Functions

static void pipewire_opened (GObject *source, GAsyncResult *res, void *user_data)
 
static void session_created (uint32_t response, GVariant *results, ScreenCastPortal_impl *s)
 
static void sources_selected (uint32_t response, GVariant *results, ScreenCastPortal_impl *s)
 
static void started (uint32_t response, GVariant *results, void *user_data)
 

Private Attributes

GDBusConnection * connection
 
GMainLoop * dbus_loop
 
std::promise< std::string > promise
 
int pw_fd = -1
 
uint32_t pw_node = UINT32_MAX
 
std::string restore_file
 
GDBusProxy * screencast_proxy
 
session_path_t session
 
bool show_cursor = false
 
std::string unique_name
 

Detailed Description

Definition at line 110 of file dbus_portal.cpp.

Constructor & Destructor Documentation

◆ ScreenCastPortal_impl()

ScreenCastPortal_impl::ScreenCastPortal_impl ( )

Definition at line 191 of file dbus_portal.cpp.

191 {
192 GError *error = nullptr;
193
194 dbus_loop = g_main_loop_new(nullptr, false);
195 connection = g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error);
196 g_assert_no_error(error);
197 assert(connection != nullptr);
198
199 unique_name = g_dbus_connection_get_unique_name(connection) + 1;
200 std::replace(unique_name.begin(), unique_name.end(), '.', '_');
201 screencast_proxy = g_dbus_proxy_new_sync(
202 connection, G_DBUS_PROXY_FLAGS_NONE, nullptr,
203 "org.freedesktop.portal.Desktop",
204 "/org/freedesktop/portal/desktop",
205 "org.freedesktop.portal.ScreenCast", nullptr, &error);
206 g_assert_no_error(error);
207 assert(screencast_proxy != nullptr);
208
209 session = session_path_t::create(unique_name);
210 LOG(LOG_LEVEL_VERBOSE) << MOD_NAME "session path: '" << session.path << "'" << " token: '" << session.token << "'\n";
211}
GDBusConnection * connection
session_path_t session
GDBusProxy * screencast_proxy
#define MOD_NAME
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
#define LOG(level)
Definition debug.h:313

References connection, dbus_loop, LOG, LOG_LEVEL_VERBOSE, MOD_NAME, screencast_proxy, session, and unique_name.

◆ ~ScreenCastPortal_impl()

ScreenCastPortal_impl::~ScreenCastPortal_impl ( )

Definition at line 213 of file dbus_portal.cpp.

213 {
214 g_dbus_connection_call(dbus_connection(),
215 "org.freedesktop.portal.Desktop",
216 session.path.c_str(),
217 "org.freedesktop.portal.Session",
218 "Close", nullptr, nullptr,
219 G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr,
220 nullptr);
221 g_main_loop_quit(dbus_loop);
222 g_object_unref(screencast_proxy);
223 g_object_unref(connection);
224 g_main_loop_unref(dbus_loop);
225}
GDBusConnection * dbus_connection() const

References connection, dbus_connection(), dbus_loop, screencast_proxy, and session.

Here is the call graph for this function:

Member Function Documentation

◆ call_with_request()

template<auto callback>
void ScreenCastPortal_impl::call_with_request ( const char * method_name,
std::initializer_list< GVariant * > arguments,
GVariantBuilder & params_builder )
private

Definition at line 253 of file dbus_portal.cpp.

256{
257 assert(method_name != nullptr);
258 request_path_t request_path = request_path_t::create(sender_name());
259 LOG(LOG_LEVEL_VERBOSE) << MOD_NAME "call_with_request: '" << method_name << "' request: '" << request_path.path << "'\n";
260
261 g_dbus_connection_signal_subscribe(connection, "org.freedesktop.portal.Desktop",
262 "org.freedesktop.portal.Request",
263 "Response",
264 request_path.path.c_str(),
265 nullptr,
266 G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
268 this,
269 nullptr);
270
271 auto call_finished = [](GObject *source_object, GAsyncResult *result, gpointer user_data) {
272 auto s = static_cast<ScreenCastPortal_impl *>(user_data);
273 GError *error = nullptr;
274 GVariant_uniq result_finished(g_dbus_proxy_call_finish(G_DBUS_PROXY(source_object), result, &error));
275
276 if(error != nullptr){
277 s->promise.set_value(error->message);
278 return;
279 }
280
281 const char *path = nullptr;
282 g_variant_get(result_finished.get(), "(o)", &path);
283 LOG(LOG_LEVEL_VERBOSE) << MOD_NAME "call_with_request finished: '" << path << "'\n";
284 };
285
286
287 g_variant_builder_add(&params_builder, "{sv}", "handle_token", g_variant_new_string(request_path.token.c_str()));
288
289 GVariantBuilder args_builder;
290 g_variant_builder_init(&args_builder, G_VARIANT_TYPE_TUPLE);
291 for(GVariant* arg : arguments){
292 g_variant_builder_add_value(&args_builder, arg);
293 }
294 g_variant_builder_add_value(&args_builder, g_variant_builder_end(&params_builder));
295
296 g_dbus_proxy_call(screencast_proxy, method_name, g_variant_builder_end(&args_builder), G_DBUS_CALL_FLAGS_NONE, -1, nullptr, call_finished, this);
297}
const std::string & sender_name() const
void CallbackWrapper(GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data)

References CallbackWrapper(), connection, LOG, LOG_LEVEL_VERBOSE, MOD_NAME, screencast_proxy, and sender_name().

Referenced by run(), session_created(), and sources_selected().

Here is the call graph for this function:

◆ dbus_connection()

GDBusConnection * ScreenCastPortal_impl::dbus_connection ( ) const
inline

Definition at line 171 of file dbus_portal.cpp.

171 {
172 return connection;
173 }

References connection.

Referenced by ~ScreenCastPortal_impl(), and run().

◆ get_future()

std::future< std::string > ScreenCastPortal_impl::get_future ( )
inline

Definition at line 150 of file dbus_portal.cpp.

150 {
151 return promise.get_future();
152 }
std::promise< std::string > promise

References promise.

◆ get_pw_fd()

int ScreenCastPortal_impl::get_pw_fd ( )
inline

Definition at line 154 of file dbus_portal.cpp.

154{ return pw_fd; }

References pw_fd.

◆ get_pw_node()

uint32_t ScreenCastPortal_impl::get_pw_node ( )
inline

Definition at line 155 of file dbus_portal.cpp.

155{ return pw_node; }

References pw_node.

◆ pipewire_opened()

void ScreenCastPortal_impl::pipewire_opened ( GObject * source,
GAsyncResult * res,
void * user_data )
staticprivate

Definition at line 311 of file dbus_portal.cpp.

314{
315 auto s = static_cast<ScreenCastPortal_impl *>(user_data);
316 GError *error = nullptr;
317 GUnixFDList *fd_list = nullptr;
318
319 GVariant_uniq result(g_dbus_proxy_call_with_unix_fd_list_finish(G_DBUS_PROXY(source), &fd_list, res, &error));
320 g_assert_no_error(error);
321
322 gint32 handle;
323 g_variant_get(result.get(), "(h)", &handle);
324 assert(handle == 0); //it should always be the first index
325
326 s->pw_fd = g_unix_fd_list_get(fd_list, handle, &error);
327 g_assert_no_error(error);
328
329 s->promise.set_value("");
330}
Definition rtp.c:206

Referenced by started().

◆ proxy()

GDBusProxy * ScreenCastPortal_impl::proxy ( )
inline

Definition at line 167 of file dbus_portal.cpp.

167 {
168 return screencast_proxy;
169 }

References screencast_proxy.

◆ quit_loop()

void ScreenCastPortal_impl::quit_loop ( )
inline

Definition at line 163 of file dbus_portal.cpp.

163 {
164 g_main_loop_quit(dbus_loop);
165 }

References dbus_loop.

◆ run()

void ScreenCastPortal_impl::run ( std::string restore_file,
bool show_cursor )

Definition at line 424 of file dbus_portal.cpp.

424 {
426 this->show_cursor = show_cursor;
427
428 g_dbus_connection_signal_subscribe(dbus_connection(),
429 nullptr, // sender
430 "org.freedesktop.portal.Session", // interface_name
431 "closed", //signal name
432 session_path().c_str(), // object path
433 nullptr, // arg0
434 G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
436 nullptr,
437 nullptr);
438
439 GVariantBuilder params;
440 g_variant_builder_init(&params, G_VARIANT_TYPE_VARDICT);
441 g_variant_builder_add(&params, "{sv}", "session_handle_token", g_variant_new_string(session_token().c_str()));
442
443 call_with_request<session_created>("CreateSession", {}, params);
444
445 run_loop();
446}
void call_with_request(const char *method_name, std::initializer_list< GVariant * > arguments, GVariantBuilder &params_builder)
const std::string & session_token() const
const std::string & session_path() const
static void on_portal_session_closed(GDBusConnection *connection, const gchar *sender_name, const gchar *object_path, const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data)
static struct @19 params[100]

References call_with_request(), dbus_connection(), on_portal_session_closed(), params, restore_file, run_loop(), session_path(), session_token(), and show_cursor.

Here is the call graph for this function:

◆ run_loop()

void ScreenCastPortal_impl::run_loop ( )
inline

Definition at line 158 of file dbus_portal.cpp.

158 {
159 g_main_loop_run(dbus_loop);
160 LOG(LOG_LEVEL_VERBOSE) << MOD_NAME "finished dbus loop \n";
161 }

References dbus_loop, LOG, LOG_LEVEL_VERBOSE, and MOD_NAME.

Referenced by run().

◆ sender_name()

const std::string & ScreenCastPortal_impl::sender_name ( ) const
inline

Definition at line 175 of file dbus_portal.cpp.

176 {
177 return unique_name;
178 }

References unique_name.

Referenced by call_with_request().

◆ session_created()

void ScreenCastPortal_impl::session_created ( uint32_t response,
GVariant * results,
ScreenCastPortal_impl * s )
staticprivate

Definition at line 384 of file dbus_portal.cpp.

384 {
386 s->promise.set_value("Failed to create session");
387 return;
388 }
389
390 const char *session_handle = nullptr;
391 g_variant_lookup(results, "session_handle", "s", &session_handle);
392
393 LOG(LOG_LEVEL_DEBUG) << MOD_NAME "session created with handle: " << session_handle << "\n";
394 assert(s->session_path() == session_handle);
395
396 {
397 GVariantBuilder params;
398 g_variant_builder_init(&params, G_VARIANT_TYPE_VARDICT);
399 g_variant_builder_add(&params, "{sv}", "types", g_variant_new_uint32(3)); // 1 full screen, 2 - a window, 3 - both
400 g_variant_builder_add(&params, "{sv}", "multiple", g_variant_new_boolean(false));
401 if(s->show_cursor)
402 g_variant_builder_add(&params, "{sv}", "cursor_mode", g_variant_new_uint32(2));
403
404 if(!s->restore_file.empty()){
405 std::string token;
406 std::ifstream file(s->restore_file);
407
408 if(file.is_open()) {
409 std::ostringstream ss;
410 ss << file.rdbuf();
411 token = ss.str();
412 }
413
414 // 0: Do not persist (default), 1: Permissions persist as long as the application is running, 2: Permissions persist until explicitly revoked
415 g_variant_builder_add(&params, "{sv}", "persist_mode", g_variant_new_uint32(2));
416 if(!token.empty())
417 g_variant_builder_add(&params, "{sv}", "restore_token", g_variant_new_string(token.c_str()));
418 }
419
420 s->call_with_request<sources_selected>("SelectSources", {g_variant_new_object_path(s->session_path().c_str())}, params);
421 }
422};
static void sources_selected(uint32_t response, GVariant *results, ScreenCastPortal_impl *s)
static constexpr uint32_t REQUEST_RESPONSE_OK
#define LOG_LEVEL_DEBUG
Definition kernels.cu:48

References call_with_request(), LOG, LOG_LEVEL_DEBUG, MOD_NAME, params, promise, REQUEST_RESPONSE_OK, restore_file, session_path(), show_cursor, and sources_selected().

Here is the call graph for this function:

◆ session_path()

const std::string & ScreenCastPortal_impl::session_path ( ) const
inline

Definition at line 180 of file dbus_portal.cpp.

181 {
182 return session.path;
183 }

References session.

Referenced by run(), session_created(), and sources_selected().

◆ session_token()

const std::string & ScreenCastPortal_impl::session_token ( ) const
inline

Definition at line 185 of file dbus_portal.cpp.

186 {
187 return session.token;
188 }

References session.

Referenced by run().

◆ sources_selected()

void ScreenCastPortal_impl::sources_selected ( uint32_t response,
GVariant * results,
ScreenCastPortal_impl * s )
staticprivate

Definition at line 367 of file dbus_portal.cpp.

367 {
368 gchar *pretty = g_variant_print(results, true);
369 LOG(LOG_LEVEL_INFO) << MOD_NAME "selected sources: " << pretty << "\n";
370 g_free((gpointer) pretty);
371
373 s->promise.set_value("Failed to select sources");
374 return;
375 }
376
377 {
378 GVariantBuilder options;
379 g_variant_builder_init(&options, G_VARIANT_TYPE_VARDICT);
380 s->call_with_request<started>("Start", {g_variant_new_object_path(s->session_path().c_str()), /*parent window: */ g_variant_new_string("")}, options);
381 }
382};
static void started(uint32_t response, GVariant *results, void *user_data)
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
Definition rtp.c:253

References call_with_request(), LOG, LOG_LEVEL_INFO, MOD_NAME, promise, REQUEST_RESPONSE_OK, session_path(), and started().

Referenced by session_created().

Here is the call graph for this function:

◆ started()

void ScreenCastPortal_impl::started ( uint32_t response,
GVariant * results,
void * user_data )
staticprivate

Definition at line 332 of file dbus_portal.cpp.

332 {
333 auto s = static_cast<ScreenCastPortal_impl *>(user_data);
334 LOG(LOG_LEVEL_DEBUG) << MOD_NAME "started: " << g_variant_print(results, true) << "\n";
335
337 s->promise.set_value("failed to start (dialog cancelled by user)");
338 return;
340 s->promise.set_value("failed to start (unknown reason)");
341 return;
342 }
343
344 const char *restore_token = nullptr;
345 if (g_variant_lookup(results, "restore_token", "s", &restore_token)){
346 std::ofstream file(s->restore_file);
347 file<<restore_token;
348 }
349
350 GVariant *streams = g_variant_lookup_value(results, "streams", G_VARIANT_TYPE_ARRAY);
351 GVariant *stream_properties;
352 GVariantIter iter;
353 g_variant_iter_init(&iter, streams);
354 assert(g_variant_iter_n_children(&iter) == 1);
355 bool got_item = g_variant_iter_loop(&iter, "(u@a{sv})", &s->pw_node, &stream_properties);
356 assert(got_item);
357
358 GVariantBuilder builder;
359 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
360 g_dbus_proxy_call_with_unix_fd_list(s->proxy(), "OpenPipeWireRemote",
361 g_variant_new("(oa{sv})", s->session_path().c_str(), &builder),
362 G_DBUS_CALL_FLAGS_NONE, -1,
363 nullptr, nullptr, ScreenCastPortal_impl::pipewire_opened, s);
364 g_variant_builder_clear(&builder);
365}
static void pipewire_opened(GObject *source, GAsyncResult *res, void *user_data)
static constexpr uint32_t REQUEST_RESPONSE_CANCELLED_BY_USER

References LOG, LOG_LEVEL_DEBUG, MOD_NAME, pipewire_opened(), REQUEST_RESPONSE_CANCELLED_BY_USER, and REQUEST_RESPONSE_OK.

Referenced by sources_selected().

Here is the call graph for this function:

Member Data Documentation

◆ connection

GDBusConnection* ScreenCastPortal_impl::connection
private

◆ dbus_loop

GMainLoop* ScreenCastPortal_impl::dbus_loop
private

◆ promise

std::promise<std::string> ScreenCastPortal_impl::promise
private

Definition at line 137 of file dbus_portal.cpp.

Referenced by get_future(), session_created(), and sources_selected().

◆ pw_fd

int ScreenCastPortal_impl::pw_fd = -1
private

Definition at line 134 of file dbus_portal.cpp.

Referenced by get_pw_fd().

◆ pw_node

uint32_t ScreenCastPortal_impl::pw_node = UINT32_MAX
private

Definition at line 135 of file dbus_portal.cpp.

Referenced by get_pw_node().

◆ REQUEST_RESPONSE_CANCELLED_BY_USER

uint32_t ScreenCastPortal_impl::REQUEST_RESPONSE_CANCELLED_BY_USER = 1
staticconstexpr

Definition at line 142 of file dbus_portal.cpp.

Referenced by started().

◆ REQUEST_RESPONSE_OK

uint32_t ScreenCastPortal_impl::REQUEST_RESPONSE_OK = 0
staticconstexpr

Definition at line 141 of file dbus_portal.cpp.

Referenced by session_created(), sources_selected(), and started().

◆ REQUEST_RESPONSE_OTHER_ERROR

uint32_t ScreenCastPortal_impl::REQUEST_RESPONSE_OTHER_ERROR = 2
staticconstexpr

Definition at line 143 of file dbus_portal.cpp.

◆ restore_file

std::string ScreenCastPortal_impl::restore_file
private

Definition at line 131 of file dbus_portal.cpp.

Referenced by run(), and session_created().

◆ screencast_proxy

GDBusProxy* ScreenCastPortal_impl::screencast_proxy
private

◆ session

session_path_t ScreenCastPortal_impl::session
private

◆ show_cursor

bool ScreenCastPortal_impl::show_cursor = false
private

Definition at line 132 of file dbus_portal.cpp.

Referenced by run(), and session_created().

◆ unique_name

std::string ScreenCastPortal_impl::unique_name
private

Definition at line 128 of file dbus_portal.cpp.

Referenced by ScreenCastPortal_impl(), and sender_name().


The documentation for this class was generated from the following file: