summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/modules/alsa/alsa-util.c74
-rw-r--r--src/modules/alsa/alsa-util.h37
-rw-r--r--src/modules/alsa/module-alsa-sink.c18
-rw-r--r--src/modules/alsa/module-alsa-source.c18
4 files changed, 106 insertions, 41 deletions
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index b7f44b85..e154f6ea 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -574,7 +574,7 @@ static const struct pa_alsa_profile_info device_table[] = {
{{ 0, { 0 }}, NULL, NULL, NULL, 0 }
};
-snd_pcm_t *pa_alsa_open_by_device_id(
+snd_pcm_t *pa_alsa_open_by_device_id_auto(
const char *dev_id,
char **dev,
pa_sample_spec *ss,
@@ -585,8 +585,7 @@ snd_pcm_t *pa_alsa_open_by_device_id(
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap,
pa_bool_t *use_tsched,
- const char**config_description,
- const char **config_name) {
+ const pa_alsa_profile_info **profile) {
int i;
int direction = 1;
@@ -642,11 +641,8 @@ snd_pcm_t *pa_alsa_open_by_device_id(
*map = device_table[i].map;
pa_assert(map->channels == ss->channels);
- if (config_description)
- *config_description = device_table[i].description;
- if (config_name)
- *config_name = device_table[i].name;
-
+ if (profile)
+ *profile = &device_table[i];
return pcm_handle;
}
@@ -703,10 +699,64 @@ snd_pcm_t *pa_alsa_open_by_device_id(
pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched, FALSE);
pa_xfree(d);
- if (pcm_handle) {
- *config_description = NULL;
- *config_name = NULL;
- }
+ if (pcm_handle && profile)
+ *profile = NULL;
+
+ return pcm_handle;
+}
+
+snd_pcm_t *pa_alsa_open_by_device_id_profile(
+ const char *dev_id,
+ char **dev,
+ pa_sample_spec *ss,
+ pa_channel_map* map,
+ int mode,
+ uint32_t *nfrags,
+ snd_pcm_uframes_t *period_size,
+ snd_pcm_uframes_t tsched_size,
+ pa_bool_t *use_mmap,
+ pa_bool_t *use_tsched,
+ const pa_alsa_profile_info *profile) {
+
+ char *d;
+ snd_pcm_t *pcm_handle;
+ pa_sample_spec try_ss;
+
+ pa_assert(dev_id);
+ pa_assert(dev);
+ pa_assert(ss);
+ pa_assert(map);
+ pa_assert(nfrags);
+ pa_assert(period_size);
+ pa_assert(profile);
+
+ d = pa_sprintf_malloc("%s:%s", profile->alsa_name, dev_id);
+
+ try_ss.channels = profile->map.channels;
+ try_ss.rate = ss->rate;
+ try_ss.format = ss->format;
+
+ pcm_handle = pa_alsa_open_by_device_string(
+ d,
+ dev,
+ &try_ss,
+ map,
+ mode,
+ nfrags,
+ period_size,
+ tsched_size,
+ use_mmap,
+ use_tsched,
+ TRUE);
+
+ pa_xfree(d);
+
+ if (!pcm_handle)
+ return NULL;
+
+ *ss = try_ss;
+ *map = profile->map;
+ pa_assert(map->channels == ss->channels);
return pcm_handle;
}
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 59656252..18b04028 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -54,7 +54,16 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min);
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);
-snd_pcm_t *pa_alsa_open_by_device_id(
+typedef struct pa_alsa_profile_info {
+ pa_channel_map map;
+ const char *alsa_name;
+ const char *description;
+ const char *name;
+ unsigned priority;
+} pa_alsa_profile_info;
+
+/* Picks a working profile based on the specified ss/map */
+snd_pcm_t *pa_alsa_open_by_device_id_auto(
const char *dev_id,
char **dev,
pa_sample_spec *ss,
@@ -65,9 +74,23 @@ snd_pcm_t *pa_alsa_open_by_device_id(
snd_pcm_uframes_t tsched_size,
pa_bool_t *use_mmap,
pa_bool_t *use_tsched,
- const char **config_name,
- const char **config_description);
+ const pa_alsa_profile_info **profile);
+/* Uses the specified profile */
+snd_pcm_t *pa_alsa_open_by_device_id_profile(
+ const char *dev_id,
+ char **dev,
+ pa_sample_spec *ss,
+ pa_channel_map* map,
+ int mode,
+ uint32_t *nfrags,
+ snd_pcm_uframes_t *period_size,
+ snd_pcm_uframes_t tsched_size,
+ pa_bool_t *use_mmap,
+ pa_bool_t *use_tsched,
+ const pa_alsa_profile_info *profile);
+
+/* Opens the explicit ALSA device */
snd_pcm_t *pa_alsa_open_by_device_string(
const char *device,
char **dev,
@@ -81,14 +104,6 @@ snd_pcm_t *pa_alsa_open_by_device_string(
pa_bool_t *use_tsched,
pa_bool_t require_exact_channel_number);
-typedef struct pa_alsa_profile_info {
- pa_channel_map map;
- const char *alsa_name;
- const char *description;
- const char *name;
- unsigned priority;
-} pa_alsa_profile_info;
-
int pa_alsa_probe_profiles(
const char *dev_id,
const pa_sample_spec *ss,
diff --git a/src/modules/alsa/module-alsa-sink.c b/src/modules/alsa/module-alsa-sink.c
index 62ce89cb..12d34077 100644
--- a/src/modules/alsa/module-alsa-sink.c
+++ b/src/modules/alsa/module-alsa-sink.c
@@ -1253,7 +1253,7 @@ int pa__init(pa_module*m) {
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
pa_usec_t usec;
pa_sink_new_data data;
- const char *profile_description = NULL, *profile_name = NULL;
+ const pa_alsa_profile_info *profile = NULL;
snd_pcm_info_alloca(&pcm_info);
@@ -1332,13 +1332,13 @@ int pa__init(pa_module*m) {
if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
- if (!(u->pcm_handle = pa_alsa_open_by_device_id(
+ if (!(u->pcm_handle = pa_alsa_open_by_device_id_auto(
dev_id,
&u->device_name,
&ss, &map,
SND_PCM_STREAM_PLAYBACK,
&nfrags, &period_frames, tsched_frames,
- &b, &d, &profile_description, &profile_name)))
+ &b, &d, &profile)))
goto fail;
@@ -1358,8 +1358,8 @@ int pa__init(pa_module*m) {
pa_assert(u->device_name);
pa_log_info("Successfully opened device %s.", u->device_name);
- if (profile_description)
- pa_log_info("Selected configuration '%s' (%s).", profile_description, profile_name);
+ if (profile)
+ pa_log_info("Selected configuration '%s' (%s).", profile->description, profile->name);
if (use_mmap && !b) {
pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
@@ -1444,10 +1444,10 @@ int pa__init(pa_module*m) {
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
- if (profile_name)
- pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_NAME, profile_name);
- if (profile_description)
- pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile_description);
+ if (profile) {
+ pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_NAME, profile->name);
+ pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile->description);
+ }
u->sink = pa_sink_new(m->core, &data, PA_SINK_HARDWARE|PA_SINK_LATENCY);
pa_sink_new_data_done(&data);
diff --git a/src/modules/alsa/module-alsa-source.c b/src/modules/alsa/module-alsa-source.c
index 7ca305f5..08ef12fa 100644
--- a/src/modules/alsa/module-alsa-source.c
+++ b/src/modules/alsa/module-alsa-source.c
@@ -1087,7 +1087,7 @@ int pa__init(pa_module*m) {
pa_bool_t namereg_fail;
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d;
pa_source_new_data data;
- const char *profile_description = NULL, *profile_name = NULL;
+ const pa_alsa_profile_info *profile = NULL;
snd_pcm_info_alloca(&pcm_info);
@@ -1161,13 +1161,13 @@ int pa__init(pa_module*m) {
if ((dev_id = pa_modargs_get_value(ma, "device_id", NULL))) {
- if (!(u->pcm_handle = pa_alsa_open_by_device_id(
+ if (!(u->pcm_handle = pa_alsa_open_by_device_id_auto(
dev_id,
&u->device_name,
&ss, &map,
SND_PCM_STREAM_CAPTURE,
&nfrags, &period_frames, tsched_frames,
- &b, &d, &profile_description, &profile_name)))
+ &b, &d, &profile)))
goto fail;
} else {
@@ -1185,8 +1185,8 @@ int pa__init(pa_module*m) {
pa_assert(u->device_name);
pa_log_info("Successfully opened device %s.", u->device_name);
- if (profile_description)
- pa_log_info("Selected configuration '%s' (%s).", profile_description, profile_name);
+ if (profile)
+ pa_log_info("Selected configuration '%s' (%s).", profile->description, profile->name);
if (use_mmap && !b) {
pa_log_info("Device doesn't support mmap(), falling back to UNIX read/write mode.");
@@ -1271,10 +1271,10 @@ int pa__init(pa_module*m) {
pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_FRAGMENT_SIZE, "%lu", (unsigned long) (period_frames * frame_size));
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_ACCESS_MODE, u->use_tsched ? "mmap+timer" : (u->use_mmap ? "mmap" : "serial"));
- if (profile_name)
- pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_NAME, profile_name);
- if (profile_description)
- pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile_description);
+ if (profile) {
+ pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_NAME, profile->name);
+ pa_proplist_sets(data.proplist, PA_PROP_DEVICE_PROFILE_DESCRIPTION, profile->description);
+ }
u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY);
pa_source_new_data_done(&data);