/* WirePlumber * * Copyright © 2025 Collabora Ltd. * @author Julian Bouzas * * SPDX-License-Identifier: MIT */ #include #include WP_DEFINE_LOCAL_LOG_TOPIC ("m-collection-manager") /* * This module creates the "sm-collection-manager" metadata and also each * individual collection metadata. */ struct _WpCollectionManagerPlugin { WpPlugin parent; /* Props */ gchar *metadata_name; WpImplMetadata *impl_metadata; GHashTable *collection_metadatas; }; enum { PROP_0, PROP_METADATA_NAME, }; G_DECLARE_FINAL_TYPE (WpCollectionManagerPlugin, wp_collection_manager_plugin, WP, COLLECTION_MANAGER_PLUGIN, WpPlugin) G_DEFINE_TYPE (WpCollectionManagerPlugin, wp_collection_manager_plugin, WP_TYPE_PLUGIN) static void wp_collection_manager_plugin_init (WpCollectionManagerPlugin * self) { } static void on_collection_metadata_activated (GObject * o, GAsyncResult * res, gpointer d) { WpCollectionManagerPlugin *self = WP_COLLECTION_MANAGER_PLUGIN (d); g_autoptr (WpImplMetadata) m = WP_IMPL_METADATA (o); g_autoptr (WpProperties) props = NULL; const gchar *name = NULL; g_autoptr (GError) error = NULL; /* Get the metadata name */ props = wp_global_proxy_get_global_properties (WP_GLOBAL_PROXY (m)); g_return_if_fail (props); name = wp_properties_get (props, "metadata.name"); g_return_if_fail (name); /* make sure activation was successful */ if (!wp_object_activate_finish (WP_OBJECT (m), res, &error)) { wp_warning_object (self, "Failed to activate collection metadata: %s", name); return; } /* Add the metadata */ g_hash_table_insert (self->collection_metadatas, g_strdup (name), g_object_ref (m)); wp_info_object (self, "Added collection metadata: %s", name); } static void on_metadata_changed (WpMetadata *m, guint32 subject, const gchar *key, const gchar *type, const gchar *value, gpointer d) { WpCollectionManagerPlugin *self = WP_COLLECTION_MANAGER_PLUGIN (d); g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (self)); if (key) { WpImplMetadata *collection_m = g_hash_table_lookup ( self->collection_metadatas, key); if (collection_m && !value) { /* Remove collection metadata */ g_hash_table_remove (self->collection_metadatas, key); wp_info_object (self, "Removed collection metadata: %s", key); } else if (!collection_m && value) { /* Create new collection metadata */ wp_info_object (self, "Creating collection metadata: %s", key); WpImplMetadata *new_collection_m = wp_impl_metadata_new_full (core, key, wp_properties_new ("wireplumber.collection", "true", NULL)); wp_object_activate (WP_OBJECT (new_collection_m), WP_OBJECT_FEATURES_ALL, NULL, on_collection_metadata_activated, self); } } else { /* Remove all collection metadatas */ g_hash_table_remove_all (self->collection_metadatas); wp_info_object (self, "Removed all collection metadatas"); } } static void on_metadata_activated (WpMetadata * m, GAsyncResult * res, gpointer user_data) { WpTransition *trans = WP_TRANSITION (user_data); WpCollectionManagerPlugin *self = wp_transition_get_source_object (trans); g_autoptr (GError) error = NULL; if (!wp_object_activate_finish (WP_OBJECT (m), res, &error)) { wp_transition_return_error (trans, g_error_new (WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED, "Failed to activate metadata object %s", self->metadata_name)); return; } /* monitor changes in metadata */ g_signal_connect_object (m, "changed", G_CALLBACK (on_metadata_changed), self, 0); wp_object_update_features (WP_OBJECT (self), WP_PLUGIN_FEATURE_ENABLED, 0); } static void wp_collection_manager_plugin_enable (WpPlugin * plugin, WpTransition * transition) { WpCollectionManagerPlugin * self = WP_COLLECTION_MANAGER_PLUGIN (plugin); g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (plugin)); /* Create the collection metadatas table */ self->collection_metadatas = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); /* Create the collection manager metadata */ self->impl_metadata = wp_impl_metadata_new_full (core, self->metadata_name, wp_properties_new ("wireplumber.collection-manager", "true", NULL)); wp_object_activate (WP_OBJECT (self->impl_metadata), WP_OBJECT_FEATURES_ALL, NULL, (GAsyncReadyCallback)on_metadata_activated, transition); } static void wp_collection_manager_plugin_disable (WpPlugin * plugin) { WpCollectionManagerPlugin * self = WP_COLLECTION_MANAGER_PLUGIN (plugin); g_clear_object (&self->impl_metadata); g_clear_pointer (&self->collection_metadatas, g_hash_table_unref); g_clear_pointer (&self->metadata_name, g_free); } static void wp_collection_manager_plugin_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) { WpCollectionManagerPlugin *self = WP_COLLECTION_MANAGER_PLUGIN (object); switch (property_id) { case PROP_METADATA_NAME: g_clear_pointer (&self->metadata_name, g_free); self->metadata_name = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wp_collection_manager_plugin_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { WpCollectionManagerPlugin *self = WP_COLLECTION_MANAGER_PLUGIN (object); switch (property_id) { case PROP_METADATA_NAME: g_value_set_string (value, self->metadata_name); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void wp_collection_manager_plugin_class_init (WpCollectionManagerPluginClass * klass) { WpPluginClass *plugin_class = (WpPluginClass *) klass; GObjectClass *object_class = (GObjectClass *) klass; plugin_class->enable = wp_collection_manager_plugin_enable; plugin_class->disable = wp_collection_manager_plugin_disable; object_class->set_property = wp_collection_manager_plugin_set_property; object_class->get_property = wp_collection_manager_plugin_get_property; g_object_class_install_property (object_class, PROP_METADATA_NAME, g_param_spec_string ("metadata-name", "metadata-name", "The metadata object to look after", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); } WP_PLUGIN_EXPORT GObject * wireplumber__module_init (WpCore * core, WpSpaJson * args, GError ** error) { g_autofree gchar *metadata_name = NULL; if (args) wp_spa_json_object_get (args, "metadata.name", "s", &metadata_name, NULL); return G_OBJECT (g_object_new (wp_collection_manager_plugin_get_type (), "name", "collection-manager", "core", core, "metadata-name", metadata_name ? metadata_name : "sm-collection-manager", NULL)); }