1 /*****************************************************************************
2 * alsa.c : alsa plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2000-2001 the VideoLAN team
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
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.
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.
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 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
32 #include <errno.h> /* ENOMEM */
33 #include <vlc_interface.h>
38 Note: we use the new API which is available since 0.9.0beta10a. */
39 #define ALSA_PCM_NEW_HW_PARAMS_API
40 #define ALSA_PCM_NEW_SW_PARAMS_API
41 #include <alsa/asoundlib.h>
43 /*#define ALSA_DEBUG*/
45 /*****************************************************************************
46 * aout_sys_t: ALSA audio output method descriptor
47 *****************************************************************************
48 * This structure is part of the audio output thread descriptor.
49 * It describes the ALSA specific properties of an audio device.
50 *****************************************************************************/
53 snd_pcm_t * p_snd_pcm;
54 unsigned int i_period_time;
57 snd_output_t * p_snd_stderr;
60 int b_playing; /* playing status */
66 snd_pcm_status_t *p_status;
69 #define A52_FRAME_NB 1536
71 /* These values are in frames.
72 To convert them to a number of bytes you have to multiply them by the
73 number of channel(s) (eg. 2 for stereo) and the size of a sample (eg.
75 #define ALSA_DEFAULT_PERIOD_SIZE 1024
76 #define ALSA_DEFAULT_BUFFER_SIZE ( ALSA_DEFAULT_PERIOD_SIZE << 8 )
77 #define ALSA_SPDIF_PERIOD_SIZE A52_FRAME_NB
78 #define ALSA_SPDIF_BUFFER_SIZE ( ALSA_SPDIF_PERIOD_SIZE << 4 )
79 /* Why << 4 ? --Meuuh */
80 /* Why not ? --Bozo */
83 #define DEFAULT_ALSA_DEVICE N_("default")
85 /*****************************************************************************
87 *****************************************************************************/
88 static int Open ( vlc_object_t * );
89 static void Close ( vlc_object_t * );
90 static void Play ( aout_instance_t * );
91 static int ALSAThread ( aout_instance_t * );
92 static void ALSAFill ( aout_instance_t * );
93 static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
94 vlc_value_t newval, vlc_value_t oldval, void *p_unused );
96 /*****************************************************************************
98 *****************************************************************************/
99 static const char *ppsz_devices[] = { "default" };
100 static const char *ppsz_devices_text[] = { N_("Default") };
102 set_shortname( "ALSA" );
103 set_description( _("ALSA audio output") );
104 set_category( CAT_AUDIO );
105 set_subcategory( SUBCAT_AUDIO_AOUT );
106 add_string( "alsadev", DEFAULT_ALSA_DEVICE, aout_FindAndRestart,
107 N_("ALSA Device Name"), NULL, VLC_FALSE );
109 change_string_list( ppsz_devices, ppsz_devices_text, FindDevicesCallback );
110 change_action_add( FindDevicesCallback, N_("Refresh list") );
112 set_capability( "audio output", 150 );
113 set_callbacks( Open, Close );
116 /*****************************************************************************
117 * Probe: probe the audio device for available formats and channels
118 *****************************************************************************/
119 static void Probe( aout_instance_t * p_aout,
120 const char * psz_device, const char * psz_iec_device,
121 int *pi_snd_pcm_format )
123 struct aout_sys_t * p_sys = p_aout->output.p_sys;
124 vlc_value_t val, text;
127 var_Create ( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
128 text.psz_string = _("Audio Device");
129 var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
131 /* We'll open the audio device in non blocking mode so we can just exit
132 * when it is already in use, but for the real stuff we'll still use
133 * the blocking mode */
135 /* Now test linear PCM capabilities */
136 if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
137 SND_PCM_STREAM_PLAYBACK,
138 SND_PCM_NONBLOCK ) ) )
141 snd_pcm_hw_params_t * p_hw;
142 snd_pcm_hw_params_alloca (&p_hw);
144 if ( snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) < 0 )
146 msg_Warn( p_aout, "unable to retrieve initial hardware parameters"
147 ", disabling linear PCM audio" );
148 snd_pcm_close( p_sys->p_snd_pcm );
149 var_Destroy( p_aout, "audio-device" );
153 if ( snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
154 *pi_snd_pcm_format ) < 0 )
158 if( *pi_snd_pcm_format != SND_PCM_FORMAT_S16 )
160 *pi_snd_pcm_format = SND_PCM_FORMAT_S16;
161 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
162 p_hw, *pi_snd_pcm_format );
166 msg_Warn( p_aout, "unable to set stream sample size and "
167 "word order, disabling linear PCM audio" );
168 snd_pcm_close( p_sys->p_snd_pcm );
169 var_Destroy( p_aout, "audio-device" );
174 i_channels = aout_FormatNbChannels( &p_aout->output.output );
176 while ( i_channels > 0 )
178 if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw,
181 switch ( i_channels )
184 val.i_int = AOUT_VAR_MONO;
185 text.psz_string = N_("Mono");
186 var_Change( p_aout, "audio-device",
187 VLC_VAR_ADDCHOICE, &val, &text );
190 val.i_int = AOUT_VAR_STEREO;
191 text.psz_string = N_("Stereo");
192 var_Change( p_aout, "audio-device",
193 VLC_VAR_ADDCHOICE, &val, &text );
194 var_Set( p_aout, "audio-device", val );
197 val.i_int = AOUT_VAR_2F2R;
198 text.psz_string = N_("2 Front 2 Rear");
199 var_Change( p_aout, "audio-device",
200 VLC_VAR_ADDCHOICE, &val, &text );
203 val.i_int = AOUT_VAR_5_1;
204 text.psz_string = "5.1";
205 var_Change( p_aout, "audio-device",
206 VLC_VAR_ADDCHOICE, &val, &text );
214 /* Special case for mono on stereo only boards */
215 i_channels = aout_FormatNbChannels( &p_aout->output.output );
216 var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
217 if( val.i_int <= 0 && i_channels == 1 )
219 if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw, 2 ))
221 val.i_int = AOUT_VAR_STEREO;
222 text.psz_string = N_("Stereo");
223 var_Change( p_aout, "audio-device",
224 VLC_VAR_ADDCHOICE, &val, &text );
225 var_Set( p_aout, "audio-device", val );
229 /* Close the previously opened device */
230 snd_pcm_close( p_sys->p_snd_pcm );
232 else if ( i_ret == -EBUSY )
234 msg_Warn( p_aout, "audio device: %s is already in use", psz_device );
237 /* Test for S/PDIF device if needed */
238 if ( psz_iec_device )
240 /* Opening the device should be enough */
241 if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
242 SND_PCM_STREAM_PLAYBACK,
243 SND_PCM_NONBLOCK ) ) )
245 val.i_int = AOUT_VAR_SPDIF;
246 text.psz_string = N_("A/52 over S/PDIF");
247 var_Change( p_aout, "audio-device",
248 VLC_VAR_ADDCHOICE, &val, &text );
249 if( config_GetInt( p_aout, "spdif" ) )
250 var_Set( p_aout, "audio-device", val );
252 snd_pcm_close( p_sys->p_snd_pcm );
254 else if ( i_ret == -EBUSY )
256 msg_Warn( p_aout, "audio device: %s is already in use",
261 var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
264 /* Probe() has failed. */
265 msg_Dbg( p_aout, "failed to find a useable alsa configuration" );
266 var_Destroy( p_aout, "audio-device" );
270 /* Add final settings to the variable */
271 var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
272 val.b_bool = VLC_TRUE;
273 var_Set( p_aout, "intf-change", val );
276 /*****************************************************************************
277 * Open: create a handle and open an alsa device
278 *****************************************************************************
279 * This function opens an alsa device, through the alsa API.
281 * Note: the only heap-allocated string is psz_device. All the other pointers
282 * are references to psz_device or to stack-allocated data.
283 *****************************************************************************/
284 static int Open( vlc_object_t *p_this )
286 aout_instance_t * p_aout = (aout_instance_t *)p_this;
287 struct aout_sys_t * p_sys;
290 char psz_default_iec_device[128]; /* Buffer used to store the default
292 char * psz_device, * psz_iec_device; /* device names for PCM and S/PDIF
295 int i_vlc_pcm_format; /* Audio format for VLC's data */
296 int i_snd_pcm_format; /* Audio format for ALSA's data */
298 snd_pcm_uframes_t i_buffer_size = 0;
299 snd_pcm_uframes_t i_period_size = 0;
302 snd_pcm_hw_params_t *p_hw;
303 snd_pcm_sw_params_t *p_sw;
306 unsigned int i_old_rate;
307 vlc_bool_t b_retry = VLC_TRUE;
309 /* Allocate structures */
310 p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );
313 msg_Err( p_aout, "out of memory" );
316 p_sys->b_playing = VLC_FALSE;
317 p_sys->start_date = 0;
318 vlc_cond_init( p_aout, &p_sys->wait );
319 vlc_mutex_init( p_aout, &p_sys->lock );
321 /* Get device name */
322 if( (psz_device = config_GetPsz( p_aout, "alsadev" )) == NULL )
324 msg_Err( p_aout, "no audio device given (maybe \"default\" ?)" );
325 intf_UserFatal( p_aout, VLC_FALSE, _("No Audio Device"),
326 _("No audio device name was given. You might want to " \
327 "enter \"default\".") );
332 /* Choose the IEC device for S/PDIF output:
333 if the device is overriden by the user then it will be the one
334 otherwise we compute the default device based on the output format. */
335 if( AOUT_FMT_NON_LINEAR( &p_aout->output.output )
336 && !strcmp( psz_device, DEFAULT_ALSA_DEVICE ) )
338 snprintf( psz_default_iec_device, sizeof(psz_default_iec_device),
339 "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
340 IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
341 IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
343 ( p_aout->output.output.i_rate == 48000 ?
344 IEC958_AES3_CON_FS_48000 :
345 ( p_aout->output.output.i_rate == 44100 ?
346 IEC958_AES3_CON_FS_44100 : IEC958_AES3_CON_FS_32000 ) ) );
347 psz_iec_device = psz_default_iec_device;
349 else if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
351 psz_iec_device = psz_device;
355 psz_iec_device = NULL;
358 /* Choose the linear PCM format (read the comment above about FPU
360 if( vlc_CPU() & CPU_CAPABILITY_FPU )
362 i_vlc_pcm_format = VLC_FOURCC('f','l','3','2');
363 i_snd_pcm_format = SND_PCM_FORMAT_FLOAT;
367 i_vlc_pcm_format = AOUT_FMT_S16_NE;
368 i_snd_pcm_format = SND_PCM_FORMAT_S16;
371 /* If the variable doesn't exist then it's the first time we're called
372 and we have to probe the available audio formats and channels */
373 if ( var_Type( p_aout, "audio-device" ) == 0 )
375 Probe( p_aout, psz_device, psz_iec_device, &i_snd_pcm_format );
378 if ( var_Get( p_aout, "audio-device", &val ) < 0 )
385 p_aout->output.output.i_format = i_vlc_pcm_format;
386 if ( val.i_int == AOUT_VAR_5_1 )
388 p_aout->output.output.i_physical_channels
389 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
390 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
393 psz_device = strdup( "surround51" );
395 else if ( val.i_int == AOUT_VAR_2F2R )
397 p_aout->output.output.i_physical_channels
398 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
399 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
401 psz_device = strdup( "surround40" );
403 else if ( val.i_int == AOUT_VAR_STEREO )
405 p_aout->output.output.i_physical_channels
406 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
408 else if ( val.i_int == AOUT_VAR_MONO )
410 p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
412 else if( val.i_int != AOUT_VAR_SPDIF )
414 /* This should not happen ! */
415 msg_Err( p_aout, "internal: can't find audio-device (%i)", val.i_int );
422 snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 );
425 /* Open the device */
426 if ( val.i_int == AOUT_VAR_SPDIF )
428 if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
429 SND_PCM_STREAM_PLAYBACK, 0 ) ) < 0 )
431 msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
432 psz_iec_device, snd_strerror( i_snd_rc ) );
433 intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"),
434 _("VLC could not open the ALSA device \"%s\" (%s)."),
435 psz_iec_device, snd_strerror( i_snd_rc ) );
440 i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
441 i_snd_pcm_format = SND_PCM_FORMAT_S16;
444 i_vlc_pcm_format = VLC_FOURCC('s','p','d','i');
445 p_aout->output.i_nb_samples = i_period_size = ALSA_SPDIF_PERIOD_SIZE;
446 p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
447 p_aout->output.output.i_frame_length = A52_FRAME_NB;
449 aout_VolumeNoneInit( p_aout );
455 msg_Dbg( p_aout, "opening ALSA device `%s'", psz_device );
457 /* Since it seems snd_pcm_close hasn't really released the device at
458 the time it returns, probe if the device is available in loop for 1s.
459 We cannot use blocking mode since the we would wait indefinitely when
460 switching from a dmx device to surround51. */
462 for( i = 10; i >= 0; i-- )
464 if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
465 SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) ) == -EBUSY )
467 if( i ) msleep( 100000 /* 100ms */ );
470 msg_Err( p_aout, "audio device: %s is already in use",
472 intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"),
473 _("The audio device \"%s\" is already in use."),
482 msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
483 psz_device, snd_strerror( i_snd_rc ) );
484 intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"),
485 _("VLC could not open the ALSA device \"%s\" (%s)."),
486 psz_device, snd_strerror( i_snd_rc ) );
492 /* We want blocking mode */
493 snd_pcm_nonblock( p_sys->p_snd_pcm, 0 );
495 i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
496 i_channels = aout_FormatNbChannels( &p_aout->output.output );
498 p_aout->output.i_nb_samples = i_period_size = ALSA_DEFAULT_PERIOD_SIZE;
500 aout_VolumeSoftInit( p_aout );
503 /* Free psz_device so that all the remaining data is stack-allocated */
506 p_aout->output.pf_play = Play;
508 snd_pcm_hw_params_alloca(&p_hw);
509 snd_pcm_sw_params_alloca(&p_sw);
511 /* Due to some bugs in alsa with some drivers, we need to retry in s16l
512 if snd_pcm_hw_params fails in fl32 */
517 /* Get Initial hardware parameters */
518 if ( ( i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) ) < 0 )
520 msg_Err( p_aout, "unable to retrieve initial hardware parameters (%s)",
521 snd_strerror( i_snd_rc ) );
526 if ( ( i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
527 i_snd_pcm_format ) ) < 0 )
529 if( i_snd_pcm_format != SND_PCM_FORMAT_S16 )
531 i_snd_pcm_format = SND_PCM_FORMAT_S16;
532 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
533 p_hw, i_snd_pcm_format );
537 msg_Err( p_aout, "unable to set stream sample size and "
538 "word order (%s)", snd_strerror( i_snd_rc ) );
542 if( i_vlc_pcm_format != VLC_FOURCC('s','p','d','i') )
543 switch( i_snd_pcm_format )
545 case SND_PCM_FORMAT_FLOAT:
546 i_vlc_pcm_format = VLC_FOURCC('f','l','3','2');
548 case SND_PCM_FORMAT_S16:
549 i_vlc_pcm_format = AOUT_FMT_S16_NE;
552 p_aout->output.output.i_format = i_vlc_pcm_format;
554 if ( ( i_snd_rc = snd_pcm_hw_params_set_access( p_sys->p_snd_pcm, p_hw,
555 SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 )
557 msg_Err( p_aout, "unable to set interleaved stream format (%s)",
558 snd_strerror( i_snd_rc ) );
563 if ( ( i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw,
566 msg_Err( p_aout, "unable to set number of output channels (%s)",
567 snd_strerror( i_snd_rc ) );
572 i_old_rate = p_aout->output.output.i_rate;
573 #ifdef HAVE_ALSA_NEW_API
574 i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm, p_hw,
575 &p_aout->output.output.i_rate,
578 i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm, p_hw,
579 p_aout->output.output.i_rate,
582 if( i_snd_rc < 0 || p_aout->output.output.i_rate != i_old_rate )
584 msg_Warn( p_aout, "The rate %d Hz is not supported by your " \
585 "hardware. Using %d Hz instead.\n", i_old_rate, \
586 p_aout->output.output.i_rate );
589 /* Set buffer size. */
590 #ifdef HAVE_ALSA_NEW_API
591 if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,
592 p_hw, &i_buffer_size ) ) < 0 )
594 if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,
595 p_hw, i_buffer_size ) ) < 0 )
598 msg_Err( p_aout, "unable to set buffer size (%s)",
599 snd_strerror( i_snd_rc ) );
603 /* Set period size. */
604 #ifdef HAVE_ALSA_NEW_API
605 if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,
606 p_hw, &i_period_size, NULL ) ) < 0 )
608 if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,
609 p_hw, i_period_size, NULL ) ) < 0 )
612 msg_Err( p_aout, "unable to set period size (%s)",
613 snd_strerror( i_snd_rc ) );
616 p_aout->output.i_nb_samples = i_period_size;
618 /* Commit hardware parameters. */
619 if ( ( i_snd_rc = snd_pcm_hw_params( p_sys->p_snd_pcm, p_hw ) ) < 0 )
621 if ( b_retry == VLC_FALSE &&
622 i_snd_pcm_format == SND_PCM_FORMAT_FLOAT)
625 i_snd_pcm_format = SND_PCM_FORMAT_S16;
626 p_aout->output.output.i_format = AOUT_FMT_S16_NE;
627 msg_Warn( p_aout, "unable to commit hardware configuration "
628 "with fl32 samples. Retrying with s16l (%s)", snd_strerror( i_snd_rc ) );
632 msg_Err( p_aout, "unable to commit hardware configuration (%s)",
633 snd_strerror( i_snd_rc ) );
639 #ifdef HAVE_ALSA_NEW_API
640 if( ( i_snd_rc = snd_pcm_hw_params_get_period_time( p_hw,
641 &p_sys->i_period_time, NULL ) ) < 0 )
643 if( ( p_sys->i_period_time =
644 (int)snd_pcm_hw_params_get_period_time( p_hw, NULL ) ) < 0 )
647 msg_Err( p_aout, "unable to get period time (%s)",
648 snd_strerror( i_snd_rc ) );
652 /* Get Initial software parameters */
653 snd_pcm_sw_params_current( p_sys->p_snd_pcm, p_sw );
655 i_snd_rc = snd_pcm_sw_params_set_sleep_min( p_sys->p_snd_pcm, p_sw, 0 );
657 i_snd_rc = snd_pcm_sw_params_set_avail_min( p_sys->p_snd_pcm, p_sw,
658 p_aout->output.i_nb_samples );
659 /* start playing when one period has been written */
660 i_snd_rc = snd_pcm_sw_params_set_start_threshold( p_sys->p_snd_pcm, p_sw,
661 ALSA_DEFAULT_PERIOD_SIZE);
664 msg_Err( p_aout, "unable to set start threshold (%s)",
665 snd_strerror( i_snd_rc ) );
669 /* Commit software parameters. */
670 if ( snd_pcm_sw_params( p_sys->p_snd_pcm, p_sw ) < 0 )
672 msg_Err( p_aout, "unable to set software configuration" );
677 snd_output_printf( p_sys->p_snd_stderr, "\nALSA hardware setup:\n\n" );
678 snd_pcm_dump_hw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
679 snd_output_printf( p_sys->p_snd_stderr, "\nALSA software setup:\n\n" );
680 snd_pcm_dump_sw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
681 snd_output_printf( p_sys->p_snd_stderr, "\n" );
684 /* Create ALSA thread and wait for its readiness. */
685 if( vlc_thread_create( p_aout, "aout", ALSAThread,
686 VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
688 msg_Err( p_aout, "cannot create ALSA thread (%m)" );
695 snd_pcm_close( p_sys->p_snd_pcm );
697 snd_output_close( p_sys->p_snd_stderr );
703 /*****************************************************************************
704 * Play: nothing to do
705 *****************************************************************************/
706 static void Play( aout_instance_t *p_aout )
708 if( !p_aout->output.p_sys->b_playing )
710 p_aout->output.p_sys->b_playing = 1;
712 /* get the playing date of the first aout buffer */
713 p_aout->output.p_sys->start_date =
714 aout_FifoFirstDate( p_aout, &p_aout->output.fifo );
716 /* wake up the audio output thread */
717 vlc_mutex_lock( &p_aout->output.p_sys->lock );
718 vlc_cond_signal( &p_aout->output.p_sys->wait );
719 vlc_mutex_unlock( &p_aout->output.p_sys->lock );
723 /*****************************************************************************
724 * Close: close the ALSA device
725 *****************************************************************************/
726 static void Close( vlc_object_t *p_this )
728 aout_instance_t *p_aout = (aout_instance_t *)p_this;
729 struct aout_sys_t * p_sys = p_aout->output.p_sys;
732 /* make sure the audio output thread is waken up */
733 vlc_mutex_lock( &p_aout->output.p_sys->lock );
734 vlc_cond_signal( &p_aout->output.p_sys->wait );
735 vlc_mutex_unlock( &p_aout->output.p_sys->lock );
737 vlc_object_kill( p_aout );
738 vlc_thread_join( p_aout );
739 p_aout->b_die = VLC_FALSE;
741 i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm );
745 msg_Err( p_aout, "failed closing ALSA device (%s)",
746 snd_strerror( i_snd_rc ) );
750 snd_output_close( p_sys->p_snd_stderr );
756 /*****************************************************************************
757 * ALSAThread: asynchronous thread used to DMA the data to the device
758 *****************************************************************************/
759 static int ALSAThread( aout_instance_t * p_aout )
761 struct aout_sys_t * p_sys = p_aout->output.p_sys;
762 p_sys->p_status = (snd_pcm_status_t *)malloc(snd_pcm_status_sizeof());
764 /* Wait for the exact time to start playing (avoids resampling) */
765 vlc_mutex_lock( &p_sys->lock );
766 while( !p_sys->start_date && !p_aout->b_die )
767 vlc_cond_wait( &p_sys->wait, &p_sys->lock );
768 vlc_mutex_unlock( &p_sys->lock );
773 mwait( p_sys->start_date - AOUT_PTS_TOLERANCE / 4 );
775 while ( !p_aout->b_die )
781 snd_pcm_drop( p_sys->p_snd_pcm );
782 free( p_aout->output.p_sys->p_status );
786 /*****************************************************************************
787 * ALSAFill: function used to fill the ALSA buffer as much as possible
788 *****************************************************************************/
789 static void ALSAFill( aout_instance_t * p_aout )
791 struct aout_sys_t * p_sys = p_aout->output.p_sys;
792 aout_buffer_t * p_buffer;
793 snd_pcm_status_t * p_status = p_sys->p_status;
797 /* Fill in the buffer until space or audio output buffer shortage */
800 i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );
803 msg_Err( p_aout, "cannot get device status" );
807 /* Handle buffer underruns and get the status again */
808 if( snd_pcm_status_get_state( p_status ) == SND_PCM_STATE_XRUN )
810 /* Prepare the device */
811 i_snd_rc = snd_pcm_prepare( p_sys->p_snd_pcm );
815 msg_Err( p_aout, "cannot recover from buffer underrun" );
819 msg_Dbg( p_aout, "recovered from buffer underrun" );
821 /* Get the new status */
822 i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );
825 msg_Err( p_aout, "cannot get device status after recovery" );
829 /* Underrun, try to recover as quickly as possible */
834 /* Here the device should be in RUNNING state.
835 * p_status is valid. */
836 snd_pcm_sframes_t delay = snd_pcm_status_get_delay( p_status );
837 int i_bytes = snd_pcm_frames_to_bytes( p_sys->p_snd_pcm, delay );
838 next_date = mdate() + ( (mtime_t)i_bytes * 1000000
839 / p_aout->output.output.i_bytes_per_frame
840 / p_aout->output.output.i_rate
841 * p_aout->output.output.i_frame_length );
844 snd_pcm_state_t state = snd_pcm_status_get_state( p_status );
845 if( state != SND_PCM_STATE_RUNNING )
846 msg_Err( p_aout, "pcm status (%d) != RUNNING", state );
848 msg_Dbg( p_aout, "Delay is %ld frames (%d bytes)", delay, i_bytes );
850 msg_Dbg( p_aout, "Bytes per frame: %d", p_aout->output.output.i_bytes_per_frame );
851 msg_Dbg( p_aout, "Rate: %d", p_aout->output.output.i_rate );
852 msg_Dbg( p_aout, "Frame length: %d", p_aout->output.output.i_frame_length );
854 msg_Dbg( p_aout, "Next date is in %d microseconds", (int)(next_date - mdate()) );
858 p_buffer = aout_OutputNextBuffer( p_aout, next_date,
859 (p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i')) );
861 /* Audio output buffer shortage -> stop the fill process and wait */
862 if( p_buffer == NULL )
867 i_snd_rc = snd_pcm_writei( p_sys->p_snd_pcm, p_buffer->p_buffer,
868 p_buffer->i_nb_samples );
869 if( i_snd_rc != -ESTRPIPE )
872 /* a suspend event occurred
873 * (stream is suspended and waiting for an application recovery) */
874 msg_Dbg( p_aout, "entering in suspend mode, trying to resume..." );
876 while( !p_aout->b_die && !p_aout->p_libvlc->b_die &&
877 ( i_snd_rc = snd_pcm_resume( p_sys->p_snd_pcm ) ) == -EAGAIN )
883 /* Device does not supprot resuming, restart it */
884 i_snd_rc = snd_pcm_prepare( p_sys->p_snd_pcm );
889 msg_Err( p_aout, "cannot write: %s", snd_strerror( i_snd_rc ) );
891 aout_BufferFree( p_buffer );
896 msg_Err( p_aout, "ALSA error: %s", snd_strerror( i_snd_rc ) );
897 msleep( p_sys->i_period_time >> 1 );
900 static void GetDevicesForCard( module_config_t *p_item, int i_card );
901 static void GetDevices( module_config_t *p_item );
903 /*****************************************************************************
904 * config variable callback
905 *****************************************************************************/
906 static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
907 vlc_value_t newval, vlc_value_t oldval, void *p_unused )
909 module_config_t *p_item;
912 p_item = config_FindConfig( p_this, psz_name );
913 if( !p_item ) return VLC_SUCCESS;
915 /* Clear-up the current list */
918 /* Keep the first entrie */
919 for( i = 1; i < p_item->i_list; i++ )
921 free( (char *)p_item->ppsz_list[i] );
922 free( (char *)p_item->ppsz_list_text[i] );
924 /* TODO: Remove when no more needed */
925 p_item->ppsz_list[i] = NULL;
926 p_item->ppsz_list_text[i] = NULL;
930 GetDevices( p_item );
932 /* Signal change to the interface */
933 p_item->b_dirty = VLC_TRUE;
940 static void GetDevicesForCard( module_config_t *p_item, int i_card )
942 int i_pcm_device = -1;
944 snd_pcm_info_t *p_pcm_info;
949 sprintf( psz_dev, "hw:%i", i_card );
951 if( ( i_err = snd_ctl_open( &p_ctl, psz_dev, 0 ) ) < 0 )
954 if( ( i_err = snd_card_get_name( i_card, &psz_card_name ) ) != 0)
955 psz_card_name = _("Unknown soundcard");
957 snd_pcm_info_alloca( &p_pcm_info );
961 char *psz_device, *psz_descr;
962 if( ( i_err = snd_ctl_pcm_next_device( p_ctl, &i_pcm_device ) ) < 0 )
964 if( i_pcm_device < 0 )
967 snd_pcm_info_set_device( p_pcm_info, i_pcm_device );
968 snd_pcm_info_set_subdevice( p_pcm_info, 0 );
969 snd_pcm_info_set_stream( p_pcm_info, SND_PCM_STREAM_PLAYBACK );
971 if( ( i_err = snd_ctl_pcm_info( p_ctl, p_pcm_info ) ) < 0 )
973 if( i_err != -ENOENT )
975 /*printf( "get_devices_for_card(): "
976 "snd_ctl_pcm_info() "
977 "failed (%d:%d): %s.\n", i_card,
978 i_pcm_device, snd_strerror( -i_err ) );*/
983 asprintf( &psz_device, "hw:%d,%d", i_card, i_pcm_device );
984 asprintf( &psz_descr, "%s: %s (%s)", psz_card_name,
985 snd_pcm_info_get_name(p_pcm_info), psz_device );
988 (const char **)realloc( p_item->ppsz_list,
989 (p_item->i_list + 2) * sizeof(char *) );
990 p_item->ppsz_list_text =
991 (const char **)realloc( p_item->ppsz_list_text,
992 (p_item->i_list + 2) * sizeof(char *) );
993 p_item->ppsz_list[ p_item->i_list ] = psz_device;
994 p_item->ppsz_list_text[ p_item->i_list ] = psz_descr;
996 p_item->ppsz_list[ p_item->i_list ] = NULL;
997 p_item->ppsz_list_text[ p_item->i_list ] = NULL;
1000 snd_ctl_close( p_ctl );
1005 static void GetDevices( module_config_t *p_item )
1010 if( ( i_err = snd_card_next( &i_card ) ) != 0 )
1012 /*printf( "snd_card_next() failed: %s", snd_strerror( -i_err ) );*/
1016 while( i_card > -1 )
1018 GetDevicesForCard( p_item, i_card );
1019 if( ( i_err = snd_card_next( &i_card ) ) != 0 )
1021 /*printf( "snd_card_next() failed: %s", snd_strerror( -i_err ) );*/