pa_usec_t watermark_dec_not_before;
pa_usec_t min_latency_ref;
+ pa_usec_t tsched_watermark_usec;
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, fixed_latency_range:1;
+ bool use_mmap:1, use_tsched:1, deferred_volume:1, fixed_latency_range:1;
- pa_bool_t first;
+ bool first;
pa_rtpoll_item *alsa_rtpoll_item;
pa_assert(r);
pa_assert(u);
- if (pa_source_suspend(u->source, TRUE, PA_SUSPEND_APPLICATION) < 0)
+ pa_log_debug("Suspending source %s, because another application requested us to release the device.", u->source->name);
+
+ if (pa_source_suspend(u->source, true, PA_SUSPEND_APPLICATION) < 0)
return PA_HOOK_CANCEL;
return PA_HOOK_OK;
}
static pa_hook_result_t monitor_cb(pa_reserve_monitor_wrapper *w, void* busy, struct userdata *u) {
- pa_bool_t b;
-
pa_assert(w);
pa_assert(u);
- b = PA_PTR_TO_UINT(busy) && !u->reserve;
+ if (PA_PTR_TO_UINT(busy) && !u->reserve) {
+ pa_log_debug("Suspending source %s, because another application is blocking the access to the device.", u->source->name);
+ pa_source_suspend(u->source, true, PA_SUSPEND_APPLICATION);
+ } else {
+ pa_log_debug("Resuming source %s, because other applications aren't blocking access to the device any more.", u->source->name);
+ pa_source_suspend(u->source, false, PA_SUSPEND_APPLICATION);
+ }
- pa_source_suspend(u->source, b, PA_SUSPEND_APPLICATION);
return PA_HOOK_OK;
}
if (u->tsched_watermark < u->min_wakeup)
u->tsched_watermark = u->min_wakeup;
+
+ u->tsched_watermark_usec = pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec);
}
static void increase_watermark(struct userdata *u) {
if (old_watermark != u->tsched_watermark) {
pa_log_info("Increasing wakeup watermark to %0.2f ms",
- (double) pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec) / PA_USEC_PER_MSEC);
+ (double) u->tsched_watermark_usec / PA_USEC_PER_MSEC);
return;
}
if (old_watermark != u->tsched_watermark)
pa_log_info("Decreasing wakeup watermark to %0.2f ms",
- (double) pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec) / PA_USEC_PER_MSEC);
+ (double) u->tsched_watermark_usec / PA_USEC_PER_MSEC);
/* We don't change the latency range*/
if (usec == (pa_usec_t) -1)
usec = pa_bytes_to_usec(u->hwbuf_size, &u->source->sample_spec);
- wm = pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec);
+ wm = u->tsched_watermark_usec;
if (wm > usec)
wm = usec/2;
return -1;
}
- u->first = TRUE;
+ u->first = true;
return 0;
}
-static size_t check_left_to_record(struct userdata *u, size_t n_bytes, pa_bool_t on_timeout) {
+static size_t check_left_to_record(struct userdata *u, size_t n_bytes, bool on_timeout) {
size_t left_to_record;
size_t rec_space = u->hwbuf_size - u->hwbuf_unused;
- pa_bool_t overrun = FALSE;
+ bool overrun = false;
/* We use <= instead of < for this check here because an overrun
* only happens after the last sample was processed, not already when
/* We got a dropout. What a mess! */
left_to_record = 0;
- overrun = TRUE;
+ overrun = true;
#ifdef DEBUG_TIMING
PA_DEBUG_TRAP;
#endif
if (u->use_tsched) {
- pa_bool_t reset_not_before = TRUE;
+ bool reset_not_before = true;
if (overrun || left_to_record < u->watermark_inc_threshold)
increase_watermark(u);
else if (left_to_record > u->watermark_dec_threshold) {
- reset_not_before = FALSE;
+ reset_not_before = false;
/* We decrease the watermark only if have actually
* been woken up by a timeout. If something else woke
return left_to_record;
}
-static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled, pa_bool_t on_timeout) {
- pa_bool_t work_done = FALSE;
+static int mmap_read(struct userdata *u, pa_usec_t *sleep_usec, bool polled, bool on_timeout) {
+ bool work_done = false;
pa_usec_t max_sleep_usec = 0, process_usec = 0;
size_t left_to_record;
unsigned j = 0;
snd_pcm_sframes_t n;
size_t n_bytes;
int r;
- pa_bool_t after_avail = TRUE;
+ bool after_avail = true;
if (PA_UNLIKELY((n = pa_alsa_safe_avail(u->pcm_handle, u->hwbuf_size, &u->source->sample_spec)) < 0)) {
#endif
left_to_record = check_left_to_record(u, n_bytes, on_timeout);
- on_timeout = FALSE;
+ on_timeout = false;
if (u->use_tsched)
if (!polled &&
break;
}
-
if (++j > 10) {
#ifdef DEBUG_TIMING
pa_log_debug("Not filling up, because already too many iterations.");
break;
}
- polled = FALSE;
+ polled = false;
#ifdef DEBUG_TIMING
pa_log_debug("Reading");
break;
pa_assert(frames > 0);
- after_avail = FALSE;
+ after_avail = false;
/* Check these are multiples of 8 bit */
pa_assert((areas[0].first & 7) == 0);
p = (uint8_t*) areas[0].addr + (offset * u->frame_size);
- chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, TRUE);
+ chunk.memblock = pa_memblock_new_fixed(u->core->mempool, p, frames * u->frame_size, true);
chunk.length = pa_memblock_get_length(chunk.memblock);
chunk.index = 0;
return r;
}
- work_done = TRUE;
+ work_done = true;
u->read_count += frames * u->frame_size;
if (u->use_tsched) {
*sleep_usec = pa_bytes_to_usec(left_to_record, &u->source->sample_spec);
- process_usec = pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec);
+ process_usec = u->tsched_watermark_usec;
if (*sleep_usec > process_usec)
*sleep_usec -= process_usec;
return work_done ? 1 : 0;
}
-static int unix_read(struct userdata *u, pa_usec_t *sleep_usec, pa_bool_t polled, pa_bool_t on_timeout) {
- int work_done = FALSE;
+static int unix_read(struct userdata *u, pa_usec_t *sleep_usec, bool polled, bool on_timeout) {
+ int work_done = false;
pa_usec_t max_sleep_usec = 0, process_usec = 0;
size_t left_to_record;
unsigned j = 0;
snd_pcm_sframes_t n;
size_t n_bytes;
int r;
- pa_bool_t after_avail = TRUE;
+ bool after_avail = true;
if (PA_UNLIKELY((n = pa_alsa_safe_avail(u->pcm_handle, u->hwbuf_size, &u->source->sample_spec)) < 0)) {
n_bytes = (size_t) n * u->frame_size;
left_to_record = check_left_to_record(u, n_bytes, on_timeout);
- on_timeout = FALSE;
+ on_timeout = false;
if (u->use_tsched)
if (!polled &&
break;
}
- polled = FALSE;
+ polled = false;
for (;;) {
void *p;
}
pa_assert(frames > 0);
- after_avail = FALSE;
+ after_avail = false;
chunk.index = 0;
chunk.length = (size_t) frames * u->frame_size;
pa_source_post(u->source, &chunk);
pa_memblock_unref(chunk.memblock);
- work_done = TRUE;
+ work_done = true;
u->read_count += frames * u->frame_size;
if (u->use_tsched) {
*sleep_usec = pa_bytes_to_usec(left_to_record, &u->source->sample_spec);
- process_usec = pa_bytes_to_usec(u->tsched_watermark, &u->source->sample_spec);
+ process_usec = u->tsched_watermark_usec;
if (*sleep_usec > process_usec)
*sleep_usec -= process_usec;
int err;
pa_usec_t now1 = 0, now2;
snd_pcm_status_t *status;
+ snd_htimestamp_t htstamp = { 0, 0 };
snd_pcm_status_alloca(&status);
/* Let's update the time smoother */
- if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, &delay, u->hwbuf_size, &u->source->sample_spec, TRUE)) < 0)) {
+ if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, status, &delay, u->hwbuf_size, &u->source->sample_spec, true)) < 0)) {
pa_log_warn("Failed to get delay: %s", pa_alsa_strerror(err));
return;
}
- if (PA_UNLIKELY((err = snd_pcm_status(u->pcm_handle, status)) < 0))
- pa_log_warn("Failed to get timestamp: %s", pa_alsa_strerror(err));
- else {
- snd_htimestamp_t htstamp = { 0, 0 };
- snd_pcm_status_get_htstamp(status, &htstamp);
- now1 = pa_timespec_load(&htstamp);
- }
+ snd_pcm_status_get_htstamp(status, &htstamp);
+ now1 = pa_timespec_load(&htstamp);
/* Hmm, if the timestamp is 0, then it wasn't set and we take the current time */
if (now1 <= 0)
/* Called from IO Context on unsuspend or from main thread when creating source */
static void reset_watermark(struct userdata *u, size_t tsched_watermark, pa_sample_spec *ss,
- pa_bool_t in_thread)
-{
+ bool in_thread) {
u->tsched_watermark = pa_usec_to_bytes_round_up(pa_bytes_to_usec_round_up(tsched_watermark, ss),
&u->source->sample_spec);
}
pa_log_info("Time scheduling watermark is %0.2fms",
- (double) pa_bytes_to_usec(u->tsched_watermark, ss) / PA_USEC_PER_MSEC);
+ (double) u->tsched_watermark_usec / PA_USEC_PER_MSEC);
}
/* Called from IO context */
static int unsuspend(struct userdata *u) {
pa_sample_spec ss;
int err;
- pa_bool_t b, d;
+ bool b, d;
snd_pcm_uframes_t period_size, buffer_size;
pa_assert(u);
b = u->use_mmap;
d = u->use_tsched;
- if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &period_size, &buffer_size, 0, &b, &d, TRUE)) < 0) {
+ if ((err = pa_alsa_set_hw_params(u->pcm_handle, &ss, &period_size, &buffer_size, 0, &b, &d, true)) < 0) {
pa_log("Failed to set hardware parameters: %s", pa_alsa_strerror(err));
goto fail;
}
/* FIXME: We need to reload the volume somehow */
u->read_count = 0;
- pa_smoother_reset(u->smoother, pa_rtclock_now(), TRUE);
+ pa_smoother_reset(u->smoother, pa_rtclock_now(), true);
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
u->last_smoother_update = 0;
- u->first = TRUE;
+ u->first = true;
/* reset the watermark to the value defined when source was created */
if (u->use_tsched)
- reset_watermark(u, u->tsched_watermark_ref, &u->source->sample_spec, TRUE);
+ reset_watermark(u, u->tsched_watermark_ref, &u->source->sample_spec, true);
pa_log_info("Resumed successfully...");
return 0;
if (u->source->suspend_cause & PA_SUSPEND_SESSION) {
- pa_source_set_mixer_dirty(u->source, TRUE);
+ pa_source_set_mixer_dirty(u->source, true);
return 0;
}
if (mask & SND_CTL_EVENT_MASK_VALUE) {
- pa_source_get_volume(u->source, TRUE);
- pa_source_get_mute(u->source, TRUE);
+ pa_source_get_volume(u->source, true);
+ pa_source_get_mute(u->source, true);
}
return 0;
return 0;
if (u->source->suspend_cause & PA_SUSPEND_SESSION) {
- pa_source_set_mixer_dirty(u->source, TRUE);
+ pa_source_set_mixer_dirty(u->source, true);
return 0;
}
static void source_get_volume_cb(pa_source *s) {
struct userdata *u = s->userdata;
pa_cvolume r;
- char vol_str_pcnt[PA_CVOLUME_SNPRINT_MAX];
+ char volume_buf[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
pa_assert(u);
pa_assert(u->mixer_path);
/* Shift down by the base volume, so that 0dB becomes maximum volume */
pa_sw_cvolume_multiply_scalar(&r, &r, s->base_volume);
- pa_log_debug("Read hardware volume: %s", pa_cvolume_snprint(vol_str_pcnt, sizeof(vol_str_pcnt), &r));
-
- if (u->mixer_path->has_dB) {
- char vol_str_db[PA_SW_CVOLUME_SNPRINT_DB_MAX];
-
- pa_log_debug(" in dB: %s", pa_sw_cvolume_snprint_dB(vol_str_db, sizeof(vol_str_db), &r));
- }
+ pa_log_debug("Read hardware volume: %s",
+ pa_cvolume_snprint_verbose(volume_buf, sizeof(volume_buf), &r, &s->channel_map, u->mixer_path->has_dB));
if (pa_cvolume_equal(&u->hardware_volume, &r))
return;
static void source_set_volume_cb(pa_source *s) {
struct userdata *u = s->userdata;
pa_cvolume r;
- char vol_str_pcnt[PA_CVOLUME_SNPRINT_MAX];
- pa_bool_t deferred_volume = !!(s->flags & PA_SOURCE_DEFERRED_VOLUME);
+ char volume_buf[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
+ bool deferred_volume = !!(s->flags & PA_SOURCE_DEFERRED_VOLUME);
pa_assert(u);
pa_assert(u->mixer_path);
if (u->mixer_path->has_dB) {
pa_cvolume new_soft_volume;
- pa_bool_t accurate_enough;
- char vol_str_db[PA_SW_CVOLUME_SNPRINT_DB_MAX];
+ bool accurate_enough;
/* Match exactly what the user requested by software */
pa_sw_cvolume_divide(&new_soft_volume, &s->real_volume, &u->hardware_volume);
(pa_cvolume_min(&new_soft_volume) >= (PA_VOLUME_NORM - VOLUME_ACCURACY)) &&
(pa_cvolume_max(&new_soft_volume) <= (PA_VOLUME_NORM + VOLUME_ACCURACY));
- pa_log_debug("Requested volume: %s", pa_cvolume_snprint(vol_str_pcnt, sizeof(vol_str_pcnt), &s->real_volume));
- pa_log_debug(" in dB: %s", pa_sw_cvolume_snprint_dB(vol_str_db, sizeof(vol_str_db), &s->real_volume));
- pa_log_debug("Got hardware volume: %s", pa_cvolume_snprint(vol_str_pcnt, sizeof(vol_str_pcnt), &u->hardware_volume));
- pa_log_debug(" in dB: %s", pa_sw_cvolume_snprint_dB(vol_str_db, sizeof(vol_str_db), &u->hardware_volume));
+ pa_log_debug("Requested volume: %s",
+ pa_cvolume_snprint_verbose(volume_buf, sizeof(volume_buf), &s->real_volume, &s->channel_map, true));
+ pa_log_debug("Got hardware volume: %s",
+ pa_cvolume_snprint_verbose(volume_buf, sizeof(volume_buf), &u->hardware_volume, &s->channel_map, true));
pa_log_debug("Calculated software volume: %s (accurate-enough=%s)",
- pa_cvolume_snprint(vol_str_pcnt, sizeof(vol_str_pcnt), &new_soft_volume),
+ pa_cvolume_snprint_verbose(volume_buf, sizeof(volume_buf), &new_soft_volume, &s->channel_map, true),
pa_yes_no(accurate_enough));
- pa_log_debug(" in dB: %s", pa_sw_cvolume_snprint_dB(vol_str_db, sizeof(vol_str_db), &new_soft_volume));
if (!accurate_enough)
s->soft_volume = new_soft_volume;
} else {
- pa_log_debug("Wrote hardware volume: %s", pa_cvolume_snprint(vol_str_pcnt, sizeof(vol_str_pcnt), &r));
+ pa_log_debug("Wrote hardware volume: %s",
+ pa_cvolume_snprint_verbose(volume_buf, sizeof(volume_buf), &r, &s->channel_map, false));
/* We can't match exactly what the user requested, hence let's
* at least tell the user about it */
/* Shift up by the base volume */
pa_sw_cvolume_divide_scalar(&hw_vol, &hw_vol, s->base_volume);
- if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &hw_vol, TRUE, TRUE) < 0)
+ if (pa_alsa_path_set_volume(u->mixer_path, u->mixer_handle, &s->channel_map, &hw_vol, true, true) < 0)
pa_log_error("Writing HW volume failed");
else {
pa_cvolume tmp_vol;
- pa_bool_t accurate_enough;
+ bool accurate_enough;
/* Shift down by the base volume, so that 0dB becomes maximum volume */
pa_sw_cvolume_multiply_scalar(&hw_vol, &hw_vol, s->base_volume);
(pa_cvolume_max(&tmp_vol) <= (PA_VOLUME_NORM + VOLUME_ACCURACY));
if (!accurate_enough) {
- union {
- char db[2][PA_SW_CVOLUME_SNPRINT_DB_MAX];
- char pcnt[2][PA_CVOLUME_SNPRINT_MAX];
- } vol;
+ char volume_buf[2][PA_CVOLUME_SNPRINT_VERBOSE_MAX];
pa_log_debug("Written HW volume did not match with the request: %s (request) != %s",
- pa_cvolume_snprint(vol.pcnt[0], sizeof(vol.pcnt[0]), &s->thread_info.current_hw_volume),
- pa_cvolume_snprint(vol.pcnt[1], sizeof(vol.pcnt[1]), &hw_vol));
- pa_log_debug(" in dB: %s (request) != %s",
- pa_sw_cvolume_snprint_dB(vol.db[0], sizeof(vol.db[0]), &s->thread_info.current_hw_volume),
- pa_sw_cvolume_snprint_dB(vol.db[1], sizeof(vol.db[1]), &hw_vol));
+ pa_cvolume_snprint_verbose(volume_buf[0],
+ sizeof(volume_buf[0]),
+ &s->thread_info.current_hw_volume,
+ &s->channel_map,
+ true),
+ pa_cvolume_snprint_verbose(volume_buf[1], sizeof(volume_buf[1]), &hw_vol, &s->channel_map, true));
}
}
}
static void source_get_mute_cb(pa_source *s) {
struct userdata *u = s->userdata;
- pa_bool_t b;
+ bool b;
pa_assert(u);
pa_assert(u->mixer_path);
pa_source_set_write_volume_callback(u->source, NULL);
if (u->mixer_path->has_dB) {
- pa_source_enable_decibel_volume(u->source, TRUE);
+ pa_source_enable_decibel_volume(u->source, true);
pa_log_info("Hardware volume ranges from %0.2f dB to %0.2f dB.", u->mixer_path->min_dB, u->mixer_path->max_dB);
u->source->base_volume = pa_sw_volume_from_dB(-u->mixer_path->max_dB);
pa_log_info("Fixing base volume to %0.2f dB", pa_sw_volume_to_dB(u->source->base_volume));
} else {
- pa_source_enable_decibel_volume(u->source, FALSE);
+ pa_source_enable_decibel_volume(u->source, false);
pa_log_info("Hardware volume ranges from %li to %li.", u->mixer_path->min_volume, u->mixer_path->max_volume);
u->source->base_volume = PA_VOLUME_NORM;
pa_assert(p);
pa_assert(u->ucm_context);
- return pa_alsa_ucm_set_port(u->ucm_context, p, FALSE);
+ return pa_alsa_ucm_set_port(u->ucm_context, p, false);
}
static int source_set_port_cb(pa_source *s, pa_device_port *p) {
update_sw_params(u);
}
-static pa_bool_t source_update_rate_cb(pa_source *s, uint32_t rate)
-{
+static int source_update_rate_cb(pa_source *s, uint32_t rate) {
struct userdata *u = s->userdata;
int i;
- pa_bool_t supported = FALSE;
+ bool supported = false;
pa_assert(u);
for (i = 0; u->rates[i]; i++) {
if (u->rates[i] == rate) {
- supported = TRUE;
+ supported = true;
break;
}
}
if (!supported) {
- pa_log_info("Sink does not support sample rate of %d Hz", rate);
- return FALSE;
+ pa_log_info("Source does not support sample rate of %d Hz", rate);
+ return -1;
}
if (!PA_SOURCE_IS_OPENED(s->state)) {
pa_log_info("Updating rate for device %s, new rate is %d", u->device_name, rate);
u->source->sample_spec.rate = rate;
- return TRUE;
+ return 0;
}
- return FALSE;
+ return -1;
}
static void thread_func(void *userdata) {
for (;;) {
int ret;
- pa_usec_t rtpoll_sleep = 0;
+ pa_usec_t rtpoll_sleep = 0, real_sleep;
#ifdef DEBUG_TIMING
pa_log_debug("Loop");
if (PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
int work_done;
pa_usec_t sleep_usec = 0;
- pa_bool_t on_timeout = pa_rtpoll_timer_elapsed(u->rtpoll);
+ bool on_timeout = pa_rtpoll_timer_elapsed(u->rtpoll);
if (u->first) {
pa_log_info("Starting capture.");
snd_pcm_start(u->pcm_handle);
- pa_smoother_resume(u->smoother, pa_rtclock_now(), TRUE);
+ pa_smoother_resume(u->smoother, pa_rtclock_now(), true);
- u->first = FALSE;
+ u->first = false;
}
if (u->use_mmap)
}
}
- if (rtpoll_sleep > 0)
+ if (rtpoll_sleep > 0) {
pa_rtpoll_set_timer_relative(u->rtpoll, rtpoll_sleep);
+ real_sleep = pa_rtclock_now();
+ }
else
pa_rtpoll_set_timer_disabled(u->rtpoll);
/* Hmm, nothing to do. Let's sleep */
- if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
+ if ((ret = pa_rtpoll_run(u->rtpoll, true)) < 0)
goto fail;
+ if (rtpoll_sleep > 0) {
+ real_sleep = pa_rtclock_now() - real_sleep;
+#ifdef DEBUG_TIMING
+ pa_log_debug("Expected sleep: %0.2fms, real sleep: %0.2fms (diff %0.2f ms)",
+ (double) rtpoll_sleep / PA_USEC_PER_MSEC, (double) real_sleep / PA_USEC_PER_MSEC,
+ (double) ((int64_t) real_sleep - (int64_t) rtpoll_sleep) / PA_USEC_PER_MSEC);
+#endif
+ if (u->use_tsched && real_sleep > rtpoll_sleep + u->tsched_watermark_usec)
+ pa_log_info("Scheduling delay of %0.2f ms > %0.2f ms, you might want to investigate this to improve latency...",
+ (double) (real_sleep - rtpoll_sleep) / PA_USEC_PER_MSEC,
+ (double) (u->tsched_watermark_usec) / PA_USEC_PER_MSEC);
+ }
+
if (u->source->flags & PA_SOURCE_DEFERRED_VOLUME)
pa_source_volume_change_apply(u->source, NULL);
if (pa_alsa_recover_from_poll(u->pcm_handle, revents) < 0)
goto fail;
- u->first = TRUE;
+ u->first = true;
revents = 0;
} else if (revents && u->use_tsched && pa_log_ratelimit(PA_LOG_DEBUG))
pa_log_debug("Wakeup from ALSA!");
if ((n = pa_modargs_get_value(ma, "source_name", NULL))) {
pa_source_new_data_set_name(data, n);
- data->namereg_fail = TRUE;
+ data->namereg_fail = true;
return;
}
if ((n = pa_modargs_get_value(ma, "name", NULL)))
- data->namereg_fail = TRUE;
+ data->namereg_fail = true;
else {
n = device_id ? device_id : device_name;
- data->namereg_fail = FALSE;
+ data->namereg_fail = false;
}
if (mapping)
pa_xfree(t);
}
-static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, pa_bool_t ignore_dB) {
+static void find_mixer(struct userdata *u, pa_alsa_mapping *mapping, const char *element, bool ignore_dB) {
snd_hctl_t *hctl;
if (!mapping && !element)
}
}
-static int setup_mixer(struct userdata *u, pa_bool_t ignore_dB) {
- pa_bool_t need_mixer_callback = FALSE;
+static int setup_mixer(struct userdata *u, bool ignore_dB) {
+ bool need_mixer_callback = false;
pa_assert(u);
PA_HASHMAP_FOREACH(p, u->mixer_path_set->paths, state) {
if (p->has_volume || p->has_mute)
- need_mixer_callback = TRUE;
+ need_mixer_callback = true;
}
}
else if (u->mixer_path)
pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, pa_card *card, pa_alsa_mapping *mapping) {
struct userdata *u = NULL;
- const char *dev_id = NULL;
+ const char *dev_id = NULL, *key, *mod_name;
pa_sample_spec ss;
+ char *thread_name = NULL;
uint32_t alternate_sample_rate;
pa_channel_map map;
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, fixed_latency_range = FALSE;
+ bool 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;
+ void *state = NULL;
pa_assert(m);
pa_assert(ma);
ss = m->core->default_sample_spec;
map = m->core->default_channel_map;
+
+ /* Pick sample spec overrides from the mapping, if any */
+ if (mapping) {
+ if (mapping->sample_spec.format != PA_SAMPLE_INVALID)
+ ss.format = mapping->sample_spec.format;
+ if (mapping->sample_spec.rate != 0)
+ ss.rate = mapping->sample_spec.rate;
+ if (mapping->sample_spec.channels != 0) {
+ ss.channels = mapping->sample_spec.channels;
+ if (pa_channel_map_valid(&mapping->channel_map))
+ pa_assert(pa_channel_map_compatible(&mapping->channel_map, &ss));
+ }
+ }
+
+ /* Override with modargs if provided */
if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_ALSA) < 0) {
pa_log("Failed to parse sample specification and channel map");
goto fail;
u->use_tsched = use_tsched;
u->deferred_volume = deferred_volume;
u->fixed_latency_range = fixed_latency_range;
- u->first = TRUE;
+ u->first = true;
u->rtpoll = pa_rtpoll_new();
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
u->smoother = pa_smoother_new(
SMOOTHER_ADJUST_USEC,
SMOOTHER_WINDOW_USEC,
- TRUE,
- TRUE,
+ true,
+ true,
5,
pa_rtclock_now(),
- TRUE);
+ true);
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
/* use ucm */
goto fail;
}
+ if ((mod_name = pa_proplist_gets(mapping->proplist, PA_ALSA_PROP_UCM_MODIFIER))) {
+ if (snd_use_case_set(u->ucm_context->ucm->ucm_mgr, "_enamod", mod_name) < 0)
+ pa_log("Failed to enable ucm modifier %s", mod_name);
+ else
+ pa_log_debug("Enabled ucm modifier %s", mod_name);
+ }
+
if (!(u->pcm_handle = pa_alsa_open_by_device_id_mapping(
dev_id,
&u->device_name,
&ss, &map,
SND_PCM_STREAM_CAPTURE,
&period_frames, &buffer_frames, tsched_frames,
- &b, &d, FALSE)))
+ &b, &d, false)))
goto fail;
}
if (use_mmap && !b) {
pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
- u->use_mmap = use_mmap = FALSE;
+ u->use_mmap = use_mmap = false;
}
if (use_tsched && (!b || !d)) {
pa_log_info("Cannot enable timer-based scheduling, falling back to sound IRQ scheduling.");
- u->use_tsched = use_tsched = FALSE;
+ u->use_tsched = use_tsched = false;
}
if (u->use_mmap)
pa_log_info("Disabling latency range changes on overrun");
}
- u->rates = pa_alsa_get_supported_rates(u->pcm_handle);
+ u->rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
if (!u->rates) {
pa_log_error("Failed to find any supported sample rates.");
goto fail;
if (mapping) {
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_NAME, mapping->name);
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, mapping->description);
+
+ while ((key = pa_proplist_iterate(mapping->proplist, &state)))
+ pa_proplist_sets(data.proplist, key, pa_proplist_gets(mapping->proplist, key));
}
- pa_alsa_init_description(data.proplist);
+ pa_alsa_init_description(data.proplist, card);
if (u->control_device)
pa_alsa_init_proplist_ctl(data.proplist, u->control_device);
}
if (u->ucm_context)
- pa_alsa_ucm_add_ports(&data.ports, data.proplist, u->ucm_context, FALSE, card);
+ pa_alsa_ucm_add_ports(&data.ports, data.proplist, u->ucm_context, false, card);
else if (u->mixer_path_set)
pa_alsa_add_ports(&data, u->mixer_path_set, card);
if (u->use_tsched) {
u->tsched_watermark_ref = tsched_watermark;
- reset_watermark(u, u->tsched_watermark_ref, &ss, FALSE);
+ reset_watermark(u, u->tsched_watermark_ref, &ss, false);
}
else
pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(u->hwbuf_size, &ss));
goto fail;
if (u->ucm_context) {
- if (u->source->active_port && pa_alsa_ucm_set_port(u->ucm_context, u->source->active_port, FALSE) < 0)
+ if (u->source->active_port && pa_alsa_ucm_set_port(u->ucm_context, u->source->active_port, false) < 0)
goto fail;
} else if (setup_mixer(u, ignore_dB) < 0)
goto fail;
pa_alsa_dump(PA_LOG_DEBUG, u->pcm_handle);
- if (!(u->thread = pa_thread_new("alsa-source", thread_func, u))) {
+ thread_name = pa_sprintf_malloc("alsa-source-%s", pa_strnull(pa_proplist_gets(u->source->proplist, "alsa.id")));
+ if (!(u->thread = pa_thread_new(thread_name, thread_func, u))) {
pa_log("Failed to create thread.");
goto fail;
}
+ pa_xfree(thread_name);
+ thread_name = NULL;
/* Get initial mixer settings */
if (data.volume_is_set) {
return u->source;
fail:
+ pa_xfree(thread_name);
if (u)
userdata_free(u);