00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <string.h>
00029 #include <stdlib.h>
00030
00031 #include <vlc/vlc.h>
00032 #include <vlc/aout.h>
00033 #include <portaudio.h>
00034
00035 #include "aout_internal.h"
00036
00037 #define FRAME_SIZE 1024
00038
00039 #ifdef WIN32
00040 # define PORTAUDIO_IS_SERIOUSLY_BROKEN 1
00041 #endif
00042
00043
00044
00045
00046 typedef struct pa_thread_t
00047 {
00048 VLC_COMMON_MEMBERS
00049 aout_instance_t *p_aout;
00050
00051 vlc_cond_t wait;
00052 vlc_mutex_t lock_wait;
00053 vlc_bool_t b_wait;
00054 vlc_cond_t signal;
00055 vlc_mutex_t lock_signal;
00056 vlc_bool_t b_signal;
00057
00058 } pa_thread_t;
00059
00060 struct aout_sys_t
00061 {
00062 aout_instance_t *p_aout;
00063 PaStream *p_stream;
00064
00065 PaDeviceIndex i_devices;
00066 int i_sample_size;
00067 PaDeviceIndex i_device_id;
00068 const PaDeviceInfo *deviceInfo;
00069
00070 vlc_bool_t b_chan_reorder;
00071 int pi_chan_table[AOUT_CHAN_MAX];
00072 uint32_t i_channel_mask;
00073 uint32_t i_bits_per_sample;
00074 uint32_t i_channels;
00075 };
00076
00077 static const uint32_t pi_channels_in[] =
00078 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
00079 AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
00080 AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
00081 AOUT_CHAN_CENTER, AOUT_CHAN_LFE, 0 };
00082 static const uint32_t pi_channels_out[] =
00083 { AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT,
00084 AOUT_CHAN_CENTER, AOUT_CHAN_LFE,
00085 AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,
00086 AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT, 0 };
00087
00088 #ifdef PORTAUDIO_IS_SERIOUSLY_BROKEN
00089 static vlc_bool_t b_init = 0;
00090 static pa_thread_t *pa_thread;
00091 static void PORTAUDIOThread( pa_thread_t * );
00092 #endif
00093
00094
00095
00096
00097 static int Open ( vlc_object_t * );
00098 static void Close ( vlc_object_t * );
00099 static void Play ( aout_instance_t * );
00100
00101 static int PAOpenDevice( aout_instance_t * );
00102 static int PAOpenStream( aout_instance_t * );
00103
00104
00105
00106
00107 #define DEVICE_TEXT N_("Output device")
00108 #define DEVICE_LONGTEXT N_("Portaudio identifier for the output device")
00109
00110 vlc_module_begin();
00111 set_shortname( "PortAudio" );
00112 set_description( N_("PORTAUDIO audio output") );
00113 set_category( CAT_AUDIO );
00114 set_subcategory( SUBCAT_AUDIO_AOUT );
00115 add_integer( "portaudio-device", 0, NULL,
00116 DEVICE_TEXT, DEVICE_LONGTEXT, VLC_FALSE );
00117 set_capability( "audio output", 0 );
00118 set_callbacks( Open, Close );
00119 vlc_module_end();
00120
00121
00122
00123
00124
00125 static int paCallback( const void *inputBuffer, void *outputBuffer,
00126 unsigned long framesPerBuffer,
00127 const PaStreamCallbackTimeInfo *paDate,
00128 PaStreamCallbackFlags statusFlags, void *p_cookie )
00129 {
00130 struct aout_sys_t *p_sys = (struct aout_sys_t*) p_cookie;
00131 aout_instance_t *p_aout = p_sys->p_aout;
00132 aout_buffer_t *p_buffer;
00133 mtime_t out_date;
00134
00135 out_date = mdate() + (mtime_t) ( 1000000 *
00136 ( paDate->outputBufferDacTime - paDate->currentTime ) );
00137 p_buffer = aout_OutputNextBuffer( p_aout, out_date, VLC_TRUE );
00138
00139 if ( p_buffer != NULL )
00140 {
00141 if( p_sys->b_chan_reorder )
00142 {
00143
00144 aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_nb_bytes,
00145 p_sys->i_channels, p_sys->pi_chan_table,
00146 p_sys->i_bits_per_sample );
00147 }
00148 p_aout->p_vlc->pf_memcpy( outputBuffer, p_buffer->p_buffer,
00149 framesPerBuffer * p_sys->i_sample_size );
00150
00151
00152
00153
00154
00155
00156 aout_BufferFree( p_buffer );
00157 }
00158 else
00159
00160 {
00161 p_aout->p_vlc->pf_memset( outputBuffer, 0,
00162 framesPerBuffer * p_sys->i_sample_size );
00163 }
00164 return 0;
00165 }
00166
00167
00168
00169
00170 static int Open( vlc_object_t * p_this )
00171 {
00172 aout_instance_t *p_aout = (aout_instance_t *)p_this;
00173 struct aout_sys_t * p_sys;
00174 vlc_value_t val;
00175 int i_err;
00176
00177 msg_Dbg( p_aout, "Entering Open()");
00178
00179
00180 p_sys = (aout_sys_t *)malloc( sizeof(aout_sys_t) );
00181 if( p_sys == NULL )
00182 {
00183 msg_Err( p_aout, "out of memory" );
00184 return VLC_ENOMEM;
00185 }
00186 p_sys->p_aout = p_aout;
00187 p_sys->p_stream = 0;
00188 p_aout->output.p_sys = p_sys;
00189 p_aout->output.pf_play = Play;
00190
00191
00192 var_Create( p_aout, "portaudio-device", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT);
00193 var_Get( p_aout, "portaudio-device", &val );
00194 p_sys->i_device_id = val.i_int;
00195
00196 #ifdef PORTAUDIO_IS_SERIOUSLY_BROKEN
00197 if( !b_init )
00198 {
00199
00200 if( PAOpenDevice( p_aout ) != VLC_SUCCESS )
00201 {
00202 msg_Err( p_aout, "cannot open portaudio device" );
00203 free( p_sys );
00204 return VLC_EGENERIC;
00205 }
00206
00207
00208 if( ( i_err = Pa_Terminate() ) != paNoError )
00209 {
00210 msg_Err( p_aout, "Pa_Terminate returned %d", i_err );
00211 }
00212
00213 b_init = VLC_TRUE;
00214
00215
00216 pa_thread = vlc_object_create( p_aout, sizeof(pa_thread_t) );
00217 pa_thread->p_aout = p_aout;
00218 pa_thread->b_error = VLC_FALSE;
00219 vlc_mutex_init( p_aout, &pa_thread->lock_wait );
00220 vlc_cond_init( p_aout, &pa_thread->wait );
00221 pa_thread->b_wait = VLC_FALSE;
00222 vlc_mutex_init( p_aout, &pa_thread->lock_signal );
00223 vlc_cond_init( p_aout, &pa_thread->signal );
00224 pa_thread->b_signal = VLC_FALSE;
00225
00226
00227 if( vlc_thread_create( pa_thread, "aout", PORTAUDIOThread,
00228 VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
00229 {
00230 msg_Err( p_aout, "cannot create PORTAUDIO thread" );
00231 return VLC_EGENERIC;
00232 }
00233 }
00234 else
00235 {
00236 pa_thread->p_aout = p_aout;
00237 pa_thread->b_wait = VLC_FALSE;
00238 pa_thread->b_signal = VLC_FALSE;
00239 pa_thread->b_error = VLC_FALSE;
00240 }
00241
00242
00243 vlc_mutex_lock( &pa_thread->lock_signal );
00244 pa_thread->b_signal = VLC_TRUE;
00245 vlc_cond_signal( &pa_thread->signal );
00246 vlc_mutex_unlock( &pa_thread->lock_signal );
00247
00248
00249 vlc_mutex_lock( &pa_thread->lock_wait );
00250 if( !pa_thread->b_wait )
00251 vlc_cond_wait( &pa_thread->wait, &pa_thread->lock_wait );
00252 vlc_mutex_unlock( &pa_thread->lock_wait );
00253 pa_thread->b_wait = VLC_FALSE;
00254
00255 if( pa_thread->b_error )
00256 {
00257 msg_Err( p_aout, "PORTAUDIO thread failed" );
00258 Close( p_this );
00259 return VLC_EGENERIC;
00260 }
00261
00262 return VLC_SUCCESS;
00263
00264 #else
00265
00266 if( PAOpenDevice( p_aout ) != VLC_SUCCESS )
00267 {
00268 msg_Err( p_aout, "cannot open portaudio device" );
00269 free( p_sys );
00270 return VLC_EGENERIC;
00271 }
00272
00273 if( PAOpenStream( p_aout ) != VLC_SUCCESS )
00274 {
00275 msg_Err( p_aout, "cannot open portaudio device" );
00276 }
00277
00278 return VLC_SUCCESS;
00279
00280 #endif
00281 }
00282
00283
00284
00285
00286 static void Close ( vlc_object_t *p_this )
00287 {
00288 aout_instance_t *p_aout = (aout_instance_t *)p_this;
00289 aout_sys_t *p_sys = p_aout->output.p_sys;
00290 int i_err;
00291
00292 msg_Dbg( p_aout, "closing portaudio");
00293
00294 #ifdef PORTAUDIO_IS_SERIOUSLY_BROKEN
00295
00296
00297 vlc_mutex_lock( &pa_thread->lock_signal );
00298 pa_thread->b_signal = VLC_TRUE;
00299 vlc_cond_signal( &pa_thread->signal );
00300 vlc_mutex_unlock( &pa_thread->lock_signal );
00301
00302
00303 vlc_mutex_lock( &pa_thread->lock_wait );
00304 if( !pa_thread->b_wait )
00305 vlc_cond_wait( &pa_thread->wait, &pa_thread->lock_wait );
00306 vlc_mutex_unlock( &pa_thread->lock_wait );
00307 pa_thread->b_wait = VLC_FALSE;
00308
00309 #else
00310
00311 i_err = Pa_StopStream( p_sys->p_stream );
00312 if( i_err != paNoError )
00313 {
00314 msg_Err( p_aout, "Pa_StopStream: %d (%s)", i_err,
00315 Pa_GetErrorText( i_err ) );
00316 }
00317 i_err = Pa_CloseStream( p_sys->p_stream );
00318 if( i_err != paNoError )
00319 {
00320 msg_Err( p_aout, "Pa_CloseStream: %d (%s)", i_err,
00321 Pa_GetErrorText( i_err ) );
00322 }
00323
00324 i_err = Pa_Terminate();
00325 if( i_err != paNoError )
00326 {
00327 msg_Err( p_aout, "Pa_Terminate: %d (%s)", i_err,
00328 Pa_GetErrorText( i_err ) );
00329 }
00330
00331 #endif
00332
00333 msg_Dbg( p_aout, "portaudio closed");
00334 free( p_sys );
00335 }
00336
00337 static int PAOpenDevice( aout_instance_t *p_aout )
00338 {
00339 aout_sys_t *p_sys = p_aout->output.p_sys;
00340 const PaDeviceInfo *p_pdi;
00341 PaError i_err;
00342 vlc_value_t val, text;
00343 int i;
00344
00345
00346 i_err = Pa_Initialize();
00347 if( i_err != paNoError )
00348 {
00349 msg_Err( p_aout, "Pa_Initialize returned %d : %s",
00350 i_err, Pa_GetErrorText( i_err ) );
00351
00352 return VLC_EGENERIC;
00353 }
00354
00355 p_sys->i_devices = Pa_GetDeviceCount();
00356 if( p_sys->i_devices < 0 )
00357 {
00358 i_err = p_sys->i_devices;
00359 msg_Err( p_aout, "Pa_GetDeviceCount returned %d : %s", i_err,
00360 Pa_GetErrorText( i_err ) );
00361
00362 goto error;
00363 }
00364
00365
00366 msg_Dbg( p_aout, "number of devices = %d", p_sys->i_devices );
00367 for( i = 0; i < p_sys->i_devices; i++ )
00368 {
00369 p_pdi = Pa_GetDeviceInfo( i );
00370 msg_Dbg( p_aout, "------------------------------------- #%d", i );
00371 msg_Dbg( p_aout, "Name = %s", p_pdi->name );
00372 msg_Dbg( p_aout, "Max Inputs = %d, Max Outputs = %d",
00373 p_pdi->maxInputChannels, p_pdi->maxOutputChannels );
00374 }
00375 msg_Dbg( p_aout, "-------------------------------------" );
00376
00377 msg_Dbg( p_aout, "requested device is #%d", p_sys->i_device_id );
00378 if( p_sys->i_device_id >= p_sys->i_devices )
00379 {
00380 msg_Err( p_aout, "device %d does not exist", p_sys->i_device_id );
00381 goto error;
00382 }
00383 p_sys->deviceInfo = Pa_GetDeviceInfo( p_sys->i_device_id );
00384
00385 if( p_sys->deviceInfo->maxOutputChannels < 1 )
00386 {
00387 msg_Err( p_aout, "no channel available" );
00388 goto error;
00389 }
00390
00391 if( var_Type( p_aout, "audio-device" ) == 0 )
00392 {
00393 var_Create( p_aout, "audio-device", VLC_VAR_INTEGER|VLC_VAR_HASCHOICE);
00394 text.psz_string = _("Audio Device");
00395 var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
00396
00397 if( p_sys->deviceInfo->maxOutputChannels >= 1 )
00398 {
00399 val.i_int = AOUT_VAR_MONO;
00400 text.psz_string = N_("Mono");
00401 var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE,
00402 &val, &text );
00403 msg_Dbg( p_aout, "device supports 1 channel" );
00404 }
00405 if( p_sys->deviceInfo->maxOutputChannels >= 2 )
00406 {
00407 val.i_int = AOUT_VAR_STEREO;
00408 text.psz_string = N_("Stereo");
00409 var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE,
00410 &val, &text );
00411 var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT,
00412 &val, NULL );
00413 var_Set( p_aout, "audio-device", val );
00414 msg_Dbg( p_aout, "device supports 2 channels" );
00415 }
00416 if( p_sys->deviceInfo->maxOutputChannels >= 4 )
00417 {
00418 val.i_int = AOUT_VAR_2F2R;
00419 text.psz_string = N_("2 Front 2 Rear");
00420 var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE,
00421 &val, &text );
00422 msg_Dbg( p_aout, "device supports 4 channels" );
00423 }
00424 if( p_sys->deviceInfo->maxOutputChannels >= 5 )
00425 {
00426 val.i_int = AOUT_VAR_3F2R;
00427 text.psz_string = N_("3 Front 2 Rear");
00428 var_Change( p_aout, "audio-device",
00429 VLC_VAR_ADDCHOICE, &val, &text );
00430 msg_Dbg( p_aout, "device supports 5 channels" );
00431 }
00432 if( p_sys->deviceInfo->maxOutputChannels >= 6 )
00433 {
00434 val.i_int = AOUT_VAR_5_1;
00435 text.psz_string = N_("5.1");
00436 var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE,
00437 &val, &text );
00438 msg_Dbg( p_aout, "device supports 5.1 channels" );
00439 }
00440
00441 var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL );
00442
00443 val.b_bool = VLC_TRUE;
00444 var_Set( p_aout, "intf-change", val );
00445 }
00446
00447
00448 p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2');
00449
00450 return VLC_SUCCESS;
00451
00452 error:
00453 if( ( i_err = Pa_Terminate() ) != paNoError )
00454 {
00455 msg_Err( p_aout, "Pa_Terminate returned %d", i_err );
00456 }
00457 return VLC_EGENERIC;
00458 }
00459
00460 static int PAOpenStream( aout_instance_t *p_aout )
00461 {
00462 aout_sys_t *p_sys = p_aout->output.p_sys;
00463 const PaHostErrorInfo* paLastHostErrorInfo = Pa_GetLastHostErrorInfo();
00464 PaStreamParameters paStreamParameters;
00465 vlc_value_t val;
00466 int i_channels, i_err;
00467 uint32_t i_channel_mask;
00468
00469 if( var_Get( p_aout, "audio-device", &val ) < 0 )
00470 {
00471 return VLC_EGENERIC;
00472 }
00473
00474 if( val.i_int == AOUT_VAR_5_1 )
00475 {
00476 p_aout->output.output.i_physical_channels
00477 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00478 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
00479 | AOUT_CHAN_LFE;
00480 }
00481 else if( val.i_int == AOUT_VAR_3F2R )
00482 {
00483 p_aout->output.output.i_physical_channels
00484 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
00485 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
00486 }
00487 else if( val.i_int == AOUT_VAR_2F2R )
00488 {
00489 p_aout->output.output.i_physical_channels
00490 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
00491 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
00492 }
00493 else if( val.i_int == AOUT_VAR_MONO )
00494 {
00495 p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER;
00496 }
00497 else
00498 {
00499 p_aout->output.output.i_physical_channels
00500 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
00501 }
00502
00503 i_channels = aout_FormatNbChannels( &p_aout->output.output );
00504 msg_Dbg( p_aout, "nb_channels requested = %d", i_channels );
00505 i_channel_mask = p_aout->output.output.i_physical_channels;
00506
00507
00508 p_sys->i_sample_size = 4 * i_channels;
00509 p_aout->output.i_nb_samples = FRAME_SIZE;
00510 aout_FormatPrepare( &p_aout->output.output );
00511 aout_VolumeSoftInit( p_aout );
00512
00513
00514 p_aout->output.p_sys->i_channel_mask = i_channel_mask;
00515 p_aout->output.p_sys->i_bits_per_sample = 32;
00516 p_aout->output.p_sys->i_channels = i_channels;
00517
00518 p_aout->output.p_sys->b_chan_reorder =
00519 aout_CheckChannelReorder( pi_channels_in, pi_channels_out,
00520 i_channel_mask, i_channels,
00521 p_aout->output.p_sys->pi_chan_table );
00522
00523 if( p_aout->output.p_sys->b_chan_reorder )
00524 {
00525 msg_Dbg( p_aout, "channel reordering needed" );
00526 }
00527
00528 paStreamParameters.device = p_sys->i_device_id;
00529 paStreamParameters.channelCount = i_channels;
00530 paStreamParameters.sampleFormat = paFloat32;
00531 paStreamParameters.suggestedLatency =
00532 p_sys->deviceInfo->defaultLowOutputLatency;
00533 paStreamParameters.hostApiSpecificStreamInfo = NULL;
00534
00535 i_err = Pa_OpenStream( &p_sys->p_stream, NULL ,
00536 &paStreamParameters, (double)p_aout->output.output.i_rate,
00537 FRAME_SIZE, paClipOff, paCallback, p_sys );
00538 if( i_err != paNoError )
00539 {
00540 msg_Err( p_aout, "Pa_OpenStream returns %d : %s", i_err,
00541 Pa_GetErrorText( i_err ) );
00542 if( i_err == paUnanticipatedHostError )
00543 {
00544 msg_Err( p_aout, "type %d code %ld : %s",
00545 paLastHostErrorInfo->hostApiType,
00546 paLastHostErrorInfo->errorCode,
00547 paLastHostErrorInfo->errorText );
00548 }
00549 p_sys->p_stream = 0;
00550 return VLC_EGENERIC;
00551 }
00552
00553 i_err = Pa_StartStream( p_sys->p_stream );
00554 if( i_err != paNoError )
00555 {
00556 msg_Err( p_aout, "Pa_StartStream() failed" );
00557 Pa_CloseStream( p_sys->p_stream );
00558 return VLC_EGENERIC;
00559 }
00560
00561 return VLC_SUCCESS;
00562 }
00563
00564
00565
00566
00567 static void Play( aout_instance_t * p_aout )
00568 {
00569 }
00570
00571 #ifdef PORTAUDIO_IS_SERIOUSLY_BROKEN
00572
00573
00574
00575
00576 static void PORTAUDIOThread( pa_thread_t *pa_thread )
00577 {
00578 aout_instance_t *p_aout;
00579 aout_sys_t *p_sys;
00580 int i_err;
00581
00582 while( !pa_thread->b_die )
00583 {
00584
00585 vlc_mutex_lock( &pa_thread->lock_signal );
00586 if( !pa_thread->b_signal )
00587 vlc_cond_wait( &pa_thread->signal, &pa_thread->lock_signal );
00588 vlc_mutex_unlock( &pa_thread->lock_signal );
00589 pa_thread->b_signal = VLC_FALSE;
00590
00591 p_aout = pa_thread->p_aout;
00592 p_sys = p_aout->output.p_sys;
00593
00594 if( PAOpenDevice( p_aout ) != VLC_SUCCESS )
00595 {
00596 msg_Err( p_aout, "cannot open portaudio device" );
00597 pa_thread->b_error = VLC_TRUE;
00598 }
00599
00600 if( !pa_thread->b_error && PAOpenStream( p_aout ) != VLC_SUCCESS )
00601 {
00602 msg_Err( p_aout, "cannot open portaudio device" );
00603 pa_thread->b_error = VLC_TRUE;
00604
00605 i_err = Pa_Terminate();
00606 if( i_err != paNoError )
00607 {
00608 msg_Err( p_aout, "Pa_Terminate: %d (%s)", i_err,
00609 Pa_GetErrorText( i_err ) );
00610 }
00611 }
00612
00613
00614 vlc_mutex_lock( &pa_thread->lock_wait );
00615 pa_thread->b_wait = VLC_TRUE;
00616 vlc_cond_signal( &pa_thread->wait );
00617 vlc_mutex_unlock( &pa_thread->lock_wait );
00618
00619
00620 vlc_mutex_lock( &pa_thread->lock_signal );
00621 if( !pa_thread->b_signal )
00622 vlc_cond_wait( &pa_thread->signal, &pa_thread->lock_signal );
00623 vlc_mutex_unlock( &pa_thread->lock_signal );
00624 pa_thread->b_signal = VLC_FALSE;
00625
00626 if( pa_thread->b_error ) continue;
00627
00628 i_err = Pa_StopStream( p_sys->p_stream );
00629 if( i_err != paNoError )
00630 {
00631 msg_Err( p_aout, "Pa_StopStream: %d (%s)", i_err,
00632 Pa_GetErrorText( i_err ) );
00633 }
00634 i_err = Pa_CloseStream( p_sys->p_stream );
00635 if( i_err != paNoError )
00636 {
00637 msg_Err( p_aout, "Pa_CloseStream: %d (%s)", i_err,
00638 Pa_GetErrorText( i_err ) );
00639 }
00640 i_err = Pa_Terminate();
00641 if( i_err != paNoError )
00642 {
00643 msg_Err( p_aout, "Pa_Terminate: %d (%s)", i_err,
00644 Pa_GetErrorText( i_err ) );
00645 }
00646
00647
00648 vlc_mutex_lock( &pa_thread->lock_wait );
00649 pa_thread->b_wait = VLC_TRUE;
00650 vlc_cond_signal( &pa_thread->wait );
00651 vlc_mutex_unlock( &pa_thread->lock_wait );
00652 }
00653 }
00654 #endif