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);  | 
