From 29eb58f7a26be3a864bf760ce8220a217c2f93fa Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 17 Aug 2017 18:59:03 +0200 Subject: [PATCH] Add systemd socket activation files Notify of jack graph changes --- meson.build | 1 + src/daemon/meson.build | 2 ++ src/daemon/systemd/meson.build | 1 + src/daemon/systemd/user/meson.build | 15 ++++++++++++ src/daemon/systemd/user/pipewire.service.in | 26 +++++++++++++++++++++ src/daemon/systemd/user/pipewire.socket | 10 ++++++++ src/modules/module-jack.c | 22 +++++------------ src/modules/module-jack/jack-node.c | 9 +++++++ src/modules/module-jack/jack-node.h | 5 ++++ src/modules/module-jack/server.h | 1 - src/modules/module-jack/shared.h | 3 ++- src/pipewire/core.c | 4 +++- src/pipewire/core.h | 4 +++- 13 files changed, 83 insertions(+), 20 deletions(-) create mode 100644 src/daemon/systemd/meson.build create mode 100644 src/daemon/systemd/user/meson.build create mode 100644 src/daemon/systemd/user/pipewire.service.in create mode 100644 src/daemon/systemd/user/pipewire.socket diff --git a/meson.build b/meson.build index ba3e7ea8c..60730cecc 100644 --- a/meson.build +++ b/meson.build @@ -22,6 +22,7 @@ soversion = 0 libversion = '@0@.@1@.0'.format(soversion, pipewire_version_minor.to_int() * 100 + pipewire_version_micro.to_int()) prefix = get_option('prefix') +pipewire_bindir = join_paths(prefix, get_option('bindir')) pipewire_datadir = join_paths(prefix, get_option('datadir')) pipewire_libdir = join_paths(prefix, get_option('libdir')) pipewire_localedir = join_paths(prefix, get_option('localedir')) diff --git a/src/daemon/meson.build b/src/daemon/meson.build index 6bd4f31c9..e841fca70 100644 --- a/src/daemon/meson.build +++ b/src/daemon/meson.build @@ -28,3 +28,5 @@ executable('pipewire', include_directories : [configinc, spa_inc], dependencies : [pipewire_dep], ) + +subdir('systemd') diff --git a/src/daemon/systemd/meson.build b/src/daemon/systemd/meson.build new file mode 100644 index 000000000..45f23466c --- /dev/null +++ b/src/daemon/systemd/meson.build @@ -0,0 +1 @@ +subdir('user') diff --git a/src/daemon/systemd/user/meson.build b/src/daemon/systemd/user/meson.build new file mode 100644 index 000000000..826153182 --- /dev/null +++ b/src/daemon/systemd/user/meson.build @@ -0,0 +1,15 @@ +systemd_install_dir = '@0@/systemd/user'.format(get_option('libdir')) + +pipewire_systemd_files = [ + 'pipewire.socket', +] + +install_data(pipewire_systemd_files, install_dir : systemd_install_dir) + +systemd_config = configuration_data() +systemd_config.set('PW_BINARY', '@0@/pipewire'.format(pipewire_bindir)) + +configure_file(input : 'pipewire.service.in', + output : 'pipewire.service', + configuration : systemd_config, + install_dir : systemd_install_dir) diff --git a/src/daemon/systemd/user/pipewire.service.in b/src/daemon/systemd/user/pipewire.service.in new file mode 100644 index 000000000..f05788918 --- /dev/null +++ b/src/daemon/systemd/user/pipewire.service.in @@ -0,0 +1,26 @@ +[Unit] +Description=Multimedia Service + +# We require pipewire.socket to be active before starting the daemon, because +# while it is possible to use the service without the socket, it is not clear +# why it would be desirable. +# +# A user installing pipewire and doing `systemctl --user start pipewire` +# will not get the socket started, which might be confusing and problematic if +# the server is to be restarted later on, as the client autospawn feature +# might kick in. Also, a start of the socket unit will fail, adding to the +# confusion. +# +# After=pipewire.socket is not needed, as it is already implicit in the +# socket-service relationship, see systemd.socket(5). +Requires=pipewire.socket + +[Service] +# Note that notify will only work if --daemonize=no +Type=notify +ExecStart=@PW_BINARY@ +Restart=on-failure + +[Install] +Also=pipewire.socket +WantedBy=default.target diff --git a/src/daemon/systemd/user/pipewire.socket b/src/daemon/systemd/user/pipewire.socket new file mode 100644 index 000000000..df0c79c85 --- /dev/null +++ b/src/daemon/systemd/user/pipewire.socket @@ -0,0 +1,10 @@ +[Unit] +Description=Multimedia System + +[Socket] +Priority=6 +Backlog=5 +ListenStream=%t/pipewire-0 + +[Install] +WantedBy=sockets.target diff --git a/src/modules/module-jack.c b/src/modules/module-jack.c index b6612be5b..289d5e9a9 100644 --- a/src/modules/module-jack.c +++ b/src/modules/module-jack.c @@ -996,8 +996,12 @@ static void jack_node_pull(void *data) struct jack_graph_manager *mgr = server->graph_manager; struct spa_graph_node *n = &jc->node->node->rt.node, *pn; struct spa_graph_port *p, *pp; + bool res; - jack_graph_manager_try_switch(mgr); + jack_graph_manager_try_switch(mgr, &res); + if (res) { + notify_clients(impl, jack_notify_GraphOrderCallback, false, "", 0, 0); + } spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) { if ((pp = p->peer) == NULL || ((pn = pp->node) == NULL)) @@ -1108,7 +1112,6 @@ make_audio_client(struct impl *impl) server->audio_ref_num = ref_num; server->audio_node = node; - server->audio_node_node = node->node; pw_log_debug("module-jack %p: Added audio driver %d", impl, ref_num); @@ -1171,7 +1174,7 @@ static bool on_global(void *data, struct pw_global *global) if (strcmp(str, "Audio/Sink") != 0) return true; - out_port = pw_node_get_free_port(impl->server.audio_node_node, PW_DIRECTION_OUTPUT); + out_port = pw_node_get_free_port(impl->server.audio_node->node, PW_DIRECTION_OUTPUT); in_port = pw_node_get_free_port(node, PW_DIRECTION_INPUT); if (out_port == NULL || in_port == NULL) return true; @@ -1191,23 +1194,10 @@ static bool on_global(void *data, struct pw_global *global) static bool init_nodes(struct impl *impl) { struct pw_core *core = impl->core; -#if 0 - struct timespec timeout, interval; -#endif make_audio_client(impl); make_freewheel_client(impl); -#if 0 - timeout.tv_sec = 0; - timeout.tv_nsec = 1; - interval.tv_sec = 0; - interval.tv_nsec = 10 * SPA_NSEC_PER_MSEC; - - impl->timer = pw_loop_add_timer(pw_core_get_main_loop(impl->core), on_timeout, impl); - pw_loop_update_timer(pw_core_get_main_loop(impl->core), impl->timer, &timeout, &interval, false); -#endif - pw_core_for_each_global(core, on_global, impl); return true; diff --git a/src/modules/module-jack/jack-node.c b/src/modules/module-jack/jack-node.c index 364056b6d..f6470ebe3 100644 --- a/src/modules/module-jack/jack-node.c +++ b/src/modules/module-jack/jack-node.c @@ -647,8 +647,16 @@ static void node_free(void *data) spa_hook_list_call(&nd->listener_list, struct pw_jack_node_events, free); } +static void node_state_changed(void *data, enum pw_node_state old, + enum pw_node_state state, const char *error) +{ + struct node_data *nd = data; + spa_hook_list_call(&nd->listener_list, struct pw_jack_node_events, state_changed, old, state, error); +} + static const struct pw_node_events node_events = { PW_VERSION_NODE_EVENTS, + .state_changed = node_state_changed, .destroy = node_destroy, .free = node_free, }; @@ -759,6 +767,7 @@ pw_jack_driver_new(struct pw_core *core, spa_hook_list_init(&nd->listener_list); init_type(&nd->type, pw_core_get_type(core)->map); + pw_node_add_listener(node, &nd->node_listener, &node_events, nd); pw_node_set_implementation(node, &driver_impl, nd); this = &nd->node; diff --git a/src/modules/module-jack/jack-node.h b/src/modules/module-jack/jack-node.h index dfae0e392..14b961104 100644 --- a/src/modules/module-jack/jack-node.h +++ b/src/modules/module-jack/jack-node.h @@ -50,8 +50,13 @@ struct pw_jack_node_events { uint32_t version; void (*destroy) (void *data); + void (*free) (void *data); + /** the state of the node changed */ + void (*state_changed) (void *data, enum pw_node_state old, + enum pw_node_state state, const char *error); + void (*pull) (void *data); void (*push) (void *data); diff --git a/src/modules/module-jack/server.h b/src/modules/module-jack/server.h index a45132c1e..dc1da83db 100644 --- a/src/modules/module-jack/server.h +++ b/src/modules/module-jack/server.h @@ -44,7 +44,6 @@ struct jack_server { int freewheel_ref_num; struct pw_jack_node *audio_node; - struct pw_node *audio_node_node; int audio_used; }; diff --git a/src/modules/module-jack/shared.h b/src/modules/module-jack/shared.h index b0a5715b1..f1aed5338 100644 --- a/src/modules/module-jack/shared.h +++ b/src/modules/module-jack/shared.h @@ -849,13 +849,14 @@ jack_graph_manager_get_current(struct jack_graph_manager *manager) } static inline struct jack_connection_manager * -jack_graph_manager_try_switch(struct jack_graph_manager *manager) +jack_graph_manager_try_switch(struct jack_graph_manager *manager, bool *res) { struct jack_atomic_counter old_val; struct jack_atomic_counter new_val; do { old_val = manager->state.counter; new_val = old_val; + *res = CurIndex(new_val) != NextIndex(new_val); CurIndex(new_val) = NextIndex(new_val); } while (!__atomic_compare_exchange_n((uint32_t*)&manager->state.counter, diff --git a/src/pipewire/core.c b/src/pipewire/core.c index b42a8c388..49d09471a 100644 --- a/src/pipewire/core.c +++ b/src/pipewire/core.c @@ -404,11 +404,13 @@ void pw_core_destroy(struct pw_core *core) struct pw_global *global, *t; pw_log_debug("core %p: destroy", core); - spa_hook_list_call(&core->listener_list, struct pw_core_events, destroy, core); + spa_hook_list_call(&core->listener_list, struct pw_core_events, destroy); spa_list_for_each_safe(global, t, &core->global_list, link) pw_global_destroy(global); + spa_hook_list_call(&core->listener_list, struct pw_core_events, free); + pw_data_loop_destroy(core->data_loop_impl); pw_properties_free(core->properties); diff --git a/src/pipewire/core.h b/src/pipewire/core.h index f6b9a782e..6d21cf26a 100644 --- a/src/pipewire/core.h +++ b/src/pipewire/core.h @@ -117,7 +117,9 @@ struct pw_core_events { #define PW_VERSION_CORE_EVENTS 0 uint32_t version; - void (*destroy) (void *data, struct pw_core *core); + void (*destroy) (void *data); + + void (*free) (void *data); void (*info_changed) (void *data, struct pw_core_info *info);