diff options
Diffstat (limited to 'src/modules/alsa')
-rw-r--r-- | src/modules/alsa/alsa-sink.c | 65 | ||||
-rw-r--r-- | src/modules/alsa/alsa-sink.h | 2 | ||||
-rw-r--r-- | src/modules/alsa/alsa-source.c | 37 | ||||
-rw-r--r-- | src/modules/alsa/alsa-source.h | 2 | ||||
-rw-r--r-- | src/modules/alsa/alsa-util.c | 44 | ||||
-rw-r--r-- | src/modules/alsa/alsa-util.h | 3 | ||||
-rw-r--r-- | src/modules/alsa/module-alsa-card.c | 8 | ||||
-rw-r--r-- | src/modules/alsa/module-alsa-sink.c | 2 | ||||
-rw-r--r-- | src/modules/alsa/module-alsa-source.c | 2 |
9 files changed, 109 insertions, 56 deletions
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index dbd95b63..7bf16c3c 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -6,7 +6,7 @@ PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but @@ -61,10 +61,11 @@ /* #define DEBUG_TIMING */ #define DEFAULT_DEVICE "default" -#define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC) /* 2s */ -#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC) /* 20ms */ -#define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */ -#define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms */ +#define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC) /* 2s -- Overall buffer size */ +#define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC) /* 20ms -- Fill up when only this much is left in the buffer */ +#define TSCHED_WATERMARK_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms -- On underrun, increase watermark by this */ +#define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms -- Sleep at least 10ms on each iteration */ +#define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms -- Wakeup at least this long before the buffer runs empty*/ struct userdata { pa_core *core; @@ -86,7 +87,16 @@ struct userdata { pa_bool_t mixer_seperate_channels:1; pa_cvolume hardware_volume; - size_t frame_size, fragment_size, hwbuf_size, tsched_watermark, hwbuf_unused, min_sleep, min_wakeup; + size_t + frame_size, + fragment_size, + hwbuf_size, + tsched_watermark, + hwbuf_unused, + min_sleep, + min_wakeup, + watermark_step; + unsigned nfragments; pa_memchunk memchunk; @@ -138,7 +148,7 @@ static void reserve_update(struct userdata *u) { const char *description; pa_assert(u); - if (!u->sink) + if (!u->sink || !u->reserve) return; if ((description = pa_proplist_gets(u->sink->proplist, PA_PROP_DEVICE_DESCRIPTION))) @@ -154,6 +164,9 @@ static int reserve_init(struct userdata *u, const char *dname) { if (u->reserve) return 0; + if (pa_in_system_mode()) + return 0; + /* We are resuming, try to lock the device */ if (!(rname = pa_alsa_get_reserve_name(dname))) return 0; @@ -205,10 +218,11 @@ static void adjust_after_underrun(struct userdata *u) { pa_usec_t old_min_latency, new_min_latency; pa_assert(u); + pa_assert(u->use_tsched); /* First, just try to increase the watermark */ old_watermark = u->tsched_watermark; - u->tsched_watermark *= 2; + u->tsched_watermark = PA_MIN(u->tsched_watermark * 2, u->tsched_watermark + u->watermark_step); fix_tsched_watermark(u); if (old_watermark != u->tsched_watermark) { @@ -219,7 +233,8 @@ static void adjust_after_underrun(struct userdata *u) { /* Hmm, we cannot increase the watermark any further, hence let's raise the latency */ old_min_latency = u->sink->thread_info.min_latency; - new_min_latency = PA_MIN(old_min_latency * 2, u->sink->thread_info.max_latency); + new_min_latency = PA_MIN(old_min_latency * 2, old_min_latency + TSCHED_WATERMARK_STEP_USEC); + new_min_latency = PA_MIN(new_min_latency, u->sink->thread_info.max_latency); if (old_min_latency != new_min_latency) { pa_log_notice("Increasing minimal latency to %0.2f ms", @@ -1175,17 +1190,11 @@ static int process_rewind(struct userdata *u) { /* Figure out how much we shall rewind and reset the counter */ rewind_nbytes = u->sink->thread_info.rewind_nbytes; - u->sink->thread_info.rewind_nbytes = 0; - if (rewind_nbytes <= 0) - goto finish; - - pa_assert(rewind_nbytes > 0); pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes); - snd_pcm_hwsync(u->pcm_handle); - if ((unused = snd_pcm_avail_update(u->pcm_handle)) < 0) { - pa_log("snd_pcm_avail_update() failed: %s", snd_strerror((int) unused)); + if (PA_UNLIKELY((unused = pa_alsa_safe_avail(u->pcm_handle, u->hwbuf_size, &u->sink->sample_spec)) < 0)) { + pa_log("snd_pcm_avail() failed: %s", snd_strerror((int) unused)); return -1; } @@ -1227,12 +1236,8 @@ static int process_rewind(struct userdata *u) { } else pa_log_debug("Mhmm, actually there is nothing to rewind."); -finish: - pa_sink_process_rewind(u->sink, 0); - return 0; - } static void thread_func(void *userdata) { @@ -1261,7 +1266,7 @@ static void thread_func(void *userdata) { int work_done; pa_usec_t sleep_usec = 0; - if (u->sink->thread_info.rewind_requested) + if (PA_UNLIKELY(u->sink->thread_info.rewind_requested)) if (process_rewind(u) < 0) goto fail; @@ -1484,7 +1489,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca struct userdata *u = NULL; const char *dev_id = NULL; - pa_sample_spec ss; + pa_sample_spec ss, requested_ss; pa_channel_map map; uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark; snd_pcm_uframes_t period_frames, tsched_frames; @@ -1503,6 +1508,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca goto fail; } + requested_ss = ss; frame_size = pa_frame_size(&ss); nfrags = m->core->default_n_fragments; @@ -1654,6 +1660,8 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile->description); } + pa_alsa_init_description(data.proplist); + u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY); pa_sink_new_data_done(&data); @@ -1674,19 +1682,20 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size); u->nfragments = nfrags; u->hwbuf_size = u->fragment_size * nfrags; - u->tsched_watermark = tsched_watermark; + u->tsched_watermark = pa_usec_to_bytes_round_up(pa_bytes_to_usec_round_up(tsched_watermark, &requested_ss), &u->sink->sample_spec); pa_cvolume_mute(&u->hardware_volume, u->sink->sample_spec.channels); if (use_tsched) { fix_min_sleep_wakeup(u); fix_tsched_watermark(u); - } - u->sink->thread_info.max_rewind = use_tsched ? u->hwbuf_size : 0; - u->sink->thread_info.max_request = u->hwbuf_size; + u->watermark_step = pa_usec_to_bytes(TSCHED_WATERMARK_STEP_USEC, &u->sink->sample_spec); + } + pa_sink_set_max_rewind(u->sink, use_tsched ? u->hwbuf_size : 0); + pa_sink_set_max_request(u->sink, u->hwbuf_size); pa_sink_set_latency_range(u->sink, - !use_tsched ? pa_bytes_to_usec(u->hwbuf_size, &ss) : (pa_usec_t) -1, + use_tsched ? (pa_usec_t) -1 : pa_bytes_to_usec(u->hwbuf_size, &ss), pa_bytes_to_usec(u->hwbuf_size, &ss)); pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms", diff --git a/src/modules/alsa/alsa-sink.h b/src/modules/alsa/alsa-sink.h index 47ece9e0..bbf64234 100644 --- a/src/modules/alsa/alsa-sink.h +++ b/src/modules/alsa/alsa-sink.h @@ -9,7 +9,7 @@ PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index 39df4a91..f4acad8c 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -6,7 +6,7 @@ PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but @@ -64,6 +64,7 @@ #define DEFAULT_DEVICE "default" #define DEFAULT_TSCHED_BUFFER_USEC (2*PA_USEC_PER_SEC) /* 2s */ #define DEFAULT_TSCHED_WATERMARK_USEC (20*PA_USEC_PER_MSEC) /* 20ms */ +#define TSCHED_WATERMARK_STEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */ #define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms */ #define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms */ @@ -88,7 +89,16 @@ struct userdata { pa_cvolume hardware_volume; - size_t frame_size, fragment_size, hwbuf_size, tsched_watermark, hwbuf_unused, min_sleep, min_wakeup; + size_t + frame_size, + fragment_size, + hwbuf_size, + tsched_watermark, + hwbuf_unused, + min_sleep, + min_wakeup, + watermark_step; + unsigned nfragments; char *device_name; @@ -136,7 +146,7 @@ static void reserve_update(struct userdata *u) { const char *description; pa_assert(u); - if (!u->source) + if (!u->source || !u->reserve) return; if ((description = pa_proplist_gets(u->source->proplist, PA_PROP_DEVICE_DESCRIPTION))) @@ -152,6 +162,9 @@ static int reserve_init(struct userdata *u, const char *dname) { if (u->reserve) return 0; + if (pa_in_system_mode()) + return 0; + /* We are resuming, try to lock the device */ if (!(rname = pa_alsa_get_reserve_name(dname))) return 0; @@ -202,10 +215,12 @@ static void adjust_after_overrun(struct userdata *u) { pa_usec_t old_min_latency, new_min_latency; pa_assert(u); + pa_assert(u->use_tsched); /* First, just try to increase the watermark */ old_watermark = u->tsched_watermark; - u->tsched_watermark *= 2; + u->tsched_watermark = PA_MIN(u->tsched_watermark * 2, u->tsched_watermark + u->watermark_step); + fix_tsched_watermark(u); if (old_watermark != u->tsched_watermark) { @@ -216,7 +231,8 @@ static void adjust_after_overrun(struct userdata *u) { /* Hmm, we cannot increase the watermark any further, hence let's raise the latency */ old_min_latency = u->source->thread_info.min_latency; - new_min_latency = PA_MIN(old_min_latency * 2, u->source->thread_info.max_latency); + new_min_latency = PA_MIN(old_min_latency * 2, old_min_latency + TSCHED_WATERMARK_STEP_USEC); + new_min_latency = PA_MIN(new_min_latency, u->source->thread_info.max_latency); if (old_min_latency != new_min_latency) { pa_log_notice("Increasing minimal latency to %0.2f ms", @@ -1331,7 +1347,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p struct userdata *u = NULL; const char *dev_id = NULL; - pa_sample_spec ss; + pa_sample_spec ss, requested_ss; pa_channel_map map; uint32_t nfrags, hwbuf_size, frag_size, tsched_size, tsched_watermark; snd_pcm_uframes_t period_frames, tsched_frames; @@ -1349,6 +1365,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p goto fail; } + requested_ss = ss; frame_size = pa_frame_size(&ss); nfrags = m->core->default_n_fragments; @@ -1495,6 +1512,8 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile->description); } + pa_alsa_init_description(data.proplist); + u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY); pa_source_new_data_done(&data); @@ -1515,16 +1534,18 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p u->fragment_size = frag_size = (uint32_t) (period_frames * frame_size); u->nfragments = nfrags; u->hwbuf_size = u->fragment_size * nfrags; - u->tsched_watermark = tsched_watermark; + u->tsched_watermark = pa_usec_to_bytes_round_up(pa_bytes_to_usec_round_up(tsched_watermark, &requested_ss), &u->source->sample_spec); pa_cvolume_mute(&u->hardware_volume, u->source->sample_spec.channels); if (use_tsched) { fix_min_sleep_wakeup(u); fix_tsched_watermark(u); + + u->watermark_step = pa_usec_to_bytes(TSCHED_WATERMARK_STEP_USEC, &u->source->sample_spec); } pa_source_set_latency_range(u->source, - !use_tsched ? pa_bytes_to_usec(u->hwbuf_size, &ss) : (pa_usec_t) -1, + use_tsched ? (pa_usec_t) -1 : pa_bytes_to_usec(u->hwbuf_size, &ss), pa_bytes_to_usec(u->hwbuf_size, &ss)); pa_log_info("Using %u fragments of size %lu bytes, buffer time is %0.2fms", diff --git a/src/modules/alsa/alsa-source.h b/src/modules/alsa/alsa-source.h index 5fed6cc8..9cbb0e17 100644 --- a/src/modules/alsa/alsa-source.h +++ b/src/modules/alsa/alsa-source.h @@ -9,7 +9,7 @@ PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c index 6740c069..454cfd4e 100644 --- a/src/modules/alsa/alsa-util.c +++ b/src/modules/alsa/alsa-util.c @@ -6,7 +6,7 @@ PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but @@ -47,6 +47,10 @@ #include "hal-util.h" #endif +#ifdef HAVE_UDEV +#include "udev-util.h" +#endif + struct pa_alsa_fdlist { unsigned num_fds; struct pollfd *fds; @@ -1362,6 +1366,26 @@ void pa_alsa_redirect_errors_dec(void) { snd_lib_error_set_handler(NULL); } +pa_bool_t pa_alsa_init_description(pa_proplist *p) { + const char *s; + pa_assert(p); + + if (pa_device_init_description(p)) + return TRUE; + + if ((s = pa_proplist_gets(p, "alsa.card_name"))) { + pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s); + return TRUE; + } + + if ((s = pa_proplist_gets(p, "alsa.name"))) { + pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, s); + return TRUE; + } + + return FALSE; +} + void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) { char *cn, *lcn, *dn; @@ -1385,6 +1409,10 @@ void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card) { pa_xfree(dn); } +#ifdef HAVE_UDEV + pa_udev_get_info(c, p, card); +#endif + #ifdef HAVE_HAL pa_hal_get_info(c, p, card); #endif @@ -1411,7 +1439,7 @@ void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t * snd_pcm_class_t class; snd_pcm_subclass_t subclass; - const char *n, *id, *sdn, *cn = NULL; + const char *n, *id, *sdn; int card; pa_assert(p); @@ -1426,6 +1454,7 @@ void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t * if (alsa_class_table[class]) pa_proplist_sets(p, "alsa.class", alsa_class_table[class]); } + subclass = snd_pcm_info_get_subclass(pcm_info); if (subclass <= SND_PCM_SUBCLASS_LAST) if (alsa_subclass_table[subclass]) @@ -1443,17 +1472,8 @@ void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t * pa_proplist_setf(p, "alsa.device", "%u", snd_pcm_info_get_device(pcm_info)); - if ((card = snd_pcm_info_get_card(pcm_info)) >= 0) { + if ((card = snd_pcm_info_get_card(pcm_info)) >= 0) pa_alsa_init_proplist_card(c, p, card); - cn = pa_proplist_gets(p, "alsa.card_name"); - } - - if (cn && n && !strstr(cn, n) && !strstr(n, cn)) - pa_proplist_setf(p, PA_PROP_DEVICE_DESCRIPTION, "%s, %s", cn, n); - else if (cn && (!n || strstr(cn, n))) - pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, cn); - else if (n) - pa_proplist_sets(p, PA_PROP_DEVICE_DESCRIPTION, n); } void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm) { diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h index 899532e2..fe0f71e0 100644 --- a/src/modules/alsa/alsa-util.h +++ b/src/modules/alsa/alsa-util.h @@ -9,7 +9,7 @@ PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but @@ -123,6 +123,7 @@ void pa_alsa_redirect_errors_dec(void); void pa_alsa_init_proplist_pcm_info(pa_core *c, pa_proplist *p, snd_pcm_info_t *pcm_info); void pa_alsa_init_proplist_card(pa_core *c, pa_proplist *p, int card); void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm); +pa_bool_t pa_alsa_init_description(pa_proplist *p); int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents); diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index fc6b886b..d5e2cdc2 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -5,7 +5,7 @@ PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but @@ -310,14 +310,16 @@ int pa__init(pa_module *m) { pa_snprintf(rname, sizeof(rname), "Audio%i", alsa_card_index); - if (!(reserve = pa_reserve_wrapper_get(m->core, rname))) - goto fail; + if (!pa_in_system_mode()) + if (!(reserve = pa_reserve_wrapper_get(m->core, rname))) + goto fail; pa_card_new_data_init(&data); data.driver = __FILE__; data.module = m; pa_alsa_init_proplist_card(m->core, data.proplist, alsa_card_index); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, u->device_id); + pa_alsa_init_description(data.proplist); set_card_name(&data, ma, u->device_id); if (reserve) diff --git a/src/modules/alsa/module-alsa-sink.c b/src/modules/alsa/module-alsa-sink.c index 4f844e08..c728a446 100644 --- a/src/modules/alsa/module-alsa-sink.c +++ b/src/modules/alsa/module-alsa-sink.c @@ -6,7 +6,7 @@ PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but diff --git a/src/modules/alsa/module-alsa-source.c b/src/modules/alsa/module-alsa-source.c index c35936df..6188019f 100644 --- a/src/modules/alsa/module-alsa-source.c +++ b/src/modules/alsa/module-alsa-source.c @@ -6,7 +6,7 @@ PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation; either version 2 of the License, + by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. PulseAudio is distributed in the hope that it will be useful, but |