This is pretty cosmetic change; there's no actual functionality added. Previously the volume_writable information was available through the pa_sink_input_is_volume_writable() function, but I find it cleaner to have a real variable. The sink input introspection variable name was also changed from read_only_volume to volume_writable for consistency. --- PROTOCOL | 2 +- src/modules/dbus/iface-stream.c | 10 ++++---- src/modules/module-stream-restore.c | 6 ++-- src/pulse/introspect.c | 6 ++-- src/pulse/introspect.h | 2 +- src/pulsecore/cli-command.c | 2 +- src/pulsecore/protocol-native.c | 4 +- src/pulsecore/sink-input.c | 36 ++++++---------------------------- src/pulsecore/sink-input.h | 6 +++- 9 files changed, 27 insertions(+), 47 deletions(-) diff --git a/PROTOCOL b/PROTOCOL index c2bb209..a15d116 100644 --- a/PROTOCOL +++ b/PROTOCOL @@ -212,4 +212,4 @@ New flag at the end of sink input and source output introspection data: Two new flags at the end of sink input introspection data: bool has_volume - bool read_only_volume + bool volume_writable diff --git a/src/modules/dbus/iface-stream.c b/src/modules/dbus/iface-stream.c index e3464fd..d9f1237 100644 --- a/src/modules/dbus/iface-stream.c +++ b/src/modules/dbus/iface-stream.c @@ -57,7 +57,6 @@ struct pa_dbusiface_stream { pa_proplist *proplist; pa_bool_t has_volume; - pa_bool_t read_only_volume; pa_dbus_protocol *dbus_protocol; pa_subscription *subscription; @@ -357,6 +356,7 @@ static void handle_get_volume(DBusConnection *conn, DBusMessage *msg, void *user static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessageIter *iter, void *userdata) { pa_dbusiface_stream *s = userdata; + pa_bool_t volume_writable = TRUE; DBusMessageIter array_iter; int stream_channels = 0; dbus_uint32_t *volume = NULL; @@ -369,12 +369,14 @@ static void handle_set_volume(DBusConnection *conn, DBusMessage *msg, DBusMessag pa_assert(iter); pa_assert(s); - if (!s->has_volume || s->read_only_volume) { + volume_writable = (s->type == STREAM_TYPE_PLAYBACK) ? s->sink_input->volume_writable : FALSE; + + if (!s->has_volume || !volume_writable) { char *str = stream_to_string(s); if (!s->has_volume) pa_dbus_send_error(conn, msg, PA_DBUS_ERROR_NO_SUCH_PROPERTY, "%s doesn't have volume.", str); - else if (s->read_only_volume) + else if (!volume_writable) pa_dbus_send_error(conn, msg, DBUS_ERROR_ACCESS_DENIED, "%s has read-only volume.", str); pa_xfree(str); @@ -853,7 +855,6 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_playback(pa_dbusiface_core *core, p s->sink = pa_sink_ref(sink_input->sink); s->sample_rate = sink_input->sample_spec.rate; s->has_volume = pa_sink_input_is_volume_readable(sink_input); - s->read_only_volume = s->has_volume ? !pa_sink_input_is_volume_writable(sink_input) : FALSE; if (s->has_volume) pa_sink_input_get_volume(sink_input, &s->volume, TRUE); @@ -891,7 +892,6 @@ pa_dbusiface_stream *pa_dbusiface_stream_new_record(pa_dbusiface_core *core, pa_ s->mute = FALSE; s->proplist = pa_proplist_copy(source_output->proplist); s->has_volume = FALSE; - s->read_only_volume = FALSE; s->dbus_protocol = pa_dbus_protocol_get(source_output->core); s->subscription = pa_subscription_new(source_output->core, PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, subscription_cb, s); s->send_event_slot = pa_hook_connect(&source_output->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_SEND_EVENT], diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c index df48dce..8edfee0 100644 --- a/src/modules/module-stream-restore.c +++ b/src/modules/module-stream-restore.c @@ -1168,7 +1168,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3 } if (sink_input->save_volume) { - pa_assert(pa_sink_input_is_volume_writable(sink_input)); + pa_assert(sink_input->volume_writable); entry.channel_map = sink_input->channel_map; pa_sink_input_get_volume(sink_input, &entry.volume, FALSE); @@ -1329,7 +1329,7 @@ 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 && e->volume_valid) { - if (!pa_sink_input_new_data_is_volume_writable(new_data)) + if (!new_data->volume_writable) pa_log_debug("Not restoring volume for sink input %s, because its volume can't be changed.", name); else if (new_data->volume_is_set) pa_log_debug("Not restoring volume for sink input %s, because already set.", name); @@ -1619,7 +1619,7 @@ static void apply_entry(struct userdata *u, const char *name, struct entry *e) { } pa_xfree(n); - if (u->restore_volume && e->volume_valid && pa_sink_input_is_volume_writable(si)) { + if (u->restore_volume && e->volume_valid && si->volume_writable) { pa_cvolume v; v = e->volume; diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c index ec27b92..c93fb06 100644 --- a/src/pulse/introspect.c +++ b/src/pulse/introspect.c @@ -995,7 +995,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm while (!pa_tagstruct_eof(t)) { pa_sink_input_info i; - pa_bool_t mute = FALSE, corked = FALSE, has_volume = FALSE, read_only_volume = FALSE; + pa_bool_t mute = FALSE, corked = FALSE, has_volume = FALSE, volume_writable = TRUE; pa_zero(i); i.proplist = pa_proplist_new(); @@ -1016,7 +1016,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm (o->context->version >= 13 && pa_tagstruct_get_proplist(t, i.proplist) < 0) || (o->context->version >= 19 && pa_tagstruct_get_boolean(t, &corked) < 0) || (o->context->version >= 20 && (pa_tagstruct_get_boolean(t, &has_volume) < 0 || - pa_tagstruct_get_boolean(t, &read_only_volume) < 0))) { + pa_tagstruct_get_boolean(t, &volume_writable) < 0))) { pa_context_fail(o->context, PA_ERR_PROTOCOL); pa_proplist_free(i.proplist); @@ -1026,7 +1026,7 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm i.mute = (int) mute; i.corked = (int) corked; i.has_volume = (int) has_volume; - i.read_only_volume = (int) read_only_volume; + i.volume_writable = (int) volume_writable; if (o->callback) { pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback; diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h index 1cadee5..297b4ba 100644 --- a/src/pulse/introspect.h +++ b/src/pulse/introspect.h @@ -504,7 +504,7 @@ typedef struct pa_sink_input_info { pa_proplist *proplist; /**< Property list \since 0.9.11 */ int corked; /**< Stream corked \since 1.0 */ int has_volume; /**< Stream has volume. If not set, then the meaning of this struct's volume member is unspecified. \since 1.0 */ - int read_only_volume; /**< Stream volume can only be read. Although volume control is disabled, the stream volume is still not necessarily constant. \since 1.0 */ + int volume_writable; /**< The volume can be set. If not set, the volume can still change even though clients can't control the volume. \since 1.0 */ } pa_sink_input_info; /** Callback prototype for pa_context_get_sink_input_info() and friends*/ diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c index de4995e..17b0e15 100644 --- a/src/pulsecore/cli-command.c +++ b/src/pulsecore/cli-command.c @@ -585,7 +585,7 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb return -1; } - if (!pa_sink_input_is_volume_writable(si)) { + if (!si->volume_writable) { pa_strbuf_puts(buf, "This sink input's volume can't be changed.\n"); return -1; } diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index bb4be72..4952ee4 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -3089,7 +3089,7 @@ static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_tagstruct_put_boolean(t, (pa_sink_input_get_state(s) == PA_SINK_INPUT_CORKED)); if (c->version >= 20) { pa_tagstruct_put_boolean(t, has_volume); - pa_tagstruct_put_boolean(t, has_volume ? !pa_sink_input_is_volume_writable(s) : FALSE); + pa_tagstruct_put_boolean(t, s->volume_writable); } } @@ -3472,7 +3472,7 @@ static void command_set_volume( pa_log_debug("Client %s changes volume of source %s.", client_name, source->name); pa_source_set_volume(source, &volume, TRUE); } else if (si) { - CHECK_VALIDITY(c->pstream, pa_sink_input_is_volume_writable(si), tag, PA_ERR_INVALID); + CHECK_VALIDITY(c->pstream, si->volume_writable, tag, PA_ERR_BADSTATE); CHECK_VALIDITY(c->pstream, volume.channels == 1 || pa_cvolume_compatible(&volume, &si->sample_spec), tag, PA_ERR_INVALID); pa_log_debug("Client %s changes volume of sink input %s.", diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index e0e81be..46f26f9 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -88,6 +88,7 @@ pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data pa_zero(*data); data->resample_method = PA_RESAMPLER_INVALID; data->proplist = pa_proplist_new(); + data->volume_writable = TRUE; return data; } @@ -106,21 +107,9 @@ void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const data->channel_map = *map; } -pa_bool_t pa_sink_input_new_data_is_volume_writable(pa_sink_input_new_data *data) { - pa_assert(data); - - if (data->flags & PA_SINK_INPUT_PASSTHROUGH) - return FALSE; - - if (data->origin_sink && (data->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) - return FALSE; - - return TRUE; -} - void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume) { pa_assert(data); - pa_assert(pa_sink_input_new_data_is_volume_writable(data)); + pa_assert(data->volume_writable); if ((data->volume_is_set = !!volume)) data->volume = *volume; @@ -209,10 +198,12 @@ int pa_sink_input_new( if (data->client) pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist); + if (data->origin_sink && (data->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) + data->volume_writable = FALSE; + if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], data)) < 0) return r; - pa_assert(!data->volume_is_set || pa_sink_input_new_data_is_volume_writable(data)); pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID); if (!data->sink) { @@ -353,6 +344,7 @@ int pa_sink_input_new( i->real_ratio = i->reference_ratio = data->volume; pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels); pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels); + i->volume_writable = data->volume_writable; i->save_volume = data->save_volume; i->save_sink = data->save_sink; i->save_muted = data->save_muted; @@ -1026,7 +1018,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo pa_assert(volume); pa_assert(pa_cvolume_valid(volume)); pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec)); - pa_assert(pa_sink_input_is_volume_writable(i)); + pa_assert(i->volume_writable); if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) { v = i->sink->reference_volume; @@ -1104,20 +1096,6 @@ pa_bool_t pa_sink_input_is_volume_readable(pa_sink_input *i) { } /* Called from main context */ -pa_bool_t pa_sink_input_is_volume_writable(pa_sink_input *i) { - pa_sink_input_assert_ref(i); - pa_assert_ctl_context(); - - if (i->flags & PA_SINK_INPUT_PASSTHROUGH) - return FALSE; - - if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) - return FALSE; - - return TRUE; -} - -/* Called from main context */ 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_ctl_context(); diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 588005f..11f6608 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -104,6 +104,8 @@ struct pa_sink_input { pa_cvolume volume_factor_sink; /* A second volume factor in format of the sink this stream is connected to */ + pa_bool_t volume_writable:1; + pa_bool_t muted:1; /* if TRUE then the source we are connected to and/or the volume @@ -289,13 +291,14 @@ typedef struct pa_sink_input_new_data { pa_bool_t volume_is_absolute:1; + pa_bool_t volume_writable:1; + pa_bool_t save_sink:1, save_volume:1, save_muted:1; } pa_sink_input_new_data; pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data); void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const pa_sample_spec *spec); void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map); -pa_bool_t pa_sink_input_new_data_is_volume_writable(pa_sink_input_new_data *data); void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume); void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, const pa_cvolume *volume_factor); void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor); @@ -341,7 +344,6 @@ 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); pa_bool_t pa_sink_input_is_volume_readable(pa_sink_input *i); -pa_bool_t pa_sink_input_is_volume_writable(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); -- 1.7.4.1