From 4a93bea2031e4967dce482b9413b8aba15924118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Tue, 27 May 2025 19:04:40 +0200 Subject: [PATCH 1/4] Revert "meson: Remove GIR init section" This reverts commit b05f0f2b30057b49baeb24c809bcedc8f2965042. --- src/lib/clapper-gtk/meson.build | 1 + src/lib/clapper/meson.build | 1 + src/lib/meson.build | 6 ++++++ 3 files changed, 8 insertions(+) diff --git a/src/lib/clapper-gtk/meson.build b/src/lib/clapper-gtk/meson.build index 026422dc..f2dacb82 100644 --- a/src/lib/clapper-gtk/meson.build +++ b/src/lib/clapper-gtk/meson.build @@ -176,6 +176,7 @@ if build_gir clappergtk_enums, ], extra_args: [ + gir_init_section, '--quiet', '--warn-all', '-DCLAPPER_GTK_COMPILATION', diff --git a/src/lib/clapper/meson.build b/src/lib/clapper/meson.build index 8e2d1afd..77de1517 100644 --- a/src/lib/clapper/meson.build +++ b/src/lib/clapper/meson.build @@ -235,6 +235,7 @@ if build_gir clapper_enums, ], extra_args: [ + gir_init_section, '--quiet', '--warn-all', '-DCLAPPER_COMPILATION', diff --git a/src/lib/meson.build b/src/lib/meson.build index fc93cc90..70569fb3 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -4,6 +4,12 @@ build_gir = (gir.found() and not get_option('introspection').disabled()) vapigen = find_program('vapigen', required: get_option('vapi')) build_vapi = (vapigen.found() and not get_option('vapi').disabled()) +gir_init_section = '--add-init-section=extern void gst_init(gint*,gchar**);' + \ + 'g_setenv("GST_REGISTRY_1.0", "@0@", TRUE);'.format(meson.current_build_dir() + '/gir_empty_registry.reg') + \ + 'g_setenv("GST_PLUGIN_PATH_1_0", "", TRUE);' + \ + 'g_setenv("GST_PLUGIN_SYSTEM_PATH_1_0", "", TRUE);' + \ + 'gst_init(NULL,NULL);' + subdir('gst') subdir('clapper') subdir('clapper-gtk') From 0b8d3598440c08b64a64fea1c881df19cacc7a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Mon, 2 Jun 2025 19:53:46 +0200 Subject: [PATCH 2/4] meson: Improve GIR init section Init with disabled registry and remove it only for clapper-gtk where its not needed. --- src/lib/clapper-gtk/meson.build | 1 - src/lib/meson.build | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/clapper-gtk/meson.build b/src/lib/clapper-gtk/meson.build index f2dacb82..026422dc 100644 --- a/src/lib/clapper-gtk/meson.build +++ b/src/lib/clapper-gtk/meson.build @@ -176,7 +176,6 @@ if build_gir clappergtk_enums, ], extra_args: [ - gir_init_section, '--quiet', '--warn-all', '-DCLAPPER_GTK_COMPILATION', diff --git a/src/lib/meson.build b/src/lib/meson.build index 70569fb3..604a4ead 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -5,7 +5,8 @@ vapigen = find_program('vapigen', required: get_option('vapi')) build_vapi = (vapigen.found() and not get_option('vapi').disabled()) gir_init_section = '--add-init-section=extern void gst_init(gint*,gchar**);' + \ - 'g_setenv("GST_REGISTRY_1.0", "@0@", TRUE);'.format(meson.current_build_dir() + '/gir_empty_registry.reg') + \ + 'g_setenv("GST_REGISTRY_DISABLE", "yes", TRUE);' + \ + 'g_setenv("GST_REGISTRY_1_0", "@0@", TRUE);'.format(meson.current_build_dir() + '/gir_empty_registry.reg') + \ 'g_setenv("GST_PLUGIN_PATH_1_0", "", TRUE);' + \ 'g_setenv("GST_PLUGIN_SYSTEM_PATH_1_0", "", TRUE);' + \ 'gst_init(NULL,NULL);' From e9d0d8f345564ae553656d1740b7d4a163ad902b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Mon, 2 Jun 2025 20:01:46 +0200 Subject: [PATCH 3/4] clapper: Add taglist to media items Allow apps to read and/or populate initial taglist within media item. Apps might care about other tags that Clapper application does not, so this single property allows them to read whatever tag they might need. --- src/lib/clapper/clapper-media-item.c | 315 +++++++++++++++++++----- src/lib/clapper/clapper-media-item.h | 9 +- src/lib/clapper/clapper-utils-private.h | 3 + src/lib/clapper/clapper-utils.c | 57 +++++ 4 files changed, 326 insertions(+), 58 deletions(-) diff --git a/src/lib/clapper/clapper-media-item.c b/src/lib/clapper/clapper-media-item.c index e7be5faf..2532c3cf 100644 --- a/src/lib/clapper/clapper-media-item.c +++ b/src/lib/clapper/clapper-media-item.c @@ -43,6 +43,7 @@ struct _ClapperMediaItem gchar *uri; gchar *suburi; + GstTagList *tags; ClapperTimeline *timeline; guint id; @@ -56,6 +57,13 @@ struct _ClapperMediaItem gboolean used; }; +typedef struct +{ + ClapperMediaItem *item; + gboolean changed; + gboolean from_user; +} ClapperMediaItemTagIterData; + enum { PROP_0, @@ -63,6 +71,7 @@ enum PROP_URI, PROP_SUBURI, PROP_CACHE_LOCATION, + PROP_TAGS, PROP_TITLE, PROP_CONTAINER_FORMAT, PROP_DURATION, @@ -111,8 +120,8 @@ clapper_media_item_new (const gchar *uri) /* FIXME: Set initial container format from file extension parsing */ - GST_TRACE_OBJECT (item, "New media item, ID: %u, URI: %s, title: %s", - item->id, item->uri, item->title); + GST_TRACE_OBJECT (item, "New media item, ID: %u, URI: \"%s\", title: \"%s\"", + item->id, item->uri, GST_STR_NULL (item->title)); return item; } @@ -258,27 +267,6 @@ clapper_media_item_get_suburi (ClapperMediaItem *self) return suburi; } -static gboolean -clapper_media_item_take_title (ClapperMediaItem *self, gchar *title, - ClapperAppBus *app_bus) -{ - gboolean changed; - - GST_OBJECT_LOCK (self); - if ((changed = g_strcmp0 (self->title, title) != 0)) { - g_free (self->title); - self->title = title; - } - GST_OBJECT_UNLOCK (self); - - if (changed) - clapper_app_bus_post_prop_notify (app_bus, GST_OBJECT_CAST (self), param_specs[PROP_TITLE]); - else - g_free (title); - - return changed; -} - /** * clapper_media_item_get_title: * @item: a #ClapperMediaItem @@ -305,25 +293,24 @@ clapper_media_item_get_title (ClapperMediaItem *self) return title; } -static gboolean -clapper_media_item_take_container_format (ClapperMediaItem *self, gchar *container_format, - ClapperAppBus *app_bus) +static inline gboolean +_refresh_tag_prop_unlocked (ClapperMediaItem *self, const gchar *tag, + gboolean from_user, gchar **tag_ptr) { - gboolean changed; + const gchar *string; - GST_OBJECT_LOCK (self); - if ((changed = g_strcmp0 (self->container_format, container_format) != 0)) { - g_free (self->container_format); - self->container_format = container_format; - } - GST_OBJECT_UNLOCK (self); + if ((*tag_ptr && from_user) // if already set, user cannot modify it + || !gst_tag_list_peek_string_index (self->tags, tag, 0, &string) // guarantees non-empty string + || (g_strcmp0 (*tag_ptr, string) == 0)) + return FALSE; - if (changed) - clapper_app_bus_post_prop_notify (app_bus, GST_OBJECT_CAST (self), param_specs[PROP_CONTAINER_FORMAT]); - else - g_free (container_format); + GST_LOG_OBJECT (self, "Tag prop \"%s\" update: \"%s\" -> \"%s\"", + tag, GST_STR_NULL (*tag_ptr), string); - return changed; + g_free (*tag_ptr); + *tag_ptr = g_strdup (string); + + return TRUE; } /** @@ -333,6 +320,8 @@ clapper_media_item_take_container_format (ClapperMediaItem *self, gchar *contain * Get media item container format. * * Returns: (transfer full) (nullable): media container format. + * + * Deprecated: 0.10: Get `container-format` from [property@Clapper.MediaItem:tags] instead. */ gchar * clapper_media_item_get_container_format (ClapperMediaItem *self) @@ -389,11 +378,207 @@ clapper_media_item_get_duration (ClapperMediaItem *self) return duration; } +/** + * clapper_media_item_get_tags: + * @item: a #ClapperMediaItem + * + * Get readable list of tags stored in media item. + * + * Returns: (transfer full): a #GstTagList. + * + * Since: 0.10 + */ +GstTagList * +clapper_media_item_get_tags (ClapperMediaItem *self) +{ + GstTagList *tags = NULL; + + g_return_val_if_fail (CLAPPER_IS_MEDIA_ITEM (self), NULL); + + GST_OBJECT_LOCK (self); + tags = gst_tag_list_ref (self->tags); + GST_OBJECT_UNLOCK (self); + + return tags; +} + +static void +_tags_replace_func (const GstTagList *tags, const gchar *tag, ClapperMediaItemTagIterData *data) +{ + ClapperMediaItem *self = data->item; + guint index = 0; + gboolean replace = FALSE; + + while (TRUE) { + const GValue *old_value = gst_tag_list_get_value_index (self->tags, tag, index); + const GValue *new_value = gst_tag_list_get_value_index (tags, tag, index); + + /* Number of old values is the same or greater and + * all values until this iteration were the same */ + if (!new_value) + break; + + /* A wild new tag appeared */ + if (!old_value) { + replace = TRUE; + break; + } + + /* Users can only set non-existing tags */ + if (data->from_user) + break; + + /* Check with tolerance for doubles */ + if (G_VALUE_TYPE (old_value) == G_TYPE_DOUBLE + && G_VALUE_TYPE (new_value) == G_TYPE_DOUBLE) { + gdouble old_dbl, new_dbl; + + old_dbl = g_value_get_double (old_value); + new_dbl = g_value_get_double (new_value); + + if ((replace = !G_APPROX_VALUE (old_dbl, new_dbl, FLT_EPSILON))) + break; + } else if (gst_value_compare (old_value, new_value) != GST_VALUE_EQUAL) { + replace = TRUE; + break; + } + + ++index; + } + + if (replace) { + const GValue *value; + index = 0; + + GST_LOG_OBJECT (self, "Replacing \"%s\" tag value", tag); + + /* Ensure writable, but only when replacing something */ + if (!data->changed) { + self->tags = gst_tag_list_make_writable (self->tags); + data->changed = TRUE; + } + + /* Replace first tag value (so it becomes sole member) */ + value = gst_tag_list_get_value_index (tags, tag, index); + gst_tag_list_add_value (self->tags, GST_TAG_MERGE_REPLACE, tag, value); + + /* Append any remaining tags (so next time we iterate indexes will match) */ + while ((value = gst_tag_list_get_value_index (tags, tag, ++index))) + gst_tag_list_add_value (self->tags, GST_TAG_MERGE_APPEND, tag, value); + } +} + +static gboolean +clapper_media_item_insert_tags_internal (ClapperMediaItem *self, const GstTagList *tags, + ClapperAppBus *app_bus, gboolean from_user) +{ + ClapperMediaItemTagIterData data; + gboolean title_changed = FALSE, cont_changed = FALSE; + + GST_OBJECT_LOCK (self); + + data.item = self; + data.changed = FALSE; + data.from_user = from_user; + + if (G_LIKELY (tags != self->tags)) + gst_tag_list_foreach (tags, (GstTagForeachFunc) _tags_replace_func, &data); + + if (data.changed) { + title_changed = _refresh_tag_prop_unlocked (self, GST_TAG_TITLE, + from_user, &self->title); + cont_changed = _refresh_tag_prop_unlocked (self, GST_TAG_CONTAINER_FORMAT, + from_user, &self->container_format); + } + + GST_OBJECT_UNLOCK (self); + + if (!data.changed) + return FALSE; + + if (app_bus) { + GstObject *src = GST_OBJECT_CAST (self); + + clapper_app_bus_post_prop_notify (app_bus, src, param_specs[PROP_TAGS]); + + if (title_changed) + clapper_app_bus_post_prop_notify (app_bus, src, param_specs[PROP_TITLE]); + if (cont_changed) + clapper_app_bus_post_prop_notify (app_bus, src, param_specs[PROP_CONTAINER_FORMAT]); + } else { + GObject *src = G_OBJECT (self); + + clapper_utils_prop_notify_on_main_sync (src, param_specs[PROP_TAGS]); + + if (title_changed) + clapper_utils_prop_notify_on_main_sync (src, param_specs[PROP_TITLE]); + if (cont_changed) + clapper_utils_prop_notify_on_main_sync (src, param_specs[PROP_CONTAINER_FORMAT]); + } + + return TRUE; +} + +/** + * clapper_media_item_populate_tags: + * @item: a #ClapperMediaItem + * @tags: a #GstTagList of GLOBAL scope + * + * Populate non-existing tags in @item tag list. + * + * Passed @tags must use [enum@Gst.TagScope.GLOBAL] scope. + * + * Note that tags are automatically determined during media playback + * and those take precedence. This function can be useful if an app can + * determine some tags that are not in media metadata or for filling + * item with some initial/cached tags to display in UI before playback. + * + * When a tag already exists in the tag list (was populated) this + * function will not overwrite it. If you really need to permanently + * override some tags in media, you can use `taginject` element as + * player video/audio filter instead. + * + * Returns: whether at least one tag got updated. + * + * Since: 0.10 + */ +gboolean +clapper_media_item_populate_tags (ClapperMediaItem *self, const GstTagList *tags) +{ + ClapperPlayer *player; + ClapperAppBus *app_bus = NULL; + gboolean changed; + + g_return_val_if_fail (CLAPPER_IS_MEDIA_ITEM (self), FALSE); + g_return_val_if_fail (tags != NULL, FALSE); + + if (G_UNLIKELY (gst_tag_list_get_scope (tags) != GST_TAG_SCOPE_GLOBAL)) { + g_warning ("Cannot populate media item tags using a list with non-global tag scope"); + return FALSE; + } + + if ((player = clapper_player_get_from_ancestor (GST_OBJECT_CAST (self)))) + app_bus = player->app_bus; + + changed = clapper_media_item_insert_tags_internal (self, tags, app_bus, TRUE); + + if (changed && player) { + ClapperFeaturesManager *features_manager; + + if ((features_manager = clapper_player_get_features_manager (player))) + clapper_features_manager_trigger_item_updated (features_manager, self); + } + + gst_clear_object (&player); + + return changed; +} + /** * clapper_media_item_get_timeline: * @item: a #ClapperMediaItem * - * Get the [class@Clapper.Timeline] assosiated with @item. + * Get the [class@Clapper.Timeline] associated with @item. * * Returns: (transfer none): a #ClapperTimeline of item. */ @@ -405,21 +590,6 @@ clapper_media_item_get_timeline (ClapperMediaItem *self) return self->timeline; } -static gboolean -clapper_media_item_update_from_container_tags (ClapperMediaItem *self, const GstTagList *tags, - ClapperAppBus *app_bus) -{ - gchar *string = NULL; - gboolean changed = FALSE; - - if (gst_tag_list_get_string (tags, GST_TAG_CONTAINER_FORMAT, &string)) - changed |= clapper_media_item_take_container_format (self, string, app_bus); - if (gst_tag_list_get_string (tags, GST_TAG_TITLE, &string)) - changed |= clapper_media_item_take_title (self, string, app_bus); - - return changed; -} - void clapper_media_item_update_from_tag_list (ClapperMediaItem *self, const GstTagList *tags, ClapperPlayer *player) @@ -427,7 +597,7 @@ clapper_media_item_update_from_tag_list (ClapperMediaItem *self, const GstTagLis GstTagScope scope = gst_tag_list_get_scope (tags); if (scope == GST_TAG_SCOPE_GLOBAL) { - gboolean changed = clapper_media_item_update_from_container_tags (self, tags, player->app_bus); + gboolean changed = clapper_media_item_insert_tags_internal (self, tags, player->app_bus, FALSE); if (changed) { ClapperFeaturesManager *features_manager; @@ -459,7 +629,7 @@ clapper_media_item_update_from_discoverer_info (ClapperMediaItem *self, GstDisco GstDiscovererContainerInfo *cinfo = (GstDiscovererContainerInfo *) sinfo; if ((tags = gst_discoverer_container_info_get_tags (cinfo))) - changed |= clapper_media_item_update_from_container_tags (self, tags, player->app_bus); + changed |= clapper_media_item_insert_tags_internal (self, tags, player->app_bus, FALSE); } gst_discoverer_stream_info_unref (sinfo); } @@ -542,6 +712,9 @@ clapper_media_item_get_used (ClapperMediaItem *self) static void clapper_media_item_init (ClapperMediaItem *self) { + self->tags = gst_tag_list_new_empty (); + gst_tag_list_set_scope (self->tags, GST_TAG_SCOPE_GLOBAL); + self->timeline = clapper_timeline_new (); gst_object_set_parent (GST_OBJECT_CAST (self->timeline), GST_OBJECT_CAST (self)); } @@ -571,6 +744,8 @@ clapper_media_item_finalize (GObject *object) g_free (self->title); g_free (self->container_format); + gst_tag_list_unref (self->tags); + gst_object_unparent (GST_OBJECT_CAST (self->timeline)); gst_object_unref (self->timeline); @@ -617,6 +792,9 @@ clapper_media_item_get_property (GObject *object, guint prop_id, case PROP_SUBURI: g_value_take_string (value, clapper_media_item_get_suburi (self)); break; + case PROP_TAGS: + g_value_take_boxed (value, clapper_media_item_get_tags (self)); + break; case PROP_TITLE: g_value_take_string (value, clapper_media_item_get_title (self)); break; @@ -686,10 +864,27 @@ clapper_media_item_class_init (ClapperMediaItemClass *klass) NULL, NULL, NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + /** + * ClapperMediaItem:tags: + * + * A readable list of tags stored in media item. + * + * Since: 0.10 + */ + param_specs[PROP_TAGS] = g_param_spec_boxed ("tags", + NULL, NULL, GST_TYPE_TAG_LIST, + G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + + /* FIXME: 1.0: Consider rename to e.g. "(menu/display)-title" + * and also make it non-nullable (return URI as final fallback) */ /** * ClapperMediaItem:title: * * Media title. + * + * This might be a different string compared to `title` from + * [property@Clapper.MediaItem:tags], as this gives parsed + * title from file name/URI as fallback when no `title` tag. */ param_specs[PROP_TITLE] = g_param_spec_string ("title", NULL, NULL, NULL, @@ -699,15 +894,21 @@ clapper_media_item_class_init (ClapperMediaItemClass *klass) * ClapperMediaItem:container-format: * * Media container format. + * + * Deprecated: 0.10: Get `container-format` from [property@Clapper.MediaItem:tags] instead. */ param_specs[PROP_CONTAINER_FORMAT] = g_param_spec_string ("container-format", NULL, NULL, NULL, - G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS | G_PARAM_DEPRECATED); /** * ClapperMediaItem:duration: * * Media duration as a decimal number in seconds. + * + * This might be a different value compared to `duration` from + * [property@Clapper.MediaItem:tags], as this value is updated + * during decoding instead of being a fixed value from metadata. */ param_specs[PROP_DURATION] = g_param_spec_double ("duration", NULL, NULL, 0, G_MAXDOUBLE, 0, diff --git a/src/lib/clapper/clapper-media-item.h b/src/lib/clapper/clapper-media-item.h index 12744df0..5b0e3039 100644 --- a/src/lib/clapper/clapper-media-item.h +++ b/src/lib/clapper/clapper-media-item.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -63,12 +64,18 @@ gchar * clapper_media_item_get_suburi (ClapperMediaItem *item); CLAPPER_API gchar * clapper_media_item_get_title (ClapperMediaItem *item); -CLAPPER_API +CLAPPER_DEPRECATED_FOR(clapper_media_item_get_tags) gchar * clapper_media_item_get_container_format (ClapperMediaItem *item); CLAPPER_API gdouble clapper_media_item_get_duration (ClapperMediaItem *item); +CLAPPER_API +GstTagList * clapper_media_item_get_tags (ClapperMediaItem *item); + +CLAPPER_API +gboolean clapper_media_item_populate_tags (ClapperMediaItem *item, const GstTagList *tags); + CLAPPER_API ClapperTimeline * clapper_media_item_get_timeline (ClapperMediaItem *item); diff --git a/src/lib/clapper/clapper-utils-private.h b/src/lib/clapper/clapper-utils-private.h index 3f990056..8e402a6a 100644 --- a/src/lib/clapper/clapper-utils-private.h +++ b/src/lib/clapper/clapper-utils-private.h @@ -45,6 +45,9 @@ void clapper_utils_queue_remove_on_main_sync (ClapperQueue *queue, ClapperMediaI G_GNUC_INTERNAL void clapper_utils_queue_clear_on_main_sync (ClapperQueue *queue); +G_GNUC_INTERNAL +void clapper_utils_prop_notify_on_main_sync (GObject *object, GParamSpec *pspec); + G_GNUC_INTERNAL gchar * clapper_utils_uri_from_file (GFile *file); diff --git a/src/lib/clapper/clapper-utils.c b/src/lib/clapper/clapper-utils.c index 6df1d511..86db8e90 100644 --- a/src/lib/clapper/clapper-utils.c +++ b/src/lib/clapper/clapper-utils.c @@ -39,6 +39,12 @@ typedef struct ClapperUtilsQueueAlterMethod method; } ClapperUtilsQueueAlterData; +typedef struct +{ + GObject *object; + GParamSpec *pspec; +} ClapperUtilsPropNotifyData; + void clapper_utils_initialize (void) { @@ -71,6 +77,27 @@ clapper_utils_queue_alter_data_free (ClapperUtilsQueueAlterData *data) g_free (data); } +static ClapperUtilsPropNotifyData * +clapper_utils_prop_notify_data_new (GObject *object, GParamSpec *pspec) +{ + ClapperUtilsPropNotifyData *data = g_new (ClapperUtilsPropNotifyData, 1); + + data->object = object; + data->pspec = pspec; + + GST_TRACE ("Created prop notify data: %p", data); + + return data; +} + +static void +clapper_utils_prop_notify_data_free (ClapperUtilsPropNotifyData *data) +{ + GST_TRACE ("Freeing prop notify data: %p", data); + + g_free (data); +} + static gpointer clapper_utils_queue_alter_on_main (ClapperUtilsQueueAlterData *data) { @@ -110,6 +137,15 @@ clapper_utils_queue_alter_on_main (ClapperUtilsQueueAlterData *data) return NULL; } +static gpointer +clapper_utils_prop_notify_on_main (ClapperUtilsPropNotifyData *data) +{ + GST_DEBUG ("Prop notify invoked"); + g_object_notify_by_pspec (data->object, data->pspec); + + return NULL; +} + static inline void clapper_utils_queue_alter_invoke_on_main_sync_take (ClapperUtilsQueueAlterData *data) { @@ -155,6 +191,27 @@ clapper_utils_queue_clear_on_main_sync (ClapperQueue *queue) clapper_utils_queue_alter_invoke_on_main_sync_take (data); } +void +clapper_utils_prop_notify_on_main_sync (GObject *object, GParamSpec *pspec) +{ + ClapperUtilsPropNotifyData *data; + + if (g_main_context_is_owner (g_main_context_default ())) { // already in main thread + g_object_notify_by_pspec (object, pspec); + return; + } + + data = clapper_utils_prop_notify_data_new (object, pspec); + + GST_DEBUG ("Invoking prop notify on main..."); + + clapper_shared_utils_context_invoke_sync_full (g_main_context_default (), + (GThreadFunc) clapper_utils_prop_notify_on_main, data, + (GDestroyNotify) clapper_utils_prop_notify_data_free); + + GST_DEBUG ("Prop notify invoke finished"); +} + gchar * clapper_utils_uri_from_file (GFile *file) { From 72ab32d4ef203a5a8d43a1ad5cea00696d81a475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Fri, 6 Jun 2025 21:17:56 +0200 Subject: [PATCH 4/4] shared: Do not print deprecations when compiling own code We keep and use old functions in code for the compatibility reasons with older API versions. Do not print warnings about them being deprecated when compiling Clapper library that has and uses such function internally. --- src/lib/shared/clapper-api-visibility.h.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib/shared/clapper-api-visibility.h.in b/src/lib/shared/clapper-api-visibility.h.in index 4a02dde5..60a5314b 100644 --- a/src/lib/shared/clapper-api-visibility.h.in +++ b/src/lib/shared/clapper-api-visibility.h.in @@ -41,5 +41,11 @@ #endif #define @CLAPPER_API@_API _@CLAPPER_API@_VISIBILITY + +#if !defined(@CLAPPER_API@_COMPILATION) #define @CLAPPER_API@_DEPRECATED G_DEPRECATED _@CLAPPER_API@_VISIBILITY #define @CLAPPER_API@_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _@CLAPPER_API@_VISIBILITY +#else +#define @CLAPPER_API@_DEPRECATED _@CLAPPER_API@_VISIBILITY +#define @CLAPPER_API@_DEPRECATED_FOR(f) _@CLAPPER_API@_VISIBILITY +#endif