/*****************************************************************************
* 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;
bool b_wait;
vlc_cond_t signal;
vlc_mutex_t lock_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;
#ifdef PORTAUDIO_IS_SERIOUSLY_BROKEN
static bool b_init = 0;
static pa_thread_t *pa_thread;
-static void* PORTAUDIOThread( vlc_object_t * );
+static void* PORTAUDIOThread( void * );
#endif
/*****************************************************************************
*****************************************************************************/
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
set_description( N_("PORTAUDIO audio output") )
set_category( CAT_AUDIO )
set_subcategory( SUBCAT_AUDIO_AOUT )
- add_integer( "portaudio-audio-device", 0, NULL,
+ add_integer( "portaudio-audio-device", 0,
DEVICE_TEXT, DEVICE_LONGTEXT, false )
- add_deprecated_alias( "portaudio-device" ) /* deprecated since 0.9.3 */
set_capability( "audio output", 0 )
set_callbacks( Open, Close )
vlc_module_end ()
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, 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 );
}
vlc_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.
- */
aout_BufferFree( p_buffer );
}
else
*****************************************************************************/
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;
- int i_err;
msg_Dbg( p_aout, "entering Open()");
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 */
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 )
{
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 = false;
vlc_mutex_init( &pa_thread->lock_wait );
pa_thread->b_signal = false;
/* Create PORTAUDIOThread */
- if( vlc_thread_create( pa_thread, "aout", PORTAUDIOThread,
+ if( vlc_clone( &pa_thread->thread, PORTAUDIOThread, pa_thread,
VLC_THREAD_PRIORITY_OUTPUT ) )
{
msg_Err( p_aout, "cannot create PORTAUDIO thread" );
/* 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 = false;
*****************************************************************************/
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;
+ audio_output_t *p_aout = (audio_output_t *)p_this;
+ aout_sys_t *p_sys = p_aout->sys;
msg_Dbg( p_aout, "closing portaudio");
/* 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 = false;
#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;
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 );
- var_SetBool( p_aout, "intf-change", true );
+ var_TriggerCallback( p_aout, "intf-change" );
}
/* Audio format is paFloat32 (always supported by portaudio v19) */
- p_aout->output.output.i_format = VLC_CODEC_FL32;
+ p_aout->format.i_format = VLC_CODEC_FL32;
return VLC_SUCCESS;
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;
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 =
+ 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" );
}
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 )
{
paLastHostErrorInfo->errorText );
}
p_sys->p_stream = 0;
+ aout_PacketDestroy( p_aout );
return VLC_EGENERIC;
}
{
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 )
-{
- VLC_UNUSED( 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( vlc_object_t *p_this )
+static void* PORTAUDIOThread( void *data )
{
- pa_thread_t *pa_thread = (pa_thread_t*)p_this;
- 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( vlc_object_alive (pa_thread) )
+ 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 = 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 )
{
/* 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 = false;