diff options
author | Colin Guthrie <colin@mageia.org> | 2011-08-24 22:50:28 +0100 |
---|---|---|
committer | Colin Guthrie <colin@mageia.org> | 2011-08-29 09:59:47 +0100 |
commit | a13a402ed3c48d3df52c523edb232bc8c7c9479c (patch) | |
tree | 6bcb5cfc653399b8de219eb8c91292fddfad1e5b | |
parent | 1ee97e57caf34576ba97cf3b6e7b51388442e3c2 (diff) |
device-restore: Restore volumes on port change.
This will allow for volumes to be saved separately for e.g. Headphones vs. Speakers.
At present it is possible that no volume will be saved for the device prior to the port
switch. In this case the volume will not change from the value set under the other port.
In an ideal world we would save the volume before switching port, but that would require
a new hook.
-rw-r--r-- | src/modules/module-device-restore.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c index 090d6b24..a96ec08e 100644 --- a/src/modules/module-device-restore.c +++ b/src/modules/module-device-restore.c @@ -83,9 +83,11 @@ struct userdata { pa_hook_slot *sink_new_hook_slot, *sink_fixate_hook_slot, + *sink_port_hook_slot, *sink_put_hook_slot, *source_new_hook_slot, *source_fixate_hook_slot, + *source_port_hook_slot, *connection_unlink_hook_slot; pa_time_event *save_time_event; pa_database *database; @@ -804,6 +806,46 @@ static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data * return PA_HOOK_OK; } +static pa_hook_result_t sink_port_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) { + char *name; + struct perportentry *e; + + pa_assert(c); + pa_assert(sink); + pa_assert(u); + pa_assert(u->restore_volume || u->restore_muted); + + name = pa_sprintf_malloc("sink:%s:%s", sink->name, (sink->active_port ? sink->active_port->name : "null")); + + if ((e = perportentry_read(u, name))) { + + if (u->restore_volume && e->volume_valid) { + + pa_cvolume v; + + pa_log_info("Restoring volume for sink %s.", sink->name); + + v = e->volume; + pa_cvolume_remap(&v, &e->channel_map, &sink->channel_map); + pa_sink_set_volume(sink, &v, TRUE, FALSE); + sink->save_volume = TRUE; + } + + if (u->restore_muted && e->muted_valid) { + + pa_log_info("Restoring mute state for sink %s.", sink->name); + pa_sink_set_mute(sink, e->muted, FALSE); + sink->save_muted = TRUE; + } + + perportentry_free(e); + } + + pa_xfree(name); + + return PA_HOOK_OK; +} + static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, struct userdata *u) { char *name; struct perportentry *e; @@ -905,6 +947,46 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da return PA_HOOK_OK; } +static pa_hook_result_t source_port_hook_callback(pa_core *c, pa_source *source, struct userdata *u) { + char *name; + struct perportentry *e; + + pa_assert(c); + pa_assert(source); + pa_assert(u); + pa_assert(u->restore_volume || u->restore_muted); + + name = pa_sprintf_malloc("source:%s:%s", source->name, (source->active_port ? source->active_port->name : "null")); + + if ((e = perportentry_read(u, name))) { + + if (u->restore_volume && e->volume_valid) { + + pa_cvolume v; + + pa_log_info("Restoring volume for source %s.", source->name); + + v = e->volume; + pa_cvolume_remap(&v, &e->channel_map, &source->channel_map); + pa_source_set_volume(source, &v, TRUE, FALSE); + source->save_volume = TRUE; + } + + if (u->restore_muted && e->muted_valid) { + + pa_log_info("Restoring mute state for source %s.", source->name); + pa_source_set_mute(source, e->muted, FALSE); + source->save_muted = TRUE; + } + + perportentry_free(e); + } + + pa_xfree(name); + + return PA_HOOK_OK; +} + #define EXT_VERSION 1 static void read_sink_format_reply(struct userdata *u, pa_tagstruct *reply, pa_sink *sink) { @@ -1170,6 +1252,9 @@ int pa__init(pa_module*m) { if (restore_muted || restore_volume) { u->sink_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) sink_fixate_hook_callback, u); u->source_fixate_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_fixate_hook_callback, u); + + u->sink_port_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PORT_CHANGED], PA_HOOK_EARLY, (pa_hook_cb_t) sink_port_hook_callback, u); + u->source_port_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PORT_CHANGED], PA_HOOK_EARLY, (pa_hook_cb_t) source_port_hook_callback, u); } if (restore_formats) @@ -1224,6 +1309,10 @@ void pa__done(pa_module*m) { pa_hook_slot_free(u->sink_new_hook_slot); if (u->source_new_hook_slot) pa_hook_slot_free(u->source_new_hook_slot); + if (u->sink_port_hook_slot) + pa_hook_slot_free(u->sink_port_hook_slot); + if (u->source_port_hook_slot) + pa_hook_slot_free(u->source_port_hook_slot); if (u->sink_put_hook_slot) pa_hook_slot_free(u->sink_put_hook_slot); |