//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #ifdef OSX #include #include #endif #include "tier0/platform.h" #include "ivoicerecord.h" #include "voice_mixer_controls.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" #ifndef OSX class CMixerControls : public IMixerControls { public: CMixerControls() {} virtual ~CMixerControls() {} virtual void Release() {} virtual bool GetValue_Float(Control iControl, float &value ) {return false;} virtual bool SetValue_Float(Control iControl, float value) {return false;} virtual bool SelectMicrophoneForWaveInput() {return false;} virtual const char *GetMixerName() {return "Linux"; } private: }; IMixerControls* g_pMixerControls = NULL; void InitMixerControls() { if ( !g_pMixerControls ) { g_pMixerControls = new CMixerControls; } } void ShutdownMixerControls() { delete g_pMixerControls; g_pMixerControls = NULL; } #elif defined(OSX) class CMixerControls : public IMixerControls { public: CMixerControls(); virtual ~CMixerControls(); virtual void Release(); virtual bool GetValue_Float(Control iControl, float &value); virtual bool SetValue_Float(Control iControl, float value); virtual bool SelectMicrophoneForWaveInput(); virtual const char *GetMixerName(); private: AudioObjectID GetDefaultInputDevice(); char *m_szMixerName; AudioObjectID m_theDefaultDeviceID; }; CMixerControls::CMixerControls() { m_szMixerName = NULL; m_theDefaultDeviceID = GetDefaultInputDevice(); OSStatus theStatus; UInt32 outSize = sizeof(UInt32); theStatus = AudioDeviceGetPropertyInfo( m_theDefaultDeviceID, 0, TRUE, kAudioDevicePropertyDeviceName, &outSize, NULL); if ( theStatus == noErr ) { m_szMixerName = (char *)malloc( outSize*sizeof(char)); theStatus = AudioDeviceGetProperty( m_theDefaultDeviceID, 0, TRUE, kAudioDevicePropertyDeviceName, &outSize, m_szMixerName); if ( theStatus != noErr ) { free( m_szMixerName ); m_szMixerName = NULL; } } } CMixerControls::~CMixerControls() { if ( m_szMixerName ) free( m_szMixerName ); } void CMixerControls::Release() { } bool CMixerControls::SelectMicrophoneForWaveInput() { return true; // not needed } const char *CMixerControls::GetMixerName() { return m_szMixerName; } bool CMixerControls::GetValue_Float(Control iControl, float &value) { switch( iControl) { case MicBoost: { value = 0.0f; return true; } case MicVolume: { OSStatus theError = noErr; for ( uint iChannel = 0; iChannel < 3; iChannel++ ) { // scan the channel list until you find a channel set to non-zero, then use that Float32 theVolume = 0; UInt32 theSize = sizeof(Float32); AudioObjectPropertyAddress theAddress = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeInput, iChannel }; theError = AudioObjectGetPropertyData(m_theDefaultDeviceID, &theAddress, 0, NULL, &theSize, &theVolume); value = theVolume; if ( theError == noErr && theVolume != 0.0f ) break; } return theError == noErr; } case MicMute: // Mic playback muting. You usually want this set to false, otherwise the sound card echoes whatever you say into the mic. { Float32 theMute = 0; UInt32 theSize = sizeof(Float32); AudioObjectPropertyAddress theAddress = { kAudioDevicePropertyMute, kAudioDevicePropertyScopeInput, 1 }; OSStatus theError = AudioObjectGetPropertyData(m_theDefaultDeviceID, &theAddress, 0, NULL, &theSize, &theMute); value = theMute; return theError == noErr; } default: assert( !"Invalid Control type" ); value = 0.0f; return false; }; } bool CMixerControls::SetValue_Float(Control iControl, float value) { switch( iControl) { case MicBoost: { return false; } case MicVolume: { if ( value <= 0.0 ) return false; // don't let the volume be set to zero Float32 theVolume = value; UInt32 size = sizeof(Float32); Boolean canset = false; AudioObjectID defaultInputDevice = m_theDefaultDeviceID; size = sizeof(canset); OSStatus err = AudioDeviceGetPropertyInfo( defaultInputDevice, 0, true, kAudioDevicePropertyVolumeScalar, &size, &canset); if(err==noErr && canset==true) { size = sizeof(theVolume); err = AudioDeviceSetProperty( defaultInputDevice, NULL, 0, true, kAudioDevicePropertyVolumeScalar, size, &theVolume); return err==noErr; } // try seperate channels // get channels UInt32 channels[2]; size = sizeof(channels); err = AudioDeviceGetProperty(defaultInputDevice, 0, true, kAudioDevicePropertyPreferredChannelsForStereo, &size,&channels); if(err!=noErr) return false; // set volume size = sizeof(float); err = AudioDeviceSetProperty(defaultInputDevice, 0, channels[0], true, kAudioDevicePropertyVolumeScalar, size, &theVolume); //AssertMsg1( noErr==err, "error setting volume of channel %d\n",(int)channels[0]); err = AudioDeviceSetProperty(defaultInputDevice, 0, channels[1], true, kAudioDevicePropertyVolumeScalar, size, &theVolume); //AssertMsg1( noErr==err, "error setting volume of channel %d\n",(int)channels[1]); return err == noErr; } case MicMute: // Mic playback muting. You usually want this set to false, otherwise the sound card echoes whatever you say into the mic. { Float32 theMute = value; UInt32 theMuteSize = sizeof(Float32); OSStatus theError = paramErr; theError = AudioDeviceSetProperty( m_theDefaultDeviceID, NULL, 0, TRUE, kAudioDevicePropertyMute, theMuteSize, &theMute); return theError == noErr; } default: assert( !"Invalid Control type" ); return false; }; } AudioObjectID CMixerControls::GetDefaultInputDevice() { AudioObjectID theDefaultDeviceID = kAudioObjectUnknown; AudioObjectPropertyAddress theDefaultDeviceAddress = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; UInt32 theDefaultDeviceSize = sizeof(AudioObjectID); OSStatus theError = AudioObjectGetPropertyData (kAudioObjectSystemObject, &theDefaultDeviceAddress, 0, NULL, &theDefaultDeviceSize, &theDefaultDeviceID); return theDefaultDeviceID; } IMixerControls* g_pMixerControls = NULL; void InitMixerControls() { if ( !g_pMixerControls ) { g_pMixerControls = new CMixerControls; } } void ShutdownMixerControls() { delete g_pMixerControls; g_pMixerControls = NULL; } #else #error #endif