diff --git a/src/tools/wpctl.c b/src/tools/wpctl.c index e059a532..15f149bd 100644 --- a/src/tools/wpctl.c +++ b/src/tools/wpctl.c @@ -89,6 +89,10 @@ static struct { gboolean reset; } settings; + struct { + const gchar *collection_name; + } collections; + struct { guint64 id; const char *level; @@ -1592,6 +1596,139 @@ out: g_main_loop_quit (self->loop); } +/* collections */ + +static gboolean +collections_parse_positional (gint argc, gchar ** argv, GError **error) +{ + cmdline.collections.collection_name = NULL; + + if (argc >= 3) + cmdline.collections.collection_name = argv[2]; + + return TRUE; +} + +static gboolean +collections_prepare (WpCtl * self, GError ** error) +{ + wp_object_manager_add_interest (self->om, WP_TYPE_GLOBAL_PROXY, NULL); + wp_object_manager_request_object_features (self->om, WP_TYPE_GLOBAL_PROXY, + WP_OBJECT_FEATURES_ALL); + return TRUE; +} + +static void +print_global (WpCollection *collection, WpGlobalProxy *global) +{ + g_autoptr (WpProperties) props = NULL; + const gchar *global_name = NULL; + gchar global_type = '-'; + guint32 bound_id; + + props = wp_global_proxy_get_global_properties (global); + bound_id = wp_proxy_get_bound_id (WP_PROXY (global)); + + if (WP_IS_NODE (global)) { + global_name = wp_properties_get (props, "node.name"); + global_type = 'n'; + } else if (WP_IS_PORT (global)) { + global_name = wp_properties_get (props, "port.name"); + global_type = 'p'; + } else if (WP_IS_DEVICE (global)) { + global_name = wp_properties_get (props, "device.name"); + global_type = 'd'; + } else if (WP_IS_CLIENT (global)) { + global_name = wp_properties_get (props, "client.name"); + global_type = 'c'; + } else if (WP_IS_METADATA (global)) { + global_name = wp_properties_get (props, "metadata.name"); + global_type = 'm'; + } else if (WP_IS_FACTORY (global)) { + global_name = wp_properties_get (props, "factory.name"); + global_type = 'f'; + } + + g_print (" [%c] %4u. %s\n", global_type, bound_id, + global_name ? global_name : "UNKNOWN"); +} + +static void +print_collection (WpCollectionManager *cm, WpCollection *collection) +{ + const gchar *collection_name = wp_collection_get_name (collection); + g_autoptr (WpMetadata) meta = NULL; + g_autoptr (WpIterator) iter = NULL; + g_auto (GValue) val = G_VALUE_INIT; + guint32 bound_id; + + meta = wp_collection_get_metadata (collection); + if (!meta) + return; + bound_id = wp_proxy_get_bound_id (WP_PROXY (meta)); + + g_print ("%4u. %s\n", + bound_id, + collection_name); + + iter = wp_collection_manager_new_global_iterator (cm, collection_name); + while (wp_iterator_next (iter, &val)) { + WpGlobalProxy *global = g_value_get_object (&val); + print_global (collection, global); + g_value_unset (&val); + } + + printf ("\n"); +} + +static void +print_collections (WpCollectionManager *cm) +{ + g_autoptr (WpIterator) it = NULL; + g_auto (GValue) item = G_VALUE_INIT; + + printf ("Collections:\n\n"); + + it = wp_collection_manager_new_collection_iterator (cm); + while (wp_iterator_next (it, &item)) { + WpCollection *collection = g_value_get_object (&item); + print_collection (cm, collection); + g_value_unset (&item); + } +} + +static void +collections_run (WpCtl * self) +{ + g_autoptr (WpCollectionManager) cm = NULL; + const gchar *collection_name = cmdline.collections.collection_name; + + cm = wp_collection_manager_find (self->core, NULL); + if (!cm) { + printf ("Could not find registered collection manager\n"); + goto error; + } + + /* Print all collections if name is not provided */ + if (collection_name) { + WpCollection *collection; + collection = wp_collection_manager_get_collection (cm, collection_name); + if (collection) + print_collection (cm, collection); + else + printf ("Collection '%s' does not exist\n", collection_name); + } else { + print_collections (cm); + } + + wp_core_sync (self->core, NULL, (GAsyncReadyCallback) async_quit, self); + return; + +error: + self->exit_code = 3; + g_main_loop_quit (self->loop); +} + /* set-log-level */ static gboolean @@ -1840,6 +1977,16 @@ static const struct subcommand { .prepare = settings_prepare, .run = settings_run, }, + { + .name = "collections", + .positional_args = "[COLLECTION]", + .summary = "Shows information about collections", + .description = NULL, + .entries = { { NULL } }, + .parse_positional = collections_parse_positional, + .prepare = collections_prepare, + .run = collections_run, + }, { .name = "set-log-level", .positional_args = "[ID] LEVEL", @@ -1867,6 +2014,22 @@ on_settings_activated (WpSettings *s, GAsyncResult *res, WpCtl *ctl) wp_core_register_object (ctl->core, g_object_ref (s)); } +static void +on_collection_manager_activated (WpCollectionManager *cm, GAsyncResult *res, + WpCtl *ctl) +{ + GError *error = NULL; + + if (!wp_object_activate_finish (WP_OBJECT (cm), res, &error)) { + fprintf (stderr, "%s\n", error->message); + ctl->exit_code = 1; + g_main_loop_quit (ctl->loop); + return; + } + + wp_core_register_object (ctl->core, g_object_ref (cm)); +} + static void on_plugin_loaded (WpCore * core, GAsyncResult * res, WpCtl *ctl) { @@ -1894,6 +2057,7 @@ main (gint argc, gchar **argv) g_autoptr (GError) error = NULL; g_autofree gchar *summary = NULL; g_autoptr (WpSettings) settings = NULL; + g_autoptr (WpCollectionManager) collection_manager = NULL; setlocale (LC_ALL, ""); setlocale (LC_NUMERIC, "C"); @@ -1976,6 +2140,14 @@ main (gint argc, gchar **argv) (GAsyncReadyCallback)on_settings_activated, &ctl); + /* load and register the collection manager */ + collection_manager = wp_collection_manager_new (ctl.core, NULL); + wp_object_activate (WP_OBJECT (collection_manager), + WP_OBJECT_FEATURES_ALL, + NULL, + (GAsyncReadyCallback)on_collection_manager_activated, + &ctl); + /* load required API modules */ ctl.pending_plugins++; wp_core_load_component (ctl.core, "libwireplumber-module-default-nodes-api",