[vlc-commits] ALSA: add configuration item for channels, remove broken autodetection

Rémi Denis-Courmont git at videolan.org
Sat Mar 3 19:20:24 CET 2012


vlc/vlc-2.0 | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sat Mar  3 16:39:26 2012 +0200| [a25f5071116efd046ffa993d1aadc14258e79f59] | committer: Rémi Denis-Courmont

ALSA: add configuration item for channels, remove broken autodetection

There is no reliable way to determine the channel configuration of a
certain ALSA device. The ALSA operates at too low level for that.
So add a configuration option with default to stereo (as in previous
VLC versions). However, the user will not need to re-enable 5.1 every
time.

This commit also removes all the fancy device choices. The static
choices are overriden dynamically by the UI anyway. So the only use of
the list was in vlc --help.
(cherry picked from commit 0ae23c20130ceee59fc3d8e39f7892c789e150aa)

> http://git.videolan.org/gitweb.cgi/vlc/vlc-2.0.git/?a=commit;h=a25f5071116efd046ffa993d1aadc14258e79f59
---

 modules/audio_output/alsa.c |  169 ++++++++++++++-----------------------------
 1 files changed, 55 insertions(+), 114 deletions(-)

diff --git a/modules/audio_output/alsa.c b/modules/audio_output/alsa.c
index 8a6edd6..87c0cfb 100644
--- a/modules/audio_output/alsa.c
+++ b/modules/audio_output/alsa.c
@@ -47,33 +47,32 @@ struct aout_sys_t
 
 #define A52_FRAME_NB 1536
 
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
 static int Open (vlc_object_t *);
 static void Close (vlc_object_t *);
 static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
                                 vlc_value_t newval, vlc_value_t oldval, void *p_unused );
 static void GetDevices (vlc_object_t *, module_config_t *, const char *);
 
-/*****************************************************************************
- * Module descriptor
- *****************************************************************************/
-static const char *const ppsz_devices[] = {
-    "default", "plug:front",
-    "plug:side", "plug:rear", "plug:center_lfe",
-    "plug:surround40", "plug:surround41",
-    "plug:surround50", "plug:surround51",
-    "plug:surround71",
-    "hdmi", "iec958",
+#define AUDIO_DEV_TEXT N_("Audio output device")
+#define AUDIO_DEV_LONGTEXT N_("Audio output device (using ALSA syntax).")
+static const char *const devices[] = {
+    "default",
+};
+static const char *const devices_text[] = {
+    N_("Default"),
 };
-static const char *const ppsz_devices_text[] = {
-    N_("Default"), N_("Front speakers"),
-    N_("Side speakers"), N_("Rear speakers"), N_("Center and subwoofer"),
-    N_("Surround 4.0"), N_("Surround 4.1"),
-    N_("Surround 5.0"), N_("Surround 5.1"),
-    N_("Surround 7.1"),
-    N_("HDMI"), N_("S/PDIF"),
+
+#define AUDIO_CHAN_TEXT N_("Audio output channels")
+#define AUDIO_CHAN_LONGTEXT N_("Channels available for audio output." \
+    "If the input has more channels than the output, it will be down-mixed." \
+    "This parameter is ignored when digital pass-through is active.")
+static const int channels[] = {
+    AOUT_CHAN_CENTER, AOUT_CHANS_STEREO, AOUT_CHANS_4_0, AOUT_CHANS_4_1,
+    AOUT_CHANS_5_0, AOUT_CHANS_5_1, AOUT_CHANS_7_1,
+};
+static const char *const channels_text[] = {
+    N_("Mono"), N_("Stereo"), N_("Surround 4.0"), N_("Surround 4.1"),
+    N_("Surround 5.0"), N_("Surround 5.1"), N_("Surround 7.1"),
 };
 
 vlc_module_begin ()
@@ -81,10 +80,13 @@ vlc_module_begin ()
     set_description( N_("ALSA audio output") )
     set_category( CAT_AUDIO )
     set_subcategory( SUBCAT_AUDIO_AOUT )
-    add_string ("alsa-audio-device", "default", N_("ALSA device"), NULL, false)
-        change_string_list( ppsz_devices, ppsz_devices_text, FindDevicesCallback )
+    add_string ("alsa-audio-device", "default",
+                AUDIO_DEV_TEXT, AUDIO_DEV_LONGTEXT, false)
+        change_string_list( devices, devices_text, FindDevicesCallback )
         change_action_add( FindDevicesCallback, N_("Refresh list") )
-
+    add_integer ("alsa-audio-channels", AOUT_CHANS_FRONT,
+                 AUDIO_CHAN_TEXT, AUDIO_CHAN_LONGTEXT, false)
+        change_integer_list (channels, channels_text)
     set_capability( "audio output", 150 )
     set_callbacks( Open, Close )
 vlc_module_end ()
@@ -244,6 +246,12 @@ static int Open (vlc_object_t *obj)
         default:
             if (AOUT_FMT_SPDIF(&aout->format))
                 spdif = var_InheritBool (aout, "spdif");
+            if (spdif)
+            {
+                fourcc = VLC_CODEC_SPDIFL;
+                pcm_format = SND_PCM_FORMAT_S16;
+            }
+            else
             if (HAVE_FPU)
             {
                 fourcc = VLC_CODEC_FL32;
@@ -256,6 +264,20 @@ static int Open (vlc_object_t *obj)
             }
     }
 
+    /* ALSA channels */
+    /* XXX: maybe this should be shared with other dumb outputs */
+    uint32_t map = var_InheritInteger (aout, "alsa-audio-channels");
+    map &= aout->format.i_physical_channels;
+    if (unlikely(map == 0)) /* WTH? */
+        map = AOUT_CHANS_STEREO;
+
+    unsigned channels = popcount (map);
+    if (channels < aout_FormatNbChannels (&aout->format))
+        msg_Dbg (aout, "downmixing from %u to %u channels",
+                 aout_FormatNbChannels (&aout->format), channels);
+    else
+        msg_Dbg (aout, "keeping %u channels", channels);
+
     /* Choose the IEC device for S/PDIF output:
        if the device is overridden by the user then it will be the one.
        Otherwise we compute the default device based on the output format. */
@@ -299,8 +321,6 @@ static int Open (vlc_object_t *obj)
     snd_pcm_t *pcm;
     /* VLC always has a resampler. No need for ALSA's. */
     const int mode = SND_PCM_NO_AUTO_RESAMPLE
-    /* ALSA discards extra channels (by default). This is not good. */
-                   | SND_PCM_NO_AUTO_CHANNELS
     /* VLC is currently unable to leverage ALSA softvol. No need for it. */
                    | SND_PCM_NO_SOFTVOL;
 
@@ -344,16 +364,6 @@ static int Open (vlc_object_t *obj)
     msg_Dbg (aout, "using ALSA device: %s", device);
     DumpDevice (VLC_OBJECT(aout), pcm);
 
-    /* Setup */
-    unsigned channels = aout_FormatNbChannels (&aout->format);
-
-    if (spdif)
-    {
-        fourcc = VLC_CODEC_SPDIFL;
-        pcm_format = SND_PCM_FORMAT_S16;
-        channels = 2;
-    }
-
     /* Get Initial hardware parameters */
     snd_pcm_hw_params_t *hw;
     unsigned param;
@@ -390,45 +400,18 @@ static int Open (vlc_object_t *obj)
     }
 
     /* Set channels count */
-    unsigned chans;
-    /* By default, ALSA plug will discard extra channels and zero missing ones
-     * instead of remixing, so remixing was disabled at snd_pcm_open() above.
-     * Then, the configuration space will contain only channels configurations
-     * supported by the audio device, but not necessarily functional (e.g.
-     * surround-capable card with stereo speakers). */
-    /* If there is only channels configuration, use that one.
-     * This should deal with "surround40", "surround51" and "surround71". */
-    if (snd_pcm_hw_params_get_channels (hw, &chans) == 0)
-        ;
-    /* Otherwise, if we have 5 channels and they are supported, use that.
-     * This should deal with "surround41" and "surround50" routers.
-     * This assumes that no real hardware supports exactly 5 channels. */
-    else if (channels == 5
-     && snd_pcm_hw_params_set_channels (pcm, hw, channels))
-        chans = channels;
-    /* Otherwise, if stereo is supported, then use that. This deals with
-     * the "front" device that fails to enforce stereo on Surround cards. */
-    else if (snd_pcm_hw_params_set_channels (pcm, hw, 2) == 0)
-        chans = 2;
-    /* Out of desperation, try the original channels count. */
-    else if (snd_pcm_hw_params_set_channels (pcm, hw, channels) == 0)
-        ;
-    /* As last chance, try anything. */
-    else
+    /* By default, ALSA plug will pad missing channels with zeroes, which is
+     * usually fine. However, it will also discard extraneous channels, which
+     * is not acceptable. Thus the user must configure the physically
+     * available channels, and VLC will downmix if needed. */
+    val = snd_pcm_hw_params_set_channels (pcm, hw, channels);
+    if (val)
     {
-        chans = channels;
-        val = snd_pcm_hw_params_set_channels_near (pcm, hw, &chans);
-        if (val)
-        {
-            msg_Err (aout, "cannot set channels count: %s",
-                     snd_strerror (val));
-            goto error;
-        }
+        msg_Err (aout, "cannot set %u channels: %s", channels,
+                 snd_strerror (val));
+        goto error;
     }
 
-    if (channels != chans)
-        msg_Dbg (aout, "remixing from %u to %u channels", channels, chans);
-
     /* Set sample rate */
     unsigned rate = aout->format.i_rate;
     val = snd_pcm_hw_params_set_rate_near (pcm, hw, &rate, NULL);
@@ -508,48 +491,6 @@ static int Open (vlc_object_t *obj)
         goto error;
     }
 
-    /* Guess the channel map */
-    switch (chans)
-    {
-        case 1:
-            chans = AOUT_CHAN_CENTER;
-            break;
-        case 2: /* front */
-            chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
-            break;
-        case 4: /* surround40 */
-            chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
-                  | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
-            break;
-        case 5: /* surround50 ... or surround41! Uho! */
-#if 1
-            chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
-                  | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
-                  | AOUT_CHAN_LFE;
-#else
-            chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
-                  | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
-                  | AOUT_CHAN_CENTER;
-#endif
-            break;
-        case 6: /* surround51 */
-            chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
-                  | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
-                  | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
-            break;
-#if 0 /* FIXME reorder */
-         case 8: /* surround71 */
-            chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
-                  | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
-                  | AOUT_CHAN_CENTER | AOUT_CHAN_LFE
-                  | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT;
-            break;
-#endif
-        default:
-            msg_Err (aout, "unknown %u channels configuration", chans);
-            goto error;
-    }
-
     /* Setup audio_output_t */
     aout->format.i_format = fourcc;
     aout->format.i_rate = rate;
@@ -562,7 +503,7 @@ static int Open (vlc_object_t *obj)
     else
     {
         aout->format.i_original_channels =
-        aout->format.i_physical_channels = chans;
+        aout->format.i_physical_channels = map;
         aout_VolumeSoftInit (aout);
     }
 



More information about the vlc-commits mailing list