]> git.sesse.net Git - vlc/blob - modules/audio_output/alsa.c
146e11d802ea34e4fc153c8b73db18ff01e576d6
[vlc] / modules / audio_output / alsa.c
1 /*****************************************************************************
2  * alsa.c : alsa plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Henri Fallon <henri@videolan.org> - Original Author
8  *          Jeffrey Baker <jwbaker@acm.org> - Port to ALSA 1.0 API
9  *          John Paul Lorenti <jpl31@columbia.edu> - Device selection
10  *          Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> - S/PDIF and aout3
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <assert.h>
35
36 #include <vlc_common.h>
37 #include <vlc_plugin.h>
38
39 #include <errno.h>                                                 /* ENOMEM */
40 #include <vlc_dialog.h>
41
42 #include <vlc_aout.h>
43 #include <vlc_cpu.h>
44
45 /* ALSA part
46    Note: we use the new API which is available since 0.9.0beta10a. */
47 #define ALSA_PCM_NEW_HW_PARAMS_API
48 #define ALSA_PCM_NEW_SW_PARAMS_API
49 #include <alsa/asoundlib.h>
50 #include <alsa/version.h>
51
52 /*#define ALSA_DEBUG*/
53
54 /*****************************************************************************
55  * aout_sys_t: ALSA audio output method descriptor
56  *****************************************************************************
57  * This structure is part of the audio output thread descriptor.
58  * It describes the ALSA specific properties of an audio device.
59  *****************************************************************************/
60 struct aout_sys_t
61 {
62     snd_pcm_t         * p_snd_pcm;
63     unsigned int                 i_period_time;
64
65 #ifdef ALSA_DEBUG
66     snd_output_t      * p_snd_stderr;
67 #endif
68
69     mtime_t      start_date;
70     vlc_thread_t thread;
71     vlc_sem_t    wait;
72 };
73
74 #define A52_FRAME_NB 1536
75
76 /* These values are in frames.
77    To convert them to a number of bytes you have to multiply them by the
78    number of channel(s) (eg. 2 for stereo) and the size of a sample (eg.
79    2 for int16_t). */
80 #define ALSA_DEFAULT_PERIOD_SIZE        1024
81 #define ALSA_DEFAULT_BUFFER_SIZE        ( ALSA_DEFAULT_PERIOD_SIZE << 8 )
82 #define ALSA_SPDIF_PERIOD_SIZE          A52_FRAME_NB
83 #define ALSA_SPDIF_BUFFER_SIZE          ( ALSA_SPDIF_PERIOD_SIZE << 4 )
84 /* Why << 4 ? --Meuuh */
85 /* Why not ? --Bozo */
86 /* Right. --Meuuh */
87
88 #define DEFAULT_ALSA_DEVICE N_("default")
89
90 /*****************************************************************************
91  * Local prototypes
92  *****************************************************************************/
93 static int   Open         ( vlc_object_t * );
94 static void  Close        ( vlc_object_t * );
95 static void  Play         ( aout_instance_t * );
96 static void* ALSAThread   ( void * );
97 static void  ALSAFill     ( aout_instance_t * );
98 static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
99                                 vlc_value_t newval, vlc_value_t oldval, void *p_unused );
100 static void GetDevicesForCard( vlc_object_t *, module_config_t *, int card );
101 static void GetDevices( vlc_object_t *, module_config_t * );
102
103 /*****************************************************************************
104  * Module descriptor
105  *****************************************************************************/
106 static const char *const ppsz_devices[] = { "default" };
107 static const char *const ppsz_devices_text[] = { N_("Default") };
108 vlc_module_begin ()
109     set_shortname( "ALSA" )
110     set_description( N_("ALSA audio output") )
111     set_category( CAT_AUDIO )
112     set_subcategory( SUBCAT_AUDIO_AOUT )
113     add_string( "alsa-audio-device", DEFAULT_ALSA_DEVICE, aout_FindAndRestart,
114                 N_("ALSA Device Name"), NULL, false )
115         add_deprecated_alias( "alsadev" )   /* deprecated since 0.9.3 */
116         change_string_list( ppsz_devices, ppsz_devices_text, FindDevicesCallback )
117         change_action_add( FindDevicesCallback, N_("Refresh list") )
118
119     set_capability( "audio output", 150 )
120     set_callbacks( Open, Close )
121 vlc_module_end ()
122
123 /*****************************************************************************
124  * Probe: probe the audio device for available formats and channels
125  *****************************************************************************/
126 static void Probe( aout_instance_t * p_aout,
127                    const char * psz_device, const char * psz_iec_device,
128                    int *pi_snd_pcm_format )
129 {
130     struct aout_sys_t * p_sys = p_aout->output.p_sys;
131     vlc_value_t val, text;
132     int i_ret;
133
134     var_Create ( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
135     text.psz_string = _("Audio Device");
136     var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
137
138     /* We'll open the audio device in non blocking mode so we can just exit
139      * when it is already in use, but for the real stuff we'll still use
140      * the blocking mode */
141
142     /* Now test linear PCM capabilities */
143     if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
144                                  SND_PCM_STREAM_PLAYBACK,
145                                  SND_PCM_NONBLOCK ) ) )
146     {
147         int i_channels;
148         snd_pcm_hw_params_t * p_hw;
149         snd_pcm_hw_params_alloca (&p_hw);
150
151         if ( snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) < 0 )
152         {
153             msg_Warn( p_aout, "unable to retrieve initial hardware parameters"
154                               ", disabling linear PCM audio" );
155             snd_pcm_close( p_sys->p_snd_pcm );
156             var_Destroy( p_aout, "audio-device" );
157             return;
158         }
159
160         if ( snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
161                                            *pi_snd_pcm_format ) < 0 )
162         {
163             int i_snd_rc = -1;
164
165             if( *pi_snd_pcm_format != SND_PCM_FORMAT_S16 )
166             {
167                 *pi_snd_pcm_format = SND_PCM_FORMAT_S16;
168                 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
169                                                     p_hw, *pi_snd_pcm_format );
170             }
171             if ( i_snd_rc < 0 )
172             {
173                 msg_Warn( p_aout, "unable to set stream sample size and "
174                           "word order, disabling linear PCM audio" );
175                 snd_pcm_close( p_sys->p_snd_pcm );
176                 var_Destroy( p_aout, "audio-device" );
177                 return;
178             }
179         }
180
181         i_channels = aout_FormatNbChannels( &p_aout->output.output );
182
183         while ( i_channels > 0 )
184         {
185             if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw,
186                                                    i_channels ) )
187             {
188                 switch ( i_channels )
189                 {
190                 case 1:
191                     val.i_int = AOUT_VAR_MONO;
192                     text.psz_string = _("Mono");
193                     var_Change( p_aout, "audio-device",
194                                 VLC_VAR_ADDCHOICE, &val, &text );
195                     break;
196                 case 2:
197                     val.i_int = AOUT_VAR_STEREO;
198                     text.psz_string = _("Stereo");
199                     var_Change( p_aout, "audio-device",
200                                 VLC_VAR_ADDCHOICE, &val, &text );
201                     var_Set( p_aout, "audio-device", val );
202                     break;
203                 case 4:
204                     val.i_int = AOUT_VAR_2F2R;
205                     text.psz_string = _("2 Front 2 Rear");
206                     var_Change( p_aout, "audio-device",
207                                 VLC_VAR_ADDCHOICE, &val, &text );
208                     break;
209                 case 6:
210                     val.i_int = AOUT_VAR_5_1;
211                     text.psz_string = "5.1";
212                     var_Change( p_aout, "audio-device",
213                                 VLC_VAR_ADDCHOICE, &val, &text );
214                     break;
215                 }
216             }
217
218             --i_channels;
219         }
220
221         /* Special case for mono on stereo only boards */
222         i_channels = aout_FormatNbChannels( &p_aout->output.output );
223         var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
224         if( val.i_int <= 0 && i_channels == 1 )
225         {
226             if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw, 2 ))
227             {
228                 val.i_int = AOUT_VAR_STEREO;
229                 text.psz_string = (char*)N_("Stereo");
230                 var_Change( p_aout, "audio-device",
231                             VLC_VAR_ADDCHOICE, &val, &text );
232                 var_Set( p_aout, "audio-device", val );
233             }
234         }
235
236         /* Close the previously opened device */
237         snd_pcm_close( p_sys->p_snd_pcm );
238     }
239     else if ( i_ret == -EBUSY )
240     {
241         msg_Warn( p_aout, "audio device: %s is already in use", psz_device );
242     }
243
244     /* Test for S/PDIF device if needed */
245     if ( psz_iec_device )
246     {
247         /* Opening the device should be enough */
248         if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
249                                      SND_PCM_STREAM_PLAYBACK,
250                                      SND_PCM_NONBLOCK ) ) )
251         {
252             val.i_int = AOUT_VAR_SPDIF;
253             text.psz_string = (char*)N_("A/52 over S/PDIF");
254             var_Change( p_aout, "audio-device",
255                         VLC_VAR_ADDCHOICE, &val, &text );
256             if( var_InheritBool( p_aout, "spdif" ) )
257                 var_Set( p_aout, "audio-device", val );
258
259             snd_pcm_close( p_sys->p_snd_pcm );
260         }
261         else if ( i_ret == -EBUSY )
262         {
263             msg_Warn( p_aout, "audio device: %s is already in use",
264                       psz_iec_device );
265         }
266     }
267
268     var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
269 #if (SND_LIB_VERSION <= 0x010015)
270 # warning Please update alsa-lib to version > 1.0.21a.
271     var_Create( p_aout->p_libvlc, "alsa-working", VLC_VAR_BOOL );
272     if( val.i_int <= 0 )
273     {
274         if( var_GetBool( p_aout->p_libvlc, "alsa-working" ) )
275             dialog_Fatal( p_aout, "ALSA version problem",
276                 "VLC failed to re-initialize your sound output device.\n"
277                 "Please update alsa-lib to version 1.0.22 or higher "
278                 "to fix this issue." );
279     }
280     else
281         var_SetBool( p_aout->p_libvlc, "alsa-working", true );
282 #endif
283     if( val.i_int <= 0 )
284     {
285         /* Probe() has failed. */
286 #if (SND_LIB_VERSION <= 0x010017)
287 # warning Please update alsa-lib to version > 1.0.23.
288         var_Create( p_aout->p_libvlc, "alsa-broken", VLC_VAR_BOOL );
289         if( !var_GetBool( p_aout->p_libvlc, "alsa-broken" ) )
290         {
291             var_SetBool( p_aout->p_libvlc, "alsa-broken", true );
292             dialog_Fatal( p_aout, "Potential ALSA version problem",
293                 "VLC failed to initialize your sound output device (if any).\n"
294                 "Please update alsa-lib to version 1.0.24 or higher "
295                 "to try to fix this issue." );
296         }
297 #endif
298         msg_Dbg( p_aout, "failed to find a usable ALSA configuration" );
299         var_Destroy( p_aout, "audio-device" );
300         GetDevices( VLC_OBJECT(p_aout), NULL );
301         return;
302     }
303
304     /* Add final settings to the variable */
305     var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
306     var_SetBool( p_aout, "intf-change", true );
307 }
308
309 /*****************************************************************************
310  * Open: create a handle and open an alsa device
311  *****************************************************************************
312  * This function opens an alsa device, through the alsa API.
313  *
314  * Note: the only heap-allocated string is psz_device. All the other pointers
315  * are references to psz_device or to stack-allocated data.
316  *****************************************************************************/
317 static int Open( vlc_object_t *p_this )
318 {
319     aout_instance_t * p_aout = (aout_instance_t *)p_this;
320     struct aout_sys_t * p_sys;
321     vlc_value_t val;
322
323     char psz_default_iec_device[128]; /* Buffer used to store the default
324                                          S/PDIF device */
325     char * psz_device, * psz_iec_device; /* device names for PCM and S/PDIF
326                                             output */
327
328     int i_vlc_pcm_format; /* Audio format for VLC's data */
329     int i_snd_pcm_format; /* Audio format for ALSA's data */
330
331     snd_pcm_uframes_t i_buffer_size = 0;
332     snd_pcm_uframes_t i_period_size = 0;
333     int i_channels = 0;
334
335     snd_pcm_hw_params_t *p_hw;
336     snd_pcm_sw_params_t *p_sw;
337
338     int i_snd_rc = -1;
339     unsigned int i_old_rate;
340     bool b_retry = true;
341
342     /* Allocate structures */
343     p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );
344     if( p_sys == NULL )
345         return VLC_ENOMEM;
346
347     /* Get device name */
348     if( (psz_device = var_InheritString( p_aout, "alsa-audio-device" )) == NULL )
349     {
350         msg_Err( p_aout, "no audio device given (maybe \"default\" ?)" );
351         dialog_Fatal( p_aout, _("No Audio Device"), "%s",
352                         _("No audio device name was given. You might want to " \
353                           "enter \"default\".") );
354         free( p_sys );
355         return VLC_EGENERIC;
356     }
357
358     /* Choose the IEC device for S/PDIF output:
359        if the device is overriden by the user then it will be the one
360        otherwise we compute the default device based on the output format. */
361     if( AOUT_FMT_NON_LINEAR( &p_aout->output.output )
362         && !strcmp( psz_device, DEFAULT_ALSA_DEVICE ) )
363     {
364         snprintf( psz_default_iec_device, sizeof(psz_default_iec_device),
365                   "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
366                   IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
367                   IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
368                   0,
369                   ( p_aout->output.output.i_rate == 48000 ?
370                     IEC958_AES3_CON_FS_48000 :
371                     ( p_aout->output.output.i_rate == 44100 ?
372                       IEC958_AES3_CON_FS_44100 : IEC958_AES3_CON_FS_32000 ) ) );
373         psz_iec_device = psz_default_iec_device;
374     }
375     else if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
376     {
377         psz_iec_device = psz_device;
378     }
379     else
380     {
381         psz_iec_device = NULL;
382     }
383
384     /* Choose the linear PCM format (read the comment above about FPU
385        and float32) */
386     if( HAVE_FPU )
387     {
388         i_vlc_pcm_format = VLC_CODEC_FL32;
389         i_snd_pcm_format = SND_PCM_FORMAT_FLOAT;
390     }
391     else
392     {
393         i_vlc_pcm_format = VLC_CODEC_S16N;
394         i_snd_pcm_format = SND_PCM_FORMAT_S16;
395     }
396
397     /* If the variable doesn't exist then it's the first time we're called
398        and we have to probe the available audio formats and channels */
399     if ( var_Type( p_aout, "audio-device" ) == 0 )
400     {
401         Probe( p_aout, psz_device, psz_iec_device, &i_snd_pcm_format );
402     }
403
404     if ( var_Get( p_aout, "audio-device", &val ) < 0 )
405     {
406         free( p_sys );
407         free( psz_device );
408         return VLC_EGENERIC;
409     }
410
411     p_aout->output.output.i_format = i_vlc_pcm_format;
412     if ( val.i_int == AOUT_VAR_5_1 )
413     {
414         p_aout->output.output.i_physical_channels
415             = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
416                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
417                | AOUT_CHAN_LFE;
418         free( psz_device );
419         psz_device = strdup( "surround51" );
420     }
421     else if ( val.i_int == AOUT_VAR_2F2R )
422     {
423         p_aout->output.output.i_physical_channels
424             = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
425                | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
426         free( psz_device );
427         psz_device = strdup( "surround40" );
428     }
429     else if ( val.i_int == AOUT_VAR_STEREO )
430     {
431         p_aout->output.output.i_physical_channels
432             = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
433     }
434     else if ( val.i_int == AOUT_VAR_MONO )
435     {
436         p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
437     }
438     else if( val.i_int != AOUT_VAR_SPDIF )
439     {
440         /* This should not happen ! */
441         msg_Err( p_aout, "internal: can't find audio-device (%"PRId64")",
442                  val.i_int );
443         free( p_sys );
444         free( psz_device );
445         return VLC_EGENERIC;
446     }
447
448 #ifdef ALSA_DEBUG
449     snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 );
450 #endif
451
452     /* Open the device */
453     if ( val.i_int == AOUT_VAR_SPDIF )
454     {
455         if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
456                             SND_PCM_STREAM_PLAYBACK, 0 ) ) < 0 )
457         {
458             msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
459                              psz_iec_device, snd_strerror( i_snd_rc ) );
460             dialog_Fatal( p_aout, _("Audio output failed"),
461                             _("VLC could not open the ALSA device \"%s\" (%s)."),
462                             psz_iec_device, snd_strerror( i_snd_rc ) );
463             free( p_sys );
464             free( psz_device );
465             return VLC_EGENERIC;
466         }
467         i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
468         i_snd_pcm_format = SND_PCM_FORMAT_S16;
469         i_channels = 2;
470
471         i_vlc_pcm_format = VLC_CODEC_SPDIFL;
472         p_aout->output.i_nb_samples = i_period_size = ALSA_SPDIF_PERIOD_SIZE;
473         p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
474         p_aout->output.output.i_frame_length = A52_FRAME_NB;
475
476         aout_VolumeNoneInit( p_aout );
477     }
478     else
479     {
480         int i;
481
482         msg_Dbg( p_aout, "opening ALSA device `%s'", psz_device );
483
484         /* Since it seems snd_pcm_close hasn't really released the device at
485           the time it returns, probe if the device is available in loop for 1s.
486           We cannot use blocking mode since the we would wait indefinitely when
487           switching from a dmx device to surround51. */
488
489         for( i = 10; i >= 0; i-- )
490         {
491             if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
492                    SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) ) == -EBUSY )
493             {
494                 if( i ) msleep( 100000 /* 100ms */ );
495                 else
496                 {
497                     msg_Err( p_aout, "audio device: %s is already in use",
498                               psz_device );
499                     dialog_Fatal( p_aout, _("Audio output failed"),
500                                     _("The audio device \"%s\" is already in use."),
501                                     psz_device );
502                 }
503                 continue;
504             }
505             break;
506         }
507         if( i_snd_rc < 0 )
508         {
509             msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
510                              psz_device, snd_strerror( i_snd_rc ) );
511             dialog_Fatal( p_aout, _("Audio output failed"),
512                             _("VLC could not open the ALSA device \"%s\" (%s)."),
513                             psz_device, snd_strerror( i_snd_rc ) );
514             free( p_sys );
515             free( psz_device );
516             return VLC_EGENERIC;
517         }
518
519         /* We want blocking mode */
520         snd_pcm_nonblock( p_sys->p_snd_pcm, 0 );
521
522         i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
523         i_channels = aout_FormatNbChannels( &p_aout->output.output );
524
525         p_aout->output.i_nb_samples = i_period_size = ALSA_DEFAULT_PERIOD_SIZE;
526
527         aout_VolumeSoftInit( p_aout );
528     }
529
530     /* Free psz_device so that all the remaining data is stack-allocated */
531     free( psz_device );
532
533     p_aout->output.pf_play = Play;
534
535     snd_pcm_hw_params_alloca(&p_hw);
536     snd_pcm_sw_params_alloca(&p_sw);
537
538     /* Due to some bugs in alsa with some drivers, we need to retry in s16l
539        if snd_pcm_hw_params fails in fl32 */
540     while ( b_retry )
541     {
542         b_retry = false;
543
544         /* Get Initial hardware parameters */
545         if ( ( i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) ) < 0 )
546         {
547             msg_Err( p_aout, "unable to retrieve initial hardware parameters (%s)",
548                          snd_strerror( i_snd_rc ) );
549             goto error;
550         }
551
552         /* Set format. */
553         if ( ( i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
554                                                     i_snd_pcm_format ) ) < 0 )
555         {
556             if( i_snd_pcm_format != SND_PCM_FORMAT_S16 )
557             {
558                 i_snd_pcm_format = SND_PCM_FORMAT_S16;
559                 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
560                                                      p_hw, i_snd_pcm_format );
561             }
562             if ( i_snd_rc < 0 )
563             {
564                 msg_Err( p_aout, "unable to set stream sample size and "
565                      "word order (%s)", snd_strerror( i_snd_rc ) );
566                 goto error;
567             }
568         }
569         if( i_vlc_pcm_format != VLC_CODEC_SPDIFL )
570         switch( i_snd_pcm_format )
571         {
572         case SND_PCM_FORMAT_FLOAT:
573             i_vlc_pcm_format = VLC_CODEC_FL32;
574             break;
575         case SND_PCM_FORMAT_S16:
576             i_vlc_pcm_format = VLC_CODEC_S16N;
577             break;
578         }
579         p_aout->output.output.i_format = i_vlc_pcm_format;
580
581         if ( ( i_snd_rc = snd_pcm_hw_params_set_access( p_sys->p_snd_pcm, p_hw,
582                                     SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 )
583         {
584             msg_Err( p_aout, "unable to set interleaved stream format (%s)",
585                              snd_strerror( i_snd_rc ) );
586             goto error;
587         }
588
589         /* Set channels. */
590         if ( ( i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw,
591                                                       i_channels ) ) < 0 )
592         {
593             msg_Err( p_aout, "unable to set number of output channels (%s)",
594                              snd_strerror( i_snd_rc ) );
595             goto error;
596         }
597
598         /* Set rate. */
599         i_old_rate = p_aout->output.output.i_rate;
600         i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm, p_hw,
601                                                 &p_aout->output.output.i_rate,
602                                                 NULL );
603         if( i_snd_rc < 0 || p_aout->output.output.i_rate != i_old_rate )
604         {
605             msg_Warn( p_aout, "The rate %d Hz is not supported by your " \
606                 "hardware. Using %d Hz instead.\n", i_old_rate, \
607                 p_aout->output.output.i_rate );
608         }
609
610         /* Set period size. */
611         if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,
612                                     p_hw, &i_period_size, NULL ) ) < 0 )
613         {
614             msg_Err( p_aout, "unable to set period size (%s)",
615                          snd_strerror( i_snd_rc ) );
616             goto error;
617         }
618         p_aout->output.i_nb_samples = i_period_size;
619
620 /* Set buffer size. */
621         if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,
622                                     p_hw, &i_buffer_size ) ) < 0 )
623         {
624             msg_Err( p_aout, "unable to set buffer size (%s)",
625                          snd_strerror( i_snd_rc ) );
626             goto error;
627         }
628
629         /* Commit hardware parameters. */
630         if ( ( i_snd_rc = snd_pcm_hw_params( p_sys->p_snd_pcm, p_hw ) ) < 0 )
631         {
632             if ( b_retry == false &&
633                                 i_snd_pcm_format == SND_PCM_FORMAT_FLOAT)
634             {
635                 b_retry = true;
636                 i_snd_pcm_format = SND_PCM_FORMAT_S16;
637                 p_aout->output.output.i_format = VLC_CODEC_S16N;
638                 msg_Warn( p_aout, "unable to commit hardware configuration "
639                                   "with fl32 samples. Retrying with s16l (%s)",                                     snd_strerror( i_snd_rc ) );
640             }
641             else
642             {
643                 msg_Err( p_aout, "unable to commit hardware configuration (%s)",
644                          snd_strerror( i_snd_rc ) );
645                 goto error;
646             }
647         }
648     }
649
650     if( ( i_snd_rc = snd_pcm_hw_params_get_period_time( p_hw,
651                                     &p_sys->i_period_time, NULL ) ) < 0 )
652     {
653         msg_Err( p_aout, "unable to get period time (%s)",
654                          snd_strerror( i_snd_rc ) );
655         goto error;
656     }
657
658     /* Get Initial software parameters */
659     snd_pcm_sw_params_current( p_sys->p_snd_pcm, p_sw );
660
661     i_snd_rc = snd_pcm_sw_params_set_sleep_min( p_sys->p_snd_pcm, p_sw, 0 );
662
663     i_snd_rc = snd_pcm_sw_params_set_avail_min( p_sys->p_snd_pcm, p_sw,
664                                                 p_aout->output.i_nb_samples );
665     /* start playing when one period has been written */
666     i_snd_rc = snd_pcm_sw_params_set_start_threshold( p_sys->p_snd_pcm, p_sw,
667                                                       ALSA_DEFAULT_PERIOD_SIZE);
668     if( i_snd_rc < 0 )
669     {
670         msg_Err( p_aout, "unable to set start threshold (%s)",
671                           snd_strerror( i_snd_rc ) );
672         goto error;
673     }
674
675     /* Commit software parameters. */
676     if ( snd_pcm_sw_params( p_sys->p_snd_pcm, p_sw ) < 0 )
677     {
678         msg_Err( p_aout, "unable to set software configuration" );
679         goto error;
680     }
681
682 #ifdef ALSA_DEBUG
683     snd_output_printf( p_sys->p_snd_stderr, "\nALSA hardware setup:\n\n" );
684     snd_pcm_dump_hw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
685     snd_output_printf( p_sys->p_snd_stderr, "\nALSA software setup:\n\n" );
686     snd_pcm_dump_sw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
687     snd_output_printf( p_sys->p_snd_stderr, "\n" );
688 #endif
689
690     p_sys->start_date = 0;
691     vlc_sem_init( &p_sys->wait, 0 );
692
693     /* Create ALSA thread and wait for its readiness. */
694     if( vlc_clone( &p_sys->thread, ALSAThread, p_aout,
695                    VLC_THREAD_PRIORITY_OUTPUT ) )
696     {
697         msg_Err( p_aout, "cannot create ALSA thread (%m)" );
698         vlc_sem_destroy( &p_sys->wait );
699         goto error;
700     }
701
702     return 0;
703
704 error:
705     snd_pcm_close( p_sys->p_snd_pcm );
706 #ifdef ALSA_DEBUG
707     snd_output_close( p_sys->p_snd_stderr );
708 #endif
709     free( p_sys );
710     return VLC_EGENERIC;
711 }
712
713 static void PlayIgnore( aout_instance_t *p_aout )
714 {   /* Already playing - nothing to do */
715     (void) p_aout;
716 }
717
718 /*****************************************************************************
719  * Play: start playback
720  *****************************************************************************/
721 static void Play( aout_instance_t *p_aout )
722 {
723     p_aout->output.pf_play = PlayIgnore;
724
725     /* get the playing date of the first aout buffer */
726     p_aout->output.p_sys->start_date =
727         aout_FifoFirstDate( p_aout, &p_aout->output.fifo );
728
729     /* wake up the audio output thread */
730     sem_post( &p_aout->output.p_sys->wait );
731 }
732
733 /*****************************************************************************
734  * Close: close the ALSA device
735  *****************************************************************************/
736 static void Close( vlc_object_t *p_this )
737 {
738     aout_instance_t *p_aout = (aout_instance_t *)p_this;
739     struct aout_sys_t * p_sys = p_aout->output.p_sys;
740     int i_snd_rc;
741
742     /* Make sure that the thread will stop once it is waken up */
743     vlc_cancel( p_sys->thread );
744     vlc_join( p_sys->thread, NULL );
745     vlc_sem_destroy( &p_sys->wait );
746
747     /* */
748     i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm );
749
750     if( i_snd_rc > 0 )
751     {
752         msg_Err( p_aout, "failed closing ALSA device (%s)",
753                          snd_strerror( i_snd_rc ) );
754     }
755
756 #ifdef ALSA_DEBUG
757     snd_output_close( p_sys->p_snd_stderr );
758 #endif
759
760     free( p_sys );
761 }
762
763 static void pcm_drop(void *pcm)
764 {
765     snd_pcm_drop(pcm);
766 }
767
768 /*****************************************************************************
769  * ALSAThread: asynchronous thread used to DMA the data to the device
770  *****************************************************************************/
771 static void* ALSAThread( void *data )
772 {
773     aout_instance_t * p_aout = data;
774     struct aout_sys_t * p_sys = p_aout->output.p_sys;
775
776     /* Wait for the exact time to start playing (avoids resampling) */
777     vlc_sem_wait( &p_sys->wait );
778     mwait( p_sys->start_date - AOUT_PTS_TOLERANCE / 4 );
779
780     vlc_cleanup_push( pcm_drop, p_sys->p_snd_pcm );
781     for(;;)
782         ALSAFill( p_aout );
783
784     assert(0);
785     vlc_cleanup_pop();
786 }
787
788 /*****************************************************************************
789  * ALSAFill: function used to fill the ALSA buffer as much as possible
790  *****************************************************************************/
791 static void ALSAFill( aout_instance_t * p_aout )
792 {
793     struct aout_sys_t * p_sys = p_aout->output.p_sys;
794     snd_pcm_t *p_pcm = p_sys->p_snd_pcm;
795     snd_pcm_status_t * p_status;
796     int i_snd_rc;
797     mtime_t next_date;
798
799     int canc = vlc_savecancel();
800     /* Fill in the buffer until space or audio output buffer shortage */
801
802     /* Get the status */
803     snd_pcm_status_alloca(&p_status);
804     i_snd_rc = snd_pcm_status( p_pcm, p_status );
805     if( i_snd_rc < 0 )
806     {
807         msg_Err( p_aout, "cannot get device status" );
808         goto error;
809     }
810
811     /* Handle buffer underruns and get the status again */
812     if( snd_pcm_status_get_state( p_status ) == SND_PCM_STATE_XRUN )
813     {
814         /* Prepare the device */
815         i_snd_rc = snd_pcm_prepare( p_pcm );
816         if( i_snd_rc )
817         {
818             msg_Err( p_aout, "cannot recover from buffer underrun" );
819             goto error;
820         }
821
822         msg_Dbg( p_aout, "recovered from buffer underrun" );
823
824         /* Get the new status */
825         i_snd_rc = snd_pcm_status( p_pcm, p_status );
826         if( i_snd_rc < 0 )
827         {
828             msg_Err( p_aout, "cannot get device status after recovery" );
829             goto error;
830         }
831
832         /* Underrun, try to recover as quickly as possible */
833         next_date = mdate();
834     }
835     else
836     {
837         /* Here the device should be in RUNNING state, p_status is valid. */
838         snd_pcm_sframes_t delay = snd_pcm_status_get_delay( p_status );
839         if( delay == 0 ) /* workaround buggy alsa drivers */
840             if( snd_pcm_delay( p_pcm, &delay ) < 0 )
841                 delay = 0; /* FIXME: use a positive minimal delay */
842
843         size_t i_bytes = snd_pcm_frames_to_bytes( p_pcm, delay );
844         mtime_t delay_us = CLOCK_FREQ * i_bytes
845                 / p_aout->output.output.i_bytes_per_frame
846                 / p_aout->output.output.i_rate
847                 * p_aout->output.output.i_frame_length;
848
849 #ifdef ALSA_DEBUG
850         snd_pcm_state_t state = snd_pcm_status_get_state( p_status );
851         if( state != SND_PCM_STATE_RUNNING )
852             msg_Err( p_aout, "pcm status (%d) != RUNNING", state );
853
854         msg_Dbg( p_aout, "Delay is %ld frames (%zu bytes)", delay, i_bytes );
855
856         msg_Dbg( p_aout, "Bytes per frame: %d", p_aout->output.output.i_bytes_per_frame );
857         msg_Dbg( p_aout, "Rate: %d", p_aout->output.output.i_rate );
858         msg_Dbg( p_aout, "Frame length: %d", p_aout->output.output.i_frame_length );
859         msg_Dbg( p_aout, "Next date: in %"PRId64" microseconds", delay_us );
860 #endif
861         next_date = mdate() + delay_us;
862     }
863
864     block_t *p_buffer = aout_OutputNextBuffer( p_aout, next_date,
865            (p_aout->output.output.i_format ==  VLC_CODEC_SPDIFL) );
866
867     /* Audio output buffer shortage -> stop the fill process and wait */
868     if( p_buffer == NULL )
869         goto error;
870
871     block_cleanup_push( p_buffer );
872     for (;;)
873     {
874         int n = snd_pcm_poll_descriptors_count(p_pcm);
875         struct pollfd ufd[n];
876         unsigned short revents;
877
878         snd_pcm_poll_descriptors(p_pcm, ufd, n);
879         do
880         {
881             vlc_restorecancel(canc);
882             poll(ufd, n, -1);
883             canc = vlc_savecancel();
884             snd_pcm_poll_descriptors_revents(p_pcm, ufd, n, &revents);
885         }
886         while(!revents);
887
888         if(revents & POLLOUT)
889         {
890             i_snd_rc = snd_pcm_writei( p_pcm, p_buffer->p_buffer,
891                                        p_buffer->i_nb_samples );
892             if( i_snd_rc != -ESTRPIPE )
893                 break;
894         }
895
896         /* a suspend event occurred
897          * (stream is suspended and waiting for an application recovery) */
898         msg_Dbg( p_aout, "entering in suspend mode, trying to resume..." );
899
900         while( ( i_snd_rc = snd_pcm_resume( p_pcm ) ) == -EAGAIN )
901         {
902             vlc_restorecancel(canc);
903             msleep(CLOCK_FREQ); /* device still suspended, wait... */
904             canc = vlc_savecancel();
905         }
906
907         if( i_snd_rc < 0 )
908             /* Device does not support resuming, restart it */
909             i_snd_rc = snd_pcm_prepare( p_pcm );
910
911     }
912
913     if( i_snd_rc < 0 )
914         msg_Err( p_aout, "cannot write: %s", snd_strerror( i_snd_rc ) );
915
916     vlc_restorecancel(canc);
917     vlc_cleanup_run();
918     return;
919
920 error:
921     if( i_snd_rc < 0 )
922         msg_Err( p_aout, "ALSA error: %s", snd_strerror( i_snd_rc ) );
923
924     vlc_restorecancel(canc);
925     msleep(p_sys->i_period_time / 2);
926 }
927
928 /*****************************************************************************
929  * config variable callback
930  *****************************************************************************/
931 static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
932                                vlc_value_t newval, vlc_value_t oldval, void *p_unused )
933 {
934     module_config_t *p_item;
935     (void)newval;
936     (void)oldval;
937     (void)p_unused;
938
939     p_item = config_FindConfig( p_this, psz_name );
940     if( !p_item ) return VLC_SUCCESS;
941
942     /* Clear-up the current list */
943     if( p_item->i_list )
944     {
945         int i;
946
947         /* Keep the first entrie */
948         for( i = 1; i < p_item->i_list; i++ )
949         {
950             free( (char *)p_item->ppsz_list[i] );
951             free( (char *)p_item->ppsz_list_text[i] );
952         }
953         /* TODO: Remove when no more needed */
954         p_item->ppsz_list[i] = NULL;
955         p_item->ppsz_list_text[i] = NULL;
956     }
957     p_item->i_list = 1;
958
959     GetDevices( p_this, p_item );
960
961     /* Signal change to the interface */
962     p_item->b_dirty = true;
963
964     return VLC_SUCCESS;
965 }
966
967
968 static void GetDevicesForCard( vlc_object_t *obj, module_config_t *p_item,
969                                int i_card )
970 {
971     int i_pcm_device = -1;
972     int i_err = 0;
973     snd_pcm_info_t *p_pcm_info;
974     snd_ctl_t *p_ctl;
975     char psz_dev[4 + 3 * sizeof(int)];
976     char *psz_card_name;
977
978     snprintf( psz_dev, sizeof (psz_dev), "hw:%u", i_card );
979
980     if( ( i_err = snd_ctl_open( &p_ctl, psz_dev, 0 ) ) < 0 )
981         return;
982
983     if( ( i_err = snd_card_get_name( i_card, &psz_card_name ) ) != 0)
984         psz_card_name = _("Unknown soundcard");
985
986     snd_pcm_info_alloca( &p_pcm_info );
987
988     for (;;)
989     {
990         char *psz_device, *psz_descr;
991         if( ( i_err = snd_ctl_pcm_next_device( p_ctl, &i_pcm_device ) ) < 0 )
992             i_pcm_device = -1;
993         if( i_pcm_device < 0 )
994             break;
995
996         snd_pcm_info_set_device( p_pcm_info, i_pcm_device );
997         snd_pcm_info_set_subdevice( p_pcm_info, 0 );
998         snd_pcm_info_set_stream( p_pcm_info, SND_PCM_STREAM_PLAYBACK );
999
1000         if( ( i_err = snd_ctl_pcm_info( p_ctl, p_pcm_info ) ) < 0 )
1001         {
1002             if( i_err != -ENOENT )
1003                 msg_Err( obj, "cannot get PCM device %d:%d infos: %s", i_card,
1004                          i_pcm_device, snd_strerror( -i_err ) );
1005             continue;
1006         }
1007
1008         if( asprintf( &psz_device, "plughw:%u,%u", i_card, i_pcm_device ) == -1 )
1009             continue;
1010         if( asprintf( &psz_descr, "%s: %s (%s)", psz_card_name,
1011                   snd_pcm_info_get_name(p_pcm_info), psz_device ) == -1 )
1012         {
1013             free( psz_device );
1014             continue;
1015         }
1016
1017         msg_Dbg( obj, "  %s", psz_descr );
1018
1019         if( p_item )
1020         {
1021             p_item->ppsz_list = xrealloc( p_item->ppsz_list,
1022                                   (p_item->i_list + 2) * sizeof(char *) );
1023             p_item->ppsz_list_text = xrealloc( p_item->ppsz_list_text,
1024                                   (p_item->i_list + 2) * sizeof(char *) );
1025             p_item->ppsz_list[ p_item->i_list ] = psz_device;
1026             p_item->ppsz_list_text[ p_item->i_list ] = psz_descr;
1027             p_item->i_list++;
1028             p_item->ppsz_list[ p_item->i_list ] = NULL;
1029             p_item->ppsz_list_text[ p_item->i_list ] = NULL;
1030         }
1031         else
1032         {
1033             free( psz_device );
1034             free( psz_descr );
1035         }
1036     }
1037
1038     snd_ctl_close( p_ctl );
1039 }
1040
1041
1042 static void GetDevices( vlc_object_t *obj, module_config_t *p_item )
1043 {
1044     int i_card = -1;
1045     int i_err;
1046
1047     msg_Dbg( obj, "Available alsa output devices:" );
1048     while( (i_err = snd_card_next( &i_card )) == 0 && i_card > -1 )
1049         GetDevicesForCard( obj, p_item, i_card );
1050
1051     if( i_err )
1052         msg_Err( obj, "cannot enumerate cards: %s", snd_strerror( -i_err ) );
1053 }