diff options
-rw-r--r-- | src/modules/alsa/alsa-sink.c | 8 | ||||
-rw-r--r-- | src/modules/alsa/alsa-source.c | 8 | ||||
-rw-r--r-- | src/modules/alsa/alsa-util.c | 57 | ||||
-rw-r--r-- | src/modules/alsa/alsa-util.h | 4 |
4 files changed, 63 insertions, 14 deletions
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 2745a14e..784a8dd5 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -1508,6 +1508,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca size_t frame_size; pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE; pa_sink_new_data data; + char *control_device = NULL; pa_assert(m); pa_assert(ma); @@ -1664,7 +1665,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca /* ALSA might tweak the sample spec, so recalculate the frame size */ frame_size = pa_frame_size(&ss); - pa_alsa_find_mixer_and_elem(u->pcm_handle, &u->mixer_handle, &u->mixer_elem, pa_modargs_get_value(ma, "control", NULL), profile); + pa_alsa_find_mixer_and_elem(u->pcm_handle, &control_device, &u->mixer_handle, &u->mixer_elem, pa_modargs_get_value(ma, "control", NULL), profile); pa_sink_new_data_init(&data); data.driver = driver; @@ -1687,6 +1688,11 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca pa_alsa_init_description(data.proplist); + if (control_device) { + pa_alsa_init_proplist_ctl(data.proplist, control_device); + pa_xfree(control_device); + } + u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY|(u->use_tsched ? PA_SINK_DYNAMIC_LATENCY : 0)); pa_sink_new_data_done(&data); diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index af567c90..780da831 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -1366,6 +1366,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p size_t frame_size; pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE; pa_source_new_data data; + char *control_device = NULL; pa_assert(m); pa_assert(ma); @@ -1519,7 +1520,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p /* ALSA might tweak the sample spec, so recalculate the frame size */ frame_size = pa_frame_size(&ss); - pa_alsa_find_mixer_and_elem(u->pcm_handle, &u->mixer_handle, &u->mixer_elem, pa_modargs_get_value(ma, "control", NULL), profile); + pa_alsa_find_mixer_and_elem(u->pcm_handle, &control_device, &u->mixer_handle, &u->mixer_elem, pa_modargs_get_value(ma, "control", NULL), profile); pa_source_new_data_init(&data); data.driver = driver; @@ -1542,6 +1543,11 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p pa_alsa_init_description(data.proplist); + if (control_device) { + pa_alsa_init_proplist_ctl(data.proplist, control_device); + pa_xfree(control_device); + } + u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY|(u->use_tsched ? PA_SOURCE_DYNAMIC_LATENCY : 0)); pa_source_new_data_done(&data); diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c index 107bec35..17c7c80f 100644 --- a/src/modules/alsa/alsa-util.c +++ b/src/modules/alsa/alsa-util.c @@ -189,15 +189,6 @@ struct pa_alsa_fdlist *pa_alsa_fdlist_new(void) { fdl = pa_xnew0(struct pa_alsa_fdlist, 1); - fdl->num_fds = 0; - fdl->fds = NULL; - fdl->work_fds = NULL; - fdl->mixer = NULL; - fdl->m = NULL; - fdl->defer = NULL; - fdl->ios = NULL; - fdl->polled = FALSE; - return fdl; } @@ -1176,6 +1167,7 @@ success: int pa_alsa_find_mixer_and_elem( snd_pcm_t *pcm, + char **ctl_device, snd_mixer_t **_m, snd_mixer_elem_t **_e, const char *control_name, @@ -1203,9 +1195,13 @@ int pa_alsa_find_mixer_and_elem( /* First, try by name */ if ((dev = snd_pcm_name(pcm))) - if (pa_alsa_prepare_mixer(m, dev) >= 0) + if (pa_alsa_prepare_mixer(m, dev) >= 0) { found = TRUE; + if (ctl_device) + *ctl_device = pa_xstrdup(dev); + } + /* Then, try by card index */ if (!found) { snd_pcm_info_t* info; @@ -1220,9 +1216,15 @@ int pa_alsa_find_mixer_and_elem( md = pa_sprintf_malloc("hw:%i", card_idx); if (!dev || !pa_streq(dev, md)) - if (pa_alsa_prepare_mixer(m, md) >= 0) + if (pa_alsa_prepare_mixer(m, md) >= 0) { found = TRUE; + if (ctl_device) { + *ctl_device = md; + md = NULL; + } + } + pa_xfree(md); } } @@ -1258,6 +1260,9 @@ int pa_alsa_find_mixer_and_elem( } if (!e) { + if (ctl_device) + pa_xfree(*ctl_device); + snd_mixer_close(m); return -1; } @@ -1601,6 +1606,36 @@ void pa_alsa_init_proplist_pcm(pa_core *c, pa_proplist *p, snd_pcm_t *pcm, snd_m pa_alsa_init_proplist_pcm_info(c, p, info); } +void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name) { + int err; + snd_ctl_t *ctl; + snd_ctl_card_info_t *info; + const char *t; + + pa_assert(p); + + snd_ctl_card_info_alloca(&info); + + if ((err = snd_ctl_open(&ctl, name, 0)) < 0) { + pa_log_warn("Error opening low-level control device '%s'", name); + return; + } + + if ((err = snd_ctl_card_info(ctl, info)) < 0) { + pa_log_warn("Control device %s card info: %s", name, snd_strerror(err)); + snd_ctl_close(ctl); + return; + } + + if ((t = snd_ctl_card_info_get_mixername(info))) + pa_proplist_sets(p, "alsa.mixer_name", t); + + if ((t = snd_ctl_card_info_get_components(info))) + pa_proplist_sets(p, "alsa.components", t); + + snd_ctl_close(ctl); +} + int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents) { snd_pcm_state_t state; int err; diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h index 4c5d336d..27f43712 100644 --- a/src/modules/alsa/alsa-util.h +++ b/src/modules/alsa/alsa-util.h @@ -66,7 +66,9 @@ typedef struct pa_alsa_profile_info { int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev); snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback, pa_bool_t playback); -int pa_alsa_find_mixer_and_elem(snd_pcm_t *pcm, snd_mixer_t **_m, snd_mixer_elem_t **_e, const char *control_name, const pa_alsa_profile_info*profile); +int pa_alsa_find_mixer_and_elem(snd_pcm_t *pcm, char **ctl_device, snd_mixer_t **_m, snd_mixer_elem_t **_e, const char *control_name, const pa_alsa_profile_info*profile); + +void pa_alsa_init_proplist_ctl(pa_proplist *p, const char *name); /* Picks a working profile based on the specified ss/map */ snd_pcm_t *pa_alsa_open_by_device_id_auto( |