📄 auhal.c
字号:
{ if( p_format_list[j].mSampleRate == p_aout->output.output.i_rate ) { i_requested_rate_format = j; break; } else if( p_format_list[j].mSampleRate == p_sys->sfmt_revert.mSampleRate ) { i_current_rate_format = j; } else { if( i_backup_rate_format < 0 || p_format_list[j].mSampleRate > p_format_list[i_backup_rate_format].mSampleRate ) i_backup_rate_format = j; } } } if( i_requested_rate_format >= 0 ) /* We prefer to output at the samplerate of the original audio */ p_sys->stream_format = p_format_list[i_requested_rate_format]; else if( i_current_rate_format >= 0 ) /* If not possible, we will try to use the current samplerate of the device */ p_sys->stream_format = p_format_list[i_current_rate_format]; else p_sys->stream_format = p_format_list[i_backup_rate_format]; /* And if we have to, any digital format will be just fine (highest rate possible) */ } if( p_format_list ) free( p_format_list ); } if( p_streams ) free( p_streams ); msg_Dbg( p_aout, STREAM_FORMAT_MSG( "original stream format: ", p_sys->sfmt_revert ) ); if( !AudioStreamChangeFormat( p_aout, p_sys->i_stream_id, p_sys->stream_format ) ) return VLC_FALSE; /* Set the format flags */ if( p_sys->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian ) p_aout->output.output.i_format = VLC_FOURCC('s','p','d','b'); else p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i'); p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE; p_aout->output.output.i_frame_length = A52_FRAME_NB; p_aout->output.i_nb_samples = p_aout->output.output.i_frame_length; p_aout->output.output.i_rate = (unsigned int)p_sys->stream_format.mSampleRate; aout_FormatPrepare( &p_aout->output.output ); aout_VolumeNoneInit( p_aout ); /* Add IOProc callback */ err = AudioDeviceAddIOProc( p_sys->i_selected_dev, (AudioDeviceIOProc)RenderCallbackSPDIF, (void *)p_aout ); if( err != noErr ) { msg_Err( p_aout, "AudioDeviceAddIOProc failed: [%4.4s]", (char *)&err ); return VLC_FALSE; } /* Check for the difference between the Device clock and mdate */ p_sys->clock_diff = - (mtime_t) AudioConvertHostTimeToNanos( AudioGetCurrentHostTime() ) / 1000; p_sys->clock_diff += mdate(); /* Start device */ err = AudioDeviceStart( p_sys->i_selected_dev, (AudioDeviceIOProc)RenderCallbackSPDIF ); if( err != noErr ) { msg_Err( p_aout, "AudioDeviceStart failed: [%4.4s]", (char *)&err ); err = AudioDeviceRemoveIOProc( p_sys->i_selected_dev, (AudioDeviceIOProc)RenderCallbackSPDIF ); if( err != noErr ) { msg_Err( p_aout, "AudioDeviceRemoveIOProc failed: [%4.4s]", (char *)&err ); } return VLC_FALSE; } return VLC_TRUE;}/***************************************************************************** * Close: Close HAL AudioUnit *****************************************************************************/static void Close( vlc_object_t * p_this ){ aout_instance_t *p_aout = (aout_instance_t *)p_this; struct aout_sys_t *p_sys = p_aout->output.p_sys; OSStatus err = noErr; UInt32 i_param_size = 0; if( p_sys->au_unit ) { verify_noerr( AudioOutputUnitStop( p_sys->au_unit ) ); verify_noerr( AudioUnitUninitialize( p_sys->au_unit ) ); verify_noerr( CloseComponent( p_sys->au_unit ) ); } if( p_sys->b_digital ) { /* Stop device */ err = AudioDeviceStop( p_sys->i_selected_dev, (AudioDeviceIOProc)RenderCallbackSPDIF ); if( err != noErr ) { msg_Err( p_aout, "AudioDeviceStop failed: [%4.4s]", (char *)&err ); } /* Remove IOProc callback */ err = AudioDeviceRemoveIOProc( p_sys->i_selected_dev, (AudioDeviceIOProc)RenderCallbackSPDIF ); if( err != noErr ) { msg_Err( p_aout, "AudioDeviceRemoveIOProc failed: [%4.4s]", (char *)&err ); } if( p_sys->b_revert ) { AudioStreamChangeFormat( p_aout, p_sys->i_stream_id, p_sys->sfmt_revert ); } if( p_sys->b_changed_mixing && p_sys->sfmt_revert.mFormatID != kAudioFormat60958AC3 ) { int b_mix; Boolean b_writeable; /* Revert mixable to true if we are allowed to */ err = AudioDeviceGetPropertyInfo( p_sys->i_selected_dev, 0, FALSE, kAudioDevicePropertySupportsMixing, &i_param_size, &b_writeable ); err = AudioDeviceGetProperty( p_sys->i_selected_dev, 0, FALSE, kAudioDevicePropertySupportsMixing, &i_param_size, &b_mix ); if( !err && b_writeable ) { msg_Dbg( p_aout, "mixable is: %d", b_mix ); b_mix = 1; err = AudioDeviceSetProperty( p_sys->i_selected_dev, 0, 0, FALSE, kAudioDevicePropertySupportsMixing, i_param_size, &b_mix ); } if( err != noErr ) { msg_Err( p_aout, "failed to set mixmode: [%4.4s]", (char *)&err ); } } } err = AudioHardwareRemovePropertyListener( kAudioHardwarePropertyDevices, HardwareListener ); if( err != noErr ) { msg_Err( p_aout, "AudioHardwareRemovePropertyListener failed: [%4.4s]", (char *)&err ); } if( p_sys->i_hog_pid == getpid() ) { p_sys->i_hog_pid = -1; i_param_size = sizeof( p_sys->i_hog_pid ); err = AudioDeviceSetProperty( p_sys->i_selected_dev, 0, 0, FALSE, kAudioDevicePropertyHogMode, i_param_size, &p_sys->i_hog_pid ); if( err != noErr ) msg_Err( p_aout, "Could not release hogmode: [%4.4s]", (char *)&err ); } if( p_sys ) free( p_sys );}/***************************************************************************** * Play: nothing to do *****************************************************************************/static void Play( aout_instance_t * p_aout ){}/***************************************************************************** * Probe: Check which devices the OS has, and add them to our audio-device menu *****************************************************************************/static void Probe( aout_instance_t * p_aout ){ OSStatus err = noErr; UInt32 i = 0, i_param_size = 0; AudioDeviceID devid_def = 0; AudioDeviceID *p_devices = NULL; vlc_value_t val, text; struct aout_sys_t *p_sys = p_aout->output.p_sys; /* Get number of devices */ err = AudioHardwareGetPropertyInfo( kAudioHardwarePropertyDevices, &i_param_size, NULL ); if( err != noErr ) { msg_Err( p_aout, "Could not get number of devices: [%4.4s]", (char *)&err ); goto error; } p_sys->i_devices = i_param_size / sizeof( AudioDeviceID ); if( p_sys->i_devices < 1 ) { msg_Err( p_aout, "No audio output devices were found." ); goto error; } msg_Dbg( p_aout, "system has [%ld] device(s)", p_sys->i_devices ); /* Allocate DeviceID array */ p_devices = (AudioDeviceID*)malloc( sizeof(AudioDeviceID) * p_sys->i_devices ); if( p_devices == NULL ) { msg_Err( p_aout, "out of memory" ); goto error; } /* Populate DeviceID array */ err = AudioHardwareGetProperty( kAudioHardwarePropertyDevices, &i_param_size, p_devices ); if( err != noErr ) { msg_Err( p_aout, "could not get the device IDs: [%4.4s]", (char *)&err ); goto error; } /* Find the ID of the default Device */ i_param_size = sizeof( AudioDeviceID ); err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice, &i_param_size, &devid_def ); if( err != noErr ) { msg_Err( p_aout, "could not get default audio device: [%4.4s]", (char *)&err ); goto error; } p_sys->i_default_dev = devid_def; 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 ); for( i = 0; i < p_sys->i_devices; i++ ) { char *psz_name; i_param_size = 0; /* Retrieve the length of the device name */ err = AudioDeviceGetPropertyInfo( p_devices[i], 0, VLC_FALSE, kAudioDevicePropertyDeviceName, &i_param_size, NULL); if( err ) goto error; /* Retrieve the name of the device */ psz_name = (char *)malloc( i_param_size ); err = AudioDeviceGetProperty( p_devices[i], 0, VLC_FALSE, kAudioDevicePropertyDeviceName, &i_param_size, psz_name); if( err ) goto error; msg_Dbg( p_aout, "DevID: %#lx DevName: %s", p_devices[i], psz_name ); if( !AudioDeviceHasOutput( p_devices[i]) ) { msg_Dbg( p_aout, "this device is INPUT only. skipping..." ); continue; } /* Add the menu entries */ val.i_int = (int)p_devices[i]; text.psz_string = strdup( psz_name ); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); if( p_sys->i_default_dev == p_devices[i] ) { /* The default device is the selected device normally */ var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL ); var_Set( p_aout, "audio-device", val ); } if( AudioDeviceSupportsDigital( p_aout, p_devices[i] ) ) { val.i_int = (int)p_devices[i] | AOUT_VAR_SPDIF_FLAG; asprintf( &text.psz_string, _("%s (Encoded Output)"), psz_name ); var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val, &text ); if( p_sys->i_default_dev == p_devices[i] && config_GetInt( p_aout, "spdif" ) ) { /* We selected to prefer SPDIF output if available * then this "dummy" entry should be selected */ var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL ); var_Set( p_aout, "audio-device", val ); } } free( psz_name); } /* If a device is already "preselected", then use this device */ var_Get( p_aout->p_vlc, "macosx-audio-device", &val ); if( val.i_int > 0 ) { var_Change( p_aout, "audio-device", VLC_VAR_SETDEFAULT, &val, NULL ); var_Set( p_aout, "audio-device", val ); } /* If we change the device we want to use, we should renegotiate the audio chain */ var_AddCallback( p_aout, "audio-device", AudioDeviceCallback, NULL ); /* Attach a Listener so that we are notified of a change in the Device setup */ err = AudioHardwareAddPropertyListener( kAudioHardwarePropertyDevices, HardwareListener, (void *)p_aout ); if( err ) goto error; if( p_devices ) free( p_devices ); return;error: var_Destroy( p_aout, "audio-device" ); if( p_devices ) free( p_devices ); return;}/***************************************************************************** * AudioDeviceHasOutput: Checks if the Device actually provides any outputs at all *****************************************************************************/static int AudioDeviceHasOutput( AudioDeviceID i_dev_id ){ UInt32 dataSize; Boolean isWritable; verify_noerr( AudioDeviceGetPropertyInfo( i_dev_id, 0, FALSE, kAudioDevicePropertyStreams, &dataSize, &isWritable) ); if (dataSize == 0) return FALSE; return TRUE;}/***************************************************************************** * AudioDeviceSupportsDigital: Check i_dev_id for digital stream support. *****************************************************************************/static int AudioDeviceSupportsDigital( aout_instance_t *p_aout, AudioDeviceID i_dev_id ){ OSStatus err = noErr; UInt32 i_param_size = 0; AudioStreamID *p_streams = NULL; int i = 0, i_streams = 0; vlc_bool_t b_return = VLC_FALSE; /* Retrieve all the output streams */ err = AudioDeviceGetPropertyInfo( i_dev_id, 0, FALSE, kAudioDevicePropertyStreams, &i_param_size, NULL ); if( err != noErr ) { msg_Err( p_aout, "could not get number of streams: [%4.4s]", (char *)&err ); return VLC_FALSE; } i_streams = i_param_size / sizeof( AudioStreamID ); p_streams = (AudioStreamID *)malloc( i_param_size ); if( p_streams == NULL ) { msg_Err( p_aout, "out of memory" ); return VLC_ENOMEM; } err = AudioDeviceGetProperty( i_dev_id, 0, FALSE,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -