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 *****************************************************************************/
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
37 #include <errno.h> /* ENOMEM */
38 #include <vlc_dialog.h>
44 Note: we use the new API which is available since 0.9.0beta10a. */
45 #define ALSA_PCM_NEW_HW_PARAMS_API
46 #define ALSA_PCM_NEW_SW_PARAMS_API
47 #include <alsa/asoundlib.h>
49 /*#define ALSA_DEBUG*/
51 /*****************************************************************************
52 * aout_sys_t: ALSA audio output method descriptor
53 *****************************************************************************
54 * This structure is part of the audio output thread descriptor.
55 * It describes the ALSA specific properties of an audio device.
56 *****************************************************************************/
59 snd_pcm_t * p_snd_pcm;
60 unsigned int i_period_time;
63 snd_output_t * p_snd_stderr;
66 bool b_playing; /* playing status */
74 #define A52_FRAME_NB 1536
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.
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 */
88 #define DEFAULT_ALSA_DEVICE N_("default")
90 /*****************************************************************************
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 );
101 /*****************************************************************************
103 *****************************************************************************/
104 static const char *const ppsz_devices[] = { "default" };
105 static const char *const ppsz_devices_text[] = { N_("Default") };
107 set_shortname( "ALSA" )
108 set_description( N_("ALSA audio output") )
109 set_category( CAT_AUDIO )
110 set_subcategory( SUBCAT_AUDIO_AOUT )
111 add_string( "alsa-audio-device", DEFAULT_ALSA_DEVICE, aout_FindAndRestart,
112 N_("ALSA Device Name"), NULL, false )
113 add_deprecated_alias( "alsadev" ) /* deprecated since 0.9.3 */
114 change_string_list( ppsz_devices, ppsz_devices_text, FindDevicesCallback )
115 change_action_add( FindDevicesCallback, N_("Refresh list") )
117 set_capability( "audio output", 150 )
118 set_callbacks( Open, Close )
121 /*****************************************************************************
122 * Probe: probe the audio device for available formats and channels
123 *****************************************************************************/
124 static void Probe( aout_instance_t * p_aout,
125 const char * psz_device, const char * psz_iec_device,
126 int *pi_snd_pcm_format )
128 struct aout_sys_t * p_sys = p_aout->output.p_sys;
129 vlc_value_t val, text;
132 var_Create ( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
133 text.psz_string = _("Audio Device");
134 var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
136 /* We'll open the audio device in non blocking mode so we can just exit
137 * when it is already in use, but for the real stuff we'll still use
138 * the blocking mode */
140 /* Now test linear PCM capabilities */
141 if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
142 SND_PCM_STREAM_PLAYBACK,
143 SND_PCM_NONBLOCK ) ) )
146 snd_pcm_hw_params_t * p_hw;
147 snd_pcm_hw_params_alloca (&p_hw);
149 if ( snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) < 0 )
151 msg_Warn( p_aout, "unable to retrieve initial hardware parameters"
152 ", disabling linear PCM audio" );
153 snd_pcm_close( p_sys->p_snd_pcm );
154 var_Destroy( p_aout, "audio-device" );
158 if ( snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
159 *pi_snd_pcm_format ) < 0 )
163 if( *pi_snd_pcm_format != SND_PCM_FORMAT_S16 )
165 *pi_snd_pcm_format = SND_PCM_FORMAT_S16;
166 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
167 p_hw, *pi_snd_pcm_format );
171 msg_Warn( p_aout, "unable to set stream sample size and "
172 "word order, disabling linear PCM audio" );
173 snd_pcm_close( p_sys->p_snd_pcm );
174 var_Destroy( p_aout, "audio-device" );
179 i_channels = aout_FormatNbChannels( &p_aout->output.output );
181 while ( i_channels > 0 )
183 if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw,
186 switch ( i_channels )
189 val.i_int = AOUT_VAR_MONO;
190 text.psz_string = _("Mono");
191 var_Change( p_aout, "audio-device",
192 VLC_VAR_ADDCHOICE, &val, &text );
195 val.i_int = AOUT_VAR_STEREO;
196 text.psz_string = _("Stereo");
197 var_Change( p_aout, "audio-device",
198 VLC_VAR_ADDCHOICE, &val, &text );
199 var_Set( p_aout, "audio-device", val );
202 val.i_int = AOUT_VAR_2F2R;
203 text.psz_string = _("2 Front 2 Rear");
204 var_Change( p_aout, "audio-device",
205 VLC_VAR_ADDCHOICE, &val, &text );
208 val.i_int = AOUT_VAR_5_1;
209 text.psz_string = "5.1";
210 var_Change( p_aout, "audio-device",
211 VLC_VAR_ADDCHOICE, &val, &text );
219 /* Special case for mono on stereo only boards */
220 i_channels = aout_FormatNbChannels( &p_aout->output.output );
221 var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
222 if( val.i_int <= 0 && i_channels == 1 )
224 if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw, 2 ))
226 val.i_int = AOUT_VAR_STEREO;
227 text.psz_string = (char*)N_("Stereo");
228 var_Change( p_aout, "audio-device",
229 VLC_VAR_ADDCHOICE, &val, &text );
230 var_Set( p_aout, "audio-device", val );
234 /* Close the previously opened device */
235 snd_pcm_close( p_sys->p_snd_pcm );
237 else if ( i_ret == -EBUSY )
239 msg_Warn( p_aout, "audio device: %s is already in use", psz_device );
242 /* Test for S/PDIF device if needed */
243 if ( psz_iec_device )
245 /* Opening the device should be enough */
246 if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
247 SND_PCM_STREAM_PLAYBACK,
248 SND_PCM_NONBLOCK ) ) )
250 val.i_int = AOUT_VAR_SPDIF;
251 text.psz_string = (char*)N_("A/52 over S/PDIF");
252 var_Change( p_aout, "audio-device",
253 VLC_VAR_ADDCHOICE, &val, &text );
254 if( config_GetInt( p_aout, "spdif" ) )
255 var_Set( p_aout, "audio-device", val );
257 snd_pcm_close( p_sys->p_snd_pcm );
259 else if ( i_ret == -EBUSY )
261 msg_Warn( p_aout, "audio device: %s is already in use",
266 var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
269 /* Probe() has failed. */
270 msg_Dbg( p_aout, "failed to find a usable alsa configuration" );
271 var_Destroy( p_aout, "audio-device" );
275 /* Add final settings to the variable */
276 var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
277 var_SetBool( p_aout, "intf-change", true );
280 /*****************************************************************************
281 * Open: create a handle and open an alsa device
282 *****************************************************************************
283 * This function opens an alsa device, through the alsa API.
285 * Note: the only heap-allocated string is psz_device. All the other pointers
286 * are references to psz_device or to stack-allocated data.
287 *****************************************************************************/
288 static int Open( vlc_object_t *p_this )
290 aout_instance_t * p_aout = (aout_instance_t *)p_this;
291 struct aout_sys_t * p_sys;
294 char psz_default_iec_device[128]; /* Buffer used to store the default
296 char * psz_device, * psz_iec_device; /* device names for PCM and S/PDIF
299 int i_vlc_pcm_format; /* Audio format for VLC's data */
300 int i_snd_pcm_format; /* Audio format for ALSA's data */
302 snd_pcm_uframes_t i_buffer_size = 0;
303 snd_pcm_uframes_t i_period_size = 0;
306 snd_pcm_hw_params_t *p_hw;
307 snd_pcm_sw_params_t *p_sw;
310 unsigned int i_old_rate;
313 /* Allocate structures */
314 p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );
317 p_sys->b_playing = false;
318 p_sys->start_date = 0;
319 vlc_cond_init( &p_sys->wait );
320 vlc_mutex_init( &p_sys->lock );
322 /* Get device name */
323 if( (psz_device = config_GetPsz( p_aout, "alsa-audio-device" )) == NULL )
325 msg_Err( p_aout, "no audio device given (maybe \"default\" ?)" );
326 dialog_Fatal( p_aout, _("No Audio Device"), "%s",
327 _("No audio device name was given. You might want to " \
328 "enter \"default\".") );
333 /* Choose the IEC device for S/PDIF output:
334 if the device is overriden by the user then it will be the one
335 otherwise we compute the default device based on the output format. */
336 if( AOUT_FMT_NON_LINEAR( &p_aout->output.output )
337 && !strcmp( psz_device, DEFAULT_ALSA_DEVICE ) )
339 snprintf( psz_default_iec_device, sizeof(psz_default_iec_device),
340 "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
341 IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
342 IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
344 ( p_aout->output.output.i_rate == 48000 ?
345 IEC958_AES3_CON_FS_48000 :
346 ( p_aout->output.output.i_rate == 44100 ?
347 IEC958_AES3_CON_FS_44100 : IEC958_AES3_CON_FS_32000 ) ) );
348 psz_iec_device = psz_default_iec_device;
350 else if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
352 psz_iec_device = psz_device;
356 psz_iec_device = NULL;
359 /* Choose the linear PCM format (read the comment above about FPU
363 i_vlc_pcm_format = VLC_CODEC_FL32;
364 i_snd_pcm_format = SND_PCM_FORMAT_FLOAT;
368 i_vlc_pcm_format = VLC_CODEC_S16N;
369 i_snd_pcm_format = SND_PCM_FORMAT_S16;
372 /* If the variable doesn't exist then it's the first time we're called
373 and we have to probe the available audio formats and channels */
374 if ( var_Type( p_aout, "audio-device" ) == 0 )
376 Probe( p_aout, psz_device, psz_iec_device, &i_snd_pcm_format );
379 if ( var_Get( p_aout, "audio-device", &val ) < 0 )
386 p_aout->output.output.i_format = i_vlc_pcm_format;
387 if ( val.i_int == AOUT_VAR_5_1 )
389 p_aout->output.output.i_physical_channels
390 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
391 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
394 psz_device = strdup( "surround51" );
396 else if ( val.i_int == AOUT_VAR_2F2R )
398 p_aout->output.output.i_physical_channels
399 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
400 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
402 psz_device = strdup( "surround40" );
404 else if ( val.i_int == AOUT_VAR_STEREO )
406 p_aout->output.output.i_physical_channels
407 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
409 else if ( val.i_int == AOUT_VAR_MONO )
411 p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
413 else if( val.i_int != AOUT_VAR_SPDIF )
415 /* This should not happen ! */
416 msg_Err( p_aout, "internal: can't find audio-device (%i)", val.i_int );
423 snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 );
426 /* Open the device */
427 if ( val.i_int == AOUT_VAR_SPDIF )
429 if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
430 SND_PCM_STREAM_PLAYBACK, 0 ) ) < 0 )
432 msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
433 psz_iec_device, snd_strerror( i_snd_rc ) );
434 dialog_Fatal( p_aout, _("Audio output failed"),
435 _("VLC could not open the ALSA device \"%s\" (%s)."),
436 psz_iec_device, snd_strerror( i_snd_rc ) );
441 i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
442 i_snd_pcm_format = SND_PCM_FORMAT_S16;
445 i_vlc_pcm_format = VLC_CODEC_SPDIFL;
446 p_aout->output.i_nb_samples = i_period_size = ALSA_SPDIF_PERIOD_SIZE;
447 p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
448 p_aout->output.output.i_frame_length = A52_FRAME_NB;
450 aout_VolumeNoneInit( p_aout );
456 msg_Dbg( p_aout, "opening ALSA device `%s'", psz_device );
458 /* Since it seems snd_pcm_close hasn't really released the device at
459 the time it returns, probe if the device is available in loop for 1s.
460 We cannot use blocking mode since the we would wait indefinitely when
461 switching from a dmx device to surround51. */
463 for( i = 10; i >= 0; i-- )
465 if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
466 SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) ) == -EBUSY )
468 if( i ) msleep( 100000 /* 100ms */ );
471 msg_Err( p_aout, "audio device: %s is already in use",
473 dialog_Fatal( p_aout, _("Audio output failed"),
474 _("The audio device \"%s\" is already in use."),
483 msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
484 psz_device, snd_strerror( i_snd_rc ) );
485 dialog_Fatal( p_aout, _("Audio output failed"),
486 _("VLC could not open the ALSA device \"%s\" (%s)."),
487 psz_device, snd_strerror( i_snd_rc ) );
493 /* We want blocking mode */
494 snd_pcm_nonblock( p_sys->p_snd_pcm, 0 );
496 i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
497 i_channels = aout_FormatNbChannels( &p_aout->output.output );
499 p_aout->output.i_nb_samples = i_period_size = ALSA_DEFAULT_PERIOD_SIZE;
501 aout_VolumeSoftInit( p_aout );
504 /* Free psz_device so that all the remaining data is stack-allocated */
507 p_aout->output.pf_play = Play;
509 snd_pcm_hw_params_alloca(&p_hw);
510 snd_pcm_sw_params_alloca(&p_sw);
512 /* Due to some bugs in alsa with some drivers, we need to retry in s16l
513 if snd_pcm_hw_params fails in fl32 */
518 /* Get Initial hardware parameters */
519 if ( ( i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) ) < 0 )
521 msg_Err( p_aout, "unable to retrieve initial hardware parameters (%s)",
522 snd_strerror( i_snd_rc ) );
527 if ( ( i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
528 i_snd_pcm_format ) ) < 0 )
530 if( i_snd_pcm_format != SND_PCM_FORMAT_S16 )
532 i_snd_pcm_format = SND_PCM_FORMAT_S16;
533 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
534 p_hw, i_snd_pcm_format );
538 msg_Err( p_aout, "unable to set stream sample size and "
539 "word order (%s)", snd_strerror( i_snd_rc ) );
543 if( i_vlc_pcm_format != VLC_CODEC_SPDIFL )
544 switch( i_snd_pcm_format )
546 case SND_PCM_FORMAT_FLOAT:
547 i_vlc_pcm_format = VLC_CODEC_FL32;
549 case SND_PCM_FORMAT_S16:
550 i_vlc_pcm_format = VLC_CODEC_S16N;
553 p_aout->output.output.i_format = i_vlc_pcm_format;
555 if ( ( i_snd_rc = snd_pcm_hw_params_set_access( p_sys->p_snd_pcm, p_hw,
556 SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 )
558 msg_Err( p_aout, "unable to set interleaved stream format (%s)",
559 snd_strerror( i_snd_rc ) );
564 if ( ( i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw,
567 msg_Err( p_aout, "unable to set number of output channels (%s)",
568 snd_strerror( i_snd_rc ) );
573 i_old_rate = p_aout->output.output.i_rate;
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,
577 if( i_snd_rc < 0 || p_aout->output.output.i_rate != i_old_rate )
579 msg_Warn( p_aout, "The rate %d Hz is not supported by your " \
580 "hardware. Using %d Hz instead.\n", i_old_rate, \
581 p_aout->output.output.i_rate );
584 /* Set period size. */
585 if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,
586 p_hw, &i_period_size, NULL ) ) < 0 )
588 msg_Err( p_aout, "unable to set period size (%s)",
589 snd_strerror( i_snd_rc ) );
592 p_aout->output.i_nb_samples = i_period_size;
594 /* Set buffer size. */
595 if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,
596 p_hw, &i_buffer_size ) ) < 0 )
598 msg_Err( p_aout, "unable to set buffer size (%s)",
599 snd_strerror( i_snd_rc ) );
603 /* Commit hardware parameters. */
604 if ( ( i_snd_rc = snd_pcm_hw_params( p_sys->p_snd_pcm, p_hw ) ) < 0 )
606 if ( b_retry == false &&
607 i_snd_pcm_format == SND_PCM_FORMAT_FLOAT)
610 i_snd_pcm_format = SND_PCM_FORMAT_S16;
611 p_aout->output.output.i_format = VLC_CODEC_S16N;
612 msg_Warn( p_aout, "unable to commit hardware configuration "
613 "with fl32 samples. Retrying with s16l (%s)", snd_strerror( i_snd_rc ) );
617 msg_Err( p_aout, "unable to commit hardware configuration (%s)",
618 snd_strerror( i_snd_rc ) );
624 if( ( i_snd_rc = snd_pcm_hw_params_get_period_time( p_hw,
625 &p_sys->i_period_time, NULL ) ) < 0 )
627 msg_Err( p_aout, "unable to get period time (%s)",
628 snd_strerror( i_snd_rc ) );
632 /* Get Initial software parameters */
633 snd_pcm_sw_params_current( p_sys->p_snd_pcm, p_sw );
635 i_snd_rc = snd_pcm_sw_params_set_sleep_min( p_sys->p_snd_pcm, p_sw, 0 );
637 i_snd_rc = snd_pcm_sw_params_set_avail_min( p_sys->p_snd_pcm, p_sw,
638 p_aout->output.i_nb_samples );
639 /* start playing when one period has been written */
640 i_snd_rc = snd_pcm_sw_params_set_start_threshold( p_sys->p_snd_pcm, p_sw,
641 ALSA_DEFAULT_PERIOD_SIZE);
644 msg_Err( p_aout, "unable to set start threshold (%s)",
645 snd_strerror( i_snd_rc ) );
649 /* Commit software parameters. */
650 if ( snd_pcm_sw_params( p_sys->p_snd_pcm, p_sw ) < 0 )
652 msg_Err( p_aout, "unable to set software configuration" );
657 snd_output_printf( p_sys->p_snd_stderr, "\nALSA hardware setup:\n\n" );
658 snd_pcm_dump_hw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
659 snd_output_printf( p_sys->p_snd_stderr, "\nALSA software setup:\n\n" );
660 snd_pcm_dump_sw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
661 snd_output_printf( p_sys->p_snd_stderr, "\n" );
664 /* Create ALSA thread and wait for its readiness. */
665 if( vlc_clone( &p_sys->thread, ALSAThread, p_aout,
666 VLC_THREAD_PRIORITY_OUTPUT ) )
668 msg_Err( p_aout, "cannot create ALSA thread (%m)" );
675 snd_pcm_close( p_sys->p_snd_pcm );
677 snd_output_close( p_sys->p_snd_stderr );
683 /*****************************************************************************
684 * Play: nothing to do
685 *****************************************************************************/
686 static void Play( aout_instance_t *p_aout )
688 if( !p_aout->output.p_sys->b_playing )
690 p_aout->output.p_sys->b_playing = true;
692 /* get the playing date of the first aout buffer */
693 vlc_mutex_lock( &p_aout->output.p_sys->lock );
694 p_aout->output.p_sys->start_date =
695 aout_FifoFirstDate( p_aout, &p_aout->output.fifo );
697 /* wake up the audio output thread */
698 vlc_cond_signal( &p_aout->output.p_sys->wait );
699 vlc_mutex_unlock( &p_aout->output.p_sys->lock );
703 /*****************************************************************************
704 * Close: close the ALSA device
705 *****************************************************************************/
706 static void Close( vlc_object_t *p_this )
708 aout_instance_t *p_aout = (aout_instance_t *)p_this;
709 struct aout_sys_t * p_sys = p_aout->output.p_sys;
712 /* Make sure that the thread will stop once it is waken up */
713 vlc_cancel( p_sys->thread );
714 vlc_join( p_sys->thread, NULL );
716 /* make sure the audio output thread is waken up */
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 );
722 i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm );
726 msg_Err( p_aout, "failed closing ALSA device (%s)",
727 snd_strerror( i_snd_rc ) );
731 snd_output_close( p_sys->p_snd_stderr );
737 static void pcm_drop(void *pcm)
742 /*****************************************************************************
743 * ALSAThread: asynchronous thread used to DMA the data to the device
744 *****************************************************************************/
745 static void* ALSAThread( void *data )
747 aout_instance_t * p_aout = data;
748 struct aout_sys_t * p_sys = p_aout->output.p_sys;
750 /* Wait for the exact time to start playing (avoids resampling) */
751 vlc_mutex_lock( &p_sys->lock );
752 mutex_cleanup_push( &p_sys->lock );
753 while( !p_sys->start_date )
754 vlc_cond_wait( &p_sys->wait, &p_sys->lock );
757 mwait( p_sys->start_date - AOUT_PTS_TOLERANCE / 4 );
759 vlc_cleanup_push( pcm_drop, p_sys->p_snd_pcm );
767 /*****************************************************************************
768 * ALSAFill: function used to fill the ALSA buffer as much as possible
769 *****************************************************************************/
770 static void ALSAFill( aout_instance_t * p_aout )
772 struct aout_sys_t * p_sys = p_aout->output.p_sys;
773 snd_pcm_t *p_pcm = p_sys->p_snd_pcm;
774 snd_pcm_status_t * p_status;
778 int canc = vlc_savecancel();
779 /* Fill in the buffer until space or audio output buffer shortage */
782 snd_pcm_status_alloca(&p_status);
783 i_snd_rc = snd_pcm_status( p_pcm, p_status );
786 msg_Err( p_aout, "cannot get device status" );
790 /* Handle buffer underruns and get the status again */
791 if( snd_pcm_status_get_state( p_status ) == SND_PCM_STATE_XRUN )
793 /* Prepare the device */
794 i_snd_rc = snd_pcm_prepare( p_pcm );
797 msg_Err( p_aout, "cannot recover from buffer underrun" );
801 msg_Dbg( p_aout, "recovered from buffer underrun" );
803 /* Get the new status */
804 i_snd_rc = snd_pcm_status( p_pcm, p_status );
807 msg_Err( p_aout, "cannot get device status after recovery" );
811 /* Underrun, try to recover as quickly as possible */
816 /* Here the device should be in RUNNING state, p_status is valid. */
817 snd_pcm_sframes_t delay = snd_pcm_status_get_delay( p_status );
818 if( delay == 0 ) /* workaround buggy alsa drivers */
819 if( snd_pcm_delay( p_pcm, &delay ) < 0 )
820 delay = 0; /* FIXME: use a positive minimal delay */
822 size_t i_bytes = snd_pcm_frames_to_bytes( p_pcm, delay );
823 mtime_t delay_us = CLOCK_FREQ * i_bytes
824 / p_aout->output.output.i_bytes_per_frame
825 / p_aout->output.output.i_rate
826 * p_aout->output.output.i_frame_length;
829 snd_pcm_state_t state = snd_pcm_status_get_state( p_status );
830 if( state != SND_PCM_STATE_RUNNING )
831 msg_Err( p_aout, "pcm status (%d) != RUNNING", state );
833 msg_Dbg( p_aout, "Delay is %ld frames (%zu bytes)", delay, i_bytes );
835 msg_Dbg( p_aout, "Bytes per frame: %d", p_aout->output.output.i_bytes_per_frame );
836 msg_Dbg( p_aout, "Rate: %d", p_aout->output.output.i_rate );
837 msg_Dbg( p_aout, "Frame length: %d", p_aout->output.output.i_frame_length );
838 msg_Dbg( p_aout, "Next date: in %"PRId64" microseconds", delay_us );
840 next_date = mdate() + delay_us;
843 block_t *p_buffer = aout_OutputNextBuffer( p_aout, next_date,
844 (p_aout->output.output.i_format == VLC_CODEC_SPDIFL) );
846 /* Audio output buffer shortage -> stop the fill process and wait */
847 if( p_buffer == NULL )
852 int n = snd_pcm_poll_descriptors_count(p_pcm);
853 struct pollfd ufd[n];
854 unsigned short revents;
856 snd_pcm_poll_descriptors(p_pcm, ufd, n);
859 vlc_restorecancel(canc);
861 canc = vlc_savecancel();
862 snd_pcm_poll_descriptors_revents(p_pcm, ufd, n, &revents);
866 if(revents & POLLOUT)
868 i_snd_rc = snd_pcm_writei( p_pcm, p_buffer->p_buffer,
869 p_buffer->i_nb_samples );
870 if( i_snd_rc != -ESTRPIPE )
874 /* a suspend event occurred
875 * (stream is suspended and waiting for an application recovery) */
876 msg_Dbg( p_aout, "entering in suspend mode, trying to resume..." );
878 while( ( i_snd_rc = snd_pcm_resume( p_pcm ) ) == -EAGAIN )
880 vlc_restorecancel(canc);
881 msleep(CLOCK_FREQ); /* device still suspended, wait... */
882 canc = vlc_savecancel();
886 /* Device does not support resuming, restart it */
887 i_snd_rc = snd_pcm_prepare( p_pcm );
892 msg_Err( p_aout, "cannot write: %s", snd_strerror( i_snd_rc ) );
894 vlc_restorecancel(canc);
895 block_Release( p_buffer );
900 msg_Err( p_aout, "ALSA error: %s", snd_strerror( i_snd_rc ) );
902 vlc_restorecancel(canc);
903 msleep(p_sys->i_period_time / 2);
906 static void GetDevicesForCard( module_config_t *p_item, int i_card );
907 static void GetDevices( module_config_t *p_item );
909 /*****************************************************************************
910 * config variable callback
911 *****************************************************************************/
912 static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,
913 vlc_value_t newval, vlc_value_t oldval, void *p_unused )
915 module_config_t *p_item;
921 p_item = config_FindConfig( p_this, psz_name );
922 if( !p_item ) return VLC_SUCCESS;
924 /* Clear-up the current list */
927 /* Keep the first entrie */
928 for( i = 1; i < p_item->i_list; i++ )
930 free( (char *)p_item->ppsz_list[i] );
931 free( (char *)p_item->ppsz_list_text[i] );
933 /* TODO: Remove when no more needed */
934 p_item->ppsz_list[i] = NULL;
935 p_item->ppsz_list_text[i] = NULL;
939 GetDevices( p_item );
941 /* Signal change to the interface */
942 p_item->b_dirty = true;
948 static void GetDevicesForCard( module_config_t *p_item, int i_card )
950 int i_pcm_device = -1;
952 snd_pcm_info_t *p_pcm_info;
957 sprintf( psz_dev, "hw:%i", i_card );
959 if( ( i_err = snd_ctl_open( &p_ctl, psz_dev, 0 ) ) < 0 )
962 if( ( i_err = snd_card_get_name( i_card, &psz_card_name ) ) != 0)
963 psz_card_name = _("Unknown soundcard");
965 snd_pcm_info_alloca( &p_pcm_info );
969 char *psz_device, *psz_descr;
970 if( ( i_err = snd_ctl_pcm_next_device( p_ctl, &i_pcm_device ) ) < 0 )
972 if( i_pcm_device < 0 )
975 snd_pcm_info_set_device( p_pcm_info, i_pcm_device );
976 snd_pcm_info_set_subdevice( p_pcm_info, 0 );
977 snd_pcm_info_set_stream( p_pcm_info, SND_PCM_STREAM_PLAYBACK );
979 if( ( i_err = snd_ctl_pcm_info( p_ctl, p_pcm_info ) ) < 0 )
981 if( i_err != -ENOENT )
983 /*printf( "get_devices_for_card(): "
984 "snd_ctl_pcm_info() "
985 "failed (%d:%d): %s.\n", i_card,
986 i_pcm_device, snd_strerror( -i_err ) );*/
991 if( asprintf( &psz_device, "hw:%d,%d", i_card, i_pcm_device ) == -1 )
993 if( asprintf( &psz_descr, "%s: %s (%s)", psz_card_name,
994 snd_pcm_info_get_name(p_pcm_info), psz_device ) == -1 )
1001 (char **)realloc( p_item->ppsz_list,
1002 (p_item->i_list + 2) * sizeof(char *) );
1003 p_item->ppsz_list_text =
1004 (char **)realloc( p_item->ppsz_list_text,
1005 (p_item->i_list + 2) * sizeof(char *) );
1006 p_item->ppsz_list[ p_item->i_list ] = psz_device;
1007 p_item->ppsz_list_text[ p_item->i_list ] = psz_descr;
1009 p_item->ppsz_list[ p_item->i_list ] = NULL;
1010 p_item->ppsz_list_text[ p_item->i_list ] = NULL;
1013 snd_ctl_close( p_ctl );
1018 static void GetDevices( module_config_t *p_item )
1023 if( ( i_err = snd_card_next( &i_card ) ) != 0 )
1025 /*printf( "snd_card_next() failed: %s", snd_strerror( -i_err ) );*/
1029 while( i_card > -1 )
1031 GetDevicesForCard( p_item, i_card );
1032 if( ( i_err = snd_card_next( &i_card ) ) != 0 )
1034 /*printf( "snd_card_next() failed: %s", snd_strerror( -i_err ) );*/