(double) pa_sink_get_requested_latency(sink) / (double) PA_USEC_PER_MSEC,
(double) min_latency / PA_USEC_PER_MSEC,
(double) max_latency / PA_USEC_PER_MSEC);
- }
+ } else
+ pa_strbuf_printf(
+ s,
+ "\tfixed latency: %0.2f ms\n",
+ (double) pa_sink_get_requested_latency(sink) / PA_USEC_PER_MSEC);
if (sink->card)
pa_strbuf_printf(s, "\tcard: %u <%s>\n", sink->card->index, sink->card->name);
(double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC,
(double) min_latency / PA_USEC_PER_MSEC,
(double) max_latency / PA_USEC_PER_MSEC);
- }
+ } else
+ pa_strbuf_printf(
+ s,
+ "\tfixed latency: %0.2f ms\n",
+ (double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC);
if (source->monitor_of)
pa_strbuf_printf(s, "\tmonitor_of: %u\n", source->monitor_of->index);
pa_usec_t pa_sink_input_set_requested_latency_within_thread(pa_sink_input *i, pa_usec_t usec) {
pa_sink_input_assert_ref(i);
+ if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
+ usec = i->sink->fixed_latency;
+
if (usec != (pa_usec_t) -1)
usec = PA_CLAMP(usec, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
/* Called from main context */
pa_usec_t pa_sink_input_set_requested_latency(pa_sink_input *i, pa_usec_t usec) {
- pa_usec_t min_latency, max_latency;
-
pa_sink_input_assert_ref(i);
if (PA_SINK_INPUT_IS_LINKED(i->state) && i->sink) {
* we have to touch the thread info data directly */
if (i->sink) {
- pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
+ if (!(i->sink->flags & PA_SINK_DYNAMIC_LATENCY))
+ usec = i->sink->fixed_latency;
- if (usec != (pa_usec_t) -1)
+ if (usec != (pa_usec_t) -1) {
+ pa_usec_t min_latency, max_latency;
+ pa_sink_get_latency_range(i->sink, &min_latency, &max_latency);
usec = PA_CLAMP(usec, min_latency, max_latency);
+ }
}
i->thread_info.requested_sink_latency = usec;
#define MIX_BUFFER_LENGTH (PA_PAGE_SIZE)
#define ABSOLUTE_MIN_LATENCY (500)
#define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
+#define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject);
s->muted = data->muted;
s->refresh_volume = s->refresh_muted = FALSE;
+ s->fixed_latency = flags & PA_SINK_DYNAMIC_LATENCY ? 0 : DEFAULT_FIXED_LATENCY;
+
reset_callbacks(s);
s->userdata = NULL;
if (s->flags & PA_SINK_LATENCY)
s->monitor_source->flags |= PA_SOURCE_LATENCY;
- if (s->flags & PA_SINK_DYNAMIC_LATENCY)
+ if (s->flags & PA_SINK_DYNAMIC_LATENCY) {
s->monitor_source->flags |= PA_SOURCE_DYNAMIC_LATENCY;
+ s->fixed_latency = 0;
+ } else if (s->fixed_latency <= 0)
+ s->fixed_latency = DEFAULT_FIXED_LATENCY;
+
+ s->monitor_source->fixed_latency = s->fixed_latency;
pa_assert_se(sink_set_state(s, PA_SINK_IDLE) == 0);
pa_sink_assert_ref(s);
+ if (!(s->flags & PA_SINK_DYNAMIC_LATENCY))
+ return PA_CLAMP(s->fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
+
if (s->thread_info.requested_latency_valid)
return s->thread_info.requested_latency;
(result == (pa_usec_t) -1 || result > monitor_latency))
result = monitor_latency;
- if (result != (pa_usec_t) -1) {
- if (result > s->thread_info.max_latency)
- result = s->thread_info.max_latency;
-
- if (result < s->thread_info.min_latency)
- result = s->thread_info.min_latency;
- }
+ 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;
pa_sink_assert_ref(s);
+ if (!(s->flags & PA_SINK_DYNAMIC_LATENCY))
+ return;
+
s->thread_info.requested_latency_valid = FALSE;
if (PA_SINK_IS_LINKED(s->thread_info.state)) {
pa_memchunk silence;
+ pa_usec_t fixed_latency; /* for sinks with PA_SINK_DYNAMIC_LATENCY this is 0 */
+
/* Called when the main loop requests a state change. Called from
* main loop context. If returns -1 the state change will be
* inhibited */
pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output *o, pa_usec_t usec) {
pa_source_output_assert_ref(o);
+ if (!(o->source->flags & PA_SOURCE_DYNAMIC_LATENCY))
+ usec = o->source->fixed_latency;
+
if (usec != (pa_usec_t) -1)
usec = PA_CLAMP(usec, o->source->thread_info.min_latency, o->source->thread_info.max_latency);
/* Called from main context */
pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) {
- pa_usec_t min_latency, max_latency;
-
pa_source_output_assert_ref(o);
if (PA_SOURCE_OUTPUT_IS_LINKED(o->state) && o->source) {
* have to touch the thread info data directly */
if (o->source) {
- pa_source_get_latency_range(o->source, &min_latency, &max_latency);
+ if (!(o->source->flags & PA_SOURCE_DYNAMIC_LATENCY))
+ usec = o->source->fixed_latency;
- if (usec != (pa_usec_t) -1)
+ if (usec != (pa_usec_t) -1) {
+ pa_usec_t min_latency, max_latency;
+ pa_source_get_latency_range(o->source, &min_latency, &max_latency);
usec = PA_CLAMP(usec, min_latency, max_latency);
+ }
}
o->thread_info.requested_source_latency = usec;
#define ABSOLUTE_MIN_LATENCY (500)
#define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
+#define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
static PA_DEFINE_CHECK_TYPE(pa_source, pa_msgobject);
s->muted = data->muted;
s->refresh_volume = s->refresh_muted = FALSE;
+ s->fixed_latency = flags & PA_SOURCE_DYNAMIC_LATENCY ? 0 : DEFAULT_FIXED_LATENCY;
+
reset_callbacks(s);
s->userdata = NULL;
/* The following fields must be initialized properly when calling _put() */
pa_assert(s->asyncmsgq);
pa_assert(s->rtpoll);
- pa_assert(!s->thread_info.min_latency || !s->thread_info.max_latency ||
- s->thread_info.min_latency <= s->thread_info.max_latency);
+ 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;
if (s->flags & PA_SOURCE_DECIBEL_VOLUME)
s->n_volume_steps = PA_VOLUME_NORM+1;
+ 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_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
pa_source_assert_ref(s);
+ if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
+ return PA_CLAMP(s->fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
+
if (s->thread_info.requested_latency_valid)
return s->thread_info.requested_latency;
(result == (pa_usec_t) -1 || result > o->thread_info.requested_source_latency))
result = o->thread_info.requested_source_latency;
- if (result != (pa_usec_t) -1) {
- if (s->thread_info.max_latency > 0 && result > s->thread_info.max_latency)
- result = s->thread_info.max_latency;
-
- if (s->thread_info.min_latency > 0 && result < s->thread_info.min_latency)
- result = s->thread_info.min_latency;
- }
+ 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;
/* Called from main thread */
pa_usec_t pa_source_get_requested_latency(pa_source *s) {
- pa_usec_t usec;
+ pa_usec_t usec = 0;
pa_source_assert_ref(s);
pa_assert(PA_SOURCE_IS_LINKED(s->state));
pa_source_assert_ref(s);
+ if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
+ return;
+
s->thread_info.requested_latency_valid = FALSE;
if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
pa_memchunk silence;
+ pa_usec_t fixed_latency; /* for sources with PA_SOURCE_DYNAMIC_LATENCY this is 0 */
+
/* Called when the main loop requests a state change. Called from
* main loop context. If returns -1 the state change will be
* inhibited */