summaryrefslogtreecommitdiffstats
path: root/src/pulsecore/source.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulsecore/source.c')
-rw-r--r--src/pulsecore/source.c68
1 files changed, 51 insertions, 17 deletions
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 21902509..53697c57 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -180,6 +180,7 @@ pa_source* pa_source_new(
s->core = core;
s->state = PA_SOURCE_INIT;
s->flags = flags;
+ s->suspend_cause = 0;
s->name = pa_xstrdup(name);
s->proplist = pa_proplist_copy(data->proplist);
s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
@@ -308,20 +309,19 @@ void pa_source_put(pa_source *s) {
pa_assert(s->rtpoll);
pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
- if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL)) {
- s->flags |= PA_SOURCE_DECIBEL_VOLUME;
+ /* Generally, flags should be initialized via pa_source_new(). As
+ * a special exception we allow volume related flags to be set
+ * between _new() and _put(). */
- s->thread_info.soft_volume = s->soft_volume;
- s->thread_info.soft_muted = s->muted;
- }
+ if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL))
+ s->flags |= PA_SOURCE_DECIBEL_VOLUME;
- if (s->flags & PA_SOURCE_DECIBEL_VOLUME)
- s->n_volume_steps = PA_VOLUME_NORM+1;
+ s->thread_info.soft_volume = s->soft_volume;
+ s->thread_info.soft_muted = s->muted;
- if (s->flags & PA_SOURCE_DYNAMIC_LATENCY)
- s->fixed_latency = 0;
- else if (s->fixed_latency <= 0)
- s->fixed_latency = DEFAULT_FIXED_LATENCY;
+ pa_assert((s->flags & PA_SOURCE_HW_VOLUME_CTRL) || (s->base_volume == PA_VOLUME_NORM && s->flags & PA_SOURCE_DECIBEL_VOLUME));
+ pa_assert(!(s->flags & PA_SOURCE_DECIBEL_VOLUME) || s->n_volume_steps == PA_VOLUME_NORM+1);
+ pa_assert(!(s->flags & PA_SOURCE_DYNAMIC_LATENCY) == (s->fixed_latency != 0));
pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
@@ -428,14 +428,25 @@ int pa_source_update_status(pa_source*s) {
}
/* Called from main context */
-int pa_source_suspend(pa_source *s, pa_bool_t suspend) {
+int pa_source_suspend(pa_source *s, pa_bool_t suspend, pa_suspend_cause_t cause) {
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
+ pa_assert(cause != 0);
if (s->monitor_of)
return -PA_ERR_NOTSUPPORTED;
if (suspend)
+ s->suspend_cause |= cause;
+ else
+ s->suspend_cause &= ~cause;
+
+ if ((pa_source_get_state(s) == PA_SOURCE_SUSPENDED) == !!s->suspend_cause)
+ return 0;
+
+ pa_log_debug("Suspend cause of source %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming");
+
+ if (suspend)
return source_set_state(s, PA_SOURCE_SUSPENDED);
else
return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
@@ -757,8 +768,12 @@ pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) {
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
- if (old_muted != s->muted)
+ if (old_muted != s->muted) {
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+
+ /* Make sure the soft mute status stays in sync */
+ pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
+ }
}
return s->muted;
@@ -1033,12 +1048,13 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
}
/* Called from main thread */
-int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) {
+int pa_source_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause) {
uint32_t idx;
pa_source *source;
int ret = 0;
pa_core_assert_ref(c);
+ pa_assert(cause != 0);
for (source = PA_SOURCE(pa_idxset_first(c->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(c->sources, &idx))) {
int r;
@@ -1046,7 +1062,7 @@ int pa_source_suspend_all(pa_core *c, pa_bool_t suspend) {
if (source->monitor_of)
continue;
- if ((r = pa_source_suspend(source, suspend)) < 0)
+ if ((r = pa_source_suspend(source, suspend, cause)) < 0)
ret = r;
}
@@ -1118,8 +1134,11 @@ pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
if (result != (pa_usec_t) -1)
result = PA_CLAMP(result, s->thread_info.min_latency, s->thread_info.max_latency);
- s->thread_info.requested_latency = result;
- s->thread_info.requested_latency_valid = TRUE;
+ if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
+ /* Only cache this if we are fully set up */
+ s->thread_info.requested_latency = result;
+ s->thread_info.requested_latency_valid = TRUE;
+ }
return result;
}
@@ -1276,6 +1295,21 @@ void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_laten
pa_source_invalidate_requested_latency(s);
}
+/* Called from main thread, before the source is put */
+void pa_source_set_fixed_latency(pa_source *s, pa_usec_t latency) {
+ pa_source_assert_ref(s);
+
+ pa_assert(pa_source_get_state(s) == PA_SOURCE_INIT);
+
+ if (latency < ABSOLUTE_MIN_LATENCY)
+ latency = ABSOLUTE_MIN_LATENCY;
+
+ if (latency > ABSOLUTE_MAX_LATENCY)
+ latency = ABSOLUTE_MAX_LATENCY;
+
+ s->fixed_latency = latency;
+}
+
/* Called from main thread */
size_t pa_source_get_max_rewind(pa_source *s) {
size_t r;