📄 portaudio.c
字号:
}#endif msg_Dbg( p_aout, "portaudio closed"); free( p_sys );}static int PAOpenDevice( aout_instance_t *p_aout ){ aout_sys_t *p_sys = p_aout->output.p_sys; const PaDeviceInfo *p_pdi; PaError i_err; vlc_value_t val, text; int i; /* Initialize portaudio */ i_err = Pa_Initialize(); if( i_err != paNoError ) { msg_Err( p_aout, "Pa_Initialize returned %d : %s", i_err, Pa_GetErrorText( i_err ) ); return VLC_EGENERIC; } p_sys->i_devices = Pa_GetDeviceCount(); if( p_sys->i_devices < 0 ) { i_err = p_sys->i_devices; msg_Err( p_aout, "Pa_GetDeviceCount returned %d : %s", i_err, Pa_GetErrorText( i_err ) ); goto error; } /* Display all devices info */ msg_Dbg( p_aout, "number of devices = %d", p_sys->i_devices ); for( i = 0; i < p_sys->i_devices; i++ ) { p_pdi = Pa_GetDeviceInfo( i ); msg_Dbg( p_aout, "------------------------------------- #%d", i ); msg_Dbg( p_aout, "Name = %s", p_pdi->name ); msg_Dbg( p_aout, "Max Inputs = %d, Max Outputs = %d", p_pdi->maxInputChannels, p_pdi->maxOutputChannels ); } msg_Dbg( p_aout, "-------------------------------------" ); msg_Dbg( p_aout, "requested device is #%d", p_sys->i_device_id ); if( p_sys->i_device_id >= p_sys->i_devices ) { msg_Err( p_aout, "device %d does not exist", p_sys->i_device_id ); goto error; } p_sys->deviceInfo = Pa_GetDeviceInfo( p_sys->i_device_id ); if( p_sys->deviceInfo->maxOutputChannels < 1 ) { msg_Err( p_aout, "no channel available" ); goto error; } if( var_Type( p_aout, "audio-device" ) == 0 ) { var_Create( p_aout, "audio-device", VLC_VAR_INTEGER|VLC_VAR_HASCHOICE); text.psz_string = _("Audio Device"); var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL ); if( p_sys->deviceInfo->maxOutputChannels >= 1 ) { val.i_int = AOUT_VAR_MONO; text.psz_string = N_("Mono"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 1 channel" ); } if( p_sys->deviceInfo->maxOutputChannels >= 2 ) { val.i_int = AOUT_VAR_STEREO; text.psz_string = N_("Stereo"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL ); var_Set( p_aout, "audio-device", val ); msg_Dbg( p_aout, "device supports 2 channels" ); } if( p_sys->deviceInfo->maxOutputChannels >= 4 ) { val.i_int = AOUT_VAR_2F2R; text.psz_string = N_("2 Front 2 Rear"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 4 channels" ); } if( p_sys->deviceInfo->maxOutputChannels >= 5 ) { val.i_int = AOUT_VAR_3F2R; text.psz_string = N_("3 Front 2 Rear"); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); msg_Dbg( p_aout, "device supports 5 channels" ); } if( p_sys->deviceInfo->maxOutputChannels >= 6 ) { val.i_int = AOUT_VAR_5_1; text.psz_string = N_("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 ); } /* Audio format is paFloat32 (always supported by portaudio v19) */ p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2'); return VLC_SUCCESS; error: if( ( i_err = Pa_Terminate() ) != paNoError ) { msg_Err( p_aout, "Pa_Terminate returned %d", i_err ); } return VLC_EGENERIC;}static int PAOpenStream( aout_instance_t *p_aout ){ aout_sys_t *p_sys = p_aout->output.p_sys; const PaHostErrorInfo* paLastHostErrorInfo = Pa_GetLastHostErrorInfo(); PaStreamParameters paStreamParameters; vlc_value_t val; int i_channels, i_err; uint32_t i_channel_mask; if( var_Get( p_aout, "audio-device", &val ) < 0 ) { return VLC_EGENERIC; } if( val.i_int == AOUT_VAR_5_1 ) { p_aout->output.output.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 = 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 = 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; } else { p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; } i_channels = aout_FormatNbChannels( &p_aout->output.output ); msg_Dbg( p_aout, "nb_channels requested = %d", i_channels ); i_channel_mask = p_aout->output.output.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_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->output.p_sys->b_chan_reorder = aout_CheckChannelReorder( pi_channels_in, pi_channels_out, i_channel_mask, i_channels, p_aout->output.p_sys->pi_chan_table ); if( p_aout->output.p_sys->b_chan_reorder ) { msg_Dbg( p_aout, "channel reordering needed" ); } paStreamParameters.device = p_sys->i_device_id; paStreamParameters.channelCount = i_channels; paStreamParameters.sampleFormat = paFloat32; paStreamParameters.suggestedLatency = p_sys->deviceInfo->defaultLowOutputLatency; paStreamParameters.hostApiSpecificStreamInfo = NULL; i_err = Pa_OpenStream( &p_sys->p_stream, NULL /* no input */, &paStreamParameters, (double)p_aout->output.output.i_rate, FRAME_SIZE, paClipOff, paCallback, p_sys ); if( i_err != paNoError ) { msg_Err( p_aout, "Pa_OpenStream returns %d : %s", i_err, Pa_GetErrorText( i_err ) ); if( i_err == paUnanticipatedHostError ) { msg_Err( p_aout, "type %d code %ld : %s", paLastHostErrorInfo->hostApiType, paLastHostErrorInfo->errorCode, paLastHostErrorInfo->errorText ); } p_sys->p_stream = 0; return VLC_EGENERIC; } i_err = Pa_StartStream( p_sys->p_stream ); if( i_err != paNoError ) { msg_Err( p_aout, "Pa_StartStream() failed" ); Pa_CloseStream( p_sys->p_stream ); 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 ){ aout_instance_t *p_aout; aout_sys_t *p_sys; int i_err; while( !pa_thread->b_die ) { /* Wait for start of stream */ vlc_mutex_lock( &pa_thread->lock_signal ); if( !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; p_aout = pa_thread->p_aout; p_sys = p_aout->output.p_sys; if( PAOpenDevice( p_aout ) != VLC_SUCCESS ) { msg_Err( p_aout, "cannot open portaudio device" ); pa_thread->b_error = VLC_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; i_err = Pa_Terminate(); if( i_err != paNoError ) { msg_Err( p_aout, "Pa_Terminate: %d (%s)", i_err, Pa_GetErrorText( i_err ) ); } } /* Tell the main thread that we are ready */ vlc_mutex_lock( &pa_thread->lock_wait ); pa_thread->b_wait = VLC_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 ) vlc_cond_wait( &pa_thread->signal, &pa_thread->lock_signal ); vlc_mutex_unlock( &pa_thread->lock_signal ); pa_thread->b_signal = VLC_FALSE; if( pa_thread->b_error ) continue; i_err = Pa_StopStream( p_sys->p_stream ); if( i_err != paNoError ) { msg_Err( p_aout, "Pa_StopStream: %d (%s)", i_err, Pa_GetErrorText( i_err ) ); } i_err = Pa_CloseStream( p_sys->p_stream ); if( i_err != paNoError ) { msg_Err( p_aout, "Pa_CloseStream: %d (%s)", i_err, Pa_GetErrorText( i_err ) ); } i_err = Pa_Terminate(); if( i_err != paNoError ) { msg_Err( p_aout, "Pa_Terminate: %d (%s)", i_err, Pa_GetErrorText( i_err ) ); } /* Tell the main thread that we are ready */ vlc_mutex_lock( &pa_thread->lock_wait ); pa_thread->b_wait = VLC_TRUE; vlc_cond_signal( &pa_thread->wait ); vlc_mutex_unlock( &pa_thread->lock_wait ); }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -