Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

286 lines
6.9 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifdef OSX
  8. #include <Carbon/Carbon.h>
  9. #include <CoreAudio/CoreAudio.h>
  10. #endif
  11. #include "tier0/platform.h"
  12. #include "ivoicerecord.h"
  13. #include "voice_mixer_controls.h"
  14. // memdbgon must be the last include file in a .cpp file!!!
  15. #include "tier0/memdbgon.h"
  16. #ifndef OSX
  17. class CMixerControls : public IMixerControls
  18. {
  19. public:
  20. CMixerControls() {}
  21. virtual ~CMixerControls() {}
  22. virtual void Release() {}
  23. virtual bool GetValue_Float(Control iControl, float &value ) {return false;}
  24. virtual bool SetValue_Float(Control iControl, float value) {return false;}
  25. virtual bool SelectMicrophoneForWaveInput() {return false;}
  26. virtual const char *GetMixerName() {return "Linux"; }
  27. private:
  28. };
  29. IMixerControls* g_pMixerControls = NULL;
  30. void InitMixerControls()
  31. {
  32. if ( !g_pMixerControls )
  33. {
  34. g_pMixerControls = new CMixerControls;
  35. }
  36. }
  37. void ShutdownMixerControls()
  38. {
  39. delete g_pMixerControls;
  40. g_pMixerControls = NULL;
  41. }
  42. #elif defined(OSX)
  43. class CMixerControls : public IMixerControls
  44. {
  45. public:
  46. CMixerControls();
  47. virtual ~CMixerControls();
  48. virtual void Release();
  49. virtual bool GetValue_Float(Control iControl, float &value);
  50. virtual bool SetValue_Float(Control iControl, float value);
  51. virtual bool SelectMicrophoneForWaveInput();
  52. virtual const char *GetMixerName();
  53. private:
  54. AudioObjectID GetDefaultInputDevice();
  55. char *m_szMixerName;
  56. AudioObjectID m_theDefaultDeviceID;
  57. };
  58. CMixerControls::CMixerControls()
  59. {
  60. m_szMixerName = NULL;
  61. m_theDefaultDeviceID = GetDefaultInputDevice();
  62. OSStatus theStatus;
  63. UInt32 outSize = sizeof(UInt32);
  64. theStatus = AudioDeviceGetPropertyInfo( m_theDefaultDeviceID,
  65. 0,
  66. TRUE,
  67. kAudioDevicePropertyDeviceName,
  68. &outSize,
  69. NULL);
  70. if ( theStatus == noErr )
  71. {
  72. m_szMixerName = (char *)malloc( outSize*sizeof(char));
  73. theStatus = AudioDeviceGetProperty( m_theDefaultDeviceID,
  74. 0,
  75. TRUE,
  76. kAudioDevicePropertyDeviceName,
  77. &outSize,
  78. m_szMixerName);
  79. if ( theStatus != noErr )
  80. {
  81. free( m_szMixerName );
  82. m_szMixerName = NULL;
  83. }
  84. }
  85. }
  86. CMixerControls::~CMixerControls()
  87. {
  88. if ( m_szMixerName )
  89. free( m_szMixerName );
  90. }
  91. void CMixerControls::Release()
  92. {
  93. }
  94. bool CMixerControls::SelectMicrophoneForWaveInput()
  95. {
  96. return true; // not needed
  97. }
  98. const char *CMixerControls::GetMixerName()
  99. {
  100. return m_szMixerName;
  101. }
  102. bool CMixerControls::GetValue_Float(Control iControl, float &value)
  103. {
  104. switch( iControl)
  105. {
  106. case MicBoost:
  107. {
  108. value = 0.0f;
  109. return true;
  110. }
  111. case MicVolume:
  112. {
  113. OSStatus theError = noErr;
  114. for ( int iChannel = 0; iChannel < 3; iChannel++ )
  115. {
  116. // scan the channel list until you find a channel set to non-zero, then use that
  117. Float32 theVolume = 0;
  118. UInt32 theSize = sizeof(Float32);
  119. AudioObjectPropertyAddress theAddress = { kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeInput, iChannel };
  120. theError = AudioObjectGetPropertyData(m_theDefaultDeviceID,
  121. &theAddress,
  122. 0,
  123. NULL,
  124. &theSize,
  125. &theVolume);
  126. value = theVolume;
  127. if ( theError == noErr && theVolume != 0.0f )
  128. break;
  129. }
  130. return theError == noErr;
  131. }
  132. case MicMute:
  133. // Mic playback muting. You usually want this set to false, otherwise the sound card echoes whatever you say into the mic.
  134. {
  135. Float32 theMute = 0;
  136. UInt32 theSize = sizeof(Float32);
  137. AudioObjectPropertyAddress theAddress = { kAudioDevicePropertyMute, kAudioDevicePropertyScopeInput, 1 };
  138. OSStatus theError = AudioObjectGetPropertyData(m_theDefaultDeviceID,
  139. &theAddress,
  140. 0,
  141. NULL,
  142. &theSize,
  143. &theMute);
  144. value = theMute;
  145. return theError == noErr;
  146. }
  147. default:
  148. assert( !"Invalid Control type" );
  149. value = 0.0f;
  150. return false;
  151. };
  152. }
  153. bool CMixerControls::SetValue_Float(Control iControl, float value)
  154. {
  155. switch( iControl)
  156. {
  157. case MicBoost:
  158. {
  159. return false;
  160. }
  161. case MicVolume:
  162. {
  163. if ( value <= 0.0 )
  164. return false; // don't let the volume be set to zero
  165. Float32 theVolume = value;
  166. UInt32 size = sizeof(Float32);
  167. Boolean canset = false;
  168. AudioObjectID defaultInputDevice = m_theDefaultDeviceID;
  169. size = sizeof(canset);
  170. OSStatus err = AudioDeviceGetPropertyInfo( defaultInputDevice, 0, true, kAudioDevicePropertyVolumeScalar, &size, &canset);
  171. if(err==noErr && canset==true)
  172. {
  173. size = sizeof(theVolume);
  174. err = AudioDeviceSetProperty( defaultInputDevice, NULL, 0, true, kAudioDevicePropertyVolumeScalar, size, &theVolume);
  175. return err==noErr;
  176. }
  177. // try seperate channels
  178. // get channels
  179. UInt32 channels[2];
  180. size = sizeof(channels);
  181. err = AudioDeviceGetProperty(defaultInputDevice, 0, true, kAudioDevicePropertyPreferredChannelsForStereo, &size,&channels);
  182. if(err!=noErr)
  183. return false;
  184. // set volume
  185. size = sizeof(float);
  186. err = AudioDeviceSetProperty(defaultInputDevice, 0, channels[0], true, kAudioDevicePropertyVolumeScalar, size, &theVolume);
  187. //AssertMsg1( noErr==err, "error setting volume of channel %d\n",(int)channels[0]);
  188. err = AudioDeviceSetProperty(defaultInputDevice, 0, channels[1], true, kAudioDevicePropertyVolumeScalar, size, &theVolume);
  189. //AssertMsg1( noErr==err, "error setting volume of channel %d\n",(int)channels[1]);
  190. return err == noErr;
  191. }
  192. case MicMute:
  193. // Mic playback muting. You usually want this set to false, otherwise the sound card echoes whatever you say into the mic.
  194. {
  195. Float32 theMute = value;
  196. UInt32 theMuteSize = sizeof(Float32);
  197. OSStatus theError = paramErr;
  198. theError = AudioDeviceSetProperty( m_theDefaultDeviceID,
  199. NULL,
  200. 0,
  201. TRUE,
  202. kAudioDevicePropertyMute,
  203. theMuteSize,
  204. &theMute);
  205. return theError == noErr;
  206. }
  207. default:
  208. assert( !"Invalid Control type" );
  209. return false;
  210. };
  211. }
  212. AudioObjectID CMixerControls::GetDefaultInputDevice()
  213. {
  214. AudioObjectID theDefaultDeviceID = kAudioObjectUnknown;
  215. AudioObjectPropertyAddress theDefaultDeviceAddress = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
  216. UInt32 theDefaultDeviceSize = sizeof(AudioObjectID);
  217. OSStatus theError = AudioObjectGetPropertyData (kAudioObjectSystemObject, &theDefaultDeviceAddress, 0, NULL, &theDefaultDeviceSize, &theDefaultDeviceID);
  218. return theDefaultDeviceID;
  219. }
  220. IMixerControls* g_pMixerControls = NULL;
  221. void InitMixerControls()
  222. {
  223. if ( !g_pMixerControls )
  224. {
  225. g_pMixerControls = new CMixerControls;
  226. }
  227. }
  228. void ShutdownMixerControls()
  229. {
  230. delete g_pMixerControls;
  231. g_pMixerControls = NULL;
  232. }
  233. #else
  234. #error
  235. #endif