343 lines
11 KiB
Diff
343 lines
11 KiB
Diff
From 4f2a3cb6019d551ca98aa2034854985df2670a30 Mon Sep 17 00:00:00 2001
|
|
From: Lennart Poettering <lennart@poettering.net>
|
|
Date: Wed, 29 Apr 2009 01:58:18 +0200
|
|
Subject: [PATCH] alsa: allow configuration of fallback device strings in profiles
|
|
|
|
This has the benefit that we can properly support ALSA devices where
|
|
only the raw 'hw' device exists but no 'front' although it's a proper
|
|
2ch stereo device.
|
|
---
|
|
src/modules/alsa/alsa-util.c | 126 +++++++++++++++++++++++++++++------------
|
|
src/modules/alsa/alsa-util.h | 1 +
|
|
2 files changed, 90 insertions(+), 37 deletions(-)
|
|
|
|
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
|
|
index d2dc6e8..2ea0c3d 100644
|
|
--- a/src/modules/alsa/alsa-util.c
|
|
+++ b/src/modules/alsa/alsa-util.c
|
|
@@ -526,7 +526,7 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) {
|
|
|
|
static const struct pa_alsa_profile_info device_table[] = {
|
|
{{ 1, { PA_CHANNEL_POSITION_MONO }},
|
|
- "hw",
|
|
+ "hw", NULL,
|
|
N_("Analog Mono"),
|
|
"analog-mono",
|
|
1,
|
|
@@ -534,7 +534,7 @@ static const struct pa_alsa_profile_info device_table[] = {
|
|
"Capture", "Mic" },
|
|
|
|
{{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
|
|
- "front",
|
|
+ "front", "hw",
|
|
N_("Analog Stereo"),
|
|
"analog-stereo",
|
|
10,
|
|
@@ -542,7 +542,7 @@ static const struct pa_alsa_profile_info device_table[] = {
|
|
"Capture", "Mic" },
|
|
|
|
{{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
|
|
- "iec958",
|
|
+ "iec958", NULL,
|
|
N_("Digital Stereo (IEC958)"),
|
|
"iec958-stereo",
|
|
5,
|
|
@@ -550,7 +550,7 @@ static const struct pa_alsa_profile_info device_table[] = {
|
|
"IEC958 In", NULL },
|
|
|
|
{{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
|
|
- "hdmi",
|
|
+ "hdmi", NULL,
|
|
N_("Digital Stereo (HDMI)"),
|
|
"hdmi-stereo",
|
|
4,
|
|
@@ -559,7 +559,7 @@ static const struct pa_alsa_profile_info device_table[] = {
|
|
|
|
{{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
|
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
|
|
- "surround40",
|
|
+ "surround40", NULL,
|
|
N_("Analog Surround 4.0"),
|
|
"analog-surround-40",
|
|
7,
|
|
@@ -568,7 +568,7 @@ static const struct pa_alsa_profile_info device_table[] = {
|
|
|
|
{{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
|
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
|
|
- "a52",
|
|
+ "a52", NULL,
|
|
N_("Digital Surround 4.0 (IEC958/AC3)"),
|
|
"iec958-ac3-surround-40",
|
|
2,
|
|
@@ -578,7 +578,7 @@ static const struct pa_alsa_profile_info device_table[] = {
|
|
{{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
|
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
|
|
PA_CHANNEL_POSITION_LFE }},
|
|
- "surround41",
|
|
+ "surround41", NULL,
|
|
N_("Analog Surround 4.1"),
|
|
"analog-surround-41",
|
|
7,
|
|
@@ -588,7 +588,7 @@ static const struct pa_alsa_profile_info device_table[] = {
|
|
{{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
|
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
|
|
PA_CHANNEL_POSITION_CENTER }},
|
|
- "surround50",
|
|
+ "surround50", NULL,
|
|
N_("Analog Surround 5.0"),
|
|
"analog-surround-50",
|
|
7,
|
|
@@ -598,7 +598,7 @@ static const struct pa_alsa_profile_info device_table[] = {
|
|
{{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
|
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
|
|
PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE }},
|
|
- "surround51",
|
|
+ "surround51", NULL,
|
|
N_("Analog Surround 5.1"),
|
|
"analog-surround-51",
|
|
8,
|
|
@@ -608,7 +608,7 @@ static const struct pa_alsa_profile_info device_table[] = {
|
|
{{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
|
|
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
|
|
PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE}},
|
|
- "a52",
|
|
+ "a52", NULL,
|
|
N_("Digital Surround 5.1 (IEC958/AC3)"),
|
|
"iec958-ac3-surround-51",
|
|
3,
|
|
@@ -619,16 +619,72 @@ static const struct pa_alsa_profile_info device_table[] = {
|
|
PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
|
|
PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE,
|
|
PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT }},
|
|
- "surround71",
|
|
+ "surround71", NULL,
|
|
N_("Analog Surround 7.1"),
|
|
"analog-surround-71",
|
|
7,
|
|
"Master", "PCM",
|
|
"Capture", "Mic" },
|
|
|
|
- {{ 0, { 0 }}, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL }
|
|
+ {{ 0, { 0 }}, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL }
|
|
};
|
|
|
|
+static snd_pcm_t *open_by_device_string_with_fallback(
|
|
+ const char *prefix,
|
|
+ const char *prefix_fallback,
|
|
+ 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,
|
|
+ pa_bool_t require_exact_channel_number) {
|
|
+
|
|
+ snd_pcm_t *pcm_handle;
|
|
+ char *d;
|
|
+
|
|
+ d = pa_sprintf_malloc("%s:%s", prefix, dev_id);
|
|
+
|
|
+ pcm_handle = pa_alsa_open_by_device_string(
|
|
+ d,
|
|
+ dev,
|
|
+ ss,
|
|
+ map,
|
|
+ mode,
|
|
+ nfrags,
|
|
+ period_size,
|
|
+ tsched_size,
|
|
+ use_mmap,
|
|
+ use_tsched,
|
|
+ require_exact_channel_number);
|
|
+ pa_xfree(d);
|
|
+
|
|
+ if (!pcm_handle && prefix_fallback) {
|
|
+
|
|
+ d = pa_sprintf_malloc("%s:%s", prefix_fallback, dev_id);
|
|
+
|
|
+ pcm_handle = pa_alsa_open_by_device_string(
|
|
+ d,
|
|
+ dev,
|
|
+ ss,
|
|
+ map,
|
|
+ mode,
|
|
+ nfrags,
|
|
+ period_size,
|
|
+ tsched_size,
|
|
+ use_mmap,
|
|
+ use_tsched,
|
|
+ require_exact_channel_number);
|
|
+ pa_xfree(d);
|
|
+ }
|
|
+
|
|
+ return pcm_handle;
|
|
+}
|
|
+
|
|
snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|
const char *dev_id,
|
|
char **dev,
|
|
@@ -669,14 +725,14 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|
|
|
pa_log_debug("Checking for %s (%s)", device_table[i].name, device_table[i].alsa_name);
|
|
|
|
- d = pa_sprintf_malloc("%s:%s", device_table[i].alsa_name, dev_id);
|
|
-
|
|
try_ss.channels = device_table[i].map.channels;
|
|
try_ss.rate = ss->rate;
|
|
try_ss.format = ss->format;
|
|
|
|
- pcm_handle = pa_alsa_open_by_device_string(
|
|
- d,
|
|
+ pcm_handle = open_by_device_string_with_fallback(
|
|
+ device_table[i].alsa_name,
|
|
+ device_table[i].alsa_name_fallback,
|
|
+ dev_id,
|
|
dev,
|
|
&try_ss,
|
|
map,
|
|
@@ -688,8 +744,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|
use_tsched,
|
|
TRUE);
|
|
|
|
- pa_xfree(d);
|
|
-
|
|
if (pcm_handle) {
|
|
|
|
*ss = try_ss;
|
|
@@ -701,6 +755,7 @@ snd_pcm_t *pa_alsa_open_by_device_id_auto(
|
|
|
|
return pcm_handle;
|
|
}
|
|
+
|
|
}
|
|
|
|
if (direction > 0) {
|
|
@@ -773,7 +828,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_profile(
|
|
pa_bool_t *use_tsched,
|
|
const pa_alsa_profile_info *profile) {
|
|
|
|
- char *d;
|
|
snd_pcm_t *pcm_handle;
|
|
pa_sample_spec try_ss;
|
|
|
|
@@ -785,14 +839,14 @@ snd_pcm_t *pa_alsa_open_by_device_id_profile(
|
|
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,
|
|
+ pcm_handle = open_by_device_string_with_fallback(
|
|
+ profile->alsa_name,
|
|
+ profile->alsa_name_fallback,
|
|
+ dev_id,
|
|
dev,
|
|
&try_ss,
|
|
map,
|
|
@@ -804,8 +858,6 @@ snd_pcm_t *pa_alsa_open_by_device_id_profile(
|
|
use_tsched,
|
|
TRUE);
|
|
|
|
- pa_xfree(d);
|
|
-
|
|
if (!pcm_handle)
|
|
return NULL;
|
|
|
|
@@ -858,6 +910,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
|
|
goto fail;
|
|
}
|
|
|
|
+ pa_log_debug("Managed to open %s", d);
|
|
+
|
|
if ((err = pa_alsa_set_hw_params(pcm_handle, ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, require_exact_channel_number)) < 0) {
|
|
|
|
if (!reformat) {
|
|
@@ -926,26 +980,25 @@ int pa_alsa_probe_profiles(
|
|
snd_pcm_t *pcm_i = NULL;
|
|
|
|
if (i->alsa_name) {
|
|
- char *id;
|
|
pa_sample_spec try_ss;
|
|
pa_channel_map try_map;
|
|
|
|
pa_log_debug("Checking for playback on %s (%s)", i->name, i->alsa_name);
|
|
- id = pa_sprintf_malloc("%s:%s", i->alsa_name, dev_id);
|
|
|
|
try_ss = *ss;
|
|
try_ss.channels = i->map.channels;
|
|
try_map = i->map;
|
|
|
|
- pcm_i = pa_alsa_open_by_device_string(
|
|
- id, NULL,
|
|
+ pcm_i = open_by_device_string_with_fallback(
|
|
+ i->alsa_name,
|
|
+ i->alsa_name_fallback,
|
|
+ dev_id,
|
|
+ NULL,
|
|
&try_ss, &try_map,
|
|
SND_PCM_STREAM_PLAYBACK,
|
|
NULL, NULL, 0, NULL, NULL,
|
|
TRUE);
|
|
|
|
- pa_xfree(id);
|
|
-
|
|
if (!pcm_i)
|
|
continue;
|
|
}
|
|
@@ -954,26 +1007,25 @@ int pa_alsa_probe_profiles(
|
|
snd_pcm_t *pcm_j = NULL;
|
|
|
|
if (j->alsa_name) {
|
|
- char *jd;
|
|
pa_sample_spec try_ss;
|
|
pa_channel_map try_map;
|
|
|
|
pa_log_debug("Checking for capture on %s (%s)", j->name, j->alsa_name);
|
|
- jd = pa_sprintf_malloc("%s:%s", j->alsa_name, dev_id);
|
|
|
|
try_ss = *ss;
|
|
try_ss.channels = j->map.channels;
|
|
try_map = j->map;
|
|
|
|
- pcm_j = pa_alsa_open_by_device_string(
|
|
- jd, NULL,
|
|
+ pcm_j = open_by_device_string_with_fallback(
|
|
+ j->alsa_name,
|
|
+ j->alsa_name_fallback,
|
|
+ dev_id,
|
|
+ NULL,
|
|
&try_ss, &try_map,
|
|
SND_PCM_STREAM_CAPTURE,
|
|
NULL, NULL, 0, NULL, NULL,
|
|
TRUE);
|
|
|
|
- pa_xfree(jd);
|
|
-
|
|
if (!pcm_j)
|
|
continue;
|
|
}
|
|
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
|
|
index c8acc7c..c3a8117 100644
|
|
--- a/src/modules/alsa/alsa-util.h
|
|
+++ b/src/modules/alsa/alsa-util.h
|
|
@@ -56,6 +56,7 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min);
|
|
typedef struct pa_alsa_profile_info {
|
|
pa_channel_map map;
|
|
const char *alsa_name;
|
|
+ const char *alsa_name_fallback;
|
|
const char *description; /* internationalized */
|
|
const char *name;
|
|
unsigned priority;
|
|
--
|
|
1.6.0.2
|
|
|