Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
W
wireplumber
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pkg
wireplumber
Commits
811ccc9f
Commit
811ccc9f
authored
4 years ago
by
George Kiagiadakis
Browse files
Options
Downloads
Patches
Plain Diff
wpctl: add inspect command
parent
64347e67
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
tools/wpctl.c
+231
-1
231 additions, 1 deletion
tools/wpctl.c
with
231 additions
and
1 deletion
tools/wpctl.c
+
231
−
1
View file @
811ccc9f
...
...
@@ -8,6 +8,8 @@
#include
<wp/wp.h>
#include
<stdio.h>
#include
<pipewire/keys.h>
#include
<pipewire/extensions/session-manager/keys.h>
typedef
struct
_WpCtl
WpCtl
;
struct
_WpCtl
...
...
@@ -25,6 +27,12 @@ static struct {
gboolean
show_streams
;
}
status
;
struct
{
guint32
id
;
gboolean
show_referenced
;
gboolean
show_associated
;
}
inspect
;
struct
{
guint32
id
;
}
set_default
;
...
...
@@ -231,6 +239,211 @@ status_run (WpCtl * self)
g_main_loop_quit
(
self
->
loop
);
}
/* inspect */
static
gboolean
inspect_parse_positional
(
gint
argc
,
gchar
**
argv
,
GError
**
error
)
{
if
(
argc
<
3
)
{
g_set_error
(
error
,
wpctl_error_domain_quark
(),
0
,
"ID is required"
);
return
FALSE
;
}
long
id
=
strtol
(
argv
[
2
],
NULL
,
10
);
if
(
id
<=
0
)
{
g_set_error
(
error
,
wpctl_error_domain_quark
(),
0
,
"'%s' is not a valid number"
,
argv
[
2
]);
return
FALSE
;
}
cmdline
.
inspect
.
id
=
id
;
return
TRUE
;
}
static
gboolean
inspect_prepare
(
WpCtl
*
self
,
GError
**
error
)
{
/* collect all objects */
wp_object_manager_add_interest
(
self
->
om
,
WP_TYPE_PROXY
,
NULL
);
wp_object_manager_request_proxy_features
(
self
->
om
,
WP_TYPE_PROXY
,
WP_PROXY_FEATURES_STANDARD
);
return
TRUE
;
}
static
inline
void
inspect_prefix_line
(
guint
nest_level
,
gboolean
node
)
{
for
(
guint
i
=
1
;
i
<
nest_level
;
i
++
)
printf
(
TREE_INDENT_EMPTY
TREE_INDENT_LINE
);
if
(
nest_level
>
0
)
printf
(
TREE_INDENT_EMPTY
"%s"
,
node
?
TREE_INDENT_NODE
:
TREE_INDENT_LINE
);
}
struct
{
const
gchar
*
key
;
const
gchar
*
type
;
}
assoc_keys
[]
=
{
{
PW_KEY_CLIENT_ID
,
"Client"
},
{
PW_KEY_DEVICE_ID
,
"Device"
},
{
PW_KEY_ENDPOINT_CLIENT_ID
,
NULL
},
{
PW_KEY_ENDPOINT_STREAM_ID
,
"EndpointStream"
},
{
PW_KEY_ENDPOINT_LINK_OUTPUT_ENDPOINT
,
NULL
},
{
PW_KEY_ENDPOINT_LINK_OUTPUT_STREAM
,
NULL
},
{
PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT
,
NULL
},
{
PW_KEY_ENDPOINT_LINK_INPUT_STREAM
,
NULL
},
{
PW_KEY_ENDPOINT_ID
,
"Endpoint"
},
{
PW_KEY_LINK_INPUT_NODE
,
NULL
},
{
PW_KEY_LINK_INPUT_PORT
,
NULL
},
{
PW_KEY_LINK_OUTPUT_NODE
,
NULL
},
{
PW_KEY_LINK_OUTPUT_PORT
,
NULL
},
{
PW_KEY_LINK_ID
,
"Link"
},
{
PW_KEY_NODE_ID
,
"Node"
},
{
PW_KEY_PORT_ID
,
"Port"
},
{
PW_KEY_SESSION_ID
,
"Session"
},
};
static
inline
gboolean
key_is_object_reference
(
const
gchar
*
key
)
{
for
(
guint
i
=
0
;
i
<
G_N_ELEMENTS
(
assoc_keys
);
i
++
)
if
(
!
g_strcmp0
(
key
,
assoc_keys
[
i
].
key
))
return
TRUE
;
return
FALSE
;
}
static
inline
const
gchar
*
get_association_key
(
WpProxy
*
proxy
)
{
for
(
guint
i
=
0
;
i
<
G_N_ELEMENTS
(
assoc_keys
);
i
++
)
{
if
(
assoc_keys
[
i
].
type
&&
strstr
(
WP_PROXY_GET_CLASS
(
proxy
)
->
pw_iface_type
,
assoc_keys
[
i
].
type
))
return
assoc_keys
[
i
].
key
;
}
return
NULL
;
}
struct
property_item
{
const
gchar
*
key
;
const
gchar
*
value
;
};
static
gint
property_item_compare
(
gconstpointer
a
,
gconstpointer
b
)
{
return
g_strcmp0
(
((
struct
property_item
*
)
a
)
->
key
,
((
struct
property_item
*
)
b
)
->
key
);
}
static
void
inspect_print_object
(
WpCtl
*
self
,
WpProxy
*
proxy
,
guint
nest_level
)
{
g_autoptr
(
WpProperties
)
properties
=
wp_proxy_get_properties
(
proxy
);
g_autoptr
(
WpProperties
)
global_p
=
wp_proxy_get_global_properties
(
proxy
);
g_autoptr
(
GArray
)
array
=
g_array_new
(
FALSE
,
FALSE
,
sizeof
(
struct
property_item
));
/* print basic object info */
inspect_prefix_line
(
nest_level
,
TRUE
);
printf
(
"id %u, type %s
\n
"
,
wp_proxy_get_bound_id
(
proxy
),
WP_PROXY_GET_CLASS
(
proxy
)
->
pw_iface_type
);
/* merge the two property sets */
properties
=
wp_properties_ensure_unique_owner
(
properties
);
wp_properties_add
(
properties
,
global_p
);
wp_properties_set
(
properties
,
"object.id"
,
NULL
);
/* copy key/value pointers to an array for sorting */
{
g_autoptr
(
WpIterator
)
it
=
NULL
;
g_auto
(
GValue
)
item
=
G_VALUE_INIT
;
for
(
it
=
wp_properties_iterate
(
properties
);
wp_iterator_next
(
it
,
&
item
);
g_value_unset
(
&
item
))
{
struct
property_item
prop_item
=
{
.
key
=
wp_properties_iterator_item_get_key
(
&
item
),
.
value
=
wp_properties_iterator_item_get_value
(
&
item
),
};
g_array_append_val
(
array
,
prop_item
);
}
}
/* sort */
g_array_sort
(
array
,
property_item_compare
);
/* print */
for
(
guint
i
=
0
;
i
<
array
->
len
;
i
++
)
{
struct
property_item
*
prop_item
=
&
g_array_index
(
array
,
struct
property_item
,
i
);
gboolean
is_global
=
(
wp_properties_get
(
global_p
,
prop_item
->
key
)
!=
NULL
);
inspect_prefix_line
(
nest_level
,
FALSE
);
printf
(
" %c %s =
\"
%s
\"\n
"
,
is_global
?
'*'
:
' '
,
prop_item
->
key
,
prop_item
->
value
);
/* if the property is referencing an object, print the object */
if
(
cmdline
.
inspect
.
show_referenced
&&
nest_level
==
0
&&
key_is_object_reference
(
prop_item
->
key
))
{
guint
id
=
(
guint
)
strtol
(
prop_item
->
value
,
NULL
,
10
);
g_autoptr
(
WpProxy
)
refer_proxy
=
wp_object_manager_lookup
(
self
->
om
,
WP_TYPE_PROXY
,
WP_CONSTRAINT_TYPE_G_PROPERTY
,
"bound-id"
,
"=u"
,
id
,
NULL
);
if
(
refer_proxy
)
inspect_print_object
(
self
,
refer_proxy
,
nest_level
+
1
);
}
}
/* print associated objects */
if
(
cmdline
.
inspect
.
show_associated
&&
nest_level
==
0
)
{
const
gchar
*
lookup_key
=
get_association_key
(
proxy
);
if
(
lookup_key
)
{
g_autoptr
(
WpIterator
)
it
=
wp_object_manager_iterate_filtered
(
self
->
om
,
WP_TYPE_PROXY
,
WP_CONSTRAINT_TYPE_PW_PROPERTY
,
lookup_key
,
"=u"
,
wp_proxy_get_bound_id
(
proxy
),
NULL
);
g_auto
(
GValue
)
item
=
G_VALUE_INIT
;
inspect_prefix_line
(
nest_level
,
TRUE
);
printf
(
"associated objects:
\n
"
);
for
(;
wp_iterator_next
(
it
,
&
item
);
g_value_unset
(
&
item
))
{
WpProxy
*
assoc_proxy
=
g_value_get_object
(
&
item
);
inspect_print_object
(
self
,
assoc_proxy
,
nest_level
+
1
);
}
}
}
}
static
void
inspect_run
(
WpCtl
*
self
)
{
g_autoptr
(
WpProxy
)
proxy
=
NULL
;
guint32
id
=
cmdline
.
inspect
.
id
;
proxy
=
wp_object_manager_lookup
(
self
->
om
,
WP_TYPE_PROXY
,
WP_CONSTRAINT_TYPE_G_PROPERTY
,
"bound-id"
,
"=u"
,
id
,
NULL
);
if
(
!
proxy
)
{
printf
(
"Object '%d' not found
\n
"
,
id
);
goto
out_err
;
}
inspect_print_object
(
self
,
proxy
,
0
);
out:
g_main_loop_quit
(
self
->
loop
);
return
;
out_err:
self
->
exit_code
=
3
;
goto
out
;
}
/* set-default */
static
gboolean
...
...
@@ -472,7 +685,7 @@ out:
g_main_loop_quit
(
self
->
loop
);
}
#define N_ENTRIES
2
#define N_ENTRIES
3
static
const
struct
subcommand
{
/* the name to match on the command line */
...
...
@@ -506,6 +719,23 @@ static const struct subcommand {
.
prepare
=
status_prepare
,
.
run
=
status_run
,
},
{
.
name
=
"inspect"
,
.
positional_args
=
"ID"
,
.
summary
=
"Displays information about the specified object"
,
.
description
=
NULL
,
.
entries
=
{
{
"referenced"
,
'r'
,
G_OPTION_FLAG_NONE
,
G_OPTION_ARG_NONE
,
&
cmdline
.
inspect
.
show_referenced
,
"Show objects that are referenced in properties"
,
NULL
},
{
"associated"
,
'a'
,
G_OPTION_FLAG_NONE
,
G_OPTION_ARG_NONE
,
&
cmdline
.
inspect
.
show_associated
,
"Show associated objects"
,
NULL
},
{
NULL
}
},
.
parse_positional
=
inspect_parse_positional
,
.
prepare
=
inspect_prepare
,
.
run
=
inspect_run
,
},
{
.
name
=
"set-default"
,
.
positional_args
=
"ID"
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment