From d773638b20b0a6750a5405521ee0c8974d1b72ec Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Jun 2009 00:56:46 +0200 Subject: stream-restore: e don't need to save stream data that came from the database --- src/modules/module-stream-restore.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/modules/module-stream-restore.c') diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index 2de98f4e..41206c79 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -370,7 +370,7 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n if (!new_data->sink) { pa_log_info("Restoring device for stream %s.", name); new_data->sink = s; - new_data->save_sink = TRUE; + new_data->save_sink = FALSE; } else pa_log_info("Not restore device for stream %s, because already set.", name); } @@ -419,7 +419,7 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu if (!new_data->muted_is_set) { pa_log_info("Restoring mute state for sink input %s.", name); pa_sink_input_new_data_set_muted(new_data, e->muted); - new_data->save_muted = TRUE; + new_data->save_muted = FALSE; } else pa_log_debug("Not restoring mute state for sink input %s, because already set.", name); } @@ -455,7 +455,7 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou if (!new_data->source) { pa_log_info("Restoring device for stream %s.", name); new_data->source = s; - new_data->save_source = TRUE; + new_data->save_source = FALSE; } else pa_log_info("Not restoring device for stream %s, because already set", name); } @@ -503,7 +503,7 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) { if (u->restore_muted && e->muted_valid) { pa_log_info("Restoring mute state for sink input %s.", name); - pa_sink_input_set_mute(si, e->muted, TRUE); + pa_sink_input_set_mute(si, e->muted, FALSE); } if (u->restore_device && @@ -511,7 +511,7 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) { (s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SINK))) { pa_log_info("Restoring device for stream %s.", name); - pa_sink_input_move_to(si, s, TRUE); + pa_sink_input_move_to(si, s, FALSE); } } @@ -533,7 +533,7 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) { (s = pa_namereg_get(u->core, e->device, PA_NAMEREG_SOURCE))) { pa_log_info("Restoring device for stream %s.", name); - pa_source_output_move_to(so, s, TRUE); + pa_source_output_move_to(so, s, FALSE); } } } -- cgit From 4951e08031a74864b889ecdaaa3bcaa3a1f0ceb7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 18 Jun 2009 00:59:33 +0200 Subject: card,stream-restore: minor cleanups --- src/modules/module-stream-restore.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'src/modules/module-stream-restore.c') diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index 41206c79..f2aea27b 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -362,9 +362,9 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n return PA_HOOK_OK; if ((e = read_entry(u, name))) { - pa_sink *s; if (e->device_valid) { + pa_sink *s; if ((s = pa_namereg_get(c, e->device, PA_NAMEREG_SINK))) { if (!new_data->sink) { @@ -372,7 +372,7 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n new_data->sink = s; new_data->save_sink = FALSE; } else - pa_log_info("Not restore device for stream %s, because already set.", name); + pa_log_info("Not restoring device for stream %s, because already set.", name); } } @@ -404,6 +404,7 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu pa_cvolume v; pa_log_info("Restoring volume for sink input %s.", name); + v = e->volume; pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map); pa_sink_input_new_data_set_volume(new_data, &v); @@ -793,14 +794,12 @@ int pa__init(pa_module*m) { if (!restore_muted && !restore_volume && !restore_device) pa_log_warn("Neither restoring volume, nor restoring muted, nor restoring device enabled!"); - m->userdata = u = pa_xnew(struct userdata, 1); + m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; - u->save_time_event = NULL; u->restore_device = restore_device; u->restore_volume = restore_volume; u->restore_muted = restore_muted; - u->database = NULL; u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); u->protocol = pa_native_protocol_get(m->core); @@ -818,10 +817,7 @@ int pa__init(pa_module*m) { if (restore_volume || restore_muted) u->sink_input_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_fixate_hook_callback, u); - - fname = pa_state_path("stream-volumes", TRUE); - - if (!fname) + if (!(fname = pa_state_path("stream-volumes", TRUE))) goto fail; if (!(u->database = pa_database_open(fname, TRUE))) { -- cgit From 0955e3d45b6e992308e2d51fcbf28a9f9376f788 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Sun, 5 Apr 2009 02:13:43 +0300 Subject: Base mainloop on pa_rtclock_now() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the mainloop to monotonic based time events. Introduces 4 helper functions: pa_{context,core}_rttime_{new,restart}(), that fill correctly a timeval with the rtclock flag set if the mainloop supports it. Both mainloop-test and mainloop-test-glib works with rt and timeval based time events. PulseAudio and clients should be fully functional. This patch has received several iterations, and this one as been largely untested. Signed-off-by: Marc-André Lureau --- src/modules/module-stream-restore.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src/modules/module-stream-restore.c') diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index f2aea27b..99c69f66 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -61,7 +62,7 @@ PA_MODULE_USAGE( "restore_volume= " "restore_muted="); -#define SAVE_INTERVAL 10 +#define SAVE_INTERVAL (10 * PA_USEC_PER_SEC) #define IDENTIFICATION_PROPERTY "module-stream-restore.id" static const char* const valid_modargs[] = { @@ -111,12 +112,11 @@ enum { SUBCOMMAND_EVENT }; -static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) { +static void save_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) { struct userdata *u = userdata; pa_assert(a); pa_assert(e); - pa_assert(tv); pa_assert(u); pa_assert(e == u->save_time_event); @@ -210,7 +210,6 @@ fail: } static void trigger_save(struct userdata *u) { - struct timeval tv; pa_native_connection *c; uint32_t idx; @@ -230,9 +229,7 @@ static void trigger_save(struct userdata *u) { if (u->save_time_event) return; - pa_gettimeofday(&tv); - tv.tv_sec += SAVE_INTERVAL; - u->save_time_event = u->core->mainloop->time_new(u->core->mainloop, &tv, save_time_callback, u); + u->save_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + SAVE_INTERVAL, save_time_callback, u); } static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) { -- cgit From c4d90ea98617026fbeb9f8bc11e98ab528338274 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Jun 2009 22:33:09 +0200 Subject: restore: change 'save' flag behaviour to reflect whether an entry shall and/or is in the on-disk databases --- src/modules/module-stream-restore.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src/modules/module-stream-restore.c') diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index f2aea27b..b519bc17 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -353,10 +353,10 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n char *name; struct entry *e; + pa_assert(c); pa_assert(new_data); - - if (!u->restore_device) - return PA_HOOK_OK; + pa_assert(u); + pa_assert(u->restore_device); if (!(name = get_name(new_data->proplist, "sink-input"))) return PA_HOOK_OK; @@ -370,9 +370,9 @@ static pa_hook_result_t sink_input_new_hook_callback(pa_core *c, pa_sink_input_n if (!new_data->sink) { pa_log_info("Restoring device for stream %s.", name); new_data->sink = s; - new_data->save_sink = FALSE; + new_data->save_sink = TRUE; } else - pa_log_info("Not restoring device for stream %s, because already set.", name); + pa_log_debug("Not restoring device for stream %s, because already set.", name); } } @@ -388,10 +388,10 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu char *name; struct entry *e; + pa_assert(c); pa_assert(new_data); - - if (!u->restore_volume && !u->restore_muted) - return PA_HOOK_OK; + pa_assert(u); + pa_assert(u->restore_volume || u->restore_muted); if (!(name = get_name(new_data->proplist, "sink-input"))) return PA_HOOK_OK; @@ -410,7 +410,7 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu pa_sink_input_new_data_set_volume(new_data, &v); new_data->volume_is_absolute = FALSE; - new_data->save_volume = FALSE; + new_data->save_volume = TRUE; } else pa_log_debug("Not restoring volume for sink input %s, because already set.", name); } @@ -420,7 +420,7 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu if (!new_data->muted_is_set) { pa_log_info("Restoring mute state for sink input %s.", name); pa_sink_input_new_data_set_muted(new_data, e->muted); - new_data->save_muted = FALSE; + new_data->save_muted = TRUE; } else pa_log_debug("Not restoring mute state for sink input %s, because already set.", name); } @@ -437,10 +437,10 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou char *name; struct entry *e; + pa_assert(c); pa_assert(new_data); - - if (!u->restore_device) - return PA_HOOK_OK; + pa_assert(u); + pa_assert(u->restore_device); if (new_data->direct_on_input) return PA_HOOK_OK; @@ -456,9 +456,9 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou if (!new_data->source) { pa_log_info("Restoring device for stream %s.", name); new_data->source = s; - new_data->save_source = FALSE; + new_data->save_source = TRUE; } else - pa_log_info("Not restoring device for stream %s, because already set", name); + pa_log_debug("Not restoring device for stream %s, because already set", name); } } @@ -829,10 +829,10 @@ int pa__init(pa_module*m) { pa_log_info("Sucessfully opened database file '%s'.", fname); pa_xfree(fname); - for (si = pa_idxset_first(m->core->sink_inputs, &idx); si; si = pa_idxset_next(m->core->sink_inputs, &idx)) + PA_IDXSET_FOREACH(si, m->core->sink_inputs, idx) subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, si->index, u); - for (so = pa_idxset_first(m->core->source_outputs, &idx); so; so = pa_idxset_next(m->core->source_outputs, &idx)) + PA_IDXSET_FOREACH(so, m->core->source_outputs, idx) subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, so->index, u); pa_modargs_free(ma); -- cgit From 60d36c7e74204bb8a479272c870736017e102c58 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Jun 2009 22:35:55 +0200 Subject: module-stream-restore: recheck stream database on hotplug/unplug and potentially move streams --- src/modules/module-stream-restore.c | 194 +++++++++++++++++++++++++++++++++++- 1 file changed, 190 insertions(+), 4 deletions(-) (limited to 'src/modules/module-stream-restore.c') diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index b519bc17..bf100e2d 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -59,7 +59,9 @@ PA_MODULE_LOAD_ONCE(TRUE); PA_MODULE_USAGE( "restore_device= " "restore_volume= " - "restore_muted="); + "restore_muted= " + "on_hotplug= " + "on_rescue="); #define SAVE_INTERVAL 10 #define IDENTIFICATION_PROPERTY "module-stream-restore.id" @@ -68,6 +70,8 @@ static const char* const valid_modargs[] = { "restore_device", "restore_volume", "restore_muted", + "on_hotplug", + "on_rescue", NULL }; @@ -79,6 +83,10 @@ struct userdata { *sink_input_new_hook_slot, *sink_input_fixate_hook_slot, *source_output_new_hook_slot, + *sink_put_hook_slot, + *source_put_hook_slot, + *sink_unlink_hook_slot, + *source_unlink_hook_slot, *connection_unlink_hook_slot; pa_time_event *save_time_event; pa_database* database; @@ -86,6 +94,8 @@ struct userdata { pa_bool_t restore_device:1; pa_bool_t restore_volume:1; pa_bool_t restore_muted:1; + pa_bool_t on_hotplug:1; + pa_bool_t on_rescue:1; pa_native_protocol *protocol; pa_idxset *subscribed; @@ -470,6 +480,155 @@ static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_ou return PA_HOOK_OK; } +static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) { + pa_sink_input *si; + uint32_t idx; + + pa_assert(c); + pa_assert(sink); + pa_assert(u); + pa_assert(u->on_hotplug && u->restore_device); + + PA_IDXSET_FOREACH(si, c->sink_inputs, idx) { + char *name; + struct entry *e; + + if (si->sink == sink) + continue; + + if (si->save_sink) + continue; + + if (!(name = get_name(si->proplist, "sink-input"))) + continue; + + if ((e = read_entry(u, name))) { + if (e->device_valid && pa_streq(e->device, sink->name)) + pa_sink_input_move_to(si, sink, TRUE); + + pa_xfree(e); + } + + pa_xfree(name); + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, struct userdata *u) { + pa_source_output *so; + uint32_t idx; + + pa_assert(c); + pa_assert(source); + pa_assert(u); + pa_assert(u->on_hotplug && u->restore_device); + + PA_IDXSET_FOREACH(so, c->source_outputs, idx) { + char *name; + struct entry *e; + + if (so->source == source) + continue; + + if (so->save_source) + continue; + + if (so->direct_on_input) + continue; + + if (!(name = get_name(so->proplist, "source-input"))) + continue; + + if ((e = read_entry(u, name))) { + if (e->device_valid && pa_streq(e->device, source->name)) + pa_source_output_move_to(so, source, TRUE); + + pa_xfree(e); + } + + pa_xfree(name); + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t sink_unlink_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) { + pa_sink_input *si; + uint32_t idx; + + pa_assert(c); + pa_assert(sink); + pa_assert(u); + pa_assert(u->on_rescue && u->restore_device); + + /* There's no point in doing anything if the core is shut down anyway */ + if (c->state == PA_CORE_SHUTDOWN) + return PA_HOOK_OK; + + PA_IDXSET_FOREACH(si, sink->inputs, idx) { + char *name; + struct entry *e; + + if (!(name = get_name(si->proplist, "sink-input"))) + continue; + + if ((e = read_entry(u, name))) { + + if (e->device_valid) { + pa_sink *d; + + if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SINK)) && d != sink) + pa_sink_input_move_to(si, d, TRUE); + } + + pa_xfree(e); + } + + pa_xfree(name); + } + + return PA_HOOK_OK; +} + +static pa_hook_result_t source_unlink_hook_callback(pa_core *c, pa_source *source, struct userdata *u) { + pa_source_output *so; + uint32_t idx; + + pa_assert(c); + pa_assert(source); + pa_assert(u); + pa_assert(u->on_rescue && u->restore_device); + + /* There's no point in doing anything if the core is shut down anyway */ + if (c->state == PA_CORE_SHUTDOWN) + return PA_HOOK_OK; + + PA_IDXSET_FOREACH(so, source->outputs, idx) { + char *name; + struct entry *e; + + if (!(name = get_name(so->proplist, "source-output"))) + continue; + + if ((e = read_entry(u, name))) { + + if (e->device_valid) { + pa_source *d; + + if ((d = pa_namereg_get(c, e->device, PA_NAMEREG_SOURCE)) && d != source) + pa_source_output_move_to(so, d, TRUE); + } + + pa_xfree(e); + } + + pa_xfree(name); + } + + return PA_HOOK_OK; +} + #define EXT_VERSION 1 static void apply_entry(struct userdata *u, const char *name, struct entry *e) { @@ -775,7 +934,7 @@ int pa__init(pa_module*m) { pa_sink_input *si; pa_source_output *so; uint32_t idx; - pa_bool_t restore_device = TRUE, restore_volume = TRUE, restore_muted = TRUE; + pa_bool_t restore_device = TRUE, restore_volume = TRUE, restore_muted = TRUE, on_hotplug = TRUE, on_rescue = TRUE; pa_assert(m); @@ -786,8 +945,10 @@ int pa__init(pa_module*m) { if (pa_modargs_get_value_boolean(ma, "restore_device", &restore_device) < 0 || pa_modargs_get_value_boolean(ma, "restore_volume", &restore_volume) < 0 || - pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0) { - pa_log("restore_device=, restore_volume= and restore_muted= expect boolean arguments"); + pa_modargs_get_value_boolean(ma, "restore_muted", &restore_muted) < 0 || + pa_modargs_get_value_boolean(ma, "on_hotplug", &on_hotplug) < 0 || + pa_modargs_get_value_boolean(ma, "on_rescue", &on_rescue) < 0) { + pa_log("restore_device=, restore_volume=, restore_muted=, on_hotplug= and on_rescue= expect boolean arguments"); goto fail; } @@ -800,6 +961,8 @@ int pa__init(pa_module*m) { u->restore_device = restore_device; u->restore_volume = restore_volume; u->restore_muted = restore_muted; + u->on_hotplug = on_hotplug; + u->on_rescue = on_rescue; u->subscribed = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); u->protocol = pa_native_protocol_get(m->core); @@ -810,10 +973,23 @@ int pa__init(pa_module*m) { u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK_INPUT|PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscribe_callback, u); if (restore_device) { + /* A little bit earlier than module-intended-roles ... */ u->sink_input_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_new_hook_callback, u); u->source_output_new_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_new_hook_callback, u); } + if (restore_device && on_hotplug) { + /* A little bit earlier than module-intended-roles ... */ + u->sink_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE, (pa_hook_cb_t) sink_put_hook_callback, u); + u->source_put_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE, (pa_hook_cb_t) source_put_hook_callback, u); + } + + if (restore_device && on_rescue) { + /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */ + u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_unlink_hook_callback, NULL); + u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) source_unlink_hook_callback, NULL); + } + if (restore_volume || restore_muted) u->sink_input_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_fixate_hook_callback, u); @@ -865,6 +1041,16 @@ void pa__done(pa_module*m) { if (u->source_output_new_hook_slot) pa_hook_slot_free(u->source_output_new_hook_slot); + if (u->sink_put_hook_slot) + pa_hook_slot_free(u->sink_put_hook_slot); + if (u->source_put_hook_slot) + pa_hook_slot_free(u->source_put_hook_slot); + + if (u->sink_unlink_hook_slot) + pa_hook_slot_free(u->sink_unlink_hook_slot); + if (u->source_unlink_hook_slot) + pa_hook_slot_free(u->source_unlink_hook_slot); + if (u->connection_unlink_hook_slot) pa_hook_slot_free(u->connection_unlink_hook_slot); -- cgit From ef85558abd380254086a81923fa4d35938e9921b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 23 Jun 2009 04:25:45 +0200 Subject: modules: pass properly initialized userdata pointers to various hooks --- src/modules/module-stream-restore.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/modules/module-stream-restore.c') diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index 7ae93c7d..e60cc735 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -983,8 +983,8 @@ int pa__init(pa_module*m) { if (restore_device && on_rescue) { /* A little bit earlier than module-intended-roles, module-rescue-streams, ... */ - u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_unlink_hook_callback, NULL); - u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) source_unlink_hook_callback, NULL); + u->sink_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_unlink_hook_callback, u); + u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) source_unlink_hook_callback, u); } if (restore_volume || restore_muted) -- cgit