diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index 315360740..baa35afbf 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -1294,7 +1294,6 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 /* These are only used when D-Bus is enabled, but in order to reduce ifdef * clutter these are defined here unconditionally. */ bool created_new_entry = true; - bool device_updated = false; bool volume_updated = false; bool mute_updated = false; @@ -1350,25 +1349,6 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted); } - - if (sink_input->preferred_sink != NULL || !created_new_entry) { - pa_sink *s = NULL; - - pa_xfree(entry->device); - entry->device = pa_xstrdup(sink_input->preferred_sink); - entry->device_valid = true; - if (!entry->device) - entry->device_valid = false; - - device_updated = !created_new_entry && !pa_safe_streq(entry->device, old->device); - pa_xfree(entry->card); - entry->card = NULL; - entry->card_valid = false; - if (entry->device_valid && (s = pa_namereg_get(c, entry->device, PA_NAMEREG_SINK)) && s->card) { - entry->card = pa_xstrdup(s->card->name); - entry->card_valid = true; - } - } } else { pa_source_output *source_output; @@ -1410,26 +1390,6 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 mute_updated = !created_new_entry && (!old->muted_valid || entry->muted != old->muted); } - - if (source_output->preferred_source != NULL || !created_new_entry) { - pa_source *s = NULL; - - pa_xfree(entry->device); - entry->device = pa_xstrdup(source_output->preferred_source); - entry->device_valid = true; - - if (!entry->device) - entry->device_valid = false; - - device_updated = !created_new_entry && !pa_safe_streq(entry->device, old->device); - pa_xfree(entry->card); - entry->card = NULL; - entry->card_valid = false; - if (entry->device_valid && (s = pa_namereg_get(c, entry->device, PA_NAMEREG_SOURCE)) && s->card) { - entry->card = pa_xstrdup(s->card->name); - entry->card_valid = true; - } - } } pa_assert(entry); @@ -1446,12 +1406,12 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 entry_free(old); } - pa_log_info("Storing volume/mute/device for stream %s.", name); + pa_log_info("Storing volume/mute for stream %s.", name); if (entry_write(u, name, entry, true)) { trigger_save(u); } else { - pa_log_error("Could not store volume/mute/device for stream %s.", name); + pa_log_error("Could not store volume/mute for stream %s.", name); } #ifdef HAVE_DBUS @@ -1460,8 +1420,6 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0); send_new_entry_signal(de); } else { - if (device_updated) - send_device_updated_signal(de, entry); if (volume_updated) send_volume_updated_signal(de, entry); if (mute_updated) @@ -1469,7 +1427,6 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 } #else /* Silence compiler warnings */ - (void) device_updated; (void) volume_updated; (void) mute_updated; #endif @@ -1582,6 +1539,79 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu return PA_HOOK_OK; } +static void update_preferred_device(struct userdata *u, const char *name, const char *device, const char *card) { + struct entry *old; + struct entry *entry; +#ifdef HAVE_DBUS + bool created_new_entry = false; + struct dbus_entry *de; +#endif + + pa_assert(u); + pa_assert(name); + + if ((old = entry_read(u, name))) + entry = entry_copy(old); + else { + entry = entry_new(); +#ifdef HAVE_DBUS + created_new_entry = true; +#endif + } + + pa_xfree(entry->device); + entry->device = pa_xstrdup(device); + entry->device_valid = !!device; + + pa_xfree(entry->card); + entry->card = pa_xstrdup(card); + entry->card_valid = !!card; + + pa_log_info("Storing device for stream %s.", name); + + entry_write(u, name, entry, true); + trigger_save(u); + +#if HAVE_DBUS + if (!(de = pa_hashmap_get(u->dbus_entries, name))) { + de = dbus_entry_new(u, name); + pa_assert_se(pa_hashmap_put(u->dbus_entries, de->entry_name, de) == 0); + send_new_entry_signal(de); + } else { + /* We send a D-Bus signal when the device changes, but not when the + * card changes. That's becaues the D-Bus interface doesn't expose the + * card field to clients at all. */ + if (!created_new_entry && !pa_safe_streq(entry->device, old->device)) + send_device_updated_signal(de, entry); + } +#endif + + entry_free(entry); + if (old) + entry_free(old); +} + +static pa_hook_result_t sink_input_preferred_sink_changed_cb(pa_core *c, pa_sink_input *sink_input, struct userdata *u) { + char *name; + pa_sink *sink; + const char *card_name; + + pa_assert(c); + pa_assert(sink_input); + pa_assert(u); + + if (!(name = pa_proplist_get_stream_group(sink_input->proplist, "sink-input", IDENTIFICATION_PROPERTY))) + return PA_HOOK_OK; + + if (sink_input->preferred_sink && (sink = pa_namereg_get(c, sink_input->preferred_sink, PA_NAMEREG_SINK)) && sink->card) + card_name = sink->card->name; + + update_preferred_device(u, name, sink_input->preferred_sink, card_name); + pa_xfree(name); + + return PA_HOOK_OK; +} + static pa_hook_result_t source_output_new_hook_callback(pa_core *c, pa_source_output_new_data *new_data, struct userdata *u) { char *name; struct entry *e; @@ -1690,6 +1720,27 @@ static pa_hook_result_t source_output_fixate_hook_callback(pa_core *c, pa_source return PA_HOOK_OK; } +static pa_hook_result_t source_output_preferred_source_changed_cb(pa_core *c, pa_source_output *source_output, struct userdata *u) { + char *name; + pa_source *source; + const char *card_name; + + pa_assert(c); + pa_assert(source_output); + pa_assert(u); + + if (!(name = pa_proplist_get_stream_group(source_output->proplist, "source-output", IDENTIFICATION_PROPERTY))) + return PA_HOOK_OK; + + if (source_output->preferred_source && (source = pa_namereg_get(c, source_output->preferred_source, PA_NAMEREG_SOURCE)) && source->card) + card_name = source->card->name; + + update_preferred_device(u, name, source_output->preferred_source, card_name); + pa_xfree(name); + + return PA_HOOK_OK; +} + static int fill_db(struct userdata *u, const char *filename) { FILE *f; int n = 0; @@ -2317,6 +2368,11 @@ int pa__init(pa_module*m) { /* A little bit earlier than module-intended-roles ... */ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) sink_input_new_hook_callback, u); pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_new_hook_callback, u); + + pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PREFERRED_SINK_CHANGED], PA_HOOK_NORMAL, + (pa_hook_cb_t) sink_input_preferred_sink_changed_cb, u); + pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PREFERRED_SOURCE_CHANGED], PA_HOOK_NORMAL, + (pa_hook_cb_t) source_output_preferred_source_changed_cb, u); } if (restore_volume || restore_muted) {