char *device_name; /* name of the PCM device */
char *control_device; /* name of the control device */
- pa_bool_t use_mmap:1, use_tsched:1, deferred_volume:1;
+ pa_bool_t use_mmap:1, use_tsched:1, deferred_volume:1, fixed_latency_range:1;
pa_bool_t first, after_rewind;
return;
}
- /* Hmm, we cannot increase the watermark any further, hence let's raise the latency */
+ /* Hmm, we cannot increase the watermark any further, hence let's
+ raise the latency, unless doing so was disabled in
+ configuration */
+ if (u->fixed_latency_range)
+ return;
+
old_min_latency = u->sink->thread_info.min_latency;
new_min_latency = PA_MIN(old_min_latency * 2, old_min_latency + TSCHED_WATERMARK_INC_STEP_USEC);
new_min_latency = PA_MIN(new_min_latency, u->sink->thread_info.max_latency);
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark, rewind_safeguard;
snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
size_t frame_size;
- pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE, namereg_fail = FALSE, deferred_volume = FALSE, set_formats = FALSE;
+ pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE, namereg_fail = FALSE, deferred_volume = FALSE, set_formats = FALSE, fixed_latency_range = FALSE;
pa_sink_new_data data;
pa_alsa_profile_set *profile_set = NULL;
goto fail;
}
+ if (pa_modargs_get_value_boolean(ma, "fixed_latency_range", &fixed_latency_range) < 0) {
+ pa_log("Failed to parse fixed_latency_range argument.");
+ goto fail;
+ }
+
use_tsched = pa_alsa_may_tsched(use_tsched);
u = pa_xnew0(struct userdata, 1);
u->use_mmap = use_mmap;
u->use_tsched = use_tsched;
u->deferred_volume = deferred_volume;
+ u->fixed_latency_range = fixed_latency_range;
u->first = TRUE;
u->rewind_safeguard = rewind_safeguard;
u->rtpoll = pa_rtpoll_new();
if (u->use_mmap)
pa_log_info("Successfully enabled mmap() mode.");
- if (u->use_tsched)
+ if (u->use_tsched) {
pa_log_info("Successfully enabled timer-based scheduling mode.");
+ if (u->fixed_latency_range)
+ pa_log_info("Disabling latency range changes on underrun");
+ }
+
if (is_iec958(u) || is_hdmi(u))
set_formats = TRUE;
char *device_name; /* name of the PCM device */
char *control_device; /* name of the control device */
- pa_bool_t use_mmap:1, use_tsched:1, deferred_volume:1;
+ pa_bool_t use_mmap:1, use_tsched:1, deferred_volume:1, fixed_latency_range:1;
pa_bool_t first;
return;
}
- /* Hmm, we cannot increase the watermark any further, hence let's raise the latency */
+ /* Hmm, we cannot increase the watermark any further, hence let's
+ raise the latency unless doing so was disabled in
+ configuration */
+ if (u->fixed_latency_range)
+ return;
+
old_min_latency = u->source->thread_info.min_latency;
new_min_latency = PA_MIN(old_min_latency * 2, old_min_latency + TSCHED_WATERMARK_INC_STEP_USEC);
new_min_latency = PA_MIN(new_min_latency, u->source->thread_info.max_latency);
uint32_t nfrags, frag_size, buffer_size, tsched_size, tsched_watermark;
snd_pcm_uframes_t period_frames, buffer_frames, tsched_frames;
size_t frame_size;
- pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE, namereg_fail = FALSE, deferred_volume = FALSE;
+ pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE, namereg_fail = FALSE, deferred_volume = FALSE, fixed_latency_range = FALSE;
pa_source_new_data data;
pa_alsa_profile_set *profile_set = NULL;
goto fail;
}
+ if (pa_modargs_get_value_boolean(ma, "fixed_latency_range", &fixed_latency_range) < 0) {
+ pa_log("Failed to parse fixed_latency_range argument.");
+ goto fail;
+ }
+
use_tsched = pa_alsa_may_tsched(use_tsched);
u = pa_xnew0(struct userdata, 1);
u->use_mmap = use_mmap;
u->use_tsched = use_tsched;
u->deferred_volume = deferred_volume;
+ u->fixed_latency_range = fixed_latency_range;
u->first = TRUE;
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
if (u->use_mmap)
pa_log_info("Successfully enabled mmap() mode.");
- if (u->use_tsched)
+ if (u->use_tsched) {
pa_log_info("Successfully enabled timer-based scheduling mode.");
+ if (u->fixed_latency_range)
+ pa_log_info("Disabling latency range changes on overrun");
+ }
u->rates = pa_alsa_get_supported_rates(u->pcm_handle);
if (!u->rates) {
"rewind_safeguard=<number of bytes that cannot be rewound> "
"deferred_volume=<Synchronize software and hardware volume changes to avoid momentary jumps?> "
"deferred_volume_safety_margin=<usec adjustment depending on volume direction> "
- "deferred_volume_extra_delay=<usec adjustment to HW volume changes>");
+ "deferred_volume_extra_delay=<usec adjustment to HW volume changes> "
+ "fixed_latency_range=<disable latency range changes on underrun?>");
static const char* const valid_modargs[] = {
"name",
"deferred_volume",
"deferred_volume_safety_margin",
"deferred_volume_extra_delay",
+ "fixed_latency_range",
NULL
};
"control=<name of mixer control>"
"deferred_volume=<Synchronize software and hardware volume changes to avoid momentary jumps?> "
"deferred_volume_safety_margin=<usec adjustment depending on volume direction> "
- "deferred_volume_extra_delay=<usec adjustment to HW volume changes>");
+ "deferred_volume_extra_delay=<usec adjustment to HW volume changes> "
+ "fixed_latency_range=<disable latency range changes on overrun?>");
static const char* const valid_modargs[] = {
"name",
"deferred_volume",
"deferred_volume_safety_margin",
"deferred_volume_extra_delay",
+ "fixed_latency_range",
NULL
};
tlength_usec -= s->configured_sink_latency;
}
+ pa_log_debug("Requested latency=%0.2f ms, Received latency=%0.2f ms",
+ (double) sink_usec / PA_USEC_PER_MSEC,
+ (double) s->configured_sink_latency / PA_USEC_PER_MSEC);
+
/* FIXME: This is actually larger than necessary, since not all of
* the sink latency is actually rewritable. */
if (tlength_usec < s->configured_sink_latency + 2*minreq_usec)