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);
/* 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;
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);
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);
/* 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;
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);
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;
}
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,
/* 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;
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);
}
}
}
if (!e) {
+ if (ctl_device)
+ pa_xfree(*ctl_device);
+
snd_mixer_close(m);
return -1;
}
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;
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(