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 *****************************************************************************/
35 #include <vlc_plugin.h>
37 #include <errno.h> /* ENOMEM */
38 #include <vlc_interface.h>
43 Note: we use the new API which is available since 0.9.0beta10a. */
44 #define ALSA_PCM_NEW_HW_PARAMS_API
45 #define ALSA_PCM_NEW_SW_PARAMS_API
46 #include <alsa/asoundlib.h>
48 /*#define ALSA_DEBUG*/
50 /*****************************************************************************
51 * aout_sys_t: ALSA audio output method descriptor
52 *****************************************************************************
53 * This structure is part of the audio output thread descriptor.
54 * It describes the ALSA specific properties of an audio device.
55 *****************************************************************************/
58 snd_pcm_t * p_snd_pcm;
59 unsigned int i_period_time;
62 snd_output_t * p_snd_stderr;
65 int b_playing; /* playing status */
71 snd_pcm_status_t *p_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 int ALSAThread ( aout_instance_t * );
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 *ppsz_devices[] = { "default" };
105 static const char *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( "alsadev", DEFAULT_ALSA_DEVICE, aout_FindAndRestart,
112 N_("ALSA Device Name"), NULL, false );
113 change_string_list( ppsz_devices, ppsz_devices_text, FindDevicesCallback );
114 change_action_add( FindDevicesCallback, N_("Refresh list") );
116 set_capability( "audio output", 150 );
117 set_callbacks( Open, Close );
120 /*****************************************************************************
121 * Probe: probe the audio device for available formats and channels
122 *****************************************************************************/
123 static void Probe( aout_instance_t * p_aout,
124 const char * psz_device, const char * psz_iec_device,
125 int *pi_snd_pcm_format )
127 struct aout_sys_t * p_sys = p_aout->output.p_sys;
128 vlc_value_t val, text;
131 var_Create ( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
132 text.psz_string = _("Audio Device");
133 var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
135 /* We'll open the audio device in non blocking mode so we can just exit
136 * when it is already in use, but for the real stuff we'll still use
137 * the blocking mode */
139 /* Now test linear PCM capabilities */
140 if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
141 SND_PCM_STREAM_PLAYBACK,
142 SND_PCM_NONBLOCK ) ) )
145 snd_pcm_hw_params_t * p_hw;
146 snd_pcm_hw_params_alloca (&p_hw);
148 if ( snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) < 0 )
150 msg_Warn( p_aout, "unable to retrieve initial hardware parameters"
151 ", disabling linear PCM audio" );
152 snd_pcm_close( p_sys->p_snd_pcm );
153 var_Destroy( p_aout, "audio-device" );
157 if ( snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
158 *pi_snd_pcm_format ) < 0 )
162 if( *pi_snd_pcm_format != SND_PCM_FORMAT_S16 )
164 *pi_snd_pcm_format = SND_PCM_FORMAT_S16;
165 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
166 p_hw, *pi_snd_pcm_format );
170 msg_Warn( p_aout, "unable to set stream sample size and "
171 "word order, disabling linear PCM audio" );
172 snd_pcm_close( p_sys->p_snd_pcm );
173 var_Destroy( p_aout, "audio-device" );
178 i_channels = aout_FormatNbChannels( &p_aout->output.output );
180 while ( i_channels > 0 )
182 if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw,
185 switch ( i_channels )
188 val.i_int = AOUT_VAR_MONO;
189 text.psz_string = N_("Mono");
190 var_Change( p_aout, "audio-device",
191 VLC_VAR_ADDCHOICE, &val, &text );
194 val.i_int = AOUT_VAR_STEREO;
195 text.psz_string = N_("Stereo");
196 var_Change( p_aout, "audio-device",
197 VLC_VAR_ADDCHOICE, &val, &text );
198 var_Set( p_aout, "audio-device", val );
201 val.i_int = AOUT_VAR_2F2R;
202 text.psz_string = N_("2 Front 2 Rear");
203 var_Change( p_aout, "audio-device",
204 VLC_VAR_ADDCHOICE, &val, &text );
207 val.i_int = AOUT_VAR_5_1;
208 text.psz_string = "5.1";
209 var_Change( p_aout, "audio-device",
210 VLC_VAR_ADDCHOICE, &val, &text );
218 /* Special case for mono on stereo only boards */
219 i_channels = aout_FormatNbChannels( &p_aout->output.output );
220 var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
221 if( val.i_int <= 0 && i_channels == 1 )
223 if ( !snd_pcm_hw_params_test_channels( p_sys->p_snd_pcm, p_hw, 2 ))
225 val.i_int = AOUT_VAR_STEREO;
226 text.psz_string = N_("Stereo");
227 var_Change( p_aout, "audio-device",
228 VLC_VAR_ADDCHOICE, &val, &text );
229 var_Set( p_aout, "audio-device", val );
233 /* Close the previously opened device */
234 snd_pcm_close( p_sys->p_snd_pcm );
236 else if ( i_ret == -EBUSY )
238 msg_Warn( p_aout, "audio device: %s is already in use", psz_device );
241 /* Test for S/PDIF device if needed */
242 if ( psz_iec_device )
244 /* Opening the device should be enough */
245 if ( !(i_ret = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
246 SND_PCM_STREAM_PLAYBACK,
247 SND_PCM_NONBLOCK ) ) )
249 val.i_int = AOUT_VAR_SPDIF;
250 text.psz_string = N_("A/52 over S/PDIF");
251 var_Change( p_aout, "audio-device",
252 VLC_VAR_ADDCHOICE, &val, &text );
253 if( config_GetInt( p_aout, "spdif" ) )
254 var_Set( p_aout, "audio-device", val );
256 snd_pcm_close( p_sys->p_snd_pcm );
258 else if ( i_ret == -EBUSY )
260 msg_Warn( p_aout, "audio device: %s is already in use",
265 var_Change( p_aout, "audio-device", VLC_VAR_CHOICESCOUNT, &val, NULL );
268 /* Probe() has failed. */
269 msg_Dbg( p_aout, "failed to find a useable alsa configuration" );
270 var_Destroy( p_aout, "audio-device" );
274 /* Add final settings to the variable */
275 var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
277 var_Set( p_aout, "intf-change", val );
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 msg_Err( p_aout, "out of memory" );
320 p_sys->b_playing = false;
321 p_sys->start_date = 0;
322 vlc_cond_init( p_aout, &p_sys->wait );
323 vlc_mutex_init( &p_sys->lock );
325 /* Get device name */
326 if( (psz_device = config_GetPsz( p_aout, "alsadev" )) == NULL )
328 msg_Err( p_aout, "no audio device given (maybe \"default\" ?)" );
329 intf_UserFatal( p_aout, false, _("No Audio Device"),
330 _("No audio device name was given. You might want to " \
331 "enter \"default\".") );
336 /* Choose the IEC device for S/PDIF output:
337 if the device is overriden by the user then it will be the one
338 otherwise we compute the default device based on the output format. */
339 if( AOUT_FMT_NON_LINEAR( &p_aout->output.output )
340 && !strcmp( psz_device, DEFAULT_ALSA_DEVICE ) )
342 snprintf( psz_default_iec_device, sizeof(psz_default_iec_device),
343 "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
344 IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
345 IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
347 ( p_aout->output.output.i_rate == 48000 ?
348 IEC958_AES3_CON_FS_48000 :
349 ( p_aout->output.output.i_rate == 44100 ?
350 IEC958_AES3_CON_FS_44100 : IEC958_AES3_CON_FS_32000 ) ) );
351 psz_iec_device = psz_default_iec_device;
353 else if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) )
355 psz_iec_device = psz_device;
359 psz_iec_device = NULL;
362 /* Choose the linear PCM format (read the comment above about FPU
364 if( vlc_CPU() & CPU_CAPABILITY_FPU )
366 i_vlc_pcm_format = VLC_FOURCC('f','l','3','2');
367 i_snd_pcm_format = SND_PCM_FORMAT_FLOAT;
371 i_vlc_pcm_format = AOUT_FMT_S16_NE;
372 i_snd_pcm_format = SND_PCM_FORMAT_S16;
375 /* If the variable doesn't exist then it's the first time we're called
376 and we have to probe the available audio formats and channels */
377 if ( var_Type( p_aout, "audio-device" ) == 0 )
379 Probe( p_aout, psz_device, psz_iec_device, &i_snd_pcm_format );
382 if ( var_Get( p_aout, "audio-device", &val ) < 0 )
389 p_aout->output.output.i_format = i_vlc_pcm_format;
390 if ( val.i_int == AOUT_VAR_5_1 )
392 p_aout->output.output.i_physical_channels
393 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
394 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
397 psz_device = strdup( "surround51" );
399 else if ( val.i_int == AOUT_VAR_2F2R )
401 p_aout->output.output.i_physical_channels
402 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
403 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
405 psz_device = strdup( "surround40" );
407 else if ( val.i_int == AOUT_VAR_STEREO )
409 p_aout->output.output.i_physical_channels
410 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
412 else if ( val.i_int == AOUT_VAR_MONO )
414 p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
416 else if( val.i_int != AOUT_VAR_SPDIF )
418 /* This should not happen ! */
419 msg_Err( p_aout, "internal: can't find audio-device (%i)", val.i_int );
426 snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 );
429 /* Open the device */
430 if ( val.i_int == AOUT_VAR_SPDIF )
432 if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device,
433 SND_PCM_STREAM_PLAYBACK, 0 ) ) < 0 )
435 msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
436 psz_iec_device, snd_strerror( i_snd_rc ) );
437 intf_UserFatal( p_aout, false, _("Audio output failed"),
438 _("VLC could not open the ALSA device \"%s\" (%s)."),
439 psz_iec_device, snd_strerror( i_snd_rc ) );
444 i_buffer_size = ALSA_SPDIF_BUFFER_SIZE;
445 i_snd_pcm_format = SND_PCM_FORMAT_S16;
448 i_vlc_pcm_format = VLC_FOURCC('s','p','d','i');
449 p_aout->output.i_nb_samples = i_period_size = ALSA_SPDIF_PERIOD_SIZE;
450 p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
451 p_aout->output.output.i_frame_length = A52_FRAME_NB;
453 aout_VolumeNoneInit( p_aout );
459 msg_Dbg( p_aout, "opening ALSA device `%s'", psz_device );
461 /* Since it seems snd_pcm_close hasn't really released the device at
462 the time it returns, probe if the device is available in loop for 1s.
463 We cannot use blocking mode since the we would wait indefinitely when
464 switching from a dmx device to surround51. */
466 for( i = 10; i >= 0; i-- )
468 if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_device,
469 SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) ) == -EBUSY )
471 if( i ) msleep( 100000 /* 100ms */ );
474 msg_Err( p_aout, "audio device: %s is already in use",
476 intf_UserFatal( p_aout, false, _("Audio output failed"),
477 _("The audio device \"%s\" is already in use."),
486 msg_Err( p_aout, "cannot open ALSA device `%s' (%s)",
487 psz_device, snd_strerror( i_snd_rc ) );
488 intf_UserFatal( p_aout, false, _("Audio output failed"),
489 _("VLC could not open the ALSA device \"%s\" (%s)."),
490 psz_device, snd_strerror( i_snd_rc ) );
496 /* We want blocking mode */
497 snd_pcm_nonblock( p_sys->p_snd_pcm, 0 );
499 i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE;
500 i_channels = aout_FormatNbChannels( &p_aout->output.output );
502 p_aout->output.i_nb_samples = i_period_size = ALSA_DEFAULT_PERIOD_SIZE;
504 aout_VolumeSoftInit( p_aout );
507 /* Free psz_device so that all the remaining data is stack-allocated */
510 p_aout->output.pf_play = Play;
512 snd_pcm_hw_params_alloca(&p_hw);
513 snd_pcm_sw_params_alloca(&p_sw);
515 /* Due to some bugs in alsa with some drivers, we need to retry in s16l
516 if snd_pcm_hw_params fails in fl32 */
521 /* Get Initial hardware parameters */
522 if ( ( i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) ) < 0 )
524 msg_Err( p_aout, "unable to retrieve initial hardware parameters (%s)",
525 snd_strerror( i_snd_rc ) );
530 if ( ( i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw,
531 i_snd_pcm_format ) ) < 0 )
533 if( i_snd_pcm_format != SND_PCM_FORMAT_S16 )
535 i_snd_pcm_format = SND_PCM_FORMAT_S16;
536 i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm,
537 p_hw, i_snd_pcm_format );
541 msg_Err( p_aout, "unable to set stream sample size and "
542 "word order (%s)", snd_strerror( i_snd_rc ) );
546 if( i_vlc_pcm_format != VLC_FOURCC('s','p','d','i') )
547 switch( i_snd_pcm_format )
549 case SND_PCM_FORMAT_FLOAT:
550 i_vlc_pcm_format = VLC_FOURCC('f','l','3','2');
552 case SND_PCM_FORMAT_S16:
553 i_vlc_pcm_format = AOUT_FMT_S16_NE;
556 p_aout->output.output.i_format = i_vlc_pcm_format;
558 if ( ( i_snd_rc = snd_pcm_hw_params_set_access( p_sys->p_snd_pcm, p_hw,
559 SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 )
561 msg_Err( p_aout, "unable to set interleaved stream format (%s)",
562 snd_strerror( i_snd_rc ) );
567 if ( ( i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw,
570 msg_Err( p_aout, "unable to set number of output channels (%s)",
571 snd_strerror( i_snd_rc ) );
576 i_old_rate = p_aout->output.output.i_rate;
577 #ifdef HAVE_ALSA_NEW_API
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 i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm, p_hw,
583 p_aout->output.output.i_rate,
586 if( i_snd_rc < 0 || p_aout->output.output.i_rate != i_old_rate )
588 msg_Warn( p_aout, "The rate %d Hz is not supported by your " \
589 "hardware. Using %d Hz instead.\n", i_old_rate, \
590 p_aout->output.output.i_rate );
593 /* Set period size. */
594 #ifdef HAVE_ALSA_NEW_API
595 if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,
596 p_hw, &i_period_size, NULL ) ) < 0 )
598 if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm,
599 p_hw, i_period_size, NULL ) ) < 0 )
602 msg_Err( p_aout, "unable to set period size (%s)",
603 snd_strerror( i_snd_rc ) );
606 p_aout->output.i_nb_samples = i_period_size;
608 /* Set buffer size. */
609 #ifdef HAVE_ALSA_NEW_API
610 if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,
611 p_hw, &i_buffer_size ) ) < 0 )
613 if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm,
614 p_hw, i_buffer_size ) ) < 0 )
617 msg_Err( p_aout, "unable to set buffer size (%s)",
618 snd_strerror( i_snd_rc ) );
622 /* Commit hardware parameters. */
623 if ( ( i_snd_rc = snd_pcm_hw_params( p_sys->p_snd_pcm, p_hw ) ) < 0 )
625 if ( b_retry == false &&
626 i_snd_pcm_format == SND_PCM_FORMAT_FLOAT)
629 i_snd_pcm_format = SND_PCM_FORMAT_S16;
630 p_aout->output.output.i_format = AOUT_FMT_S16_NE;
631 msg_Warn( p_aout, "unable to commit hardware configuration "
632 "with fl32 samples. Retrying with s16l (%s)", snd_strerror( i_snd_rc ) );
636 msg_Err( p_aout, "unable to commit hardware configuration (%s)",
637 snd_strerror( i_snd_rc ) );
643 #ifdef HAVE_ALSA_NEW_API
644 if( ( i_snd_rc = snd_pcm_hw_params_get_period_time( p_hw,
645 &p_sys->i_period_time, NULL ) ) < 0 )
647 if( ( p_sys->i_period_time =
648 (int)snd_pcm_hw_params_get_period_time( p_hw, NULL ) ) < 0 )
651 msg_Err( p_aout, "unable to get period time (%s)",
652 snd_strerror( i_snd_rc ) );
656 /* Get Initial software parameters */
657 snd_pcm_sw_params_current( p_sys->p_snd_pcm, p_sw );
659 i_snd_rc = snd_pcm_sw_params_set_sleep_min( p_sys->p_snd_pcm, p_sw, 0 );
661 i_snd_rc = snd_pcm_sw_params_set_avail_min( p_sys->p_snd_pcm, p_sw,
662 p_aout->output.i_nb_samples );
663 /* start playing when one period has been written */
664 i_snd_rc = snd_pcm_sw_params_set_start_threshold( p_sys->p_snd_pcm, p_sw,
665 ALSA_DEFAULT_PERIOD_SIZE);
668 msg_Err( p_aout, "unable to set start threshold (%s)",
669 snd_strerror( i_snd_rc ) );
673 /* Commit software parameters. */
674 if ( snd_pcm_sw_params( p_sys->p_snd_pcm, p_sw ) < 0 )
676 msg_Err( p_aout, "unable to set software configuration" );
681 snd_output_printf( p_sys->p_snd_stderr, "\nALSA hardware setup:\n\n" );
682 snd_pcm_dump_hw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
683 snd_output_printf( p_sys->p_snd_stderr, "\nALSA software setup:\n\n" );
684 snd_pcm_dump_sw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr );
685 snd_output_printf( p_sys->p_snd_stderr, "\n" );
688 /* Create ALSA thread and wait for its readiness. */
689 if( vlc_thread_create( p_aout, "aout", ALSAThread,
690 VLC_THREAD_PRIORITY_OUTPUT, false ) )
692 msg_Err( p_aout, "cannot create ALSA thread (%m)" );
699 snd_pcm_close( p_sys->p_snd_pcm );
701 snd_output_close( p_sys->p_snd_stderr );
707 /*****************************************************************************
708 * Play: nothing to do
709 *****************************************************************************/
710 static void Play( aout_instance_t *p_aout )
712 if( !p_aout->output.p_sys->b_playing )
714 p_aout->output.p_sys->b_playing = 1;
716 /* get the playing date of the first aout buffer */
717 p_aout->output.p_sys->start_date =
718 aout_FifoFirstDate( p_aout, &p_aout->output.fifo );
720 /* wake up the audio output thread */
721 vlc_mutex_lock( &p_aout->output.p_sys->lock );
722 vlc_cond_signal( &p_aout->output.p_sys->wait );
723 vlc_mutex_unlock( &p_aout->output.p_sys->lock );
727 /*****************************************************************************
728 * Close: close the ALSA device
729 *****************************************************************************/
730 static void Close( vlc_object_t *p_this )
732 aout_instance_t *p_aout = (aout_instance_t *)p_this;
733 struct aout_sys_t * p_sys = p_aout->output.p_sys;
736 /* make sure the audio output thread is waken up */
737 vlc_mutex_lock( &p_aout->output.p_sys->lock );
738 vlc_cond_signal( &p_aout->output.p_sys->wait );
739 vlc_mutex_unlock( &p_aout->output.p_sys->lock );
741 vlc_object_kill( p_aout );
742 vlc_thread_join( p_aout );
743 p_aout->b_die = false;
745 i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm );
749 msg_Err( p_aout, "failed closing ALSA device (%s)",
750 snd_strerror( i_snd_rc ) );
754 snd_output_close( p_sys->p_snd_stderr );
760 /*****************************************************************************
761 * ALSAThread: asynchronous thread used to DMA the data to the device
762 *****************************************************************************/
763 static int ALSAThread( aout_instance_t * p_aout )
765 struct aout_sys_t * p_sys = p_aout->output.p_sys;
766 p_sys->p_status = (snd_pcm_status_t *)malloc(snd_pcm_status_sizeof());
768 /* Wait for the exact time to start playing (avoids resampling) */
769 vlc_mutex_lock( &p_sys->lock );
770 while( !p_sys->start_date && !p_aout->b_die )
771 vlc_cond_wait( &p_sys->wait, &p_sys->lock );
772 vlc_mutex_unlock( &p_sys->lock );
777 mwait( p_sys->start_date - AOUT_PTS_TOLERANCE / 4 );
779 while ( !p_aout->b_die )
785 snd_pcm_drop( p_sys->p_snd_pcm );
786 free( p_aout->output.p_sys->p_status );
790 /*****************************************************************************
791 * ALSAFill: function used to fill the ALSA buffer as much as possible
792 *****************************************************************************/
793 static void ALSAFill( aout_instance_t * p_aout )
795 struct aout_sys_t * p_sys = p_aout->output.p_sys;
796 aout_buffer_t * p_buffer;
797 snd_pcm_status_t * p_status = p_sys->p_status;
801 /* Fill in the buffer until space or audio output buffer shortage */
804 i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );
807 msg_Err( p_aout, "cannot get device status" );
811 /* Handle buffer underruns and get the status again */
812 if( snd_pcm_status_get_state( p_status ) == SND_PCM_STATE_XRUN )
814 /* Prepare the device */
815 i_snd_rc = snd_pcm_prepare( p_sys->p_snd_pcm );
819 msg_Err( p_aout, "cannot recover from buffer underrun" );
823 msg_Dbg( p_aout, "recovered from buffer underrun" );
825 /* Get the new status */
826 i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );
829 msg_Err( p_aout, "cannot get device status after recovery" );
833 /* Underrun, try to recover as quickly as possible */
838 /* Here the device should be in RUNNING state, p_status is valid. */
839 snd_pcm_sframes_t delay = snd_pcm_status_get_delay( p_status );
840 if( delay == 0 ) /* workaround buggy alsa drivers */
841 if( snd_pcm_delay( p_sys->p_snd_pcm, &delay ) < 0 )
842 delay = 0; /* FIXME: use a positive minimal delay */
843 int i_bytes = snd_pcm_frames_to_bytes( p_sys->p_snd_pcm, delay );
844 next_date = mdate() + ( (mtime_t)i_bytes * 1000000
845 / p_aout->output.output.i_bytes_per_frame
846 / p_aout->output.output.i_rate
847 * p_aout->output.output.i_frame_length );
850 snd_pcm_state_t state = snd_pcm_status_get_state( p_status );
851 if( state != SND_PCM_STATE_RUNNING )
852 msg_Err( p_aout, "pcm status (%d) != RUNNING", state );
854 msg_Dbg( p_aout, "Delay is %ld frames (%d bytes)", delay, i_bytes );
856 msg_Dbg( p_aout, "Bytes per frame: %d", p_aout->output.output.i_bytes_per_frame );
857 msg_Dbg( p_aout, "Rate: %d", p_aout->output.output.i_rate );
858 msg_Dbg( p_aout, "Frame length: %d", p_aout->output.output.i_frame_length );
860 msg_Dbg( p_aout, "Next date is in %d microseconds", (int)(next_date - mdate()) );
864 p_buffer = aout_OutputNextBuffer( p_aout, next_date,
865 (p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i')) );
867 /* Audio output buffer shortage -> stop the fill process and wait */
868 if( p_buffer == NULL )
873 i_snd_rc = snd_pcm_writei( p_sys->p_snd_pcm, p_buffer->p_buffer,
874 p_buffer->i_nb_samples );
875 if( i_snd_rc != -ESTRPIPE )
878 /* a suspend event occurred
879 * (stream is suspended and waiting for an application recovery) */
880 msg_Dbg( p_aout, "entering in suspend mode, trying to resume..." );
882 while( !p_aout->b_die && !p_aout->p_libvlc->b_die &&
883 ( i_snd_rc = snd_pcm_resume( p_sys->p_snd_pcm ) ) == -EAGAIN )
889 /* Device does not supprot resuming, restart it */
890 i_snd_rc = snd_pcm_prepare( p_sys->p_snd_pcm );
895 msg_Err( p_aout, "cannot write: %s", snd_strerror( i_snd_rc ) );
897 aout_BufferFree( p_buffer );
902 msg_Err( p_aout, "ALSA error: %s", snd_strerror( i_snd_rc ) );
903 msleep( p_sys->i_period_time >> 1 );
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;
918 p_item = config_FindConfig( p_this, psz_name );
919 if( !p_item ) return VLC_SUCCESS;
921 /* Clear-up the current list */
924 /* Keep the first entrie */
925 for( i = 1; i < p_item->i_list; i++ )
927 free( (char *)p_item->ppsz_list[i] );
928 free( (char *)p_item->ppsz_list_text[i] );
930 /* TODO: Remove when no more needed */
931 p_item->ppsz_list[i] = NULL;
932 p_item->ppsz_list_text[i] = NULL;
936 GetDevices( p_item );
938 /* Signal change to the interface */
939 p_item->b_dirty = true;
946 static void GetDevicesForCard( module_config_t *p_item, int i_card )
948 int i_pcm_device = -1;
950 snd_pcm_info_t *p_pcm_info;
955 sprintf( psz_dev, "hw:%i", i_card );
957 if( ( i_err = snd_ctl_open( &p_ctl, psz_dev, 0 ) ) < 0 )
960 if( ( i_err = snd_card_get_name( i_card, &psz_card_name ) ) != 0)
961 psz_card_name = _("Unknown soundcard");
963 snd_pcm_info_alloca( &p_pcm_info );
967 char *psz_device, *psz_descr;
968 if( ( i_err = snd_ctl_pcm_next_device( p_ctl, &i_pcm_device ) ) < 0 )
970 if( i_pcm_device < 0 )
973 snd_pcm_info_set_device( p_pcm_info, i_pcm_device );
974 snd_pcm_info_set_subdevice( p_pcm_info, 0 );
975 snd_pcm_info_set_stream( p_pcm_info, SND_PCM_STREAM_PLAYBACK );
977 if( ( i_err = snd_ctl_pcm_info( p_ctl, p_pcm_info ) ) < 0 )
979 if( i_err != -ENOENT )
981 /*printf( "get_devices_for_card(): "
982 "snd_ctl_pcm_info() "
983 "failed (%d:%d): %s.\n", i_card,
984 i_pcm_device, snd_strerror( -i_err ) );*/
989 asprintf( &psz_device, "hw:%d,%d", i_card, i_pcm_device );
990 asprintf( &psz_descr, "%s: %s (%s)", psz_card_name,
991 snd_pcm_info_get_name(p_pcm_info), psz_device );
994 (const char **)realloc( p_item->ppsz_list,
995 (p_item->i_list + 2) * sizeof(char *) );
996 p_item->ppsz_list_text =
997 (const char **)realloc( p_item->ppsz_list_text,
998 (p_item->i_list + 2) * sizeof(char *) );
999 p_item->ppsz_list[ p_item->i_list ] = psz_device;
1000 p_item->ppsz_list_text[ p_item->i_list ] = psz_descr;
1002 p_item->ppsz_list[ p_item->i_list ] = NULL;
1003 p_item->ppsz_list_text[ p_item->i_list ] = NULL;
1006 snd_ctl_close( p_ctl );
1011 static void GetDevices( module_config_t *p_item )
1016 if( ( i_err = snd_card_next( &i_card ) ) != 0 )
1018 /*printf( "snd_card_next() failed: %s", snd_strerror( -i_err ) );*/
1022 while( i_card > -1 )
1024 GetDevicesForCard( p_item, i_card );
1025 if( ( i_err = snd_card_next( &i_card ) ) != 0 )
1027 /*printf( "snd_card_next() failed: %s", snd_strerror( -i_err ) );*/