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 );
108 change_string_list( ppsz_devices, ppsz_devices_text, FindDevicesCallback );
109 change_action_add( FindDevicesCallback, N_("Refresh list") );
111 set_capability( "audio output", 150 );
112 set_callbacks( Open, Close );
115 /*****************************************************************************
116 * Probe: probe the audio device for available formats and channels
117 *****************************************************************************/
118 static void Probe( aout_instance_t * p_aout,
119 const char * psz_device, const char * psz_iec_device,
120 int *pi_snd_pcm_format )
122 struct aout_sys_t * p_sys = p_aout->output.p_sys;
123 vlc_value_t val, text;
126 var_Create ( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
127 text.psz_string = _("Audio Device");
128 var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
130 /* We'll open the audio device in non blocking mode so we can just exit
131 * when it is already in use, but for the real stuff we'll still use
132 * the blocking mode */
134 /* Now test linear PCM capabilities */
135 if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
136 SND_PCM_STREAM_PLAYBACK,
137 SND_PCM_NONBLOCK ) ) )
140 snd_pcm_hw_params_t * p_hw;
141 snd_pcm_hw_params_alloca (&p_hw);
143 if ( snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) < 0 )
145 msg_Warn( p_aout, "unable to retrieve initial hardware parameters"
146 ", disabling linear PCM audio" );
147 snd_pcm_close( p_sys->p_snd_pcm );
148 var_Destroy( p_aout, "audio-device" );
152 if ( snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
153 *pi_snd_pcm_format ) < 0 )
157 if( *pi_snd_pcm_format != SND_PCM_FORMAT_S16 )
159 *pi_snd_pcm_format = SND_PCM_FORMAT_S16;
160 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
161 p_hw, *pi_snd_pcm_format );
165 msg_Warn( p_aout, "unable to set stream sample size and "
166 "word order, disabling linear PCM audio" );
167 snd_pcm_close( p_sys->p_snd_pcm );
168 var_Destroy( p_aout, "audio-device" );
173 i_channels = aout_FormatNbChannels( &p_aout->output.output );
175 while ( i_channels > 0 )
177 if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw,
180 switch ( i_channels )
183 val.i_int = AOUT_VAR_MONO;
184 text.psz_string = N_("Mono");
185 var_Change( p_aout, "audio-device",
186 VLC_VAR_ADDCHOICE, &val, &text );
189 val.i_int = AOUT_VAR_STEREO;
190 text.psz_string = N_("Stereo");
191 var_Change( p_aout, "audio-device",
192 VLC_VAR_ADDCHOICE, &val, &text );
193 var_Set( p_aout, "audio-device", val );
196 val.i_int = AOUT_VAR_2F2R;
197 text.psz_string = N_("2 Front 2 Rear");
198 var_Change( p_aout, "audio-device",
199 VLC_VAR_ADDCHOICE, &val, &text );
202 val.i_int = AOUT_VAR_5_1;
203 text.psz_string = "5.1";
204 var_Change( p_aout, "audio-device",
205 VLC_VAR_ADDCHOICE, &val, &text );
213 /* Special case for mono on stereo only boards */
214 i_channels = aout_FormatNbChannels( &p_aout->output.output );
215 var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
216 if( val.i_int <= 0 && i_channels == 1 )
218 if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw, 2 ))
220 val.i_int = AOUT_VAR_STEREO;
221 text.psz_string = N_("Stereo");
222 var_Change( p_aout, "audio-device",
223 VLC_VAR_ADDCHOICE, &val, &text );
224 var_Set( p_aout, "audio-device", val );
228 /* Close the previously opened device */
229 snd_pcm_close( p_sys->p_snd_pcm );
231 else if ( i_ret == -EBUSY )
233 msg_Warn( p_aout, "audio device: %s is already in use", psz_device );
236 /* Test for S/PDIF device if needed */
237 if ( psz_iec_device )
239 /* Opening the device should be enough */
240 if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
241 SND_PCM_STREAM_PLAYBACK,
242 SND_PCM_NONBLOCK ) ) )
244 val.i_int = AOUT_VAR_SPDIF;
245 text.psz_string = N_("A/52 over S/PDIF");
246 var_Change( p_aout, "audio-device",
247 VLC_VAR_ADDCHOICE, &val, &text );
248 if( config_GetInt( p_aout, "spdif" ) )
249 var_Set( p_aout, "audio-device", val );
251 snd_pcm_close( p_sys->p_snd_pcm );
253 else if ( i_ret == -EBUSY )
255 msg_Warn( p_aout, "audio device: %s is already in use",
260 var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
263 /* Probe() has failed. */
264 msg_Dbg( p_aout, "failed to find a useable alsa configuration" );
265 var_Destroy( p_aout, "audio-device" );
269 /* Add final settings to the variable */
270 var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
271 val.b_bool = VLC_TRUE;
272 var_Set( p_aout, "intf-change", val );
275 /*****************************************************************************
276 * Open: create a handle and open an alsa device
277 *****************************************************************************
278 * This function opens an alsa device, through the alsa API.
280 * Note: the only heap-allocated string is psz_device. All the other pointers
281 * are references to psz_device or to stack-allocated data.
282 *****************************************************************************/
283 static int Open( vlc_object_t *p_this )
285 aout_instance_t * p_aout = (aout_instance_t *)p_this;
286 struct aout_sys_t * p_sys;
289 char psz_default_iec_device[128]; /* Buffer used to store the default
291 char * psz_device, * psz_iec_device; /* device names for PCM and S/PDIF
294 int i_vlc_pcm_format; /* Audio format for VLC's data */
295 int i_snd_pcm_format; /* Audio format for ALSA's data */
297 snd_pcm_uframes_t i_buffer_size = 0;
298 snd_pcm_uframes_t i_period_size = 0;
301 snd_pcm_hw_params_t *p_hw;
302 snd_pcm_sw_params_t *p_sw;
305 unsigned int i_old_rate;
306 vlc_bool_t b_retry = VLC_TRUE;
308 /* Allocate structures */
309 p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );
312 msg_Err( p_aout, "out of memory" );
315 p_sys->b_playing = VLC_FALSE;
316 p_sys->start_date = 0;
317 vlc_cond_init( p_aout, &p_sys->wait );
318 vlc_mutex_init( p_aout, &p_sys->lock );
320 /* Get device name */
321 if( (psz_device = config_GetPsz( p_aout, "alsadev" )) == NULL )
323 msg_Err( p_aout, "no audio device given (maybe \"default\" ?)" );
324 intf_UserFatal( p_aout, VLC_FALSE, _("No Audio Device"),
325 _("No audio device name was given. You might want to " \
326 "enter \"default\".") );
331 /* Choose the IEC device for S/PDIF output:
332 if the device is overriden by the user then it will be the one
333 otherwise we compute the default device based on the output format. */
334 if( AOUT_FMT_NON_LINEAR( &p_aout->output.output )
335 && !strcmp( psz_device, DEFAULT_ALSA_DEVICE ) )
337 snprintf( psz_default_iec_device, sizeof(psz_default_iec_device),
338 "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
339 IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
340 IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
342 ( p_aout->output.output.i_rate == 48000 ?
343 IEC958_AES3_CON_FS_48000 :
344 ( p_aout->output.output.i_rate == 44100 ?
345 IEC958_AES3_CON_FS_44100 : IEC958_AES3_CON_FS_32000 ) ) );
346 psz_iec_device = psz_default_iec_device;
348 else if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
350 psz_iec_device = psz_device;
354 psz_iec_device = NULL;
357 /* Choose the linear PCM format (read the comment above about FPU
359 if( vlc_CPU() & CPU_CAPABILITY_FPU )
361 i_vlc_pcm_format = VLC_FOURCC('f','l','3','2');
362 i_snd_pcm_format = SND_PCM_FORMAT_FLOAT;
366 i_vlc_pcm_format = AOUT_FMT_S16_NE;
367 i_snd_pcm_format = SND_PCM_FORMAT_S16;
370 /* If the variable doesn't exist then it's the first time we're called
371 and we have to probe the available audio formats and channels */
372 if ( var_Type( p_aout, "audio-device" ) == 0 )
374 Probe( p_aout, psz_device, psz_iec_device, &i_snd_pcm_format );
377 if ( var_Get( p_aout, "audio-device", &val ) < 0 )
384 p_aout->output.output.i_format = i_vlc_pcm_format;
385 if ( val.i_int == AOUT_VAR_5_1 )
387 p_aout->output.output.i_physical_channels
388 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
389 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
392 psz_device = strdup( "surround51" );
394 else if ( val.i_int == AOUT_VAR_2F2R )
396 p_aout->output.output.i_physical_channels
397 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
398 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
400 psz_device = strdup( "surround40" );
402 else if ( val.i_int == AOUT_VAR_STEREO )
404 p_aout->output.output.i_physical_channels
405 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
407 else if ( val.i_int == AOUT_VAR_MONO )
409 p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
411 else if( val.i_int != AOUT_VAR_SPDIF )
413 /* This should not happen ! */
414 msg_Err( p_aout, "internal: can't find audio-device (%i)", val.i_int );
421 snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 );
424 /* Open the device */
425 if ( val.i_int == AOUT_VAR_SPDIF )
427 if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
428 SND_PCM_STREAM_PLAYBACK, 0 ) ) < 0 )
430 msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
431 psz_iec_device, snd_strerror( i_snd_rc ) );
432 intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"),
433 _("VLC could not open the ALSA device \"%s\" (%s)."),
434 psz_iec_device, snd_strerror( i_snd_rc ) );
439 i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
440 i_snd_pcm_format = SND_PCM_FORMAT_S16;
443 i_vlc_pcm_format = VLC_FOURCC('s','p','d','i');
444 p_aout->output.i_nb_samples = i_period_size = ALSA_SPDIF_PERIOD_SIZE;
445 p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
446 p_aout->output.output.i_frame_length = A52_FRAME_NB;
448 aout_VolumeNoneInit( p_aout );
454 msg_Dbg( p_aout, "opening ALSA device `%s'", psz_device );
456 /* Since it seems snd_pcm_close hasn't really released the device at
457 the time it returns, probe if the device is available in loop for 1s.
458 We cannot use blocking mode since the we would wait indefinitely when
459 switching from a dmx device to surround51. */
461 for( i = 10; i >= 0; i-- )
463 if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
464 SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) ) == -EBUSY )
466 if( i ) msleep( 100000 /* 100ms */ );
469 msg_Err( p_aout, "audio device: %s is already in use",
471 intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"),
472 _("The audio device \"%s\" is already in use."),
481 msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
482 psz_device, snd_strerror( i_snd_rc ) );
483 intf_UserFatal( p_aout, VLC_FALSE, _("Audio output failed"),
484 _("VLC could not open the ALSA device \"%s\" (%s)."),
485 psz_device, snd_strerror( i_snd_rc ) );
491 /* We want blocking mode */
492 snd_pcm_nonblock( p_sys->p_snd_pcm, 0 );
494 i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
495 i_channels = aout_FormatNbChannels( &p_aout->output.output );
497 p_aout->output.i_nb_samples = i_period_size = ALSA_DEFAULT_PERIOD_SIZE;
499 aout_VolumeSoftInit( p_aout );
502 /* Free psz_device so that all the remaining data is stack-allocated */
505 p_aout->output.pf_play = Play;
507 snd_pcm_hw_params_alloca(&p_hw);
508 snd_pcm_sw_params_alloca(&p_sw);
510 /* Due to some bugs in alsa with some drivers, we need to retry in s16l
511 if snd_pcm_hw_params fails in fl32 */
516 /* Get Initial hardware parameters */
517 if ( ( i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) ) < 0 )
519 msg_Err( p_aout, "unable to retrieve initial hardware parameters (%s)",
520 snd_strerror( i_snd_rc ) );
525 if ( ( i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
526 i_snd_pcm_format ) ) < 0 )
528 if( i_snd_pcm_format != SND_PCM_FORMAT_S16 )
530 i_snd_pcm_format = SND_PCM_FORMAT_S16;
531 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
532 p_hw, i_snd_pcm_format );
536 msg_Err( p_aout, "unable to set stream sample size and "
537 "word order (%s)", snd_strerror( i_snd_rc ) );
541 if( i_vlc_pcm_format != VLC_FOURCC('s','p','d','i') )
542 switch( i_snd_pcm_format )
544 case SND_PCM_FORMAT_FLOAT:
545 i_vlc_pcm_format = VLC_FOURCC('f','l','3','2');
547 case SND_PCM_FORMAT_S16:
548 i_vlc_pcm_format = AOUT_FMT_S16_NE;
551 p_aout->output.output.i_format = i_vlc_pcm_format;
553 if ( ( i_snd_rc = snd_pcm_hw_params_set_access( p_sys->p_snd_pcm, p_hw,
554 SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 )
556 msg_Err( p_aout, "unable to set interleaved stream format (%s)",
557 snd_strerror( i_snd_rc ) );
562 if ( ( i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw,
565 msg_Err( p_aout, "unable to set number of output channels (%s)",
566 snd_strerror( i_snd_rc ) );
571 i_old_rate = p_aout->output.output.i_rate;
572 #ifdef HAVE_ALSA_NEW_API
573 i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm, p_hw,
574 &p_aout->output.output.i_rate,
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 if( i_snd_rc < 0 || p_aout->output.output.i_rate != i_old_rate )
583 msg_Warn( p_aout, "The rate %d Hz is not supported by your " \
584 "hardware. Using %d Hz instead.\n", i_old_rate, \
585 p_aout->output.output.i_rate );
588 /* Set buffer size. */
589 #ifdef HAVE_ALSA_NEW_API
590 if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,
591 p_hw, &i_buffer_size ) ) < 0 )
593 if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,
594 p_hw, i_buffer_size ) ) < 0 )
597 msg_Err( p_aout, "unable to set buffer size (%s)",
598 snd_strerror( i_snd_rc ) );
602 /* Set period size. */
603 #ifdef HAVE_ALSA_NEW_API
604 if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,
605 p_hw, &i_period_size, NULL ) ) < 0 )
607 if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,
608 p_hw, i_period_size, NULL ) ) < 0 )
611 msg_Err( p_aout, "unable to set period size (%s)",
612 snd_strerror( i_snd_rc ) );
615 p_aout->output.i_nb_samples = i_period_size;
617 /* Commit hardware parameters. */
618 if ( ( i_snd_rc = snd_pcm_hw_params( p_sys->p_snd_pcm, p_hw ) ) < 0 )
620 if ( b_retry == VLC_FALSE &&
621 i_snd_pcm_format == SND_PCM_FORMAT_FLOAT)
624 i_snd_pcm_format = SND_PCM_FORMAT_S16;
625 p_aout->output.output.i_format = AOUT_FMT_S16_NE;
626 msg_Warn( p_aout, "unable to commit hardware configuration "
627 "with fl32 samples. Retrying with s16l (%s)", snd_strerror( i_snd_rc ) );
631 msg_Err( p_aout, "unable to commit hardware configuration (%s)",
632 snd_strerror( i_snd_rc ) );
638 #ifdef HAVE_ALSA_NEW_API
639 if( ( i_snd_rc = snd_pcm_hw_params_get_period_time( p_hw,
640 &p_sys->i_period_time, NULL ) ) < 0 )
642 if( ( p_sys->i_period_time =
643 (int)snd_pcm_hw_params_get_period_time( p_hw, NULL ) ) < 0 )
646 msg_Err( p_aout, "unable to get period time (%s)",
647 snd_strerror( i_snd_rc ) );
651 /* Get Initial software parameters */
652 snd_pcm_sw_params_current( p_sys->p_snd_pcm, p_sw );
654 i_snd_rc = snd_pcm_sw_params_set_sleep_min( p_sys->p_snd_pcm, p_sw, 0 );
656 i_snd_rc = snd_pcm_sw_params_set_avail_min( p_sys->p_snd_pcm, p_sw,
657 p_aout->output.i_nb_samples );
658 /* start playing when one period has been written */
659 i_snd_rc = snd_pcm_sw_params_set_start_threshold( p_sys->p_snd_pcm, p_sw,
660 ALSA_DEFAULT_PERIOD_SIZE);
663 msg_Err( p_aout, "unable to set start threshold (%s)",
664 snd_strerror( i_snd_rc ) );
668 /* Commit software parameters. */
669 if ( snd_pcm_sw_params( p_sys->p_snd_pcm, p_sw ) < 0 )
671 msg_Err( p_aout, "unable to set software configuration" );
676 snd_output_printf( p_sys->p_snd_stderr, "\nALSA hardware setup:\n\n" );
677 snd_pcm_dump_hw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
678 snd_output_printf( p_sys->p_snd_stderr, "\nALSA software setup:\n\n" );
679 snd_pcm_dump_sw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
680 snd_output_printf( p_sys->p_snd_stderr, "\n" );
683 /* Create ALSA thread and wait for its readiness. */
684 if( vlc_thread_create( p_aout, "aout", ALSAThread,
685 VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
687 msg_Err( p_aout, "cannot create ALSA thread (%m)" );
694 snd_pcm_close( p_sys->p_snd_pcm );
696 snd_output_close( p_sys->p_snd_stderr );
702 /*****************************************************************************
703 * Play: nothing to do
704 *****************************************************************************/
705 static void Play( aout_instance_t *p_aout )
707 if( !p_aout->output.p_sys->b_playing )
709 p_aout->output.p_sys->b_playing = 1;
711 /* get the playing date of the first aout buffer */
712 p_aout->output.p_sys->start_date =
713 aout_FifoFirstDate( p_aout, &p_aout->output.fifo );
715 /* wake up the audio output thread */
716 vlc_mutex_lock( &p_aout->output.p_sys->lock );
717 vlc_cond_signal( &p_aout->output.p_sys->wait );
718 vlc_mutex_unlock( &p_aout->output.p_sys->lock );
722 /*****************************************************************************
723 * Close: close the ALSA device
724 *****************************************************************************/
725 static void Close( vlc_object_t *p_this )
727 aout_instance_t *p_aout = (aout_instance_t *)p_this;
728 struct aout_sys_t * p_sys = p_aout->output.p_sys;
731 /* make sure the audio output thread is waken up */
732 vlc_mutex_lock( &p_aout->output.p_sys->lock );
733 vlc_cond_signal( &p_aout->output.p_sys->wait );
734 vlc_mutex_unlock( &p_aout->output.p_sys->lock );
736 vlc_object_kill( p_aout );
737 vlc_thread_join( p_aout );
738 p_aout->b_die = VLC_FALSE;
740 i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm );
744 msg_Err( p_aout, "failed closing ALSA device (%s)",
745 snd_strerror( i_snd_rc ) );
749 snd_output_close( p_sys->p_snd_stderr );
755 /*****************************************************************************
756 * ALSAThread: asynchronous thread used to DMA the data to the device
757 *****************************************************************************/
758 static int ALSAThread( aout_instance_t * p_aout )
760 struct aout_sys_t * p_sys = p_aout->output.p_sys;
761 p_sys->p_status = (snd_pcm_status_t *)malloc(snd_pcm_status_sizeof());
763 /* Wait for the exact time to start playing (avoids resampling) */
764 vlc_mutex_lock( &p_sys->lock );
765 while( !p_sys->start_date )
766 vlc_cond_wait( &p_sys->wait, &p_sys->lock );
767 vlc_mutex_unlock( &p_sys->lock );
769 mwait( p_sys->start_date - AOUT_PTS_TOLERANCE / 4 );
771 while ( !p_aout->b_die )
776 snd_pcm_drop( p_sys->p_snd_pcm );
777 free( p_aout->output.p_sys->p_status );
781 /*****************************************************************************
782 * ALSAFill: function used to fill the ALSA buffer as much as possible
783 *****************************************************************************/
784 static void ALSAFill( aout_instance_t * p_aout )
786 struct aout_sys_t * p_sys = p_aout->output.p_sys;
787 aout_buffer_t * p_buffer;
788 snd_pcm_status_t * p_status = p_sys->p_status;
792 /* Fill in the buffer until space or audio output buffer shortage */
795 i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );
798 msg_Err( p_aout, "cannot get device status" );
802 /* Handle buffer underruns and get the status again */
803 if( snd_pcm_status_get_state( p_status ) == SND_PCM_STATE_XRUN )
805 /* Prepare the device */
806 i_snd_rc = snd_pcm_prepare( p_sys->p_snd_pcm );
810 msg_Err( p_aout, "cannot recover from buffer underrun" );
814 msg_Dbg( p_aout, "recovered from buffer underrun" );
816 /* Get the new status */
817 i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );
820 msg_Err( p_aout, "cannot get device status after recovery" );
824 /* Underrun, try to recover as quickly as possible */
829 /* Here the device should be in RUNNING state.
830 * p_status is valid. */
831 snd_pcm_sframes_t delay = snd_pcm_status_get_delay( p_status );
832 int i_bytes = snd_pcm_frames_to_bytes( p_sys->p_snd_pcm, delay );
833 next_date = mdate() + ( (mtime_t)i_bytes * 1000000
834 / p_aout->output.output.i_bytes_per_frame
835 / p_aout->output.output.i_rate
836 * p_aout->output.output.i_frame_length );
839 snd_pcm_state_t state = snd_pcm_status_get_state( p_status );
840 if( state != SND_PCM_STATE_RUNNING )
841 msg_Err( p_aout, "pcm status (%d) != RUNNING", state );
843 msg_Dbg( p_aout, "Delay is %ld frames (%d bytes)", delay, i_bytes );
845 msg_Dbg( p_aout, "Bytes per frame: %d", p_aout->output.output.i_bytes_per_frame );
846 msg_Dbg( p_aout, "Rate: %d", p_aout->output.output.i_rate );
847 msg_Dbg( p_aout, "Frame length: %d", p_aout->output.output.i_frame_length );
849 msg_Dbg( p_aout, "Next date is in %d microseconds", (int)(next_date - mdate()) );
853 p_buffer = aout_OutputNextBuffer( p_aout, next_date,
854 (p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i')) );
856 /* Audio output buffer shortage -> stop the fill process and wait */
857 if( p_buffer == NULL )
862 i_snd_rc = snd_pcm_writei( p_sys->p_snd_pcm, p_buffer->p_buffer,
863 p_buffer->i_nb_samples );
864 if( i_snd_rc != -ESTRPIPE )
867 /* a suspend event occurred
868 * (stream is suspended and waiting for an application recovery) */
869 msg_Dbg( p_aout, "entering in suspend mode, trying to resume..." );
871 while( !p_aout->b_die && !p_aout->p_libvlc->b_die &&
872 ( i_snd_rc = snd_pcm_resume( p_sys->p_snd_pcm ) ) == -EAGAIN )
878 /* Device does not supprot resuming, restart it */
879 i_snd_rc = snd_pcm_prepare( p_sys->p_snd_pcm );
884 msg_Err( p_aout, "cannot write: %s", snd_strerror( i_snd_rc ) );
886 aout_BufferFree( p_buffer );
891 msg_Err( p_aout, "ALSA error: %s", snd_strerror( i_snd_rc ) );
892 msleep( p_sys->i_period_time >> 1 );
895 static void GetDevicesForCard( module_config_t *p_item, int i_card );
896 static void GetDevices( module_config_t *p_item );
898 /*****************************************************************************
899 * config variable callback
900 *****************************************************************************/
901 static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
902 vlc_value_t newval, vlc_value_t oldval, void *p_unused )
904 module_config_t *p_item;
907 p_item = config_FindConfig( p_this, psz_name );
908 if( !p_item ) return VLC_SUCCESS;
910 /* Clear-up the current list */
913 /* Keep the first entrie */
914 for( i = 1; i < p_item->i_list; i++ )
916 free( (char *)p_item->ppsz_list[i] );
917 free( (char *)p_item->ppsz_list_text[i] );
919 /* TODO: Remove when no more needed */
920 p_item->ppsz_list[i] = NULL;
921 p_item->ppsz_list_text[i] = NULL;
925 GetDevices( p_item );
927 /* Signal change to the interface */
928 p_item->b_dirty = VLC_TRUE;
935 static void GetDevicesForCard( module_config_t *p_item, int i_card )
937 int i_pcm_device = -1;
939 snd_pcm_info_t *p_pcm_info;
944 sprintf( psz_dev, "hw:%i", i_card );
946 if( ( i_err = snd_ctl_open( &p_ctl, psz_dev, 0 ) ) < 0 )
949 if( ( i_err = snd_card_get_name( i_card, &psz_card_name ) ) != 0)
950 psz_card_name = _("Unknown soundcard");
952 snd_pcm_info_alloca( &p_pcm_info );
956 char *psz_device, *psz_descr;
957 if( ( i_err = snd_ctl_pcm_next_device( p_ctl, &i_pcm_device ) ) < 0 )
959 if( i_pcm_device < 0 )
962 snd_pcm_info_set_device( p_pcm_info, i_pcm_device );
963 snd_pcm_info_set_subdevice( p_pcm_info, 0 );
964 snd_pcm_info_set_stream( p_pcm_info, SND_PCM_STREAM_PLAYBACK );
966 if( ( i_err = snd_ctl_pcm_info( p_ctl, p_pcm_info ) ) < 0 )
968 if( i_err != -ENOENT )
970 /*printf( "get_devices_for_card(): "
971 "snd_ctl_pcm_info() "
972 "failed (%d:%d): %s.\n", i_card,
973 i_pcm_device, snd_strerror( -i_err ) );*/
978 asprintf( &psz_device, "hw:%d,%d", i_card, i_pcm_device );
979 asprintf( &psz_descr, "%s: %s (%s)", psz_card_name,
980 snd_pcm_info_get_name(p_pcm_info), psz_device );
983 (const char **)realloc( p_item->ppsz_list,
984 (p_item->i_list + 2) * sizeof(char *) );
985 p_item->ppsz_list_text =
986 (const char **)realloc( p_item->ppsz_list_text,
987 (p_item->i_list + 2) * sizeof(char *) );
988 p_item->ppsz_list[ p_item->i_list ] = psz_device;
989 p_item->ppsz_list_text[ p_item->i_list ] = psz_descr;
991 p_item->ppsz_list[ p_item->i_list ] = NULL;
992 p_item->ppsz_list_text[ p_item->i_list ] = NULL;
995 snd_ctl_close( p_ctl );
1000 static void GetDevices( module_config_t *p_item )
1005 if( ( i_err = snd_card_next( &i_card ) ) != 0 )
1007 /*printf( "snd_card_next() failed: %s", snd_strerror( -i_err ) );*/
1011 while( i_card > -1 )
1013 GetDevicesForCard( p_item, i_card );
1014 if( ( i_err = snd_card_next( &i_card ) ) != 0 )
1016 /*printf( "snd_card_next() failed: %s", snd_strerror( -i_err ) );*/