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 *****************************************************************************/
36 #include <errno.h> /* ENOMEM */
37 #include <vlc_interface.h>
42 Note: we use the new API which is available since 0.9.0beta10a. */
43 #define ALSA_PCM_NEW_HW_PARAMS_API
44 #define ALSA_PCM_NEW_SW_PARAMS_API
45 #include <alsa/asoundlib.h>
47 /*#define ALSA_DEBUG*/
49 /*****************************************************************************
50 * aout_sys_t: ALSA audio output method descriptor
51 *****************************************************************************
52 * This structure is part of the audio output thread descriptor.
53 * It describes the ALSA specific properties of an audio device.
54 *****************************************************************************/
57 snd_pcm_t * p_snd_pcm;
58 unsigned int i_period_time;
61 snd_output_t * p_snd_stderr;
64 int b_playing; /* playing status */
70 snd_pcm_status_t *p_status;
73 #define A52_FRAME_NB 1536
75 /* These values are in frames.
76 To convert them to a number of bytes you have to multiply them by the
77 number of channel(s) (eg. 2 for stereo) and the size of a sample (eg.
79 #define ALSA_DEFAULT_PERIOD_SIZE 1024
80 #define ALSA_DEFAULT_BUFFER_SIZE ( ALSA_DEFAULT_PERIOD_SIZE << 8 )
81 #define ALSA_SPDIF_PERIOD_SIZE A52_FRAME_NB
82 #define ALSA_SPDIF_BUFFER_SIZE ( ALSA_SPDIF_PERIOD_SIZE << 4 )
83 /* Why << 4 ? --Meuuh */
84 /* Why not ? --Bozo */
87 #define DEFAULT_ALSA_DEVICE N_("default")
89 /*****************************************************************************
91 *****************************************************************************/
92 static int Open ( vlc_object_t * );
93 static void Close ( vlc_object_t * );
94 static void Play ( aout_instance_t * );
95 static int ALSAThread ( aout_instance_t * );
96 static void ALSAFill ( aout_instance_t * );
97 static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
98 vlc_value_t newval, vlc_value_t oldval, void *p_unused );
100 /*****************************************************************************
102 *****************************************************************************/
103 static const char *ppsz_devices[] = { "default" };
104 static const char *ppsz_devices_text[] = { N_("Default") };
106 set_shortname( "ALSA" );
107 set_description( _("ALSA audio output") );
108 set_category( CAT_AUDIO );
109 set_subcategory( SUBCAT_AUDIO_AOUT );
110 add_string( "alsadev", DEFAULT_ALSA_DEVICE, aout_FindAndRestart,
111 N_("ALSA Device Name"), NULL, VLC_FALSE );
112 change_string_list( ppsz_devices, ppsz_devices_text, FindDevicesCallback );
113 change_action_add( FindDevicesCallback, N_("Refresh list") );
115 set_capability( "audio output", 150 );
116 set_callbacks( Open, Close );
119 /*****************************************************************************
120 * Probe: probe the audio device for available formats and channels
121 *****************************************************************************/
122 static void Probe( aout_instance_t * p_aout,
123 const char * psz_device, const char * psz_iec_device,
124 int *pi_snd_pcm_format )
126 struct aout_sys_t * p_sys = p_aout->output.p_sys;
127 vlc_value_t val, text;
130 var_Create ( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
131 text.psz_string = _("Audio Device");
132 var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
134 /* We'll open the audio device in non blocking mode so we can just exit
135 * when it is already in use, but for the real stuff we'll still use
136 * the blocking mode */
138 /* Now test linear PCM capabilities */
139 if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
140 SND_PCM_STREAM_PLAYBACK,
141 SND_PCM_NONBLOCK ) ) )
144 snd_pcm_hw_params_t * p_hw;
145 snd_pcm_hw_params_alloca (&p_hw);
147 if ( snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) < 0 )
149 msg_Warn( p_aout, "unable to retrieve initial hardware parameters"
150 ", disabling linear PCM audio" );
151 snd_pcm_close( p_sys->p_snd_pcm );
152 var_Destroy( p_aout, "audio-device" );
156 if ( snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
157 *pi_snd_pcm_format ) < 0 )
161 if( *pi_snd_pcm_format != SND_PCM_FORMAT_S16 )
163 *pi_snd_pcm_format = SND_PCM_FORMAT_S16;
164 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
165 p_hw, *pi_snd_pcm_format );
169 msg_Warn( p_aout, "unable to set stream sample size and "
170 "word order, disabling linear PCM audio" );
171 snd_pcm_close( p_sys->p_snd_pcm );
172 var_Destroy( p_aout, "audio-device" );
177 i_channels = aout_FormatNbChannels( &p_aout->output.output );
179 while ( i_channels > 0 )
181 if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw,
184 switch ( i_channels )
187 val.i_int = AOUT_VAR_MONO;
188 text.psz_string = N_("Mono");
189 var_Change( p_aout, "audio-device",
190 VLC_VAR_ADDCHOICE, &val, &text );
193 val.i_int = AOUT_VAR_STEREO;
194 text.psz_string = N_("Stereo");
195 var_Change( p_aout, "audio-device",
196 VLC_VAR_ADDCHOICE, &val, &text );
197 var_Set( p_aout, "audio-device", val );
200 val.i_int = AOUT_VAR_2F2R;
201 text.psz_string = N_("2 Front 2 Rear");
202 var_Change( p_aout, "audio-device",
203 VLC_VAR_ADDCHOICE, &val, &text );
206 val.i_int = AOUT_VAR_5_1;
207 text.psz_string = "5.1";
208 var_Change( p_aout, "audio-device",
209 VLC_VAR_ADDCHOICE, &val, &text );
217 /* Special case for mono on stereo only boards */
218 i_channels = aout_FormatNbChannels( &p_aout->output.output );
219 var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
220 if( val.i_int <= 0 && i_channels == 1 )
222 if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw, 2 ))
224 val.i_int = AOUT_VAR_STEREO;
225 text.psz_string = N_("Stereo");
226 var_Change( p_aout, "audio-device",
227 VLC_VAR_ADDCHOICE, &val, &text );
228 var_Set( p_aout, "audio-device", val );
232 /* Close the previously opened device */
233 snd_pcm_close( p_sys->p_snd_pcm );
235 else if ( i_ret == -EBUSY )
237 msg_Warn( p_aout, "audio device: %s is already in use", psz_device );
240 /* Test for S/PDIF device if needed */
241 if ( psz_iec_device )
243 /* Opening the device should be enough */
244 if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
245 SND_PCM_STREAM_PLAYBACK,
246 SND_PCM_NONBLOCK ) ) )
248 val.i_int = AOUT_VAR_SPDIF;
249 text.psz_string = N_("A/52 over S/PDIF");
250 var_Change( p_aout, "audio-device",
251 VLC_VAR_ADDCHOICE, &val, &text );
252 if( config_GetInt( p_aout, "spdif" ) )
253 var_Set( p_aout, "audio-device", val );
255 snd_pcm_close( p_sys->p_snd_pcm );
257 else if ( i_ret == -EBUSY )
259 msg_Warn( p_aout, "audio device: %s is already in use",
264 var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
267 /* Probe() has failed. */
268 msg_Dbg( p_aout, "failed to find a useable alsa configuration" );
269 var_Destroy( p_aout, "audio-device" );
273 /* Add final settings to the variable */
274 var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
275 val.b_bool = VLC_TRUE;
276 var_Set( p_aout, "intf-change", val );
279 /*****************************************************************************
280 * Open: create a handle and open an alsa device
281 *****************************************************************************
282 * This function opens an alsa device, through the alsa API.
284 * Note: the only heap-allocated string is psz_device. All the other pointers
285 * are references to psz_device or to stack-allocated data.
286 *****************************************************************************/
287 static int Open( vlc_object_t *p_this )
289 aout_instance_t * p_aout = (aout_instance_t *)p_this;
290 struct aout_sys_t * p_sys;
293 char psz_default_iec_device[128]; /* Buffer used to store the default
295 char * psz_device, * psz_iec_device; /* device names for PCM and S/PDIF
298 int i_vlc_pcm_format; /* Audio format for VLC's data */
299 int i_snd_pcm_format; /* Audio format for ALSA's data */
301 snd_pcm_uframes_t i_buffer_size = 0;
302 snd_pcm_uframes_t i_period_size = 0;
305 snd_pcm_hw_params_t *p_hw;
306 snd_pcm_sw_params_t *p_sw;
309 unsigned int i_old_rate;
310 vlc_bool_t b_retry = VLC_TRUE;
312 /* Allocate structures */
313 p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );
316 msg_Err( p_aout, "out of memory" );
319 p_sys->b_playing = VLC_FALSE;
320 p_sys->start_date = 0;
321 vlc_cond_init( p_aout, &p_sys->wait );
322 vlc_mutex_init( p_aout, &p_sys->lock );
324 /* Get device name */
325 if( (psz_device = config_GetPsz( p_aout, "alsadev" )) == NULL )
327 msg_Err( p_aout, "no audio device given (maybe \"default\" ?)" );
328 intf_UserFatal( p_aout, VLC_FALSE, _("No Audio Device"),
329 _("No audio device name was given. You might want to " \
330 "enter \"default\".") );
335 /* Choose the IEC device for S/PDIF output:
336 if the device is overriden by the user then it will be the one
337 otherwise we compute the default device based on the output format. */
338 if( AOUT_FMT_NON_LINEAR( &p_aout->output.output )
339 && !strcmp( psz_device, DEFAULT_ALSA_DEVICE ) )
341 snprintf( psz_default_iec_device, sizeof(psz_default_iec_device),
342 "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
343 IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
344 IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
346 ( p_aout->output.output.i_rate == 48000 ?
347 IEC958_AES3_CON_FS_48000 :
348 ( p_aout->output.output.i_rate == 44100 ?
349 IEC958_AES3_CON_FS_44100 : IEC958_AES3_CON_FS_32000 ) ) );
350 psz_iec_device = psz_default_iec_device;
352 else if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
354 psz_iec_device = psz_device;
358 psz_iec_device = NULL;
361 /* Choose the linear PCM format (read the comment above about FPU
363 if( vlc_CPU() & CPU_CAPABILITY_FPU )
365 i_vlc_pcm_format = VLC_FOURCC('f','l','3','2');
366 i_snd_pcm_format = SND_PCM_FORMAT_FLOAT;
370 i_vlc_pcm_format = AOUT_FMT_S16_NE;
371 i_snd_pcm_format = SND_PCM_FORMAT_S16;
374 /* If the variable doesn't exist then it's the first time we're called
375 and we have to probe the available audio formats and channels */
376 if ( var_Type( p_aout, "audio-device" ) == 0 )
378 Probe( p_aout, psz_device, psz_iec_device, &i_snd_pcm_format );
381 if ( var_Get( p_aout, "audio-device", &val ) < 0 )
388 p_aout->output.output.i_format = i_vlc_pcm_format;
389 if ( val.i_int == AOUT_VAR_5_1 )
391 p_aout->output.output.i_physical_channels
392 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
393 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
396 psz_device = strdup( "surround51" );
398 else if ( val.i_int == AOUT_VAR_2F2R )
400 p_aout->output.output.i_physical_channels
401 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
402 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
404 psz_device = strdup( "surround40" );
406 else if ( val.i_int == AOUT_VAR_STEREO )
408 p_aout->output.output.i_physical_channels
409 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
411 else if ( val.i_int == AOUT_VAR_MONO )
413 p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
415 else if( val.i_int != AOUT_VAR_SPDIF )
417 /* This should not happen ! */
418 msg_Err( p_aout, "internal: can't find audio-device (%i)", val.i_int );
425 snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 );
428 /* Open the device */
429 if ( val.i_int == AOUT_VAR_SPDIF )
431 if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
432 SND_PCM_STREAM_PLAYBACK, 0 ) ) < 0 )
434 msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
435 psz_iec_device, snd_strerror( i_snd_rc ) );
436 intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"),
437 _("VLC could not open the ALSA device \"%s\" (%s)."),
438 psz_iec_device, snd_strerror( i_snd_rc ) );
443 i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
444 i_snd_pcm_format = SND_PCM_FORMAT_S16;
447 i_vlc_pcm_format = VLC_FOURCC('s','p','d','i');
448 p_aout->output.i_nb_samples = i_period_size = ALSA_SPDIF_PERIOD_SIZE;
449 p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
450 p_aout->output.output.i_frame_length = A52_FRAME_NB;
452 aout_VolumeNoneInit( p_aout );
458 msg_Dbg( p_aout, "opening ALSA device `%s'", psz_device );
460 /* Since it seems snd_pcm_close hasn't really released the device at
461 the time it returns, probe if the device is available in loop for 1s.
462 We cannot use blocking mode since the we would wait indefinitely when
463 switching from a dmx device to surround51. */
465 for( i = 10; i >= 0; i-- )
467 if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
468 SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) ) == -EBUSY )
470 if( i ) msleep( 100000 /* 100ms */ );
473 msg_Err( p_aout, "audio device: %s is already in use",
475 intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"),
476 _("The audio device \"%s\" is already in use."),
485 msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
486 psz_device, snd_strerror( i_snd_rc ) );
487 intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"),
488 _("VLC could not open the ALSA device \"%s\" (%s)."),
489 psz_device, snd_strerror( i_snd_rc ) );
495 /* We want blocking mode */
496 snd_pcm_nonblock( p_sys->p_snd_pcm, 0 );
498 i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
499 i_channels = aout_FormatNbChannels( &p_aout->output.output );
501 p_aout->output.i_nb_samples = i_period_size = ALSA_DEFAULT_PERIOD_SIZE;
503 aout_VolumeSoftInit( p_aout );
506 /* Free psz_device so that all the remaining data is stack-allocated */
509 p_aout->output.pf_play = Play;
511 snd_pcm_hw_params_alloca(&p_hw);
512 snd_pcm_sw_params_alloca(&p_sw);
514 /* Due to some bugs in alsa with some drivers, we need to retry in s16l
515 if snd_pcm_hw_params fails in fl32 */
520 /* Get Initial hardware parameters */
521 if ( ( i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) ) < 0 )
523 msg_Err( p_aout, "unable to retrieve initial hardware parameters (%s)",
524 snd_strerror( i_snd_rc ) );
529 if ( ( i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
530 i_snd_pcm_format ) ) < 0 )
532 if( i_snd_pcm_format != SND_PCM_FORMAT_S16 )
534 i_snd_pcm_format = SND_PCM_FORMAT_S16;
535 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
536 p_hw, i_snd_pcm_format );
540 msg_Err( p_aout, "unable to set stream sample size and "
541 "word order (%s)", snd_strerror( i_snd_rc ) );
545 if( i_vlc_pcm_format != VLC_FOURCC('s','p','d','i') )
546 switch( i_snd_pcm_format )
548 case SND_PCM_FORMAT_FLOAT:
549 i_vlc_pcm_format = VLC_FOURCC('f','l','3','2');
551 case SND_PCM_FORMAT_S16:
552 i_vlc_pcm_format = AOUT_FMT_S16_NE;
555 p_aout->output.output.i_format = i_vlc_pcm_format;
557 if ( ( i_snd_rc = snd_pcm_hw_params_set_access( p_sys->p_snd_pcm, p_hw,
558 SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 )
560 msg_Err( p_aout, "unable to set interleaved stream format (%s)",
561 snd_strerror( i_snd_rc ) );
566 if ( ( i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw,
569 msg_Err( p_aout, "unable to set number of output channels (%s)",
570 snd_strerror( i_snd_rc ) );
575 i_old_rate = p_aout->output.output.i_rate;
576 #ifdef HAVE_ALSA_NEW_API
577 i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm, p_hw,
578 &p_aout->output.output.i_rate,
581 i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm, p_hw,
582 p_aout->output.output.i_rate,
585 if( i_snd_rc < 0 || p_aout->output.output.i_rate != i_old_rate )
587 msg_Warn( p_aout, "The rate %d Hz is not supported by your " \
588 "hardware. Using %d Hz instead.\n", i_old_rate, \
589 p_aout->output.output.i_rate );
592 /* Set period size. */
593 #ifdef HAVE_ALSA_NEW_API
594 if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,
595 p_hw, &i_period_size, NULL ) ) < 0 )
597 if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,
598 p_hw, i_period_size, NULL ) ) < 0 )
601 msg_Err( p_aout, "unable to set period size (%s)",
602 snd_strerror( i_snd_rc ) );
605 p_aout->output.i_nb_samples = i_period_size;
607 /* Set buffer size. */
608 #ifdef HAVE_ALSA_NEW_API
609 if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,
610 p_hw, &i_buffer_size ) ) < 0 )
612 if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,
613 p_hw, i_buffer_size ) ) < 0 )
616 msg_Err( p_aout, "unable to set buffer size (%s)",
617 snd_strerror( i_snd_rc ) );
621 /* Commit hardware parameters. */
622 if ( ( i_snd_rc = snd_pcm_hw_params( p_sys->p_snd_pcm, p_hw ) ) < 0 )
624 if ( b_retry == VLC_FALSE &&
625 i_snd_pcm_format == SND_PCM_FORMAT_FLOAT)
628 i_snd_pcm_format = SND_PCM_FORMAT_S16;
629 p_aout->output.output.i_format = AOUT_FMT_S16_NE;
630 msg_Warn( p_aout, "unable to commit hardware configuration "
631 "with fl32 samples. Retrying with s16l (%s)", snd_strerror( i_snd_rc ) );
635 msg_Err( p_aout, "unable to commit hardware configuration (%s)",
636 snd_strerror( i_snd_rc ) );
642 #ifdef HAVE_ALSA_NEW_API
643 if( ( i_snd_rc = snd_pcm_hw_params_get_period_time( p_hw,
644 &p_sys->i_period_time, NULL ) ) < 0 )
646 if( ( p_sys->i_period_time =
647 (int)snd_pcm_hw_params_get_period_time( p_hw, NULL ) ) < 0 )
650 msg_Err( p_aout, "unable to get period time (%s)",
651 snd_strerror( i_snd_rc ) );
655 /* Get Initial software parameters */
656 snd_pcm_sw_params_current( p_sys->p_snd_pcm, p_sw );
658 i_snd_rc = snd_pcm_sw_params_set_sleep_min( p_sys->p_snd_pcm, p_sw, 0 );
660 i_snd_rc = snd_pcm_sw_params_set_avail_min( p_sys->p_snd_pcm, p_sw,
661 p_aout->output.i_nb_samples );
662 /* start playing when one period has been written */
663 i_snd_rc = snd_pcm_sw_params_set_start_threshold( p_sys->p_snd_pcm, p_sw,
664 ALSA_DEFAULT_PERIOD_SIZE);
667 msg_Err( p_aout, "unable to set start threshold (%s)",
668 snd_strerror( i_snd_rc ) );
672 /* Commit software parameters. */
673 if ( snd_pcm_sw_params( p_sys->p_snd_pcm, p_sw ) < 0 )
675 msg_Err( p_aout, "unable to set software configuration" );
680 snd_output_printf( p_sys->p_snd_stderr, "\nALSA hardware setup:\n\n" );
681 snd_pcm_dump_hw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
682 snd_output_printf( p_sys->p_snd_stderr, "\nALSA software setup:\n\n" );
683 snd_pcm_dump_sw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
684 snd_output_printf( p_sys->p_snd_stderr, "\n" );
687 /* Create ALSA thread and wait for its readiness. */
688 if( vlc_thread_create( p_aout, "aout", ALSAThread,
689 VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
691 msg_Err( p_aout, "cannot create ALSA thread (%m)" );
698 snd_pcm_close( p_sys->p_snd_pcm );
700 snd_output_close( p_sys->p_snd_stderr );
706 /*****************************************************************************
707 * Play: nothing to do
708 *****************************************************************************/
709 static void Play( aout_instance_t *p_aout )
711 if( !p_aout->output.p_sys->b_playing )
713 p_aout->output.p_sys->b_playing = 1;
715 /* get the playing date of the first aout buffer */
716 p_aout->output.p_sys->start_date =
717 aout_FifoFirstDate( p_aout, &p_aout->output.fifo );
719 /* wake up the audio output thread */
720 vlc_mutex_lock( &p_aout->output.p_sys->lock );
721 vlc_cond_signal( &p_aout->output.p_sys->wait );
722 vlc_mutex_unlock( &p_aout->output.p_sys->lock );
726 /*****************************************************************************
727 * Close: close the ALSA device
728 *****************************************************************************/
729 static void Close( vlc_object_t *p_this )
731 aout_instance_t *p_aout = (aout_instance_t *)p_this;
732 struct aout_sys_t * p_sys = p_aout->output.p_sys;
735 /* make sure the audio output thread is waken up */
736 vlc_mutex_lock( &p_aout->output.p_sys->lock );
737 vlc_cond_signal( &p_aout->output.p_sys->wait );
738 vlc_mutex_unlock( &p_aout->output.p_sys->lock );
740 vlc_object_kill( p_aout );
741 vlc_thread_join( p_aout );
742 p_aout->b_die = VLC_FALSE;
744 i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm );
748 msg_Err( p_aout, "failed closing ALSA device (%s)",
749 snd_strerror( i_snd_rc ) );
753 snd_output_close( p_sys->p_snd_stderr );
759 /*****************************************************************************
760 * ALSAThread: asynchronous thread used to DMA the data to the device
761 *****************************************************************************/
762 static int ALSAThread( aout_instance_t * p_aout )
764 struct aout_sys_t * p_sys = p_aout->output.p_sys;
765 p_sys->p_status = (snd_pcm_status_t *)malloc(snd_pcm_status_sizeof());
767 /* Wait for the exact time to start playing (avoids resampling) */
768 vlc_mutex_lock( &p_sys->lock );
769 while( !p_sys->start_date && !p_aout->b_die )
770 vlc_cond_wait( &p_sys->wait, &p_sys->lock );
771 vlc_mutex_unlock( &p_sys->lock );
776 mwait( p_sys->start_date - AOUT_PTS_TOLERANCE / 4 );
778 while ( !p_aout->b_die )
784 snd_pcm_drop( p_sys->p_snd_pcm );
785 free( p_aout->output.p_sys->p_status );
789 /*****************************************************************************
790 * ALSAFill: function used to fill the ALSA buffer as much as possible
791 *****************************************************************************/
792 static void ALSAFill( aout_instance_t * p_aout )
794 struct aout_sys_t * p_sys = p_aout->output.p_sys;
795 aout_buffer_t * p_buffer;
796 snd_pcm_status_t * p_status = p_sys->p_status;
800 /* Fill in the buffer until space or audio output buffer shortage */
803 i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );
806 msg_Err( p_aout, "cannot get device status" );
810 /* Handle buffer underruns and get the status again */
811 if( snd_pcm_status_get_state( p_status ) == SND_PCM_STATE_XRUN )
813 /* Prepare the device */
814 i_snd_rc = snd_pcm_prepare( p_sys->p_snd_pcm );
818 msg_Err( p_aout, "cannot recover from buffer underrun" );
822 msg_Dbg( p_aout, "recovered from buffer underrun" );
824 /* Get the new status */
825 i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );
828 msg_Err( p_aout, "cannot get device status after recovery" );
832 /* Underrun, try to recover as quickly as possible */
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_sys->p_snd_pcm, &delay ) < 0 )
841 delay = 0; /* FIXME: use a positive minimal delay */
842 int i_bytes = snd_pcm_frames_to_bytes( p_sys->p_snd_pcm, delay );
843 next_date = mdate() + ( (mtime_t)i_bytes * 1000000
844 / p_aout->output.output.i_bytes_per_frame
845 / p_aout->output.output.i_rate
846 * p_aout->output.output.i_frame_length );
849 snd_pcm_state_t state = snd_pcm_status_get_state( p_status );
850 if( state != SND_PCM_STATE_RUNNING )
851 msg_Err( p_aout, "pcm status (%d) != RUNNING", state );
853 msg_Dbg( p_aout, "Delay is %ld frames (%d bytes)", delay, i_bytes );
855 msg_Dbg( p_aout, "Bytes per frame: %d", p_aout->output.output.i_bytes_per_frame );
856 msg_Dbg( p_aout, "Rate: %d", p_aout->output.output.i_rate );
857 msg_Dbg( p_aout, "Frame length: %d", p_aout->output.output.i_frame_length );
859 msg_Dbg( p_aout, "Next date is in %d microseconds", (int)(next_date - mdate()) );
863 p_buffer = aout_OutputNextBuffer( p_aout, next_date,
864 (p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i')) );
866 /* Audio output buffer shortage -> stop the fill process and wait */
867 if( p_buffer == NULL )
872 i_snd_rc = snd_pcm_writei( p_sys->p_snd_pcm, p_buffer->p_buffer,
873 p_buffer->i_nb_samples );
874 if( i_snd_rc != -ESTRPIPE )
877 /* a suspend event occurred
878 * (stream is suspended and waiting for an application recovery) */
879 msg_Dbg( p_aout, "entering in suspend mode, trying to resume..." );
881 while( !p_aout->b_die && !p_aout->p_libvlc->b_die &&
882 ( i_snd_rc = snd_pcm_resume( p_sys->p_snd_pcm ) ) == -EAGAIN )
888 /* Device does not supprot resuming, restart it */
889 i_snd_rc = snd_pcm_prepare( p_sys->p_snd_pcm );
894 msg_Err( p_aout, "cannot write: %s", snd_strerror( i_snd_rc ) );
896 aout_BufferFree( p_buffer );
901 msg_Err( p_aout, "ALSA error: %s", snd_strerror( i_snd_rc ) );
902 msleep( p_sys->i_period_time >> 1 );
905 static void GetDevicesForCard( module_config_t *p_item, int i_card );
906 static void GetDevices( module_config_t *p_item );
908 /*****************************************************************************
909 * config variable callback
910 *****************************************************************************/
911 static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
912 vlc_value_t newval, vlc_value_t oldval, void *p_unused )
914 module_config_t *p_item;
917 p_item = config_FindConfig( p_this, psz_name );
918 if( !p_item ) return VLC_SUCCESS;
920 /* Clear-up the current list */
923 /* Keep the first entrie */
924 for( i = 1; i < p_item->i_list; i++ )
926 free( (char *)p_item->ppsz_list[i] );
927 free( (char *)p_item->ppsz_list_text[i] );
929 /* TODO: Remove when no more needed */
930 p_item->ppsz_list[i] = NULL;
931 p_item->ppsz_list_text[i] = NULL;
935 GetDevices( p_item );
937 /* Signal change to the interface */
938 p_item->b_dirty = VLC_TRUE;
945 static void GetDevicesForCard( module_config_t *p_item, int i_card )
947 int i_pcm_device = -1;
949 snd_pcm_info_t *p_pcm_info;
954 sprintf( psz_dev, "hw:%i", i_card );
956 if( ( i_err = snd_ctl_open( &p_ctl, psz_dev, 0 ) ) < 0 )
959 if( ( i_err = snd_card_get_name( i_card, &psz_card_name ) ) != 0)
960 psz_card_name = _("Unknown soundcard");
962 snd_pcm_info_alloca( &p_pcm_info );
966 char *psz_device, *psz_descr;
967 if( ( i_err = snd_ctl_pcm_next_device( p_ctl, &i_pcm_device ) ) < 0 )
969 if( i_pcm_device < 0 )
972 snd_pcm_info_set_device( p_pcm_info, i_pcm_device );
973 snd_pcm_info_set_subdevice( p_pcm_info, 0 );
974 snd_pcm_info_set_stream( p_pcm_info, SND_PCM_STREAM_PLAYBACK );
976 if( ( i_err = snd_ctl_pcm_info( p_ctl, p_pcm_info ) ) < 0 )
978 if( i_err != -ENOENT )
980 /*printf( "get_devices_for_card(): "
981 "snd_ctl_pcm_info() "
982 "failed (%d:%d): %s.\n", i_card,
983 i_pcm_device, snd_strerror( -i_err ) );*/
988 asprintf( &psz_device, "hw:%d,%d", i_card, i_pcm_device );
989 asprintf( &psz_descr, "%s: %s (%s)", psz_card_name,
990 snd_pcm_info_get_name(p_pcm_info), psz_device );
993 (const char **)realloc( p_item->ppsz_list,
994 (p_item->i_list + 2) * sizeof(char *) );
995 p_item->ppsz_list_text =
996 (const char **)realloc( p_item->ppsz_list_text,
997 (p_item->i_list + 2) * sizeof(char *) );
998 p_item->ppsz_list[ p_item->i_list ] = psz_device;
999 p_item->ppsz_list_text[ p_item->i_list ] = psz_descr;
1001 p_item->ppsz_list[ p_item->i_list ] = NULL;
1002 p_item->ppsz_list_text[ p_item->i_list ] = NULL;
1005 snd_ctl_close( p_ctl );
1010 static void GetDevices( module_config_t *p_item )
1015 if( ( i_err = snd_card_next( &i_card ) ) != 0 )
1017 /*printf( "snd_card_next() failed: %s", snd_strerror( -i_err ) );*/
1021 while( i_card > -1 )
1023 GetDevicesForCard( p_item, i_card );
1024 if( ( i_err = snd_card_next( &i_card ) ) != 0 )
1026 /*printf( "snd_card_next() failed: %s", snd_strerror( -i_err ) );*/