📄 coreaudio.c
字号:
p_dev = &p_sys->p_devices[p_option->i_dev]; msg_Dbg( p_aout, "getting device [%ld]", p_option->i_dev ); i_param_size = sizeof( p_sys->b_dev_alive ); err = AudioDeviceGetProperty( p_dev->devid, 0, FALSE, kAudioDevicePropertyDeviceIsAlive, &i_param_size, &p_sys->b_dev_alive ); if( err != noErr ) { msg_Err( p_aout, "could not check whether device is alive: %4.4s", (char *)&err ); return( VLC_EGENERIC ); }#define P_STREAMS p_dev->pp_streams[p_option->i_idx]#define I_STREAMS p_dev->pi_streams[p_option->i_idx] for( i = 0; i < I_STREAMS; i++ ) { if( P_STREAMS[i].mFormatID == aout_classes[p_option->i_cdx].mFormatID && P_STREAMS[i].mChannelsPerFrame == aout_classes[p_option->i_cdx].mChannelsPerFrame && P_STREAMS[i].mSampleRate == p_aout->output.output.i_rate ) { b_found = VLC_TRUE; break; } } i_stream = b_found ? i : p_option->i_sdx; i_firstChannelNum = 0; for( i = 0; i < i_stream; i++ ) { i_firstChannelNum += P_STREAMS[i].mChannelsPerFrame; } i_param_size = sizeof( p_sys->sfmt_revert ); err = AudioStreamGetProperty( p_option->i_sid, 0, kAudioStreamPropertyPhysicalFormat, &i_param_size, (void *)&p_sys->sfmt_revert ); if( err != noErr ) { msg_Err( p_aout, "could not retrieve the original streamformat: [%4.4s]", (char *)&err ); return( VLC_EGENERIC ); } if( memcmp( &P_STREAMS[i_stream], &p_sys->sfmt_revert, sizeof( p_sys->sfmt_revert ) ) != 0 ) { struct timeval now; struct timespec timeout; struct { vlc_mutex_t lock; vlc_cond_t cond; } w; vlc_cond_init( p_aout, &w.cond ); vlc_mutex_init( p_aout, &w.lock ); msg_Dbg( p_aout, STREAM_FORMAT_MSG( "stream format", p_sys->sfmt_revert ) ); err = AudioStreamAddPropertyListener( p_option->i_sid, 0, kAudioStreamPropertyPhysicalFormat, StreamListener, (void *)&w ); if( err != noErr ) { msg_Err( p_aout, "AudioStreamAddPropertyListener failed: [%4.4s]", (char *)&err ); vlc_mutex_destroy( &w.lock ); vlc_cond_destroy( &w.cond ); return( VLC_EGENERIC ); } vlc_mutex_lock( &w.lock ); msg_Dbg( p_aout, STREAM_FORMAT_MSG( "setting format", P_STREAMS[i_stream] ) ); err = AudioStreamSetProperty( p_option->i_sid, 0, 0, kAudioStreamPropertyPhysicalFormat, sizeof( P_STREAMS[i_stream] ), &P_STREAMS[i_stream] ); if( err != noErr ) { msg_Err( p_aout, "could not set the stream format: [%4.4s]", (char *)&err ); vlc_mutex_unlock( &w.lock ); vlc_mutex_destroy( &w.lock ); vlc_cond_destroy( &w.cond ); return( VLC_EGENERIC ); } gettimeofday( &now, NULL ); timeout.tv_sec = now.tv_sec; timeout.tv_nsec = (now.tv_usec + 100000) * 1000; pthread_cond_timedwait( &w.cond.cond, &w.lock.mutex, &timeout ); vlc_mutex_unlock( &w.lock ); if( GetStreamID( p_dev->devid, p_option->i_idx + 1, &p_option->i_sid ) ) { msg_Err( p_aout, "GetStreamID(%ld, %ld) failed", p_option->i_dev, p_option->i_idx ); vlc_mutex_destroy( &w.lock ); vlc_cond_destroy( &w.cond ); return( VLC_EGENERIC ); } err = AudioStreamRemovePropertyListener( p_option->i_sid, 0, kAudioStreamPropertyPhysicalFormat, StreamListener ); if( err != noErr ) { msg_Err( p_aout, "AudioStreamRemovePropertyListener failed: [%4.4s]", (char *)&err ); vlc_mutex_destroy( &w.lock ); vlc_cond_destroy( &w.cond ); return( VLC_EGENERIC ); } vlc_mutex_destroy( &w.lock ); vlc_cond_destroy( &w.cond ); p_sys->b_revert_sfmt = VLC_TRUE; } err = AudioDeviceAddPropertyListener( p_dev->devid, 0, FALSE, kAudioDevicePropertyDeviceIsAlive, DeviceListener, (void *)p_aout ); if( err != noErr ) { msg_Err( p_aout, "AudioDeviceAddPropertyListener failed: [%4.4s]", (char *)&err ); return( VLC_EGENERIC ); } config_PutInt( p_aout, "coreaudio-dev", i_option ); p_sys->i_sel_opt = i_option; p_sys->devid = p_dev->devid; p_sys->i_stream_index = p_option->i_idx;#undef I_STREAMS#undef P_STREAMS return( VLC_SUCCESS );} /***************************************************************************** * FreeDevice *****************************************************************************/static void FreeDevice( aout_instance_t * p_aout ) { OSStatus err; struct aout_sys_t * p_sys = p_aout->output.p_sys; if( p_sys->b_revert_sfmt ) { struct aout_dev_t * p_dev; struct aout_option_t * p_option; p_option = &p_sys->p_options[p_sys->i_sel_opt]; p_dev = &p_sys->p_devices[p_option->i_dev]; msg_Dbg( p_aout, STREAM_FORMAT_MSG( "reverting to format", p_sys->sfmt_revert ) ); if( GetStreamID( p_dev->devid, p_option->i_idx + 1, &p_option->i_sid ) ) { msg_Err( p_aout, "GetStreamID(%ld, %ld) failed", p_option->i_dev, p_option->i_idx ); } else { err = AudioStreamSetProperty( p_option->i_sid, 0, 0, kAudioStreamPropertyPhysicalFormat, sizeof( p_sys->sfmt_revert ), &p_sys->sfmt_revert ); if( err != noErr ) { msg_Err( p_aout, "AudioStreamSetProperty revert format failed: [%4.4s]", (char *)&err ); } } } err = AudioDeviceRemovePropertyListener( p_sys->devid, 0, FALSE, kAudioDevicePropertyDeviceIsAlive, DeviceListener ); if( err != noErr ) { msg_Err( p_aout, "AudioDeviceRemovePropertyListener failed: [%4.4s]", (char *)&err ); } }/***************************************************************************** * HardwareListener *****************************************************************************/static OSStatus HardwareListener( AudioHardwarePropertyID inPropertyID, void * inClientData ){ OSStatus err = noErr; aout_instance_t * p_aout = (aout_instance_t *)inClientData; struct aout_sys_t * p_sys = p_aout->output.p_sys; switch( inPropertyID ) { case kAudioHardwarePropertyDevices: { UInt32 i_idx = 0; UInt32 i_sdx = 0; int i_option = -1; if( p_sys->b_dev_alive ) { i_idx = p_sys->p_options[p_sys->i_sel_opt].i_idx; i_sdx = p_sys->p_options[p_sys->i_sel_opt].i_sdx; } FreeHardwareInfo( p_aout ); if( InitHardwareInfo( p_aout ) ) { msg_Err( p_aout, "InitHardwareInfo failed" ); break; } if( p_sys->b_dev_alive ) { UInt32 i; for( i = 0; i < p_sys->i_options; i++ ) { if( p_sys->p_devices[p_sys->p_options[i].i_dev].devid == p_sys->devid && p_sys->p_options[i].i_idx == i_idx && p_sys->p_options[i].i_sdx == i_sdx ) { i_option = i; break; } } } var_Destroy( p_aout, "audio-device" ); InitDeviceVar( p_aout, i_option, !p_sys->b_dev_alive ); } break; } return( err );}/***************************************************************************** * DeviceListener *****************************************************************************/static OSStatus DeviceListener( AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, void *inClientData ){ UInt32 i_param_size; OSStatus err = noErr; aout_instance_t * p_aout = (aout_instance_t *)inClientData; struct aout_sys_t * p_sys = p_aout->output.p_sys; switch( inPropertyID ) { case kAudioDevicePropertyDeviceIsAlive: { i_param_size = sizeof( p_sys->b_dev_alive ); err = AudioDeviceGetProperty( p_sys->devid, 0, FALSE, kAudioDevicePropertyDeviceIsAlive, &i_param_size, &p_sys->b_dev_alive ); if( err != noErr ) { msg_Err( p_aout, "could not determine wether device is alive: %4.4s", (char *)&err ); } } break; } return( err );}/***************************************************************************** * StreamListener *****************************************************************************/static OSStatus StreamListener( AudioStreamID inStream, UInt32 inChannel, AudioDevicePropertyID inPropertyID, void * inClientData ){ OSStatus err = noErr; struct { vlc_mutex_t lock; vlc_cond_t cond; } * w = inClientData; switch( inPropertyID ) { case kAudioStreamPropertyPhysicalFormat: vlc_mutex_lock( &w->lock ); vlc_cond_signal( &w->cond ); vlc_mutex_unlock( &w->lock ); break; default: break; } return( err );}/***************************************************************************** * InitDeviceVar *****************************************************************************/static void InitDeviceVar( aout_instance_t * p_aout, int i_option, vlc_bool_t b_change ){ UInt32 i; vlc_value_t val, text; struct aout_sys_t * p_sys = p_aout->output.p_sys; if( i_option == -1 || i_option >= (int)p_sys->i_options ) { for( i = 0; i < p_sys->i_options; i++ ) { if( p_sys->p_options[i].i_dev == p_sys->i_def_dev ) { i_option = i; break; } } } var_Create( p_aout, "audio-device", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE ); text.psz_string = ADEV_TEXT; var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL ); for( i = 0; i < p_sys->i_options; i++ ) { text.psz_string = p_sys->p_options[i].sz_option; val.i_int = i; var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); if( !b_change && i == (UInt32)i_option ) { p_sys->i_sel_opt = i; var_Set( p_aout, "audio-device", val ); config_PutInt( p_aout, "coreaudio-dev", i_option ); } } var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart, NULL ); if( b_change ) { val.i_int = i_option; var_Set( p_aout, "audio-device", val ); } val.b_bool = VLC_TRUE; var_Set( p_aout, "intf-change", val );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -