Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Julian Bouzas
WirePlumber
Commits
9667cccb
Commit
9667cccb
authored
May 25, 2020
by
Julian Bouzas
Browse files
modules: move monitor device activation logic into a new device-activation module
parent
5a9cb768
Pipeline
#151543
passed with stages
in 1 minute and 11 seconds
Changes
13
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
modules/meson.build
View file @
9667cccb
...
...
@@ -15,7 +15,7 @@ shared_library(
)
reserve_device_interface_src
=
gnome
.
gdbus_codegen
(
'reserve-device-interface'
,
sources
:
'module-
monitor
/org.freedesktop.ReserveDevice1.xml'
,
sources
:
'module-
device-activation
/org.freedesktop.ReserveDevice1.xml'
,
interface_prefix
:
'org.freedesktop.ReserveDevice1.'
,
namespace
:
'Wp'
)
...
...
@@ -24,14 +24,25 @@ shared_library(
'wireplumber-module-monitor'
,
[
'module-monitor.c'
,
'module-monitor/reserve-node.c'
,
'module-monitor/reserve-device.c'
,
'module-monitor/dbus-device-reservation.c'
,
reserve_device_interface_src
,
],
c_args
:
[
common_c_args
,
'-DG_LOG_DOMAIN="m-monitor"'
],
install
:
true
,
install_dir
:
wireplumber_module_dir
,
dependencies
:
[
wp_dep
,
pipewire_dep
],
)
shared_library
(
'wireplumber-module-device-activation'
,
[
'module-device-activation.c'
,
'module-device-activation/reserve-node.c'
,
'module-device-activation/reserve-device.c'
,
'module-device-activation/dbus-device-reservation.c'
,
reserve_device_interface_src
,
],
c_args
:
[
common_c_args
,
'-DG_LOG_DOMAIN="m-device-activation"'
],
install
:
true
,
install_dir
:
wireplumber_module_dir
,
dependencies
:
[
wp_dep
,
pipewire_dep
,
giounix_dep
],
)
...
...
modules/module-device-activation.c
0 → 100644
View file @
9667cccb
/* WirePlumber
*
* Copyright © 2020 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include
<wp/wp.h>
#include
<pipewire/pipewire.h>
#include
<spa/utils/keys.h>
#include
"module-device-activation/reserve-device.h"
#include
"module-device-activation/reserve-node.h"
G_DEFINE_QUARK
(
wp
-
module
-
device
-
activation
-
reserve
,
reserve
);
enum
{
PROP_0
,
PROP_MODE
,
};
struct
_WpDeviceActivation
{
WpPlugin
parent
;
/* Props */
gchar
*
mode
;
WpObjectManager
*
spa_devices_om
;
WpObjectManager
*
nodes_om
;
};
G_DECLARE_FINAL_TYPE
(
WpDeviceActivation
,
wp_device_activation
,
WP
,
DEVICE_ACTIVATION
,
WpPlugin
)
G_DEFINE_TYPE
(
WpDeviceActivation
,
wp_device_activation
,
WP_TYPE_PLUGIN
)
static
void
on_node_state_changed
(
WpNode
*
node
,
WpNodeState
old
,
WpNodeState
curr
,
WpReserveNode
*
node_data
)
{
g_return_if_fail
(
node_data
);
switch
(
curr
)
{
case
WP_NODE_STATE_IDLE
:
/* Release reservation after 3 seconds */
wp_reserve_node_timeout_release
(
node_data
,
3000
);
break
;
case
WP_NODE_STATE_RUNNING
:
/* Clear pending timeout if any and acquire reservation */
wp_reserve_node_acquire
(
node_data
);
break
;
default:
break
;
}
}
static
void
add_reserve_node_data
(
WpDeviceActivation
*
self
,
WpProxy
*
node
,
WpProxy
*
device
)
{
WpReserveDevice
*
device_data
=
NULL
;
g_autoptr
(
WpReserveNode
)
node_data
=
NULL
;
/* Only add reservation data on nodes whose device has reservation data */
device_data
=
g_object_get_qdata
(
G_OBJECT
(
device
),
reserve_quark
());
if
(
!
device_data
)
return
;
/* Create the node reservation data */
node_data
=
wp_reserve_node_new
(
node
,
device_data
);
/* Set the reserve node data on the node */
g_object_set_qdata_full
(
G_OBJECT
(
node
),
reserve_quark
(),
node_data
,
g_object_unref
);
/* Handle the info signal */
g_signal_connect_object
(
WP_NODE
(
node
),
"state-changed"
,
(
GCallback
)
on_node_state_changed
,
node_data
,
0
);
}
static
void
on_node_added
(
WpObjectManager
*
om
,
WpProxy
*
proxy
,
gpointer
d
)
{
WpDeviceActivation
*
self
=
WP_DEVICE_ACTIVATION
(
d
);
const
gchar
*
device_id
=
NULL
;
g_autoptr
(
WpProxy
)
device
=
NULL
;
/* Get the device associated with the node */
device_id
=
wp_proxy_get_property
(
proxy
,
PW_KEY_DEVICE_ID
);
if
(
!
device_id
)
return
;
device
=
wp_object_manager_lookup
(
self
->
spa_devices_om
,
WP_TYPE_SPA_DEVICE
,
WP_CONSTRAINT_TYPE_G_PROPERTY
,
"bound-id"
,
"=i"
,
atoi
(
device_id
),
NULL
);
if
(
!
device
)
{
wp_warning_object
(
self
,
"cannot find device for node reservation data"
);
return
;
}
/* Add reserve data */
add_reserve_node_data
(
self
,
proxy
,
device
);
}
static
void
add_reserve_device_data
(
WpDeviceActivation
*
self
,
WpProxy
*
device
,
gint
card_id
)
{
g_autoptr
(
WpCore
)
core
=
wp_proxy_get_core
(
WP_PROXY
(
device
));
g_autoptr
(
WpProperties
)
props
=
wp_proxy_get_properties
(
device
);
const
char
*
app_dev_name
=
NULL
;
g_autoptr
(
WpDbusDeviceReservation
)
reservation
=
NULL
;
g_autoptr
(
WpReserveDevice
)
device_data
=
NULL
;
app_dev_name
=
wp_properties_get
(
props
,
SPA_KEY_API_ALSA_PATH
);
/* Create the dbus device reservation */
reservation
=
wp_dbus_device_reservation_new
(
card_id
,
"PipeWire"
,
10
,
app_dev_name
);
/* Create the reserve device data */
device_data
=
wp_reserve_device_new
(
device
,
reservation
);
/* Set the reserve device data on the device */
g_object_set_qdata_full
(
G_OBJECT
(
device
),
reserve_quark
(),
g_steal_pointer
(
&
device_data
),
g_object_unref
);
}
static
void
on_device_added
(
WpObjectManager
*
om
,
WpProxy
*
proxy
,
gpointer
d
)
{
WpDeviceActivation
*
self
=
WP_DEVICE_ACTIVATION
(
d
);
const
gchar
*
card_id
=
NULL
;
/* TODO: for now we only activate devices with the ALSA Card property set.
* However, we eventually need to handle Video and MIDI devices too */
card_id
=
wp_proxy_get_property
(
proxy
,
SPA_KEY_API_ALSA_CARD
);
if
(
!
card_id
)
return
;
/* Depending on the mode, activate or let dbus activate the devices */
if
(
self
->
mode
&&
g_strcmp0
(
self
->
mode
,
"dbus"
)
==
0
)
{
add_reserve_device_data
(
self
,
proxy
,
atoi
(
card_id
));
}
else
{
g_autoptr
(
WpSpaPod
)
profile
=
wp_spa_pod_new_object
(
"Profile"
,
"Profile"
,
"index"
,
"i"
,
1
,
NULL
);
wp_proxy_set_param
(
proxy
,
"Profile"
,
profile
);
}
}
static
void
wp_device_activation_activate
(
WpPlugin
*
plugin
)
{
WpDeviceActivation
*
self
=
WP_DEVICE_ACTIVATION
(
plugin
);
g_autoptr
(
WpCore
)
core
=
wp_plugin_get_core
(
WP_PLUGIN
(
self
));
/* Create the devices object manager and handle the device added signal */
self
->
spa_devices_om
=
wp_object_manager_new
();
wp_object_manager_add_interest
(
self
->
spa_devices_om
,
WP_TYPE_SPA_DEVICE
,
NULL
);
wp_object_manager_request_proxy_features
(
self
->
spa_devices_om
,
WP_TYPE_SPA_DEVICE
,
WP_PROXY_FEATURE_BOUND
);
g_signal_connect_object
(
self
->
spa_devices_om
,
"object-added"
,
G_CALLBACK
(
on_device_added
),
self
,
0
);
wp_core_install_object_manager
(
core
,
self
->
spa_devices_om
);
/* Create the nodes object manager and handle the node added signal */
self
->
nodes_om
=
wp_object_manager_new
();
wp_object_manager_add_interest
(
self
->
nodes_om
,
WP_TYPE_NODE
,
NULL
);
wp_object_manager_request_proxy_features
(
self
->
nodes_om
,
WP_TYPE_NODE
,
WP_PROXY_FEATURES_STANDARD
);
g_signal_connect_object
(
self
->
nodes_om
,
"object-added"
,
G_CALLBACK
(
on_node_added
),
self
,
0
);
wp_core_install_object_manager
(
core
,
self
->
nodes_om
);
}
static
void
wp_device_activation_deactivate
(
WpPlugin
*
plugin
)
{
WpDeviceActivation
*
self
=
WP_DEVICE_ACTIVATION
(
plugin
);
g_clear_object
(
&
self
->
nodes_om
);
g_clear_object
(
&
self
->
spa_devices_om
);
}
static
void
wp_monitor_set_property
(
GObject
*
object
,
guint
property_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
WpDeviceActivation
*
self
=
WP_DEVICE_ACTIVATION
(
object
);
switch
(
property_id
)
{
case
PROP_MODE
:
g_clear_pointer
(
&
self
->
mode
,
g_free
);
self
->
mode
=
g_value_dup_string
(
value
);
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
property_id
,
pspec
);
break
;
}
}
static
void
wp_monitor_get_property
(
GObject
*
object
,
guint
property_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
WpDeviceActivation
*
self
=
WP_DEVICE_ACTIVATION
(
object
);
switch
(
property_id
)
{
case
PROP_MODE
:
g_value_set_string
(
value
,
self
->
mode
);
break
;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
property_id
,
pspec
);
break
;
}
}
static
void
wp_monitor_finalize
(
GObject
*
object
)
{
WpDeviceActivation
*
self
=
WP_DEVICE_ACTIVATION
(
object
);
g_clear_pointer
(
&
self
->
mode
,
g_free
);
G_OBJECT_CLASS
(
wp_device_activation_parent_class
)
->
finalize
(
object
);
}
static
void
wp_device_activation_init
(
WpDeviceActivation
*
self
)
{
}
static
void
wp_device_activation_class_init
(
WpDeviceActivationClass
*
klass
)
{
GObjectClass
*
object_class
=
(
GObjectClass
*
)
klass
;
WpPluginClass
*
plugin_class
=
(
WpPluginClass
*
)
klass
;
object_class
->
finalize
=
wp_monitor_finalize
;
object_class
->
set_property
=
wp_monitor_set_property
;
object_class
->
get_property
=
wp_monitor_get_property
;
plugin_class
->
activate
=
wp_device_activation_activate
;
plugin_class
->
deactivate
=
wp_device_activation_deactivate
;
/* Properties */
g_object_class_install_property
(
object_class
,
PROP_MODE
,
g_param_spec_string
(
"mode"
,
"mode"
,
"The mode to activate devices"
,
NULL
,
G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT
|
G_PARAM_STATIC_STRINGS
));
}
WP_PLUGIN_EXPORT
void
wireplumber__module_init
(
WpModule
*
module
,
WpCore
*
core
,
GVariant
*
args
)
{
const
gchar
*
mode
=
NULL
;
/* Get the mode */
g_variant_lookup
(
args
,
"mode"
,
"s"
,
&
mode
);
wp_plugin_register
(
g_object_new
(
wp_device_activation_get_type
(),
"module"
,
module
,
"mode"
,
mode
,
NULL
));
}
modules/module-
monitor
/dbus-device-reservation.c
→
modules/module-
device-activation
/dbus-device-reservation.c
View file @
9667cccb
File moved
modules/module-
monitor
/dbus-device-reservation.h
→
modules/module-
device-activation
/dbus-device-reservation.h
View file @
9667cccb
File moved
modules/module-
monitor
/org.freedesktop.ReserveDevice1.xml
→
modules/module-
device-activation
/org.freedesktop.ReserveDevice1.xml
View file @
9667cccb
File moved
modules/module-
monitor
/reserve-device.c
→
modules/module-
device-activation
/reserve-device.c
View file @
9667cccb
File moved
modules/module-
monitor
/reserve-device.h
→
modules/module-
device-activation
/reserve-device.h
View file @
9667cccb
File moved
modules/module-
monitor
/reserve-node.c
→
modules/module-
device-activation
/reserve-node.c
View file @
9667cccb
File moved
modules/module-
monitor
/reserve-node.h
→
modules/module-
device-activation
/reserve-node.h
View file @
9667cccb
File moved
modules/module-monitor.c
View file @
9667cccb
...
...
@@ -14,18 +14,12 @@
#include
<spa/monitor/device.h>
#include
<spa/pod/builder.h>
#include
"module-monitor/reserve-device.h"
#include
"module-monitor/reserve-node.h"
G_DEFINE_QUARK
(
wp
-
module
-
monitor
-
id
,
id
);
G_DEFINE_QUARK
(
wp
-
module
-
monitor
-
children
,
children
);
G_DEFINE_QUARK
(
wp
-
module
-
monitor
-
data
,
data
);
typedef
enum
{
FLAG_LOCAL_NODES
=
(
1
<<
0
),
FLAG_USE_ADAPTER
=
(
1
<<
1
),
FLAG_ACTIVATE_DEVICES
=
(
1
<<
2
),
FLAG_DBUS_RESERVATION
=
(
1
<<
3
),
}
MonitorFlags
;
static
const
struct
{
...
...
@@ -34,8 +28,6 @@ static const struct {
}
flag_names
[]
=
{
{
FLAG_LOCAL_NODES
,
"local-nodes"
},
{
FLAG_USE_ADAPTER
,
"use-adapter"
},
{
FLAG_ACTIVATE_DEVICES
,
"activate-devices"
},
{
FLAG_DBUS_RESERVATION
,
"dbus-reservation"
}
};
enum
{
...
...
@@ -280,54 +272,6 @@ find_child (GObject * parent, guint32 id, GList ** children, GList ** link,
}
}
static
void
on_node_event_info
(
WpProxy
*
proxy
,
GParamSpec
*
spec
,
gpointer
data
)
{
WpReserveNode
*
node_data
=
data
;
const
struct
pw_node_info
*
info
=
wp_proxy_get_info
(
proxy
);
g_return_if_fail
(
node_data
);
/* handle the different states */
switch
(
info
->
state
)
{
case
PW_NODE_STATE_IDLE
:
/* Release reservation after 3 seconds */
wp_reserve_node_timeout_release
(
node_data
,
3000
);
break
;
case
PW_NODE_STATE_RUNNING
:
/* Clear pending timeout if any and acquire reservation */
wp_reserve_node_acquire
(
node_data
);
break
;
case
PW_NODE_STATE_SUSPENDED
:
break
;
default:
break
;
}
}
static
void
add_reserve_node_data
(
WpMonitor
*
self
,
WpProxy
*
node
,
WpProxy
*
device
)
{
WpReserveDevice
*
device_data
=
NULL
;
g_autoptr
(
WpReserveNode
)
node_data
=
NULL
;
/* Only add reservation data on nodes whose device has reservation data */
device_data
=
g_object_get_qdata
(
G_OBJECT
(
device
),
data_quark
());
if
(
!
device_data
)
return
;
/* Create the node reservation data */
node_data
=
wp_reserve_node_new
(
node
,
device_data
);
/* Handle the info signal */
g_signal_connect_object
(
WP_NODE
(
node
),
"notify::info"
,
(
GCallback
)
on_node_event_info
,
node_data
,
0
);
/* Set the reserve node data on the node */
g_object_set_qdata_full
(
G_OBJECT
(
node
),
data_quark
(),
g_steal_pointer
(
&
node_data
),
g_object_unref
);
}
static
void
create_node
(
WpMonitor
*
self
,
WpProxy
*
parent
,
GList
**
children
,
guint
id
,
const
gchar
*
spa_factory
,
WpProperties
*
props
,
...
...
@@ -366,39 +310,6 @@ create_node (WpMonitor * self, WpProxy * parent, GList ** children,
g_object_set_qdata
(
G_OBJECT
(
node
),
id_quark
(),
GUINT_TO_POINTER
(
id
));
*
children
=
g_list_prepend
(
*
children
,
node
);
add_reserve_node_data
(
self
,
node
,
parent
);
}
static
void
add_reserve_device_data
(
WpMonitor
*
self
,
WpProxy
*
device
)
{
g_autoptr
(
WpCore
)
core
=
wp_proxy_get_core
(
WP_PROXY
(
device
));
g_autoptr
(
WpProperties
)
props
=
wp_proxy_get_properties
(
device
);
const
char
*
card_id
=
NULL
;
const
char
*
app_dev_name
=
NULL
;
g_autoptr
(
WpDbusDeviceReservation
)
reservation
=
NULL
;
g_autoptr
(
WpReserveDevice
)
device_data
=
NULL
;
if
((
self
->
flags
&
FLAG_DBUS_RESERVATION
)
==
0
)
return
;
card_id
=
wp_properties_get
(
props
,
SPA_KEY_API_ALSA_CARD
);
if
(
!
card_id
)
return
;
app_dev_name
=
wp_properties_get
(
props
,
SPA_KEY_API_ALSA_PATH
);
/* Create the dbus device reservation */
reservation
=
wp_dbus_device_reservation_new
(
atoi
(
card_id
),
"PipeWire"
,
10
,
app_dev_name
);
/* Create the reserve device data */
device_data
=
wp_reserve_device_new
(
device
,
reservation
);
/* Set the reserve device data on the device */
g_object_set_qdata_full
(
G_OBJECT
(
device
),
data_quark
(),
g_steal_pointer
(
&
device_data
),
g_object_unref
);
}
static
void
...
...
@@ -411,16 +322,6 @@ device_created (GObject * proxy, GAsyncResult * res, gpointer user_data)
wp_warning_object
(
self
,
"%s"
,
error
->
message
);
return
;
}
if
(
self
->
flags
&
FLAG_DBUS_RESERVATION
)
{
add_reserve_device_data
(
self
,
WP_PROXY
(
proxy
));
}
else
if
(
self
->
flags
&
FLAG_ACTIVATE_DEVICES
)
{
g_autoptr
(
WpSpaPod
)
profile
=
wp_spa_pod_new_object
(
"Profile"
,
"Profile"
,
"index"
,
"i"
,
1
,
NULL
);
wp_proxy_set_param
(
WP_PROXY
(
proxy
),
"Profile"
,
profile
);
}
}
static
void
...
...
src/config/wireplumber.conf
View file @
9667cccb
...
...
@@ -21,7 +21,7 @@ load-module C libwireplumber-module-jack-device
load
-
module
C
libwireplumber
-
module
-
monitor
{
"factory"
: <
"api.alsa.enum.udev"
>,
"flags"
: <[
"use-adapter"
,
"activate-devices"
,
"dbus-reservation"
]>
"flags"
: <[
"use-adapter"
]>
}
# load-module C libwireplumber-module-monitor {
...
...
@@ -33,6 +33,10 @@ load-module C libwireplumber-module-monitor {
"factory"
: <
"api.v4l2.enum.udev"
>
}
load
-
module
C
libwireplumber
-
module
-
device
-
activation
{
"mode"
: <
"dbus"
>
}
load
-
module
C
libwireplumber
-
module
-
node
-
suspension
load
-
module
C
libwireplumber
-
module
-
session
-
settings
...
...
tests/modules/dbus-device-reservation.c
View file @
9667cccb
...
...
@@ -9,7 +9,7 @@
#include
<wp/wp.h>
#include
<pipewire/pipewire.h>
#include
"../../modules/module-
monitor
/dbus-device-reservation.h"
#include
"../../modules/module-
device-activation
/dbus-device-reservation.h"
typedef
struct
{
GTestDBus
*
dbus_test
;
...
...
tests/modules/meson.build
View file @
9667cccb
...
...
@@ -55,7 +55,7 @@ test(
executable
(
'test-dbus-device-reservation'
,
[
'dbus-device-reservation.c'
,
'../../modules/module-
monitor
/dbus-device-reservation.c'
,
'../../modules/module-
device-activation
/dbus-device-reservation.c'
,
reserve_device_interface_src
,
],
dependencies
:
common_deps
+
[
giounix_dep
],
c_args
:
common_args
),
...
...
Write
Preview
Supports
Markdown
0%
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!
Cancel
Please
register
or
sign in
to comment