]> git.sesse.net Git - vlc/commitdiff
* modules/audio_output/alsa.c: we now open the device in SetFormat because
authorArnaud de Bossoreille de Ribou <bozo@videolan.org>
Mon, 19 Aug 2002 17:07:14 +0000 (17:07 +0000)
committerArnaud de Bossoreille de Ribou <bozo@videolan.org>
Mon, 19 Aug 2002 17:07:14 +0000 (17:07 +0000)
    it depends on the audio format. Cosmetic changes. The S/PDIF output may
    work.

modules/audio_output/alsa.c

index 8b7f59fce592863d7ccf884222a12a573faa7564..8ff964563d5299487a3ce53f59f314e1e145d727 100644 (file)
@@ -2,7 +2,7 @@
  * alsa.c : alsa plugin for vlc
  *****************************************************************************
  * Copyright (C) 2000-2001 VideoLAN
- * $Id: alsa.c,v 1.3 2002/08/15 10:31:44 bozo Exp $
+ * $Id: alsa.c,v 1.4 2002/08/19 17:07:14 bozo Exp $
  *
  * Authors: Henri Fallon <henri@videolan.org> - Original Author
  *          Jeffrey Baker <jwbaker@acm.org> - Port to ALSA 1.0 API
@@ -54,18 +54,22 @@ struct aout_sys_t
 
     volatile vlc_bool_t b_initialized;
 
+    volatile vlc_bool_t b_can_sleek;
+
 #ifdef DEBUG
     snd_output_t      * p_snd_stderr;
 #endif
 };
 
+#define A52_FRAME_NB 1536
+
 /* These values are in frames.
-   To convert them to a numer of bytes you have to multiply them by the
+   To convert them to a number of bytes you have to multiply them by the
    number of channel(s) (eg. 2 for stereo) and the size of a sample (eg.
    2 for s16). */
 #define ALSA_DEFAULT_PERIOD_SIZE        2048
 #define ALSA_DEFAULT_BUFFER_SIZE        ( ALSA_DEFAULT_PERIOD_SIZE << 4 )
-#define ALSA_SPDIF_PERIOD_SIZE          1536
+#define ALSA_SPDIF_PERIOD_SIZE          A52_FRAME_NB
 #define ALSA_SPDIF_BUFFER_SIZE          ( ALSA_SPDIF_PERIOD_SIZE << 4 )
 
 /*****************************************************************************
@@ -101,12 +105,6 @@ static int Open( vlc_object_t *p_this )
 {
     aout_instance_t * p_aout = (aout_instance_t *)p_this;
     struct aout_sys_t * p_sys;
-    char * psz_device;
-
-    /* Allows user to choose which ALSA device to use */
-    char  psz_alsadev[128];
-    char * psz_userdev;
-    int i_snd_rc;
 
     /* Allocate structures */
     p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );
@@ -116,10 +114,47 @@ static int Open( vlc_object_t *p_this )
         return -1;
     }
 
+    /* Create ALSA thread and wait for its readiness. */
+    p_sys->b_initialized = VLC_FALSE;
+    if( vlc_thread_create( p_aout, "aout", ALSAThread, VLC_FALSE ) )
+    {
+        msg_Err( p_aout, "cannot create ALSA thread (%s)", strerror(errno) );
+        free( p_sys );
+        return -1;
+    }
+
+    p_aout->output.pf_setformat = SetFormat;
+    p_aout->output.pf_play = Play;
+
 #ifdef DEBUG
     snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 );
 #endif
 
+    return 0;
+}
+
+/*****************************************************************************
+ * SetFormat : sets the alsa output format
+ *****************************************************************************
+ * This function prepares the device, sets the rate, format, the mode
+ * ( "play as soon as you have data" ), and buffer information.
+ *****************************************************************************/
+static int SetFormat( aout_instance_t * p_aout )
+{
+    struct aout_sys_t * p_sys = p_aout->output.p_sys;
+
+    int i_snd_rc;
+
+    char * psz_device;
+    char psz_alsadev[128];
+    char * psz_userdev;
+
+    int i_format;
+    int i_channels;
+
+    snd_pcm_hw_params_t *p_hw;
+    snd_pcm_sw_params_t *p_sw;
+
     /* Read in ALSA device preferences from configuration */
     psz_userdev = config_GetPsz( p_aout, "alsa-device" );
 
@@ -132,6 +167,9 @@ static int Open( vlc_object_t *p_this )
         /* Use the internal logic to decide on the device name */
         if ( p_aout->output.output.i_format == AOUT_FMT_SPDIF )
         {
+            /* Will probably need some little modification in the case
+               we want to send some data at a different rate
+               (32000, 44100 and 48000 are the possibilities) -- bozo */
             unsigned char s[4];
             s[0] = IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO;
             s[1] = IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER;
@@ -141,14 +179,10 @@ static int Open( vlc_object_t *p_this )
                      "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
                      s[0], s[1], s[2], s[3] );
             psz_device = psz_alsadev;
-            p_sys->i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
-            p_aout->output.i_nb_samples = ALSA_SPDIF_PERIOD_SIZE;
         }
         else
         {
             psz_device = "default";
-            p_sys->i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
-            p_aout->output.i_nb_samples = ALSA_DEFAULT_PERIOD_SIZE;
         }
     }
 
@@ -161,52 +195,29 @@ static int Open( vlc_object_t *p_this )
                          psz_device, snd_strerror(i_snd_rc) );
         if( psz_userdev )
             free( psz_userdev );
-        free( p_sys );
         p_sys->p_snd_pcm = NULL;
         return -1;
     }
 
     if( psz_userdev )
-    {
         free( psz_userdev );
-    }
 
-    /* Create ALSA thread and wait for its readiness. */
-    p_sys->b_initialized = VLC_FALSE;
-    if( vlc_thread_create( p_aout, "aout", ALSAThread, VLC_FALSE ) )
+    /* Default settings */
+    p_sys->b_can_sleek = VLC_FALSE;
+    i_channels = p_aout->output.output.i_channels;
+    if ( p_aout->output.output.i_format == AOUT_FMT_SPDIF )
     {
-        msg_Err( p_aout, "cannot create ALSA thread (%s)", strerror(errno) );
-        if( psz_userdev )
-            free( psz_userdev );
-        free( p_sys );
-        return -1;
+        p_sys->i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
+        p_aout->output.i_nb_samples = ALSA_SPDIF_PERIOD_SIZE;
+    }
+    else
+    {
+        p_sys->i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
+        p_aout->output.i_nb_samples = ALSA_DEFAULT_PERIOD_SIZE;
     }
 
-    p_aout->output.pf_setformat = SetFormat;
-    p_aout->output.pf_play = Play;
-
-    return 0;
-}
-
-/*****************************************************************************
- * SetFormat : sets the alsa output format
- *****************************************************************************
- * This function prepares the device, sets the rate, format, the mode
- * ( "play as soon as you have data" ), and buffer information.
- *****************************************************************************/
-static int SetFormat( aout_instance_t * p_aout )
-{
-    struct aout_sys_t * p_sys = p_aout->output.p_sys;
-
-    int i_snd_rc;
-    int i_format;
-
-    snd_pcm_hw_params_t *p_hw;
-    snd_pcm_sw_params_t *p_sw;
-
-    snd_pcm_hw_params_alloca(&p_hw);
-    snd_pcm_sw_params_alloca(&p_sw);
 
+    /* Compute the settings */
     switch (p_aout->output.output.i_format)
     {
         case AOUT_FMT_MU_LAW:    i_format = SND_PCM_FORMAT_MU_LAW; break;
@@ -219,6 +230,15 @@ static int SetFormat( aout_instance_t * p_aout )
         case AOUT_FMT_U16_LE:    i_format = SND_PCM_FORMAT_U16_LE; break;
         case AOUT_FMT_U16_BE:    i_format = SND_PCM_FORMAT_U16_BE; break;
         case AOUT_FMT_FLOAT32:   i_format = SND_PCM_FORMAT_FLOAT; break;
+        case AOUT_FMT_SPDIF:
+            /* Override some settings to make S/PDIF work */
+            p_sys->b_can_sleek = VLC_TRUE;
+            i_format = SND_PCM_FORMAT_S16_LE;
+            i_channels = 2;
+            p_aout->output.output.i_bytes_per_sec =
+                    p_aout->output.output.i_rate * AOUT_SPDIF_SIZE /
+                    ALSA_SPDIF_PERIOD_SIZE;
+            break;
         case AOUT_FMT_FIXED32:
         default:
             msg_Err( p_aout, "audio output format 0x%x not supported",
@@ -227,6 +247,9 @@ static int SetFormat( aout_instance_t * p_aout )
             break;
     }
 
+    snd_pcm_hw_params_alloca(&p_hw);
+    snd_pcm_sw_params_alloca(&p_sw);
+
     i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw );
     if( i_snd_rc < 0 )
     {
@@ -250,7 +273,7 @@ static int SetFormat( aout_instance_t * p_aout )
     }
 
     i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw,
-                    p_aout->output.output.i_channels );
+                                               i_channels );
     if( i_snd_rc < 0 )
     {
         msg_Err( p_aout, "unable to set number of output channels" );
@@ -348,6 +371,10 @@ static void Close( vlc_object_t *p_this )
         }
     }
 
+#ifdef DEBUG
+    snd_output_close( p_sys->p_snd_stderr );
+#endif
+
     free( p_sys );
 }
 
@@ -449,7 +476,8 @@ static void ALSAFill( aout_instance_t * p_aout )
             snd_pcm_status_get_tstamp( p_status, &ts_next );
             next_date = (mtime_t)ts_next.tv_sec * 1000000 + ts_next.tv_usec;
 
-            p_buffer = aout_OutputNextBuffer( p_aout, next_date, 0 );
+            p_buffer = aout_OutputNextBuffer( p_aout, next_date,
+                                              p_sys->b_can_sleek );
 
             /* Audio output buffer shortage -> stop the fill process and
                wait in ALSAThread */