diff options
Diffstat (limited to 'src/pulsecore/sink.c')
-rw-r--r-- | src/pulsecore/sink.c | 90 |
1 files changed, 76 insertions, 14 deletions
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 4102f31d..a6027e70 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -663,7 +663,6 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_sw_cvolume_multiply(&volume, &s->thread_info.soft_volume, &info[0].volume); if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&volume)) { - pa_log("adjusting volume "); pa_memchunk_make_writable(result, 0); if (s->thread_info.soft_muted || pa_cvolume_is_muted(&volume)) pa_silence_memchunk(result, &s->sample_spec); @@ -844,30 +843,55 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) { /* Called from main thread */ void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) { pa_bool_t changed; + pa_sink_set_volume_data data; pa_sink_assert_ref(s); pa_assert(PA_SINK_IS_LINKED(s->state)); pa_assert(volume); + pa_assert(pa_cvolume_valid(volume)); + pa_assert(pa_cvolume_compatible(volume, &s->sample_spec)); - changed = !pa_cvolume_equal(volume, &s->volume); - s->volume = *volume; + data.sink = s; + data.volume = *volume; + + changed = !pa_cvolume_equal(&data.volume, &s->volume); + + if (changed) { + if (pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_SET_VOLUME], &data) < 0) + return; + + changed = !pa_cvolume_equal(&data.volume, &s->volume); + } + + s->volume = data.volume; if (s->set_volume && s->set_volume(s) < 0) s->set_volume = NULL; if (!s->set_volume) - pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, volume, 0, NULL); + pa_sink_set_soft_volume(s, volume); if (changed) pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index); } /* Called from main thread */ -const pa_cvolume *pa_sink_get_volume(pa_sink *s) { +void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) { + pa_sink_assert_ref(s); + pa_assert(volume); + + if (PA_SINK_IS_LINKED(s->state)) + pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME, volume, 0, NULL); + else + s->thread_info.soft_volume = *volume; +} + +/* Called from main thread */ +const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_bool_t force_refresh) { pa_sink_assert_ref(s); pa_assert(PA_SINK_IS_LINKED(s->state)); - if (s->refresh_volume) { + if (s->refresh_volume || force_refresh) { struct pa_cvolume old_volume = s->volume; if (s->get_volume && s->get_volume(s) < 0) @@ -904,12 +928,12 @@ void pa_sink_set_mute(pa_sink *s, pa_bool_t mute) { } /* Called from main thread */ -pa_bool_t pa_sink_get_mute(pa_sink *s) { +pa_bool_t pa_sink_get_mute(pa_sink *s, pa_bool_t force_refresh) { pa_sink_assert_ref(s); pa_assert(PA_SINK_IS_LINKED(s->state)); - if (s->refresh_muted) { + if (s->refresh_muted || force_refresh) { pa_bool_t old_muted = s->muted; if (s->get_mute && s->get_mute(s) < 0) @@ -967,7 +991,7 @@ unsigned pa_sink_linked_by(pa_sink *s) { ret = pa_idxset_size(s->inputs); /* We add in the number of streams connected to us here. Please - * not the asymmmetry to pa_sink_used_by()! */ + * note the asymmmetry to pa_sink_used_by()! */ if (s->monitor_source) ret += pa_source_linked_by(s->monitor_source); @@ -991,6 +1015,38 @@ unsigned pa_sink_used_by(pa_sink *s) { return ret - s->n_corked; } +/* Called from main thread */ +unsigned pa_sink_check_suspend(pa_sink *s) { + unsigned ret; + pa_sink_input *i; + uint32_t idx; + + pa_sink_assert_ref(s); + pa_assert(PA_SINK_IS_LINKED(s->state)); + + ret = 0; + + for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) { + pa_sink_input_state_t st; + + st = pa_sink_input_get_state(i); + pa_assert(PA_SINK_INPUT_IS_LINKED(st)); + + if (st == PA_SINK_INPUT_CORKED) + continue; + + if (i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND) + continue; + + ret ++; + } + + if (s->monitor_source) + ret += pa_source_check_suspend(s->monitor_source); + + return ret; +} + /* Called from IO thread, except when it is not */ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) { pa_sink *s = PA_SINK(o); @@ -1031,11 +1087,15 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse pa_sink_input_set_state_within_thread(i, i->state); + /* The requested latency of the sink input needs to be + * fixed up and then configured on the sink */ + + if (i->thread_info.requested_sink_latency != (pa_usec_t) -1) + pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency); + pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind); pa_sink_input_update_max_request(i, s->thread_info.max_request); - pa_sink_invalidate_requested_latency(s); - /* We don't rewind here automatically. This is left to the * sink input implementor because some sink inputs need a * slow start, i.e. need some time to buffer client @@ -1147,11 +1207,12 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse if (i->attach) i->attach(i); + if (i->thread_info.requested_sink_latency != (pa_usec_t) -1) + pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency); + pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind); pa_sink_input_update_max_request(i, s->thread_info.max_request); - pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency); - if (i->thread_info.state != PA_SINK_INPUT_CORKED) { pa_usec_t usec = 0; size_t nbytes; @@ -1413,7 +1474,6 @@ void pa_sink_set_max_rewind(pa_sink *s, size_t max_rewind) { /* Called from IO thread */ void pa_sink_set_max_request(pa_sink *s, size_t max_request) { - pa_sink_input *i; void *state = NULL; pa_sink_assert_ref(s); @@ -1424,6 +1484,8 @@ void pa_sink_set_max_request(pa_sink *s, size_t max_request) { s->thread_info.max_request = max_request; if (PA_SINK_IS_LINKED(s->thread_info.state)) { + pa_sink_input *i; + while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) pa_sink_input_update_max_request(i, s->thread_info.max_request); } |