messenger-gtk

Gtk+3 graphical user interfaces for GNUnet Messenger
Log | Files | Refs | Submodules | README | LICENSE

commit 9fb1a5d25f79281977768f5514401162c4f45eff
parent 027bc5b314c3f2e36937956d2d75f5ea2d62b62a
Author: Jacki <jacki@thejackimonster.de>
Date:   Wed, 31 Jul 2024 16:46:14 +0200

Link video stream into discourse panel as widget

Signed-off-by: Jacki <jacki@thejackimonster.de>

Diffstat:
Mresources/ui/discourse_panel.ui | 1+
Msrc/discourse.c | 110++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/discourse.h | 26++++++++++++++++++++++++++
Msrc/ui/discourse.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/ui/play_media.c | 4++--
5 files changed, 212 insertions(+), 3 deletions(-)

diff --git a/resources/ui/discourse_panel.ui b/resources/ui/discourse_panel.ui @@ -36,6 +36,7 @@ Author: Tobias Frisch <property name="width-request">124</property> <property name="visible">True</property> <property name="can-focus">False</property> + <property name="valign">center</property> <property name="border-width">8</property> <property name="orientation">vertical</property> <property name="spacing">4</property> diff --git a/src/discourse.c b/src/discourse.c @@ -176,7 +176,7 @@ _setup_video_gst_pipelines_of_subscription(MESSENGER_DiscourseSubscriptionInfo * gst_caps_unref(caps); - gst_element_set_state(info->video_stream_pipeline, GST_STATE_PLAYING); + gst_element_set_state(info->video_stream_pipeline, GST_STATE_NULL); } } @@ -373,6 +373,59 @@ discourse_subscription_stream_message(MESSENGER_DiscourseSubscriptionInfo *info, _stream_video_message(info, message, available); } +static gboolean +discourse_subscription_link_widget(MESSENGER_DiscourseSubscriptionInfo *info, + GtkContainer *container, + gboolean link) +{ + g_assert((info) && (container)); + + GtkWidget *widget; + if (info->video_stream_sink) + g_object_get(info->video_stream_sink, "widget", &widget, NULL); + else + widget = NULL; + + if (!widget) + return FALSE; + + GtkWidget *parent = gtk_widget_get_parent(widget); + + if (parent) + { + GtkContainer *container = GTK_CONTAINER(parent); + + gst_element_set_state(info->video_stream_pipeline, GST_STATE_NULL); + + gtk_widget_hide(widget); + gtk_widget_unrealize(widget); + + gtk_container_remove( + container, + widget + ); + } + + if (!link) + return TRUE; + + gtk_box_pack_start( + GTK_BOX(container), + widget, + true, + true, + 0 + ); + + g_object_unref(widget); + gtk_widget_realize(widget); + + gtk_widget_show_all(GTK_WIDGET(container)); + + gst_element_set_state(info->video_stream_pipeline, GST_STATE_PLAYING); + return TRUE; +} + static void _setup_audio_gst_pipelines(MESSENGER_DiscourseInfo *info) { @@ -789,3 +842,58 @@ discourse_is_mute(struct GNUNET_CHAT_Discourse *discourse) return (GST_STATE_PLAYING != state); } + +gboolean +discourse_link_widget(const struct GNUNET_CHAT_Discourse *discourse, + const struct GNUNET_CHAT_Contact *contact, + GtkContainer *container) +{ + MESSENGER_DiscourseInfo* info = GNUNET_CHAT_discourse_get_user_pointer(discourse); + + if (!info) + return FALSE; + + GList *sub = info->subscriptions; + MESSENGER_DiscourseSubscriptionInfo *sub_info = NULL; + + while (sub) + { + sub_info = (MESSENGER_DiscourseSubscriptionInfo*) (sub->data); + if (contact == sub_info->contact) + break; + + sub = g_list_next(sub); + } + + if (!sub_info) + return FALSE; + + return discourse_subscription_link_widget(sub_info, container, TRUE); +} + +gboolean +discourse_unlink_widget(const struct GNUNET_CHAT_Discourse *discourse, + const struct GNUNET_CHAT_Contact *contact) +{ + MESSENGER_DiscourseInfo* info = GNUNET_CHAT_discourse_get_user_pointer(discourse); + + if (!info) + return FALSE; + + GList *sub = info->subscriptions; + MESSENGER_DiscourseSubscriptionInfo *sub_info = NULL; + + while (sub) + { + sub_info = (MESSENGER_DiscourseSubscriptionInfo*) (sub->data); + if (contact == sub_info->contact) + break; + + sub = g_list_next(sub); + } + + if (!sub_info) + return FALSE; + + return discourse_subscription_link_widget(sub_info, NULL, FALSE); +} diff --git a/src/discourse.h b/src/discourse.h @@ -29,6 +29,7 @@ #include <glib-2.0/glib.h> #include <gnunet/gnunet_chat_lib.h> +#include <gtk-3.0/gtk/gtk.h> #include <pthread.h> /** @@ -185,4 +186,29 @@ discourse_set_mute(struct GNUNET_CHAT_Discourse *discourse, bool discourse_is_mute(struct GNUNET_CHAT_Discourse *discourse); +/** + * Links a widget from the video pipeline of a discourse + * for a given chat contact to a selected container as + * child. + * + * @param discourse Chat discourse + * @param contact Chat contact + * @param container Container + */ +gboolean +discourse_link_widget(const struct GNUNET_CHAT_Discourse *discourse, + const struct GNUNET_CHAT_Contact *contact, + GtkContainer *container); + +/** + * Unlinks a widget from the video pipeline of a discourse + * for a given chat contact from its current parent. + * + * @param discourse Chat discourse + * @param contact Chat contact + */ +gboolean +discourse_unlink_widget(const struct GNUNET_CHAT_Discourse *discourse, + const struct GNUNET_CHAT_Contact *contact); + #endif /* DISCOURSE_H_ */ diff --git a/src/ui/discourse.c b/src/ui/discourse.c @@ -24,6 +24,7 @@ #include "discourse.h" +#include <glib-2.0/glib.h> #include <gnunet/gnunet_common.h> #include <gnunet/gnunet_chat_lib.h> #include <gnunet/gnunet_time_lib.h> @@ -413,6 +414,7 @@ append_group_contacts(void *cls, struct IterateDiscourseClosure { MESSENGER_Application *app; + UI_DISCOURSE_Handle *handle; GtkContainer *container; }; @@ -433,6 +435,10 @@ iterate_ui_discourse_update_discourse_members(void *cls, UI_DISCOURSE_PANEL_Handle* panel = ui_discourse_panel_new(closure->app); ui_discourse_panel_set_contact(panel, contact); + GtkWidget *parent = gtk_widget_get_parent(panel->panel_box); + if (parent) + gtk_container_remove(GTK_CONTAINER(parent), panel->panel_box); + gtk_flow_box_insert(flowbox, panel->panel_box, -1); GtkFlowBoxChild *child = GTK_FLOW_BOX_CHILD( @@ -466,6 +472,56 @@ iterate_ui_discourse_update_context_discourses(void *cls, return GNUNET_YES; } +struct IterateDiscourseVideoClosure { + MESSENGER_Application *app; + UI_DISCOURSE_Handle *handle; + GList *children; +}; + +static enum GNUNET_GenericReturnValue +iterate_ui_discourse_update_discourse_video(void *cls, + const struct GNUNET_CHAT_Discourse *discourse, + struct GNUNET_CHAT_Contact *contact) +{ + g_assert((cls) && (discourse) && (contact)); + + struct IterateDiscourseVideoClosure *closure = ( + (struct IterateDiscourseVideoClosure*) cls + ); + + GList *list = closure->children; + while (list) + { + GtkFlowBoxChild *child = GTK_FLOW_BOX_CHILD(list->data); + + UI_DISCOURSE_PANEL_Handle* panel = (UI_DISCOURSE_PANEL_Handle*) ( + g_object_get_qdata( + G_OBJECT(child), + closure->app->quarks.ui + ) + ); + + if (contact != panel->contact) + goto skip_child; + + const gboolean linked = discourse_link_widget( + discourse, + contact, + GTK_CONTAINER(panel->video_box) + ); + + if (linked) + gtk_stack_set_visible_child(panel->panel_stack, panel->video_box); + else + gtk_stack_set_visible_child(panel->panel_stack, panel->avatar_box); + + skip_child: + list = g_list_next(list); + } + + return GNUNET_YES; +} + static void _discourse_update_members(UI_DISCOURSE_Handle *handle) { @@ -497,6 +553,7 @@ _discourse_update_members(UI_DISCOURSE_Handle *handle) struct IterateDiscourseClosure closure; closure.app = handle->app; + closure.handle = handle; closure.container = GTK_CONTAINER(handle->members_flowbox); GNUNET_CHAT_context_iterate_discourses( @@ -504,6 +561,23 @@ _discourse_update_members(UI_DISCOURSE_Handle *handle) iterate_ui_discourse_update_context_discourses, &closure ); + + list = gtk_container_get_children(GTK_CONTAINER(handle->members_flowbox)); + if (list) + { + struct IterateDiscourseVideoClosure closure_video; + closure_video.app = handle->app; + closure_video.handle = handle; + closure_video.children = list; + + GNUNET_CHAT_discourse_iterate_contacts( + handle->video_discourse, + iterate_ui_discourse_update_discourse_video, + &closure_video + ); + + g_list_free(list); + } } static enum GNUNET_GenericReturnValue diff --git a/src/ui/play_media.c b/src/ui/play_media.c @@ -249,8 +249,8 @@ _adjust_playing_media_state(UI_PLAY_MEDIA_Handle *handle, gboolean playing) if (handle->preview_stack) gtk_stack_set_visible_child( - handle->preview_stack, - handle->video_box + handle->preview_stack, + handle->video_box ); }