mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-19 07:00:10 -05:00
Improve introspection
Add instrospection of client and source-output. Add properties to source-output and to CreateSourceOutput/Input Add helper to fill properties of context. Add client-name to pinossrc and pinossink Improve test-subscribe to show all new introspection details.
This commit is contained in:
parent
85e09e7a5b
commit
13d846ec38
21 changed files with 684 additions and 72 deletions
|
|
@ -278,6 +278,7 @@ pinos_context_init (PinosContext * context)
|
|||
|
||||
/**
|
||||
* pinos_context_new:
|
||||
* @context: a #GMainContext to run in
|
||||
* @name: an application name
|
||||
* @properties: optional properties
|
||||
*
|
||||
|
|
@ -293,7 +294,9 @@ pinos_context_new (GMainContext *context,
|
|||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
if (properties == NULL)
|
||||
properties = pinos_properties_new ("media.name", name, NULL);
|
||||
properties = pinos_properties_new ("application.name", name, NULL);
|
||||
|
||||
pinos_fill_context_properties (properties);
|
||||
|
||||
return g_object_new (PINOS_TYPE_CONTEXT,
|
||||
"main-context", context,
|
||||
|
|
@ -419,7 +422,11 @@ subscription_cb (PinosSubscribe *subscribe,
|
|||
break;
|
||||
|
||||
case PINOS_SUBSCRIPTION_FLAGS_CLIENT:
|
||||
if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) {
|
||||
if (event == PINOS_SUBSCRIPTION_EVENT_NEW) {
|
||||
priv->clients = g_list_prepend (priv->clients, object);
|
||||
} else if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) {
|
||||
priv->clients = g_list_remove (priv->clients, object);
|
||||
|
||||
if (object == priv->client) {
|
||||
priv->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CLOSED, "Client disappeared");
|
||||
context_set_state (context, PINOS_CONTEXT_STATE_ERROR);
|
||||
|
|
@ -435,6 +442,10 @@ subscription_cb (PinosSubscribe *subscribe,
|
|||
break;
|
||||
|
||||
case PINOS_SUBSCRIPTION_FLAGS_SOURCE_OUTPUT:
|
||||
if (event == PINOS_SUBSCRIPTION_EVENT_NEW)
|
||||
priv->source_outputs = g_list_prepend (priv->source_outputs, object);
|
||||
else if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE)
|
||||
priv->source_outputs = g_list_remove (priv->source_outputs, object);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,102 @@ pinos_context_get_daemon_info (PinosContext *context,
|
|||
}
|
||||
|
||||
static void
|
||||
client_fill_info (PinosSourceInfo *info, GDBusProxy *proxy)
|
||||
client_fill_info (PinosClientInfo *info, GDBusProxy *proxy)
|
||||
{
|
||||
GVariant *variant;
|
||||
|
||||
info->id = proxy;
|
||||
|
||||
if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Name"))) {
|
||||
info->name = g_variant_get_string (variant, NULL);
|
||||
g_variant_unref (variant);
|
||||
} else {
|
||||
info->name = "Unknown";
|
||||
}
|
||||
|
||||
info->properties = pinos_properties_from_variant (
|
||||
g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Properties"));
|
||||
}
|
||||
|
||||
static void
|
||||
client_clear_info (PinosClientInfo *info)
|
||||
{
|
||||
if (info->properties)
|
||||
pinos_properties_free (info->properties);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pinos_context_list_client_info:
|
||||
* @context: a connected #PinosContext
|
||||
* @flags: extra #PinosClientInfoFlags
|
||||
* @cb: a #PinosClientInfoCallback
|
||||
* @cancelable: a #GCancellable
|
||||
* @user_data: user data passed to @cb
|
||||
*
|
||||
* Call @cb for each client. @cb will be called with NULL when there
|
||||
* are no more clients to list.
|
||||
*/
|
||||
void
|
||||
pinos_context_list_client_info (PinosContext *context,
|
||||
PinosClientInfoFlags flags,
|
||||
PinosClientInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
gpointer user_data)
|
||||
{
|
||||
GList *walk;
|
||||
PinosContextPrivate *priv = context->priv;
|
||||
|
||||
g_return_if_fail (PINOS_IS_CONTEXT (context));
|
||||
g_return_if_fail (cb != NULL);
|
||||
|
||||
for (walk = priv->clients; walk; walk = g_list_next (walk)) {
|
||||
GDBusProxy *proxy = walk->data;
|
||||
PinosClientInfo info;
|
||||
|
||||
client_fill_info (&info, proxy);
|
||||
cb (context, &info, user_data);
|
||||
client_clear_info (&info);
|
||||
}
|
||||
cb (context, NULL, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_context_get_client_info_by_id:
|
||||
* @context: a connected #PinosContext
|
||||
* @id: a client id
|
||||
* @flags: extra #PinosClientInfoFlags
|
||||
* @cb: a #PinosClientInfoCallback
|
||||
* @cancelable: a #GCancellable
|
||||
* @user_data: user data passed to @cb
|
||||
*
|
||||
* Call @cb for the client with @id. Then @cb will be called with NULL.
|
||||
*/
|
||||
void
|
||||
pinos_context_get_client_info_by_id (PinosContext *context,
|
||||
gpointer id,
|
||||
PinosClientInfoFlags flags,
|
||||
PinosClientInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosClientInfo info;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
g_return_if_fail (PINOS_IS_CONTEXT (context));
|
||||
g_return_if_fail (id != NULL);
|
||||
g_return_if_fail (cb != NULL);
|
||||
|
||||
proxy = G_DBUS_PROXY (id);
|
||||
|
||||
client_fill_info (&info, proxy);
|
||||
cb (context, &info, user_data);
|
||||
client_clear_info (&info);
|
||||
cb (context, NULL, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
source_fill_info (PinosSourceInfo *info, GDBusProxy *proxy)
|
||||
{
|
||||
GVariant *variant;
|
||||
|
||||
|
|
@ -140,7 +235,7 @@ client_fill_info (PinosSourceInfo *info, GDBusProxy *proxy)
|
|||
}
|
||||
|
||||
static void
|
||||
client_clear_info (PinosSourceInfo *info)
|
||||
source_clear_info (PinosSourceInfo *info)
|
||||
{
|
||||
if (info->properties)
|
||||
pinos_properties_free (info->properties);
|
||||
|
|
@ -176,15 +271,15 @@ pinos_context_list_source_info (PinosContext *context,
|
|||
GDBusProxy *proxy = walk->data;
|
||||
PinosSourceInfo info;
|
||||
|
||||
client_fill_info (&info, proxy);
|
||||
source_fill_info (&info, proxy);
|
||||
cb (context, &info, user_data);
|
||||
client_clear_info (&info);
|
||||
source_clear_info (&info);
|
||||
}
|
||||
cb (context, NULL, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_context_get_source_info:
|
||||
* pinos_context_get_source_info_by_id:
|
||||
* @context: a connected #PinosContext
|
||||
* @id: a source id
|
||||
* @flags: extra #PinosSourceInfoFlags
|
||||
|
|
@ -192,8 +287,7 @@ pinos_context_list_source_info (PinosContext *context,
|
|||
* @cancelable: a #GCancellable
|
||||
* @user_data: user data passed to @cb
|
||||
*
|
||||
* Call @cb for each source. @cb will be called with NULL when there
|
||||
* are no more sources to list.
|
||||
* Call @cb for the source with @id. Then @cb will be called with NULL.
|
||||
*/
|
||||
void
|
||||
pinos_context_get_source_info_by_id (PinosContext *context,
|
||||
|
|
@ -212,8 +306,119 @@ pinos_context_get_source_info_by_id (PinosContext *context,
|
|||
|
||||
proxy = G_DBUS_PROXY (id);
|
||||
|
||||
client_fill_info (&info, proxy);
|
||||
source_fill_info (&info, proxy);
|
||||
cb (context, &info, user_data);
|
||||
client_clear_info (&info);
|
||||
source_clear_info (&info);
|
||||
cb (context, NULL, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
source_output_fill_info (PinosSourceOutputInfo *info, GDBusProxy *proxy)
|
||||
{
|
||||
GVariant *variant;
|
||||
|
||||
info->id = proxy;
|
||||
|
||||
if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Client"))) {
|
||||
info->client_path = g_variant_get_string (variant, NULL);
|
||||
g_variant_unref (variant);
|
||||
} else {
|
||||
info->client_path = "Unknown";
|
||||
}
|
||||
if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Source"))) {
|
||||
info->source_path = g_variant_get_string (variant, NULL);
|
||||
g_variant_unref (variant);
|
||||
} else {
|
||||
info->source_path = "Unknown";
|
||||
}
|
||||
if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "PossibleFormats"))) {
|
||||
gsize len;
|
||||
gchar *formats = g_variant_dup_string (variant, &len);
|
||||
info->possible_formats = g_bytes_new_take (formats, len + 1);
|
||||
g_variant_unref (variant);
|
||||
} else {
|
||||
info->possible_formats = NULL;
|
||||
}
|
||||
info->properties = pinos_properties_from_variant (
|
||||
g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Properties"));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
source_output_clear_info (PinosSourceOutputInfo *info)
|
||||
{
|
||||
if (info->possible_formats)
|
||||
g_bytes_unref (info->possible_formats);
|
||||
if (info->properties)
|
||||
pinos_properties_free (info->properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_context_list_source_output_info:
|
||||
* @context: a connected #PinosContext
|
||||
* @flags: extra #PinosSourceOutputInfoFlags
|
||||
* @cb: a #PinosSourceOutputInfoCallback
|
||||
* @cancelable: a #GCancellable
|
||||
* @user_data: user data passed to @cb
|
||||
*
|
||||
* Call @cb for each source-output. @cb will be called with NULL when there
|
||||
* are no more outputs to list.
|
||||
*/
|
||||
void
|
||||
pinos_context_list_source_output_info (PinosContext *context,
|
||||
PinosSourceOutputInfoFlags flags,
|
||||
PinosSourceOutputInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
gpointer user_data)
|
||||
{
|
||||
GList *walk;
|
||||
PinosContextPrivate *priv = context->priv;
|
||||
|
||||
g_return_if_fail (PINOS_IS_CONTEXT (context));
|
||||
g_return_if_fail (cb != NULL);
|
||||
|
||||
for (walk = priv->source_outputs; walk; walk = g_list_next (walk)) {
|
||||
GDBusProxy *proxy = walk->data;
|
||||
PinosSourceOutputInfo info;
|
||||
|
||||
source_output_fill_info (&info, proxy);
|
||||
cb (context, &info, user_data);
|
||||
source_output_clear_info (&info);
|
||||
}
|
||||
cb (context, NULL, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_context_get_source_output_info_by_id:
|
||||
* @context: a connected #PinosContext
|
||||
* @id: a source output id
|
||||
* @flags: extra #PinosSourceOutputInfoFlags
|
||||
* @cb: a #PinosSourceOutputInfoCallback
|
||||
* @cancelable: a #GCancellable
|
||||
* @user_data: user data passed to @cb
|
||||
*
|
||||
* Call @cb for the source output with @id. Then @cb will be called with NULL.
|
||||
*/
|
||||
void
|
||||
pinos_context_get_source_output_info_by_id (PinosContext *context,
|
||||
gpointer id,
|
||||
PinosSourceOutputInfoFlags flags,
|
||||
PinosSourceOutputInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
gpointer user_data)
|
||||
{
|
||||
PinosSourceOutputInfo info;
|
||||
GDBusProxy *proxy;
|
||||
|
||||
g_return_if_fail (PINOS_IS_CONTEXT (context));
|
||||
g_return_if_fail (id != NULL);
|
||||
g_return_if_fail (cb != NULL);
|
||||
|
||||
proxy = G_DBUS_PROXY (id);
|
||||
|
||||
source_output_fill_info (&info, proxy);
|
||||
cb (context, &info, user_data);
|
||||
source_output_clear_info (&info);
|
||||
cb (context, NULL, user_data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* PinosDeamonInfo:
|
||||
* PinosDaemonInfo:
|
||||
* @id: generic id of the daemon
|
||||
* @user_name: name of the user that started the daemon
|
||||
* @host_name: name of the machine the daemon is running on
|
||||
|
|
@ -63,6 +63,39 @@ void pinos_context_get_daemon_info (PinosContext *context,
|
|||
GCancellable *cancellable,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* PinosClientInfo:
|
||||
* @id: generic id of the client
|
||||
* @name: name of client
|
||||
* @properties: extra properties
|
||||
*
|
||||
* The client information. Extra information can be added in later
|
||||
* versions.
|
||||
*/
|
||||
typedef struct {
|
||||
gpointer id;
|
||||
const char *name;
|
||||
PinosProperties *properties;
|
||||
} PinosClientInfo;
|
||||
|
||||
typedef enum {
|
||||
PINOS_CLIENT_INFO_FLAGS_NONE = 0,
|
||||
} PinosClientInfoFlags;
|
||||
|
||||
typedef gboolean (*PinosClientInfoCallback) (PinosContext *c, const PinosClientInfo *info, gpointer userdata);
|
||||
|
||||
void pinos_context_list_client_info (PinosContext *context,
|
||||
PinosClientInfoFlags flags,
|
||||
PinosClientInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
gpointer user_data);
|
||||
void pinos_context_get_client_info_by_id (PinosContext *context,
|
||||
gpointer id,
|
||||
PinosClientInfoFlags flags,
|
||||
PinosClientInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* PinosSourceState:
|
||||
* @PINOS_SOURCE_STATE_ERROR: the source is in error
|
||||
|
|
@ -131,6 +164,48 @@ void pinos_context_get_source_info_by_id (PinosContext *context,
|
|||
GCancellable *cancellable,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* PinosSourceOutputInfo:
|
||||
* @id: generic id of the output
|
||||
* @client_path: the owner client
|
||||
* @source_path: the source path
|
||||
* @possible_formats: the possible formats
|
||||
* @properties: the properties of the source
|
||||
*
|
||||
* The source information. Extra information can be added in later
|
||||
* versions.
|
||||
*/
|
||||
typedef struct {
|
||||
gpointer id;
|
||||
const char *client_path;
|
||||
const char *source_path;
|
||||
GBytes *possible_formats;
|
||||
PinosProperties *properties;
|
||||
} PinosSourceOutputInfo;
|
||||
|
||||
/**
|
||||
* PinosSourceOutputInfoFlags:
|
||||
* @PINOS_SOURCE_OUTPUT_INFO_FLAGS_NONE: no flags
|
||||
*
|
||||
* Extra flags to pass to pinos_context_get_source_output_info_list.
|
||||
*/
|
||||
typedef enum {
|
||||
PINOS_SOURCE_OUTPUT_INFO_FLAGS_NONE = 0,
|
||||
} PinosSourceOutputInfoFlags;
|
||||
|
||||
typedef gboolean (*PinosSourceOutputInfoCallback) (PinosContext *c, const PinosSourceOutputInfo *info, gpointer userdata);
|
||||
|
||||
void pinos_context_list_source_output_info (PinosContext *context,
|
||||
PinosSourceOutputInfoFlags flags,
|
||||
PinosSourceOutputInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
gpointer user_data);
|
||||
void pinos_context_get_source_output_info_by_id (PinosContext *context,
|
||||
gpointer id,
|
||||
PinosSourceOutputInfoFlags flags,
|
||||
PinosSourceOutputInfoCallback cb,
|
||||
GCancellable *cancellable,
|
||||
gpointer user_data);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PINOS_INTROSPECT_H__ */
|
||||
|
|
|
|||
|
|
@ -34,3 +34,62 @@ pinos_init (int *argc, char **argv[])
|
|||
{
|
||||
gst_init (argc, argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_client_name:
|
||||
*
|
||||
* Make a new pinos client name that can be used to construct a context.
|
||||
*/
|
||||
gchar *
|
||||
pinos_client_name (void)
|
||||
{
|
||||
const char *c;
|
||||
|
||||
if ((c = g_get_application_name ()))
|
||||
return g_strdup (c);
|
||||
else if ((c = g_get_prgname ()))
|
||||
return g_strdup (c);
|
||||
else
|
||||
return g_strdup_printf ("pinos-pid-%lu", (gulong) getpid ());
|
||||
}
|
||||
|
||||
void
|
||||
pinos_fill_context_properties (PinosProperties *properties)
|
||||
{
|
||||
g_return_if_fail (properties != NULL);
|
||||
|
||||
if (!pinos_properties_get (properties, "application.name"))
|
||||
pinos_properties_set (properties, "application.name", g_get_application_name ());
|
||||
|
||||
if (!pinos_properties_get (properties, "application.prgname"))
|
||||
pinos_properties_set (properties, "application.prgname", g_get_prgname ());
|
||||
|
||||
if (!pinos_properties_get (properties, "application.language")) {
|
||||
const gchar *str = g_getenv ("LANG");
|
||||
if (str)
|
||||
pinos_properties_set (properties, "application.language", str);
|
||||
}
|
||||
if (!pinos_properties_get (properties, "application.process.id")) {
|
||||
gchar *str = g_strdup_printf ("%lu", (gulong) getpid());
|
||||
pinos_properties_set (properties, "application.process.id", str);
|
||||
g_free (str);
|
||||
}
|
||||
if (!pinos_properties_get (properties, "application.process.user"))
|
||||
pinos_properties_set (properties, "application.process.user", g_get_user_name ());
|
||||
|
||||
if (!pinos_properties_get (properties, "application.process.host"))
|
||||
pinos_properties_set (properties, "application.process.host", g_get_host_name ());
|
||||
|
||||
if (!pinos_properties_get (properties, "application.process.session_id")) {
|
||||
const gchar *str = g_getenv ("XDG_SESSION_ID");
|
||||
if (str)
|
||||
pinos_properties_set (properties, "application.process.session_id", str);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pinos_fill_stream_properties (PinosProperties *properties)
|
||||
{
|
||||
g_return_if_fail (properties != NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,4 +35,9 @@
|
|||
|
||||
void pinos_init (int *argc, char **argv[]);
|
||||
|
||||
gchar *pinos_client_name (void);
|
||||
|
||||
void pinos_fill_context_properties (PinosProperties *properties);
|
||||
void pinos_fill_stream_properties (PinosProperties *properties);
|
||||
|
||||
#endif /* __PINOS_H__ */
|
||||
|
|
|
|||
|
|
@ -38,5 +38,7 @@ struct _PinosContextPrivate
|
|||
PinosSubscriptionFlags subscription_mask;
|
||||
PinosSubscribe *subscribe;
|
||||
|
||||
GList *clients;
|
||||
GList *sources;
|
||||
GList *source_outputs;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -399,6 +399,12 @@ pinos_stream_new (PinosContext *context,
|
|||
g_return_val_if_fail (PINOS_IS_CONTEXT (context), NULL);
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
if (props == NULL) {
|
||||
props = pinos_properties_new ("media.name", name, NULL);
|
||||
} else if (!pinos_properties_get (props, "media.name")) {
|
||||
pinos_properties_set (props, "media.name", name);
|
||||
}
|
||||
|
||||
return g_object_new (PINOS_TYPE_STREAM,
|
||||
"context", context,
|
||||
"name", name,
|
||||
|
|
@ -532,9 +538,10 @@ do_connect_capture (PinosStream *stream)
|
|||
|
||||
g_dbus_proxy_call (context->priv->client,
|
||||
"CreateSourceOutput",
|
||||
g_variant_new ("(ss)",
|
||||
g_variant_new ("(ss@a{sv})",
|
||||
(priv->source_path ? priv->source_path : ""),
|
||||
g_bytes_get_data (priv->accepted_formats, NULL)),
|
||||
g_bytes_get_data (priv->accepted_formats, NULL),
|
||||
pinos_properties_to_variant (priv->properties)),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL, /* GCancellable *cancellable */
|
||||
|
|
@ -595,7 +602,9 @@ do_connect_provide (PinosStream *stream)
|
|||
|
||||
g_dbus_proxy_call (context->priv->client,
|
||||
"CreateSourceInput",
|
||||
g_variant_new ("(s)", g_bytes_get_data (priv->possible_formats, NULL)),
|
||||
g_variant_new ("(s@a{sv})",
|
||||
g_bytes_get_data (priv->possible_formats, NULL),
|
||||
pinos_properties_to_variant (priv->properties)),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL, /* GCancellable *cancellable */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue