2020-04-23 00:56:21 +08:00
|
|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
|
|
//
|
|
|
|
// Purpose:
|
|
|
|
//
|
|
|
|
// $NoKeywords: $
|
|
|
|
//=============================================================================//
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef OSX
|
|
|
|
#include <Carbon/Carbon.h>
|
|
|
|
#include <CoreAudio/CoreAudio.h>
|
|
|
|
#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;
|
2022-02-23 19:50:30 +08:00
|
|
|
for ( uint iChannel = 0; iChannel < 3; iChannel++ )
|
2020-04-23 00:56:21 +08:00
|
|
|
{
|
|
|
|
// 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
|
|
|
|
|