diff options
author | Colin Guthrie <pulse@colin.guthr.ie> | 2008-08-22 10:56:45 +0100 |
---|---|---|
committer | Colin Guthrie <pulse@colin.guthr.ie> | 2008-08-22 10:56:45 +0100 |
commit | 4282b726ee57ebae846ce400fd1cae43c4dfb2ae (patch) | |
tree | 2cb32c3bc52a9b9eab50a6195f3ccb190332f7d8 /src/modules/module-device-restore.c | |
parent | bf17dbb101d509e885bf689f4f13f75e4b3ab58d (diff) | |
parent | dc9b8dce309728b47059b9b44fd3bbd3798667ae (diff) |
Merge branch 'master' of git://git.0pointer.de/pulseaudio
Diffstat (limited to 'src/modules/module-device-restore.c')
-rw-r--r-- | src/modules/module-device-restore.c | 76 |
1 files changed, 48 insertions, 28 deletions
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c index c0d2ddb7..920b4517 100644 --- a/src/modules/module-device-restore.c +++ b/src/modules/module-device-restore.c @@ -1,7 +1,7 @@ /*** This file is part of PulseAudio. - Copyright 2006 Lennart Poettering + Copyright 2006-2008 Lennart Poettering PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -64,6 +64,7 @@ static const char* const valid_modargs[] = { struct userdata { pa_core *core; + pa_module *module; pa_subscription *subscription; pa_hook_slot *sink_fixate_hook_slot, @@ -76,6 +77,7 @@ struct userdata { }; struct entry { + pa_channel_map channel_map; pa_cvolume volume; pa_bool_t muted:1; }; @@ -104,7 +106,7 @@ static struct entry* read_entry(struct userdata *u, char *name) { pa_assert(name); key.dptr = name; - key.dsize = strlen(name); + key.dsize = (int) strlen(name); data = gdbm_fetch(u->gdbm_file, key); @@ -123,6 +125,16 @@ static struct entry* read_entry(struct userdata *u, char *name) { goto fail; } + if (!(pa_channel_map_valid(&e->channel_map))) { + pa_log_warn("Invalid channel map stored in database for device %s", name); + goto fail; + } + + if (e->volume.channels != e->channel_map.channels) { + pa_log_warn("Volume and channel map don't match in database entry for device %s", name); + goto fail; + } + return e; fail: @@ -131,6 +143,17 @@ fail: return NULL; } +static void trigger_save(struct userdata *u) { + struct timeval tv; + + 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); +} + static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { struct userdata *u = userdata; struct entry entry, *old; @@ -146,6 +169,8 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 t != (PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE)) return; + memset(&entry, 0, sizeof(entry)); + if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK) { pa_sink *sink; @@ -153,8 +178,9 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 return; name = pa_sprintf_malloc("sink:%s", sink->name); - entry.volume = *pa_sink_get_volume(sink); - entry.muted = pa_sink_get_mute(sink); + entry.channel_map = sink->channel_map; + entry.volume = *pa_sink_get_volume(sink, FALSE); + entry.muted = pa_sink_get_mute(sink, FALSE); } else { pa_source *source; @@ -165,13 +191,14 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 return; name = pa_sprintf_malloc("source:%s", source->name); - entry.volume = *pa_source_get_volume(source); - entry.muted = pa_source_get_mute(source); + entry.channel_map = source->channel_map; + entry.volume = *pa_source_get_volume(source, FALSE); + entry.muted = pa_source_get_mute(source, FALSE); } if ((old = read_entry(u, name))) { - if (pa_cvolume_equal(&old->volume, &entry.volume) && + if (pa_cvolume_equal(pa_cvolume_remap(&old->volume, &old->channel_map, &entry.channel_map), &entry.volume) && !old->muted == !entry.muted) { pa_xfree(old); @@ -183,7 +210,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 } key.dptr = name; - key.dsize = strlen(name); + key.dsize = (int) strlen(name); data.dptr = (void*) &entry; data.dsize = sizeof(entry); @@ -192,14 +219,9 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 gdbm_store(u->gdbm_file, key, data, GDBM_REPLACE); - if (!u->save_time_event) { - struct timeval tv; - 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); - } - pa_xfree(name); + + trigger_save(u); } static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data *new_data, struct userdata *u) { @@ -212,11 +234,9 @@ static pa_hook_result_t sink_fixate_hook_callback(pa_core *c, pa_sink_new_data * if ((e = read_entry(u, name))) { - if (u->restore_volume && - e->volume.channels == new_data->sample_spec.channels) { - + if (u->restore_volume) { pa_log_info("Restoring volume for sink %s.", new_data->name); - pa_sink_new_data_set_volume(new_data, &e->volume); + pa_sink_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map)); } if (u->restore_muted) { @@ -242,11 +262,9 @@ static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_da if ((e = read_entry(u, name))) { - if (u->restore_volume && - e->volume.channels == new_data->sample_spec.channels) { - + if (u->restore_volume) { pa_log_info("Restoring volume for source %s.", new_data->name); - pa_source_new_data_set_volume(new_data, &e->volume); + pa_source_new_data_set_volume(new_data, pa_cvolume_remap(&e->volume, &e->channel_map, &new_data->channel_map)); } if (u->restore_muted) { @@ -266,7 +284,6 @@ int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; char *fname, *fn; - char hn[256]; pa_sink *sink; pa_source *source; uint32_t idx; @@ -290,9 +307,11 @@ int pa__init(pa_module*m) { m->userdata = u = pa_xnew(struct userdata, 1); u->core = m->core; + u->module = m; u->save_time_event = NULL; u->restore_volume = restore_volume; u->restore_muted = restore_muted; + u->gdbm_file = NULL; u->subscription = pa_subscription_new(m->core, PA_SUBSCRIPTION_MASK_SINK|PA_SUBSCRIPTION_MASK_SOURCE, subscribe_callback, u); @@ -301,11 +320,12 @@ int pa__init(pa_module*m) { 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); } - if (!pa_get_host_name(hn, sizeof(hn))) - goto fail; + /* We include the host identifier in the file name because gdbm + * files are CPU dependant, and we don't want things to go wrong + * if we are on a multiarch system. */ - fn = pa_sprintf_malloc("device-volumes.%s."CANONICAL_HOST".gdbm", hn); - fname = pa_state_path(fn); + fn = pa_sprintf_malloc("device-volumes."CANONICAL_HOST".gdbm"); + fname = pa_state_path(fn, TRUE); pa_xfree(fn); if (!fname) |