X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faudio_output%2Fportaudio.c;h=6bc6c699facd449fe91fc58234a1bb28d19f2997;hb=7eb551db1c68e537c6fab6d9c68956acccd1eddd;hp=b0c4d4a72e7a243c6c9e1c7aa3cadbf933b42357;hpb=99fab9089e9e1709d9c3a4bc5ced0c137ac59134;p=vlc diff --git a/modules/audio_output/portaudio.c b/modules/audio_output/portaudio.c index b0c4d4a72e..6bc6c699fa 100644 --- a/modules/audio_output/portaudio.c +++ b/modules/audio_output/portaudio.c @@ -30,7 +30,8 @@ # include "config.h" #endif -#include +#include +#include #include @@ -45,23 +46,25 @@ /***************************************************************************** * aout_sys_t: portaudio audio output method descriptor *****************************************************************************/ -typedef struct pa_thread_t +typedef struct { - VLC_COMMON_MEMBERS - aout_instance_t *p_aout; + audio_output_t *p_aout; + vlc_thread_t thread; vlc_cond_t wait; vlc_mutex_t lock_wait; - vlc_bool_t b_wait; + bool b_wait; vlc_cond_t signal; vlc_mutex_t lock_signal; - vlc_bool_t b_signal; + bool b_signal; + bool b_error; } pa_thread_t; struct aout_sys_t { - aout_instance_t *p_aout; + aout_packet_t packet; + audio_output_t *p_aout; PaStream *p_stream; PaDeviceIndex i_devices; @@ -69,28 +72,23 @@ struct aout_sys_t PaDeviceIndex i_device_id; const PaDeviceInfo *deviceInfo; - vlc_bool_t b_chan_reorder; /* do we need channel reordering */ + bool b_chan_reorder; /* do we need channel reordering */ int pi_chan_table[AOUT_CHAN_MAX]; uint32_t i_channel_mask; uint32_t i_bits_per_sample; uint32_t i_channels; }; -static const uint32_t pi_channels_in[] = - { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, - AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, - AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, - AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 }; static const uint32_t pi_channels_out[] = { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_CENTER, AOUT_CHAN_LFE, - AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, + AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_REARCENTER, AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, 0 }; #ifdef PORTAUDIO_IS_SERIOUSLY_BROKEN -static vlc_bool_t b_init = 0; +static bool b_init = 0; static pa_thread_t *pa_thread; -static void PORTAUDIOThread( pa_thread_t * ); +static void* PORTAUDIOThread( void * ); #endif /***************************************************************************** @@ -98,10 +96,10 @@ static void PORTAUDIOThread( pa_thread_t * ); *****************************************************************************/ static int Open ( vlc_object_t * ); static void Close ( vlc_object_t * ); -static void Play ( aout_instance_t * ); +static void Play ( audio_output_t *, block_t * ); -static int PAOpenDevice( aout_instance_t * ); -static int PAOpenStream( aout_instance_t * ); +static int PAOpenDevice( audio_output_t * ); +static int PAOpenStream( audio_output_t * ); /***************************************************************************** * Module descriptor @@ -109,16 +107,16 @@ static int PAOpenStream( aout_instance_t * ); #define DEVICE_TEXT N_("Output device") #define DEVICE_LONGTEXT N_("Portaudio identifier for the output device") -vlc_module_begin(); - set_shortname( "PortAudio" ); - set_description( _("PORTAUDIO audio output") ); - set_category( CAT_AUDIO ); - set_subcategory( SUBCAT_AUDIO_AOUT ); - add_integer( "portaudio-device", 0, NULL, - DEVICE_TEXT, DEVICE_LONGTEXT, VLC_FALSE ); - set_capability( "audio output", 0 ); - set_callbacks( Open, Close ); -vlc_module_end(); +vlc_module_begin () + set_shortname( "PortAudio" ) + set_description( N_("PORTAUDIO audio output") ) + set_category( CAT_AUDIO ) + set_subcategory( SUBCAT_AUDIO_AOUT ) + add_integer( "portaudio-audio-device", 0, + DEVICE_TEXT, DEVICE_LONGTEXT, false ) + set_capability( "audio output", 0 ) + set_callbacks( Open, Close ) +vlc_module_end () /* This routine will be called by the PortAudio engine when audio is needed. * It may called at interrupt level on some machines so don't do anything @@ -129,39 +127,34 @@ static int paCallback( const void *inputBuffer, void *outputBuffer, const PaStreamCallbackTimeInfo *paDate, PaStreamCallbackFlags statusFlags, void *p_cookie ) { + VLC_UNUSED( inputBuffer ); VLC_UNUSED( statusFlags ); + struct aout_sys_t *p_sys = (struct aout_sys_t*) p_cookie; - aout_instance_t *p_aout = p_sys->p_aout; + audio_output_t *p_aout = p_sys->p_aout; aout_buffer_t *p_buffer; mtime_t out_date; out_date = mdate() + (mtime_t) ( 1000000 * ( paDate->outputBufferDacTime - paDate->currentTime ) ); - p_buffer = aout_OutputNextBuffer( p_aout, out_date, VLC_TRUE ); + p_buffer = aout_PacketNext( p_aout, out_date ); if ( p_buffer != NULL ) { if( p_sys->b_chan_reorder ) { /* Do the channel reordering here */ - aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_nb_bytes, + aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_buffer, p_sys->i_channels, p_sys->pi_chan_table, p_sys->i_bits_per_sample ); } - p_aout->p_libvlc->pf_memcpy( outputBuffer, p_buffer->p_buffer, - framesPerBuffer * p_sys->i_sample_size ); - /* aout_BufferFree may be dangereous here, but then so is - * aout_OutputNextBuffer (calls aout_BufferFree internally). - * one solution would be to link the no longer useful buffers - * in a second fifo (in aout_OutputNextBuffer too) and to - * wait until we are in Play to do the actual free. - */ + vlc_memcpy( outputBuffer, p_buffer->p_buffer, + framesPerBuffer * p_sys->i_sample_size ); aout_BufferFree( p_buffer ); } else /* Audio output buffer shortage -> stop the fill process and wait */ { - p_aout->p_libvlc->pf_memset( outputBuffer, 0, - framesPerBuffer * p_sys->i_sample_size ); + vlc_memset( outputBuffer, 0, framesPerBuffer * p_sys->i_sample_size ); } return 0; } @@ -171,33 +164,30 @@ static int paCallback( const void *inputBuffer, void *outputBuffer, *****************************************************************************/ static int Open( vlc_object_t * p_this ) { - aout_instance_t *p_aout = (aout_instance_t *)p_this; + audio_output_t *p_aout = (audio_output_t *)p_this; struct aout_sys_t * p_sys; - vlc_value_t val; - int i_err; msg_Dbg( p_aout, "entering Open()"); /* Allocate p_sys structure */ - p_sys = (aout_sys_t *)malloc( sizeof(aout_sys_t) ); + p_sys = malloc( sizeof(aout_sys_t) ); if( p_sys == NULL ) - { - msg_Err( p_aout, "out of memory" ); return VLC_ENOMEM; - } p_sys->p_aout = p_aout; p_sys->p_stream = 0; - p_aout->output.p_sys = p_sys; - p_aout->output.pf_play = Play; + p_aout->sys = p_sys; + p_aout->pf_play = aout_PacketPlay; + p_aout->pf_pause = aout_PacketPause; + p_aout->pf_flush = aout_PacketFlush; /* Retrieve output device id from config */ - var_Create( p_aout, "portaudio-device", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT); - var_Get( p_aout, "portaudio-device", &val ); - p_sys->i_device_id = val.i_int; + p_sys->i_device_id = var_CreateGetInteger( p_aout, "portaudio-audio-device" ); #ifdef PORTAUDIO_IS_SERIOUSLY_BROKEN if( !b_init ) { + int i_err; + /* Test device */ if( PAOpenDevice( p_aout ) != VLC_SUCCESS ) { @@ -212,22 +202,22 @@ static int Open( vlc_object_t * p_this ) msg_Err( p_aout, "closing the device returned %d", i_err ); } - b_init = VLC_TRUE; + b_init = true; /* Now we need to setup our DirectSound play notification structure */ - pa_thread = vlc_object_create( p_aout, sizeof(pa_thread_t) ); + pa_thread = calloc( 1, sizeof(*pa_thread) ); pa_thread->p_aout = p_aout; - pa_thread->b_error = VLC_FALSE; - vlc_mutex_init( p_aout, &pa_thread->lock_wait ); - vlc_cond_init( p_aout, &pa_thread->wait ); - pa_thread->b_wait = VLC_FALSE; - vlc_mutex_init( p_aout, &pa_thread->lock_signal ); - vlc_cond_init( p_aout, &pa_thread->signal ); - pa_thread->b_signal = VLC_FALSE; + pa_thread->b_error = false; + vlc_mutex_init( &pa_thread->lock_wait ); + vlc_cond_init( &pa_thread->wait ); + pa_thread->b_wait = false; + vlc_mutex_init( &pa_thread->lock_signal ); + vlc_cond_init( &pa_thread->signal ); + pa_thread->b_signal = false; /* Create PORTAUDIOThread */ - if( vlc_thread_create( pa_thread, "aout", PORTAUDIOThread, - VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) ) + if( vlc_clone( &pa_thread->thread, PORTAUDIOThread, pa_thread, + VLC_THREAD_PRIORITY_OUTPUT ) ) { msg_Err( p_aout, "cannot create PORTAUDIO thread" ); return VLC_EGENERIC; @@ -236,23 +226,23 @@ static int Open( vlc_object_t * p_this ) else { pa_thread->p_aout = p_aout; - pa_thread->b_wait = VLC_FALSE; - pa_thread->b_signal = VLC_FALSE; - pa_thread->b_error = VLC_FALSE; + pa_thread->b_wait = false; + pa_thread->b_signal = false; + pa_thread->b_error = false; } /* Signal start of stream */ vlc_mutex_lock( &pa_thread->lock_signal ); - pa_thread->b_signal = VLC_TRUE; + pa_thread->b_signal = true; vlc_cond_signal( &pa_thread->signal ); vlc_mutex_unlock( &pa_thread->lock_signal ); /* Wait until thread is ready */ vlc_mutex_lock( &pa_thread->lock_wait ); - if( !pa_thread->b_wait ) + while( !pa_thread->b_wait ) vlc_cond_wait( &pa_thread->wait, &pa_thread->lock_wait ); vlc_mutex_unlock( &pa_thread->lock_wait ); - pa_thread->b_wait = VLC_FALSE; + pa_thread->b_wait = false; if( pa_thread->b_error ) { @@ -287,9 +277,8 @@ static int Open( vlc_object_t * p_this ) *****************************************************************************/ static void Close ( vlc_object_t *p_this ) { - aout_instance_t *p_aout = (aout_instance_t *)p_this; - aout_sys_t *p_sys = p_aout->output.p_sys; - int i_err; + audio_output_t *p_aout = (audio_output_t *)p_this; + aout_sys_t *p_sys = p_aout->sys; msg_Dbg( p_aout, "closing portaudio"); @@ -297,20 +286,20 @@ static void Close ( vlc_object_t *p_this ) /* Signal end of stream */ vlc_mutex_lock( &pa_thread->lock_signal ); - pa_thread->b_signal = VLC_TRUE; + pa_thread->b_signal = true; vlc_cond_signal( &pa_thread->signal ); vlc_mutex_unlock( &pa_thread->lock_signal ); /* Wait until thread is ready */ vlc_mutex_lock( &pa_thread->lock_wait ); - if( !pa_thread->b_wait ) + while( !pa_thread->b_wait ) vlc_cond_wait( &pa_thread->wait, &pa_thread->lock_wait ); vlc_mutex_unlock( &pa_thread->lock_wait ); - pa_thread->b_wait = VLC_FALSE; + pa_thread->b_wait = false; #else - i_err = Pa_StopStream( p_sys->p_stream ); + int i_err = Pa_StopStream( p_sys->p_stream ); if( i_err != paNoError ) { msg_Err( p_aout, "Pa_StopStream: %d (%s)", i_err, @@ -333,12 +322,13 @@ static void Close ( vlc_object_t *p_this ) #endif msg_Dbg( p_aout, "portaudio closed"); + aout_PacketDestroy( p_aout ); free( p_sys ); } -static int PAOpenDevice( aout_instance_t *p_aout ) +static int PAOpenDevice( audio_output_t *p_aout ) { - aout_sys_t *p_sys = p_aout->output.p_sys; + aout_sys_t *p_sys = p_aout->sys; const PaDeviceInfo *p_pdi; PaError i_err; vlc_value_t val, text; @@ -399,7 +389,7 @@ static int PAOpenDevice( aout_instance_t *p_aout ) if( p_sys->deviceInfo->maxOutputChannels >= 1 ) { val.i_int = AOUT_VAR_MONO; - text.psz_string = N_("Mono"); + text.psz_string = _("Mono"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 1 channel" ); @@ -407,7 +397,7 @@ static int PAOpenDevice( aout_instance_t *p_aout ) if( p_sys->deviceInfo->maxOutputChannels >= 2 ) { val.i_int = AOUT_VAR_STEREO; - text.psz_string = N_("Stereo"); + text.psz_string = _("Stereo"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, @@ -418,7 +408,7 @@ static int PAOpenDevice( aout_instance_t *p_aout ) if( p_sys->deviceInfo->maxOutputChannels >= 4 ) { val.i_int = AOUT_VAR_2F2R; - text.psz_string = N_("2 Front 2 Rear"); + text.psz_string = _("2 Front 2 Rear"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 4 channels" ); @@ -426,7 +416,7 @@ static int PAOpenDevice( aout_instance_t *p_aout ) if( p_sys->deviceInfo->maxOutputChannels >= 5 ) { val.i_int = AOUT_VAR_3F2R; - text.psz_string = N_("3 Front 2 Rear"); + text.psz_string = _("3 Front 2 Rear"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 5 channels" ); @@ -434,20 +424,18 @@ static int PAOpenDevice( aout_instance_t *p_aout ) if( p_sys->deviceInfo->maxOutputChannels >= 6 ) { val.i_int = AOUT_VAR_5_1; - text.psz_string = "5.1"; + text.psz_string = _("5.1"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 5.1 channels" ); } var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL ); - - val.b_bool = VLC_TRUE; - var_Set( p_aout, "intf-change", val ); + var_TriggerCallback( p_aout, "intf-change" ); } /* Audio format is paFloat32 (always supported by portaudio v19) */ - p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2'); + p_aout->format.i_format = VLC_CODEC_FL32; return VLC_SUCCESS; @@ -459,9 +447,9 @@ static int PAOpenDevice( aout_instance_t *p_aout ) return VLC_EGENERIC; } -static int PAOpenStream( aout_instance_t *p_aout ) +static int PAOpenStream( audio_output_t *p_aout ) { - aout_sys_t *p_sys = p_aout->output.p_sys; + aout_sys_t *p_sys = p_aout->sys; const PaHostErrorInfo* paLastHostErrorInfo = Pa_GetLastHostErrorInfo(); PaStreamParameters paStreamParameters; vlc_value_t val; @@ -475,54 +463,54 @@ static int PAOpenStream( aout_instance_t *p_aout ) if( val.i_int == AOUT_VAR_5_1 ) { - p_aout->output.output.i_physical_channels + p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; } else if( val.i_int == AOUT_VAR_3F2R ) { - p_aout->output.output.i_physical_channels + p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; } else if( val.i_int == AOUT_VAR_2F2R ) { - p_aout->output.output.i_physical_channels + p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; } else if( val.i_int == AOUT_VAR_MONO ) { - p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER; + p_aout->format.i_physical_channels = AOUT_CHAN_CENTER; } else { - p_aout->output.output.i_physical_channels + p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; } - i_channels = aout_FormatNbChannels( &p_aout->output.output ); + i_channels = aout_FormatNbChannels( &p_aout->format ); msg_Dbg( p_aout, "nb_channels requested = %d", i_channels ); - i_channel_mask = p_aout->output.output.i_physical_channels; + i_channel_mask = p_aout->format.i_physical_channels; /* Calculate the frame size in bytes */ p_sys->i_sample_size = 4 * i_channels; - p_aout->output.i_nb_samples = FRAME_SIZE; - aout_FormatPrepare( &p_aout->output.output ); + aout_FormatPrepare( &p_aout->format ); + aout_PacketInit( p_aout, &p_sys->packet, FRAME_SIZE ); aout_VolumeSoftInit( p_aout ); /* Check for channel reordering */ - p_aout->output.p_sys->i_channel_mask = i_channel_mask; - p_aout->output.p_sys->i_bits_per_sample = 32; /* forced to paFloat32 */ - p_aout->output.p_sys->i_channels = i_channels; + p_aout->sys->i_channel_mask = i_channel_mask; + p_aout->sys->i_bits_per_sample = 32; /* forced to paFloat32 */ + p_aout->sys->i_channels = i_channels; - p_aout->output.p_sys->b_chan_reorder = - aout_CheckChannelReorder( pi_channels_in, pi_channels_out, + p_aout->sys->b_chan_reorder = + aout_CheckChannelReorder( NULL, pi_channels_out, i_channel_mask, i_channels, - p_aout->output.p_sys->pi_chan_table ); + p_aout->sys->pi_chan_table ); - if( p_aout->output.p_sys->b_chan_reorder ) + if( p_aout->sys->b_chan_reorder ) { msg_Dbg( p_aout, "channel reordering needed" ); } @@ -535,7 +523,7 @@ static int PAOpenStream( aout_instance_t *p_aout ) paStreamParameters.hostApiSpecificStreamInfo = NULL; i_err = Pa_OpenStream( &p_sys->p_stream, NULL /* no input */, - &paStreamParameters, (double)p_aout->output.output.i_rate, + &paStreamParameters, (double)p_aout->format.i_rate, FRAME_SIZE, paClipOff, paCallback, p_sys ); if( i_err != paNoError ) { @@ -549,6 +537,7 @@ static int PAOpenStream( aout_instance_t *p_aout ) paLastHostErrorInfo->errorText ); } p_sys->p_stream = 0; + aout_PacketDestroy( p_aout ); return VLC_EGENERIC; } @@ -557,52 +546,48 @@ static int PAOpenStream( aout_instance_t *p_aout ) { msg_Err( p_aout, "Pa_StartStream() failed" ); Pa_CloseStream( p_sys->p_stream ); + aout_PacketDestroy( p_aout ); return VLC_EGENERIC; } return VLC_SUCCESS; } -/***************************************************************************** - * Play: play sound - *****************************************************************************/ -static void Play( aout_instance_t * p_aout ) -{ -} - #ifdef PORTAUDIO_IS_SERIOUSLY_BROKEN /***************************************************************************** * PORTAUDIOThread: all interactions with libportaudio.a are handled * in this single thread. Otherwise libportaudio.a is _not_ happy :-( *****************************************************************************/ -static void PORTAUDIOThread( pa_thread_t *pa_thread ) +static void* PORTAUDIOThread( void *data ) { - aout_instance_t *p_aout; + pa_thread_t *pa_thread = (pa_thread_t*)data; + audio_output_t *p_aout; aout_sys_t *p_sys; int i_err; + int canc = vlc_savecancel (); - while( !pa_thread->b_die ) + for( ;; ) { /* Wait for start of stream */ vlc_mutex_lock( &pa_thread->lock_signal ); - if( !pa_thread->b_signal ) + while( !pa_thread->b_signal ) vlc_cond_wait( &pa_thread->signal, &pa_thread->lock_signal ); vlc_mutex_unlock( &pa_thread->lock_signal ); - pa_thread->b_signal = VLC_FALSE; + pa_thread->b_signal = false; p_aout = pa_thread->p_aout; - p_sys = p_aout->output.p_sys; + p_sys = p_aout->sys; if( PAOpenDevice( p_aout ) != VLC_SUCCESS ) { msg_Err( p_aout, "cannot open portaudio device" ); - pa_thread->b_error = VLC_TRUE; + pa_thread->b_error = true; } if( !pa_thread->b_error && PAOpenStream( p_aout ) != VLC_SUCCESS ) { msg_Err( p_aout, "cannot open portaudio device" ); - pa_thread->b_error = VLC_TRUE; + pa_thread->b_error = true; i_err = Pa_Terminate(); if( i_err != paNoError ) @@ -614,16 +599,16 @@ static void PORTAUDIOThread( pa_thread_t *pa_thread ) /* Tell the main thread that we are ready */ vlc_mutex_lock( &pa_thread->lock_wait ); - pa_thread->b_wait = VLC_TRUE; + pa_thread->b_wait = true; vlc_cond_signal( &pa_thread->wait ); vlc_mutex_unlock( &pa_thread->lock_wait ); /* Wait for end of stream */ vlc_mutex_lock( &pa_thread->lock_signal ); - if( !pa_thread->b_signal ) + while( !pa_thread->b_signal ) vlc_cond_wait( &pa_thread->signal, &pa_thread->lock_signal ); vlc_mutex_unlock( &pa_thread->lock_signal ); - pa_thread->b_signal = VLC_FALSE; + pa_thread->b_signal = false; if( pa_thread->b_error ) continue; @@ -648,9 +633,11 @@ static void PORTAUDIOThread( pa_thread_t *pa_thread ) /* Tell the main thread that we are ready */ vlc_mutex_lock( &pa_thread->lock_wait ); - pa_thread->b_wait = VLC_TRUE; + pa_thread->b_wait = true; vlc_cond_signal( &pa_thread->wait ); vlc_mutex_unlock( &pa_thread->lock_wait ); } + vlc_restorecancel (canc); + return NULL; } #endif