commit b2dbe8c64805cace6f4b9366b6370ce443805bf4
parent ba7c65188a8adcaa8d809c81517108ad62f1b245
Author: Jacki <jacki@thejackimonster.de>
Date: Tue, 13 Aug 2024 18:14:55 +0200
Wire up logic to set target of pipewiresrc dynamically
Signed-off-by: Jacki <jacki@thejackimonster.de>
Diffstat:
4 files changed, 127 insertions(+), 32 deletions(-)
diff --git a/src/discourse.c b/src/discourse.c
@@ -588,10 +588,14 @@ _setup_video_gst_pipelines(MESSENGER_DiscourseInfo *info)
g_assert(info);
info->video_record_pipeline = gst_parse_launch(
- "autovideosrc ! video/x-raw,framerate={ [ 0/1, 30/1 ] } ! videoscale ! video/x-raw,width=1280,height=720 ! videoconvert ! video/x-raw,format=I420 ! x264enc bitrate=1000 speed-preset=fast bframes=0 key-int-max=30 tune=zerolatency byte-stream=true ! video/x-h264,profile=baseline ! rtph264pay aggregate-mode=zero-latency mtu=45000 ! capsfilter name=filter ! fdsink name=sink",
+ "pipewiresrc name=source ! video/x-raw,framerate={ [ 0/1, 30/1 ] } ! videoscale ! video/x-raw,width=1280,height=720 ! videoconvert ! video/x-raw,format=I420 ! x264enc bitrate=1000 speed-preset=fast bframes=0 key-int-max=30 tune=zerolatency byte-stream=true ! video/x-h264,profile=baseline ! rtph264pay aggregate-mode=zero-latency mtu=45000 ! capsfilter name=filter ! fdsink name=sink",
NULL
);
+ info->video_record_source = gst_bin_get_by_name(
+ GST_BIN(info->video_record_pipeline), "source"
+ );
+
info->video_record_sink = gst_bin_get_by_name(
GST_BIN(info->video_record_pipeline), "sink"
);
@@ -643,6 +647,7 @@ discourse_create_info(struct GNUNET_CHAT_Discourse *discourse)
info->audio_record_sink = NULL;
info->video_record_pipeline = NULL;
+ info->video_record_source = NULL;
info->video_record_sink = NULL;
info->audio_mix_pipeline = NULL;
@@ -940,6 +945,24 @@ discourse_is_mute(const struct GNUNET_CHAT_Discourse *discourse)
return (GST_STATE_PLAYING != state);
}
+void
+discourse_set_target(struct GNUNET_CHAT_Discourse *discourse,
+ const char *name)
+{
+ MESSENGER_DiscourseInfo* info = GNUNET_CHAT_discourse_get_user_pointer(discourse);
+
+ if (!info)
+ return;
+
+ if (info->video_record_source)
+ g_object_set(
+ G_OBJECT(info->video_record_source),
+ "target-object",
+ name,
+ NULL
+ );
+}
+
gboolean
discourse_link_widget(const struct GNUNET_CHAT_Discourse *discourse,
const struct GNUNET_CHAT_Contact *contact,
diff --git a/src/discourse.h b/src/discourse.h
@@ -65,6 +65,7 @@ typedef struct MESSENGER_DiscourseInfo
GstElement *audio_record_sink;
GstElement *video_record_pipeline;
+ GstElement *video_record_source;
GstElement *video_record_sink;
GstElement *audio_mix_pipeline;
@@ -193,6 +194,16 @@ bool
discourse_is_mute(const struct GNUNET_CHAT_Discourse *discourse);
/**
+ * Sets the capture target of a given discourse by name.
+ *
+ * @param discourse Chat discourse
+ * @param name Target name
+ */
+void
+discourse_set_target(struct GNUNET_CHAT_Discourse *discourse,
+ const char *name);
+
+/**
* Links/Unlinks a widget from the video pipeline of a discourse
* for a given chat contact to a selected container as
* child.
diff --git a/src/ui/discourse.c b/src/ui/discourse.c
@@ -109,6 +109,65 @@ static void
_discourse_update_members(UI_DISCOURSE_Handle *handle);
static void
+_update_streaming_state(UI_DISCOURSE_Handle *handle,
+ gboolean streaming)
+{
+ handle->streaming = streaming;
+
+ if (handle->video_discourse)
+ discourse_set_mute(handle->video_discourse, !(handle->streaming));
+
+ if ((handle->app) && (!(handle->streaming)))
+ application_set_active_session(handle->app, NULL);
+
+ _discourse_update_members(handle);
+}
+
+static void
+iterate_cameras(void *cls,
+ const char *name,
+ const char *description,
+ const char *media_class,
+ const char *media_role)
+{
+ g_assert(cls);
+
+ UI_DISCOURSE_Handle *handle = (UI_DISCOURSE_Handle*) cls;
+
+ if ((!name) || (!description) || (!media_class) || (!media_role))
+ return;
+
+ if (0 != g_strcmp0(media_class, "Video/Source"))
+ return;
+ if (0 != g_strcmp0(media_role, "Camera"))
+ return;
+
+ if (handle->video_discourse)
+ discourse_set_target(handle->video_discourse, name);
+}
+
+static void
+_request_camera_callback(MESSENGER_Application *app,
+ gboolean success,
+ gboolean error,
+ gpointer user_data)
+{
+ g_assert((app) && (user_data));
+
+ UI_DISCOURSE_Handle *handle = (UI_DISCOURSE_Handle*) user_data;
+
+ if ((!success) || (error))
+ return;
+
+ media_init_camera_capturing(&(app->media.camera), app);
+ media_pw_main_loop_run(&(app->media.camera));
+
+ media_pw_iterate_nodes(&(app->media.camera), iterate_cameras, handle);
+
+ _update_streaming_state(handle, true);
+}
+
+static void
handle_camera_button_click(UNUSED GtkButton *button,
gpointer user_data)
{
@@ -116,11 +175,15 @@ handle_camera_button_click(UNUSED GtkButton *button,
UI_DISCOURSE_Handle *handle = (UI_DISCOURSE_Handle*) user_data;
- handle->stream_camera = !(handle->stream_camera);
- if (handle->video_discourse)
- discourse_set_mute(handle->video_discourse, !(handle->stream_camera));
-
- _discourse_update_members(handle);
+ if (handle->streaming)
+ _update_streaming_state(handle, false);
+ else
+ request_new_camera(
+ handle->app,
+ XDP_CAMERA_FLAG_NONE,
+ _request_camera_callback,
+ handle
+ );
}
static void
@@ -140,7 +203,8 @@ iterate_streams(void *cls,
if (0 != g_strcmp0(media_class, "Stream/Output/Video"))
return;
- // TODO
+ if (handle->video_discourse)
+ discourse_set_target(handle->video_discourse, name);
}
static void
@@ -153,19 +217,15 @@ _request_screen_callback(MESSENGER_Application *app,
UI_DISCOURSE_Handle *handle = (UI_DISCOURSE_Handle*) user_data;
-#ifndef MESSENGER_APPLICATION_NO_PORTAL
- if ((app->portal) && (success))
-#else
- if (success)
-#endif
- {
- media_init_screen_sharing(&(app->media.screen), app);
- media_pw_main_loop_run(&(app->media.screen));
+ if ((!success) || (error))
+ return;
- media_pw_iterate_nodes(&(app->media.screen), iterate_streams, handle);
+ media_init_screen_sharing(&(app->media.screen), app);
+ media_pw_main_loop_run(&(app->media.screen));
- // TODO
- }
+ media_pw_iterate_nodes(&(app->media.screen), iterate_streams, handle);
+
+ _update_streaming_state(handle, true);
}
static void
@@ -176,17 +236,18 @@ handle_screen_button_click(UNUSED GtkButton *button,
UI_DISCOURSE_Handle *handle = (UI_DISCOURSE_Handle*) user_data;
- // TODO
-
- request_new_screencast(
- handle->app,
- XDP_OUTPUT_MONITOR | XDP_OUTPUT_WINDOW,
- XDP_SCREENCAST_FLAG_NONE,
- XDP_CURSOR_MODE_EMBEDDED,
- XDP_PERSIST_MODE_TRANSIENT,
- _request_screen_callback,
- handle
- );
+ if (handle->streaming)
+ _update_streaming_state(handle, false);
+ else
+ request_new_screencast(
+ handle->app,
+ XDP_OUTPUT_MONITOR | XDP_OUTPUT_WINDOW,
+ XDP_SCREENCAST_FLAG_NONE,
+ XDP_CURSOR_MODE_EMBEDDED,
+ XDP_PERSIST_MODE_TRANSIENT,
+ _request_screen_callback,
+ handle
+ );
}
static void
@@ -267,7 +328,7 @@ handle_call_stop_button_click(UNUSED GtkButton *button,
}
handle->muted = TRUE;
- handle->stream_camera = FALSE;
+ handle->streaming = FALSE;
_update_call_button(handle);
application_chat_unlock(handle->app);
@@ -295,7 +356,7 @@ ui_discourse_window_init(MESSENGER_Application *app,
handle->video_discourse = NULL;
handle->muted = TRUE;
- handle->stream_camera = FALSE;
+ handle->streaming = FALSE;
handle->parent = GTK_WINDOW(app->ui.messenger.main_window);
diff --git a/src/ui/discourse.h b/src/ui/discourse.h
@@ -42,7 +42,7 @@ typedef struct UI_DISCOURSE_Handle
struct GNUNET_CHAT_Discourse *video_discourse;
gboolean muted;
- gboolean stream_camera;
+ gboolean streaming;
GtkWindow *parent;