diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/modules/alsa/alsa-sink.c | 2 | ||||
-rw-r--r-- | src/modules/module-device-restore.c | 2 | ||||
-rw-r--r-- | src/modules/module-lirc.c | 6 | ||||
-rw-r--r-- | src/modules/module-match.c | 2 | ||||
-rw-r--r-- | src/modules/module-mmkbd-evdev.c | 6 | ||||
-rw-r--r-- | src/modules/module-stream-restore.c | 142 | ||||
-rw-r--r-- | src/modules/oss/module-oss.c | 2 | ||||
-rw-r--r-- | src/pulsecore/cli-command.c | 6 | ||||
-rw-r--r-- | src/pulsecore/cli-text.c | 15 | ||||
-rw-r--r-- | src/pulsecore/protocol-esound.c | 5 | ||||
-rw-r--r-- | src/pulsecore/protocol-native.c | 9 | ||||
-rw-r--r-- | src/pulsecore/sink-input.c | 55 | ||||
-rw-r--r-- | src/pulsecore/sink-input.h | 8 | ||||
-rw-r--r-- | src/pulsecore/sink.c | 42 | ||||
-rw-r--r-- | src/pulsecore/sink.h | 11 |
15 files changed, 153 insertions, 160 deletions
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 3e5c219f..2fbcd7be 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -931,7 +931,7 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) { return 0; if (mask & SND_CTL_EVENT_MASK_VALUE) { - pa_sink_get_volume(u->sink, TRUE); + pa_sink_get_volume(u->sink, TRUE, FALSE); pa_sink_get_mute(u->sink, TRUE); } diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c index 0ca3dd83..7d87ca0f 100644 --- a/src/modules/module-device-restore.c +++ b/src/modules/module-device-restore.c @@ -191,7 +191,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 name = pa_sprintf_malloc("sink:%s", sink->name); entry.channel_map = sink->channel_map; - entry.volume = *pa_sink_get_volume(sink, FALSE); + entry.volume = *pa_sink_get_volume(sink, FALSE, TRUE); entry.muted = pa_sink_get_mute(sink, FALSE); } else { diff --git a/src/modules/module-lirc.c b/src/modules/module-lirc.c index 120b26e9..a1a8726f 100644 --- a/src/modules/module-lirc.c +++ b/src/modules/module-lirc.c @@ -120,7 +120,7 @@ static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event pa_log("Failed to get sink '%s'", u->sink_name); else { int i; - pa_cvolume cv = *pa_sink_get_volume(s, FALSE); + pa_cvolume cv = *pa_sink_get_volume(s, FALSE, FALSE); #define DELTA (PA_VOLUME_NORM/20) @@ -133,7 +133,7 @@ static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event cv.values[i] = PA_VOLUME_MAX; } - pa_sink_set_volume(s, &cv, TRUE, TRUE); + pa_sink_set_volume(s, &cv, TRUE, TRUE, TRUE); break; case DOWN: @@ -144,7 +144,7 @@ static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event cv.values[i] = PA_VOLUME_MUTED; } - pa_sink_set_volume(s, &cv, TRUE, TRUE); + pa_sink_set_volume(s, &cv, TRUE, TRUE, TRUE); break; case MUTE: diff --git a/src/modules/module-match.c b/src/modules/module-match.c index d7365ca7..625f2a8b 100644 --- a/src/modules/module-match.c +++ b/src/modules/module-match.c @@ -216,7 +216,7 @@ static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, v pa_cvolume cv; pa_log_debug("changing volume of sink input '%s' to 0x%03x", n, r->volume); pa_cvolume_set(&cv, si->sample_spec.channels, r->volume); - pa_sink_input_set_volume(si, &cv, TRUE); + pa_sink_input_set_volume(si, &cv, TRUE, TRUE); } } } diff --git a/src/modules/module-mmkbd-evdev.c b/src/modules/module-mmkbd-evdev.c index c43cfdac..d8b9c79e 100644 --- a/src/modules/module-mmkbd-evdev.c +++ b/src/modules/module-mmkbd-evdev.c @@ -102,7 +102,7 @@ static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event pa_log("Failed to get sink '%s'", u->sink_name); else { int i; - pa_cvolume cv = *pa_sink_get_volume(s, FALSE); + pa_cvolume cv = *pa_sink_get_volume(s, FALSE, FALSE); #define DELTA (PA_VOLUME_NORM/20) @@ -115,7 +115,7 @@ static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event cv.values[i] = PA_VOLUME_MAX; } - pa_sink_set_volume(s, &cv, TRUE, TRUE); + pa_sink_set_volume(s, &cv, TRUE, TRUE, TRUE); break; case DOWN: @@ -126,7 +126,7 @@ static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event cv.values[i] = PA_VOLUME_MUTED; } - pa_sink_set_volume(s, &cv, TRUE, TRUE); + pa_sink_set_volume(s, &cv, TRUE, TRUE, TRUE); break; case MUTE_TOGGLE: diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index 2c90e726..70cd89a7 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -91,15 +91,14 @@ struct userdata { pa_idxset *subscribed; }; -#define ENTRY_VERSION 1 +#define ENTRY_VERSION 2 struct entry { uint8_t version; - pa_bool_t muted_valid:1, relative_volume_valid:1, absolute_volume_valid:1, device_valid:1; + pa_bool_t muted_valid:1, volume_valid:1, device_valid:1; pa_bool_t muted:1; pa_channel_map channel_map; - pa_cvolume relative_volume; - pa_cvolume absolute_volume; + pa_cvolume volume; char device[PA_NAME_MAX]; } PA_GCC_PACKED; @@ -192,13 +191,12 @@ static struct entry* read_entry(struct userdata *u, const char *name) { goto fail; } - if ((e->relative_volume_valid || e->absolute_volume_valid) && !pa_channel_map_valid(&e->channel_map)) { + if (e->volume_valid && !pa_channel_map_valid(&e->channel_map)) { pa_log_warn("Invalid channel map stored in database for stream %s", name); goto fail; } - if ((e->relative_volume_valid && (!pa_cvolume_valid(&e->relative_volume) || e->relative_volume.channels != e->channel_map.channels)) || - (e->absolute_volume_valid && (!pa_cvolume_valid(&e->absolute_volume) || e->absolute_volume.channels != e->channel_map.channels))) { + if (e->volume_valid && (!pa_cvolume_valid(&e->volume) || !pa_cvolume_compatible_with_channel_map(&e->volume, &e->channel_map))) { pa_log_warn("Invalid volume stored in database for stream %s", name); goto fail; } @@ -251,14 +249,9 @@ static pa_bool_t entries_equal(const struct entry *a, const struct entry *b) { (a->muted_valid && (a->muted != b->muted))) return FALSE; - t = b->relative_volume; - if (a->relative_volume_valid != b->relative_volume_valid || - (a->relative_volume_valid && !pa_cvolume_equal(pa_cvolume_remap(&t, &b->channel_map, &a->channel_map), &a->relative_volume))) - return FALSE; - - t = b->absolute_volume; - if (a->absolute_volume_valid != b->absolute_volume_valid || - (a->absolute_volume_valid && !pa_cvolume_equal(pa_cvolume_remap(&t, &b->channel_map, &a->channel_map), &a->absolute_volume))) + t = b->volume; + if (a->volume_valid != b->volume_valid || + (a->volume_valid && !pa_cvolume_equal(pa_cvolume_remap(&t, &b->channel_map, &a->channel_map), &a->volume))) return FALSE; return TRUE; @@ -291,22 +284,24 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (!(name = get_name(sink_input->proplist, "sink-input"))) return; - entry.channel_map = sink_input->channel_map; - - pa_sink_input_get_relative_volume(sink_input, &entry.relative_volume); - entry.relative_volume_valid = sink_input->save_volume; + if ((old = read_entry(u, name))) + entry = *old; - if (sink_input->sink->flags & PA_SINK_FLAT_VOLUME) { - entry.absolute_volume = *pa_sink_input_get_volume(sink_input); - entry.absolute_volume_valid = sink_input->save_volume; - } else - entry.absolute_volume_valid = FALSE; + if (sink_input->save_volume) { + entry.channel_map = sink_input->channel_map; + pa_sink_input_get_volume(sink_input, &entry.volume, FALSE); + entry.volume_valid = TRUE; + } - entry.muted = pa_sink_input_get_mute(sink_input); - entry.muted_valid = sink_input->save_muted; + if (sink_input->save_muted) { + entry.muted = pa_sink_input_get_mute(sink_input); + entry.muted_valid = TRUE; + } - pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device)); - entry.device_valid = sink_input->save_sink; + if (sink_input->save_sink) { + pa_strlcpy(entry.device, sink_input->sink->name, sizeof(entry.device)); + entry.device_valid = TRUE; + } } else { pa_source_output *source_output; @@ -319,13 +314,16 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 if (!(name = get_name(source_output->proplist, "source-output"))) return; - entry.channel_map = source_output->channel_map; + if ((old = read_entry(u, name))) + entry = *old; - pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device)); - entry.device_valid = source_output->save_source; + if (source_output->save_source) { + pa_strlcpy(entry.device, source_output->source->name, sizeof(entry.device)); + entry.device_valid = source_output->save_source; + } } - if ((old = read_entry(u, name))) { + if (old) { if (entries_equal(old, &entry)) { pa_xfree(old); @@ -400,42 +398,24 @@ static pa_hook_result_t sink_input_fixate_hook_callback(pa_core *c, pa_sink_inpu if ((e = read_entry(u, name))) { - if (u->restore_volume) { + if (u->restore_volume && e->volume_valid) { if (!new_data->volume_is_set) { pa_cvolume v; - pa_cvolume_init(&v); - - if (new_data->sink->flags & PA_SINK_FLAT_VOLUME) { - - /* We don't check for e->device_valid here because - that bit marks whether it is a good choice for - restoring, not just if the data is filled in. */ - if (e->absolute_volume_valid && - (e->device[0] == 0 || pa_streq(new_data->sink->name, e->device))) { - - v = e->absolute_volume; - new_data->volume_is_absolute = TRUE; - } else if (e->relative_volume_valid) { - v = e->relative_volume; - new_data->volume_is_absolute = FALSE; - } - - } else if (e->relative_volume_valid) { - v = e->relative_volume; - new_data->volume_is_absolute = FALSE; - } - if (v.channels > 0) { - pa_log_info("Restoring volume for sink input %s.", name); - pa_sink_input_new_data_set_volume(new_data, pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map)); - new_data->save_volume = TRUE; - } + 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); + + new_data->volume_is_absolute = FALSE; + new_data->save_volume = FALSE; } else pa_log_debug("Not restoring volume for sink input %s, because already set.", name); } if (u->restore_muted && e->muted_valid) { + 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); @@ -532,30 +512,15 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) { } pa_xfree(n); - if (u->restore_volume) { + if (u->restore_volume && e->volume_valid) { pa_cvolume v; - pa_cvolume_init(&v); - if (si->sink->flags & PA_SINK_FLAT_VOLUME) { - - if (e->absolute_volume_valid && - (e->device[0] == 0 || pa_streq(e->device, si->sink->name))) - v = e->absolute_volume; - else if (e->relative_volume_valid) { - pa_cvolume t = *pa_sink_get_volume(si->sink, FALSE); - pa_sw_cvolume_multiply(&v, &e->relative_volume, pa_cvolume_remap(&t, &si->sink->channel_map, &e->channel_map)); - } - } else if (e->relative_volume_valid) - v = e->relative_volume; - - if (v.channels > 0) { - pa_log_info("Restoring volume for sink input %s.", name); - pa_sink_input_set_volume(si, pa_cvolume_remap(&v, &e->channel_map, &si->channel_map), TRUE); - } + v = e->volume; + pa_log_info("Restoring volume for sink input %s.", name); + pa_sink_input_set_volume(si, pa_cvolume_remap(&v, &e->channel_map, &si->channel_map), FALSE, FALSE); } - if (u->restore_muted && - e->muted_valid) { + 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); } @@ -610,10 +575,10 @@ static void dump_database(struct userdata *u) { if ((e = read_entry(u, name))) { char t[256]; pa_log("name=%s", name); - pa_log("device=%s", e->device); + pa_log("device=%s %s", e->device, pa_yes_no(e->device_valid)); pa_log("channel_map=%s", pa_channel_map_snprint(t, sizeof(t), &e->channel_map)); - pa_log("volume=%s", pa_cvolume_snprint(t, sizeof(t), &e->volume)); - pa_log("mute=%s", pa_yes_no(e->muted)); + pa_log("volume=%s %s", pa_cvolume_snprint(t, sizeof(t), &e->volume), pa_yes_no(e->volume_valid)); + pa_log("mute=%s %s", pa_yes_no(e->muted), pa_yes_no(e->volume_valid)); pa_xfree(e); } @@ -674,8 +639,8 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio pa_channel_map cm; pa_tagstruct_puts(reply, name); - pa_tagstruct_put_channel_map(reply, (e->relative_volume_valid || e->absolute_volume_valid) ? &e->channel_map : pa_channel_map_init(&cm)); - pa_tagstruct_put_cvolume(reply, e->absolute_volume_valid ? &e->absolute_volume : (e->relative_volume_valid ? &e->relative_volume : pa_cvolume_init(&r))); + pa_tagstruct_put_channel_map(reply, e->volume_valid ? &e->channel_map : pa_channel_map_init(&cm)); + pa_tagstruct_put_cvolume(reply, e->volume_valid ? &e->volume : pa_cvolume_init(&r)); pa_tagstruct_puts(reply, e->device_valid ? e->device : NULL); pa_tagstruct_put_boolean(reply, e->muted_valid ? e->muted : FALSE); @@ -718,7 +683,7 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio if (pa_tagstruct_gets(t, &name) < 0 || pa_tagstruct_get_channel_map(t, &entry.channel_map) || - pa_tagstruct_get_cvolume(t, &entry.absolute_volume) < 0 || + pa_tagstruct_get_cvolume(t, &entry.volume) < 0 || pa_tagstruct_gets(t, &device) < 0 || pa_tagstruct_get_boolean(t, &muted) < 0) goto fail; @@ -726,11 +691,10 @@ static int extension_cb(pa_native_protocol *p, pa_module *m, pa_native_connectio if (!name || !*name) goto fail; - entry.relative_volume = entry.absolute_volume; - entry.absolute_volume_valid = entry.relative_volume_valid = entry.relative_volume.channels > 0; + entry.volume_valid = entry.volume.channels > 0; - if (entry.relative_volume_valid) - if (!pa_cvolume_compatible_with_channel_map(&entry.relative_volume, &entry.channel_map)) + if (entry.volume_valid) + if (!pa_cvolume_compatible_with_channel_map(&entry.volume, &entry.channel_map)) goto fail; entry.muted = muted; diff --git a/src/modules/oss/module-oss.c b/src/modules/oss/module-oss.c index 855e8a35..9f7863f5 100644 --- a/src/modules/oss/module-oss.c +++ b/src/modules/oss/module-oss.c @@ -617,7 +617,7 @@ static int unsuspend(struct userdata *u) { build_pollfd(u); if (u->sink) - pa_sink_get_volume(u->sink, TRUE); + pa_sink_get_volume(u->sink, TRUE, FALSE); if (u->source) pa_source_get_volume(u->source, TRUE); diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index 3ea1dca5..15fe525c 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -524,7 +524,7 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu } pa_cvolume_set(&cvolume, sink->sample_spec.channels, volume); - pa_sink_set_volume(sink, &cvolume, TRUE, TRUE); + pa_sink_set_volume(sink, &cvolume, TRUE, TRUE, TRUE); return 0; } @@ -566,7 +566,7 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb } pa_cvolume_set(&cvolume, si->sample_spec.channels, volume); - pa_sink_input_set_volume(si, &cvolume, TRUE); + pa_sink_input_set_volume(si, &cvolume, TRUE, TRUE); return 0; } @@ -1516,7 +1516,7 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_b nl = 1; } - pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink, FALSE))); + pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink, FALSE, TRUE))); pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, FALSE))); pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED)); } diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index b0911ef1..604678be 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -258,10 +258,10 @@ char *pa_sink_list_to_string(pa_core *c) { sink->flags & PA_SINK_FLAT_VOLUME ? "FLAT_VOLUME " : "", sink->flags & PA_SINK_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "", sink_state_to_string(pa_sink_get_state(sink)), - pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, FALSE)), + pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, FALSE, FALSE)), sink->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t " : "", - sink->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), pa_sink_get_volume(sink, FALSE)) : "", - pa_cvolume_get_balance(pa_sink_get_volume(sink, FALSE), &sink->channel_map), + sink->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), pa_sink_get_volume(sink, FALSE, FALSE)) : "", + pa_cvolume_get_balance(pa_sink_get_volume(sink, FALSE, FALSE), &sink->channel_map), pa_volume_snprint(v, sizeof(v), sink->base_volume), sink->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t " : "", sink->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), sink->base_volume) : "", @@ -507,6 +507,9 @@ char *pa_sink_input_list_to_string(pa_core *c) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t, clt[28]; pa_usec_t cl; const char *cmn; + pa_cvolume v; + + pa_sink_input_get_volume(i, &v, TRUE); cmn = pa_channel_map_to_pretty_name(&i->channel_map); @@ -547,9 +550,9 @@ char *pa_sink_input_list_to_string(pa_core *c) { i->flags & PA_SINK_INPUT_FAIL_ON_SUSPEND ? "FAIL_ON_SUSPEND " : "", state_table[pa_sink_input_get_state(i)], i->sink->index, i->sink->name, - pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)), - pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), pa_sink_input_get_volume(i)), - pa_cvolume_get_balance(pa_sink_input_get_volume(i), &i->channel_map), + pa_cvolume_snprint(cv, sizeof(cv), &v), + pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &v), + pa_cvolume_get_balance(&v, &i->channel_map), pa_yes_no(pa_sink_input_get_mute(i)), (double) pa_sink_input_get_latency(i, NULL) / PA_USEC_PER_MSEC, clt, diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index a024471c..7e7126ea 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -638,7 +638,8 @@ static int esd_proto_all_info(connection *c, esd_proto_t request, const void *da pa_assert(t >= k*2+s); if (conn->sink_input) { - pa_cvolume volume = *pa_sink_input_get_volume(conn->sink_input); + pa_cvolume volume; + pa_sink_input_get_volume(conn->sink_input, &volume, TRUE); rate = (int32_t) conn->sink_input->sample_spec.rate; lvolume = (int32_t) ((volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); rvolume = (int32_t) ((volume.values[volume.channels == 2 ? 1 : 0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM); @@ -778,7 +779,7 @@ static int esd_proto_stream_pan(connection *c, esd_proto_t request, const void * volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE; volume.channels = conn->sink_input->sample_spec.channels; - pa_sink_input_set_volume(conn->sink_input, &volume, TRUE); + pa_sink_input_set_volume(conn->sink_input, &volume, TRUE, TRUE); ok = 1; } else ok = 0; diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 7c2183d8..aecaf71c 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -2819,7 +2819,7 @@ static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sin PA_TAG_SAMPLE_SPEC, &fixed_ss, PA_TAG_CHANNEL_MAP, &sink->channel_map, PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX, - PA_TAG_CVOLUME, pa_sink_get_volume(sink, FALSE), + PA_TAG_CVOLUME, pa_sink_get_volume(sink, FALSE, FALSE), PA_TAG_BOOLEAN, pa_sink_get_mute(sink, FALSE), PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX, PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL, @@ -2943,6 +2943,7 @@ static void module_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_m static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink_input *s) { pa_sample_spec fixed_ss; pa_usec_t sink_latency; + pa_cvolume v; pa_assert(t); pa_sink_input_assert_ref(s); @@ -2956,7 +2957,7 @@ static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_tagstruct_putu32(t, s->sink->index); pa_tagstruct_put_sample_spec(t, &fixed_ss); pa_tagstruct_put_channel_map(t, &s->channel_map); - pa_tagstruct_put_cvolume(t, pa_sink_input_get_volume(s)); + pa_tagstruct_put_cvolume(t, pa_sink_input_get_volume(s, &v, TRUE)); pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s, &sink_latency)); pa_tagstruct_put_usec(t, sink_latency); pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s))); @@ -3321,11 +3322,11 @@ static void command_set_volume( CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY); if (sink) - pa_sink_set_volume(sink, &volume, TRUE, TRUE); + pa_sink_set_volume(sink, &volume, TRUE, TRUE, TRUE); else if (source) pa_source_set_volume(source, &volume); else if (si) - pa_sink_input_set_volume(si, &volume, TRUE); + pa_sink_input_set_volume(si, &volume, TRUE, TRUE); pa_pstream_send_simple_ack(c->pstream, tag); } diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index b1b9fb56..65f1fd5e 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -176,16 +176,8 @@ int pa_sink_input_new( pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID); if (!data->volume_is_set) { - - if (data->sink->flags & PA_SINK_FLAT_VOLUME) { - data->volume = *pa_sink_get_volume(data->sink, FALSE); - pa_cvolume_remap(&data->volume, &data->sink->channel_map, &data->channel_map); - data->volume_is_absolute = TRUE; - } else { - pa_cvolume_reset(&data->volume, data->sample_spec.channels); - data->volume_is_absolute = FALSE; - } - + pa_cvolume_reset(&data->volume, data->sample_spec.channels); + data->volume_is_absolute = FALSE; data->save_volume = FALSE; } @@ -279,10 +271,9 @@ int pa_sink_input_new( /* When the 'absolute' bool is not set then we'll treat the volume * as relative to the sink volume even in flat volume mode */ - pa_cvolume t = *pa_sink_get_volume(data->sink, FALSE); - pa_cvolume_remap(&t, &data->sink->channel_map, &data->channel_map); - - pa_sw_cvolume_multiply(&i->virtual_volume, &data->volume, &t); + pa_cvolume v = data->sink->reference_volume; + pa_cvolume_remap(&v, &data->sink->channel_map, &data->channel_map); + pa_sw_cvolume_multiply(&i->virtual_volume, &data->volume, &v); } else i->virtual_volume = data->volume; @@ -451,7 +442,7 @@ void pa_sink_input_unlink(pa_sink_input *i) { if (i->sink->flags & PA_SINK_FLAT_VOLUME) { pa_cvolume new_volume; pa_sink_update_flat_volume(i->sink, &new_volume); - pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE); + pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE); } if (i->sink->asyncmsgq) @@ -529,7 +520,7 @@ void pa_sink_input_put(pa_sink_input *i) { if (i->sink->flags & PA_SINK_FLAT_VOLUME) { pa_cvolume new_volume; pa_sink_update_flat_volume(i->sink, &new_volume); - pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE); + pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE); } else pa_sink_input_set_relative_volume(i, &i->virtual_volume); @@ -881,13 +872,21 @@ pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) { } /* Called from main context */ -void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save) { +void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute) { + pa_cvolume v; + pa_sink_input_assert_ref(i); pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); pa_assert(volume); pa_assert(pa_cvolume_valid(volume)); pa_assert(pa_cvolume_compatible(volume, &i->sample_spec)); + if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) { + v = i->sink->reference_volume; + pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map); + volume = pa_sw_cvolume_multiply(&v, &v, volume); + } + if (pa_cvolume_equal(volume, &i->virtual_volume)) return; @@ -901,7 +900,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo * volumes and update the flat volume of the sink */ pa_sink_update_flat_volume(i->sink, &new_volume); - pa_sink_set_volume(i->sink, &new_volume, FALSE, TRUE); + pa_sink_set_volume(i->sink, &new_volume, FALSE, TRUE, FALSE); } else { @@ -921,11 +920,18 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo } /* Called from main context */ -const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) { +pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, pa_bool_t absolute) { pa_sink_input_assert_ref(i); pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); - return &i->virtual_volume; + if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) { + pa_cvolume v = i->sink->reference_volume; + pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map); + pa_sw_cvolume_divide(volume, &i->virtual_volume, &v); + } else + *volume = i->virtual_volume; + + return volume; } /* Called from main context */ @@ -936,7 +942,8 @@ pa_cvolume *pa_sink_input_get_relative_volume(pa_sink_input *i, pa_cvolume *v) { pa_assert(v); pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); - /* This always returns a relative volume, even in flat volume mode */ + /* This always returns the relative volume. Converts the float + * version into a pa_cvolume */ v->channels = i->sample_spec.channels; @@ -1152,7 +1159,7 @@ int pa_sink_input_start_move(pa_sink_input *i) { /* We might need to update the sink's volume if we are in flat * volume mode. */ pa_sink_update_flat_volume(i->sink, &new_volume); - pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE); + pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE); } pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0); @@ -1239,13 +1246,13 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { pa_cvolume new_volume; /* Make relative volume absolute again */ - pa_cvolume t = dest->virtual_volume; + pa_cvolume t = dest->reference_volume; pa_cvolume_remap(&t, &dest->channel_map, &i->channel_map); pa_sw_cvolume_multiply(&i->virtual_volume, &i->virtual_volume, &t); /* We might need to update the sink's volume if we are in flat volume mode. */ pa_sink_update_flat_volume(i->sink, &new_volume); - pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE); + pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE); } pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0); diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 96ad2baf..98144d41 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -91,6 +91,7 @@ struct pa_sink_input { pa_sink_input *sync_prev, *sync_next; + /* Also see http://pulseaudio.org/wiki/InternalVolumes */ pa_cvolume virtual_volume; /* The volume clients are informed about */ pa_cvolume volume_factor; /* An internally used volume factor that can be used by modules to apply effects and suchlike without having that visible to the outside */ double relative_volume[PA_CHANNELS_MAX]; /* The calculated volume relative to the sink volume as linear factors. */ @@ -309,11 +310,14 @@ void pa_sink_input_kill(pa_sink_input*i); pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency); -void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save); -const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i); +void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute); +pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, pa_bool_t absolute); + pa_cvolume *pa_sink_input_get_relative_volume(pa_sink_input *i, pa_cvolume *v); + void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save); pa_bool_t pa_sink_input_get_mute(pa_sink_input *i); + void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p); pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 93800d14..30fa5579 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -202,7 +202,7 @@ pa_sink* pa_sink_new( s->inputs = pa_idxset_new(NULL, NULL); s->n_corked = 0; - s->virtual_volume = data->volume; + s->reference_volume = s->virtual_volume = data->volume; pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels); s->base_volume = PA_VOLUME_NORM; s->n_volume_steps = PA_VOLUME_NORM+1; @@ -351,11 +351,12 @@ void pa_sink_put(pa_sink* s) { if (!(s->flags & PA_SINK_HW_VOLUME_CTRL)) { s->flags |= PA_SINK_DECIBEL_VOLUME; - - s->thread_info.soft_volume = s->soft_volume; - s->thread_info.soft_muted = s->muted; + s->base_volume = PA_VOLUME_NORM; } + s->thread_info.soft_volume = s->soft_volume; + s->thread_info.soft_muted = s->muted; + if (s->flags & PA_SINK_DECIBEL_VOLUME) s->n_volume_steps = PA_VOLUME_NORM+1; @@ -1046,16 +1047,16 @@ void pa_sink_update_flat_volume(pa_sink *s, pa_cvolume *new_volume) { pa_assert(PA_SINK_IS_LINKED(s->state)); pa_assert(s->flags & PA_SINK_FLAT_VOLUME); - /* This is called whenever a sink input volume changes and we - * might need to fix up the sink volume accordingly. Please note - * that we don't actually update the sinks volume here, we only - * return how it needs to be updated. The caller should then call - * pa_sink_set_volume().*/ + /* This is called whenever a sink input volume changes or a sink + * input is added/removed and we might need to fix up the sink + * volume accordingly. Please note that we don't actually update + * the sinks volume here, we only return how it needs to be + * updated. The caller should then call pa_sink_set_volume().*/ if (pa_idxset_isempty(s->inputs)) { /* In the special case that we have no sink input we leave the * volume unmodified. */ - *new_volume = s->virtual_volume; + *new_volume = s->reference_volume; return; } @@ -1142,7 +1143,7 @@ void pa_sink_propagate_flat_volume(pa_sink *s) { } /* Called from main thread */ -void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg) { +void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg, pa_bool_t become_reference) { pa_bool_t virtual_volume_changed; pa_sink_assert_ref(s); @@ -1154,6 +1155,9 @@ void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagat virtual_volume_changed = !pa_cvolume_equal(volume, &s->virtual_volume); s->virtual_volume = *volume; + if (become_reference) + s->reference_volume = s->virtual_volume; + /* Propagate this volume change back to the inputs */ if (virtual_volume_changed) if (propagate && (s->flags & PA_SINK_FLAT_VOLUME)) @@ -1161,8 +1165,8 @@ void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume, pa_bool_t propagat if (s->set_volume) { /* If we have a function set_volume(), then we do not apply a - * soft volume by default. However, set_volume() is apply one - * to s->soft_volume */ + * soft volume by default. However, set_volume() is free to + * apply one to s->soft_volume */ pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels); s->set_volume(s); @@ -1194,7 +1198,7 @@ void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) { } /* Called from main thread */ -const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh) { +const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh, pa_bool_t reference) { pa_sink_assert_ref(s); if (s->refresh_volume || force_refresh) { @@ -1207,6 +1211,8 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh) { if (!pa_cvolume_equal(&old_virtual_volume, &s->virtual_volume)) { + s->reference_volume = s->virtual_volume; + if (s->flags & PA_SINK_FLAT_VOLUME) pa_sink_propagate_flat_volume(s); @@ -1214,7 +1220,7 @@ const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh) { } } - return &s->virtual_volume; + return reference ? &s->reference_volume : &s->virtual_volume; } /* Called from main thread */ @@ -1226,7 +1232,11 @@ void pa_sink_volume_changed(pa_sink *s, const pa_cvolume *new_volume) { if (pa_cvolume_equal(&s->virtual_volume, new_volume)) return; - s->virtual_volume = *new_volume; + s->reference_volume = s->virtual_volume = *new_volume; + + if (s->flags & PA_SINK_FLAT_VOLUME) + pa_sink_propagate_flat_volume(s); + pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index cb4697f9..352282b8 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -74,8 +74,10 @@ struct pa_sink { pa_volume_t base_volume; /* shall be constant */ unsigned n_volume_steps; /* shall be constant */ - pa_cvolume virtual_volume; /* The volume clients are informed about */ - pa_cvolume soft_volume; /* The internal software volume we apply to all PCM data while it passes through */ + /* Also see http://pulseaudio.org/wiki/InternalVolumes */ + pa_cvolume virtual_volume; /* The volume clients are informed about */ + pa_cvolume reference_volume; /* The volume taken as refernce base for relative sink input volumes */ + pa_cvolume soft_volume; /* The internal software volume we apply to all PCM data while it passes through */ pa_bool_t muted:1; pa_bool_t refresh_volume:1; @@ -255,8 +257,9 @@ int pa_sink_suspend_all(pa_core *c, pa_bool_t suspend); void pa_sink_update_flat_volume(pa_sink *s, pa_cvolume *new_volume); void pa_sink_propagate_flat_volume(pa_sink *s); -void pa_sink_set_volume(pa_sink *sink, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg); -const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_bool_t force_refresh); +void pa_sink_set_volume(pa_sink *sink, const pa_cvolume *volume, pa_bool_t propagate, pa_bool_t sendmsg, pa_bool_t become_reference); +const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_bool_t force_refresh, pa_bool_t reference); + void pa_sink_set_mute(pa_sink *sink, pa_bool_t mute); pa_bool_t pa_sink_get_mute(pa_sink *sink, pa_bool_t force_refresh); |