blob: bdd8d8352e15b6d2a2b9b3a994c086656b64a2a2 [file] [log] [blame]
andrew@webrtc.orgb015cbe2012-10-22 18:19:231/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_MAC_H
12#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_MAC_H
13
kwibergc0677bd2016-02-24 13:00:3614#include <memory>
15
pbos@webrtc.orgbc669ac2013-07-11 13:24:3816#include "webrtc/modules/audio_device/audio_device_generic.h"
17#include "webrtc/modules/audio_device/mac/audio_mixer_manager_mac.h"
Edward Lemur76de83e2017-07-06 17:44:3418#include "webrtc/rtc_base/criticalsection.h"
sazaf7e08b22017-07-19 08:12:3619#include "webrtc/rtc_base/logging.h"
Edward Lemur76de83e2017-07-06 17:44:3420#include "webrtc/rtc_base/thread_annotations.h"
kthelgason912e1cf2017-03-31 09:03:5521#include "webrtc/system_wrappers/include/event_wrapper.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:2322
andrew@webrtc.orgb015cbe2012-10-22 18:19:2323#include <AudioToolbox/AudioConverter.h>
pbos@webrtc.orgbc669ac2013-07-11 13:24:3824#include <CoreAudio/CoreAudio.h>
andrew@webrtc.orgb015cbe2012-10-22 18:19:2325#include <mach/semaphore.h>
26
27struct PaUtilRingBuffer;
28
Peter Boströmdaf1aa42015-11-26 16:45:4729namespace rtc {
30class PlatformThread;
31} // namespace rtc
32
andrew0cbc06b2016-01-11 23:59:1733namespace webrtc {
andrew@webrtc.orgb015cbe2012-10-22 18:19:2334class EventWrapper;
andrew@webrtc.orgb015cbe2012-10-22 18:19:2335
andrew@webrtc.org1125d892013-06-08 00:43:2536const uint32_t N_REC_SAMPLES_PER_SEC = 48000;
37const uint32_t N_PLAY_SAMPLES_PER_SEC = 48000;
andrew@webrtc.orgb015cbe2012-10-22 18:19:2338
andrew0cbc06b2016-01-11 23:59:1739const uint32_t N_REC_CHANNELS = 1; // default is mono recording
40const uint32_t N_PLAY_CHANNELS = 2; // default is stereo playout
andrew@webrtc.org1125d892013-06-08 00:43:2541const uint32_t N_DEVICE_CHANNELS = 64;
andrew@webrtc.orgb015cbe2012-10-22 18:19:2342
andrewebe7b602016-01-08 09:16:1743const int kBufferSizeMs = 10;
44
45const uint32_t ENGINE_REC_BUF_SIZE_IN_SAMPLES =
46 N_REC_SAMPLES_PER_SEC * kBufferSizeMs / 1000;
47const uint32_t ENGINE_PLAY_BUF_SIZE_IN_SAMPLES =
48 N_PLAY_SAMPLES_PER_SEC * kBufferSizeMs / 1000;
andrew@webrtc.orgb015cbe2012-10-22 18:19:2349
andrew@webrtc.org64e26512013-06-07 17:56:5050const int N_BLOCKS_IO = 2;
andrew0cbc06b2016-01-11 23:59:1751const int N_BUFFERS_IN = 2; // Must be at least N_BLOCKS_IO.
andrew@webrtc.org64e26512013-06-07 17:56:5052const int N_BUFFERS_OUT = 3; // Must be at least N_BLOCKS_IO.
andrew@webrtc.orgb015cbe2012-10-22 18:19:2353
andrewebe7b602016-01-08 09:16:1754const uint32_t TIMER_PERIOD_MS = 2 * 10 * N_BLOCKS_IO * 1000000;
andrew@webrtc.orgb015cbe2012-10-22 18:19:2355
andrew@webrtc.org1125d892013-06-08 00:43:2556const uint32_t REC_BUF_SIZE_IN_SAMPLES =
andrew@webrtc.org64e26512013-06-07 17:56:5057 ENGINE_REC_BUF_SIZE_IN_SAMPLES * N_DEVICE_CHANNELS * N_BUFFERS_IN;
andrew@webrtc.org1125d892013-06-08 00:43:2558const uint32_t PLAY_BUF_SIZE_IN_SAMPLES =
andrew@webrtc.org64e26512013-06-07 17:56:5059 ENGINE_PLAY_BUF_SIZE_IN_SAMPLES * N_PLAY_CHANNELS * N_BUFFERS_OUT;
andrew@webrtc.orgb015cbe2012-10-22 18:19:2360
andrewebe7b602016-01-08 09:16:1761const int kGetMicVolumeIntervalMs = 1000;
62
andrew0cbc06b2016-01-11 23:59:1763class AudioDeviceMac : public AudioDeviceGeneric {
64 public:
sazaf7e08b22017-07-19 08:12:3665 AudioDeviceMac();
andrew0cbc06b2016-01-11 23:59:1766 ~AudioDeviceMac();
andrew@webrtc.orgb015cbe2012-10-22 18:19:2367
andrew0cbc06b2016-01-11 23:59:1768 // Retrieve the currently utilized audio layer
69 virtual int32_t ActiveAudioLayer(
70 AudioDeviceModule::AudioLayer& audioLayer) const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:2371
andrew0cbc06b2016-01-11 23:59:1772 // Main initializaton and termination
Max Morin190023d2016-07-01 11:35:1973 virtual InitStatus Init();
andrew0cbc06b2016-01-11 23:59:1774 virtual int32_t Terminate();
75 virtual bool Initialized() const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:2376
andrew0cbc06b2016-01-11 23:59:1777 // Device enumeration
78 virtual int16_t PlayoutDevices();
79 virtual int16_t RecordingDevices();
80 virtual int32_t PlayoutDeviceName(uint16_t index,
81 char name[kAdmMaxDeviceNameSize],
82 char guid[kAdmMaxGuidSize]);
83 virtual int32_t RecordingDeviceName(uint16_t index,
84 char name[kAdmMaxDeviceNameSize],
85 char guid[kAdmMaxGuidSize]);
andrew@webrtc.orgb015cbe2012-10-22 18:19:2386
andrew0cbc06b2016-01-11 23:59:1787 // Device selection
88 virtual int32_t SetPlayoutDevice(uint16_t index);
89 virtual int32_t SetPlayoutDevice(AudioDeviceModule::WindowsDeviceType device);
90 virtual int32_t SetRecordingDevice(uint16_t index);
91 virtual int32_t SetRecordingDevice(
92 AudioDeviceModule::WindowsDeviceType device);
andrew@webrtc.orgb015cbe2012-10-22 18:19:2393
andrew0cbc06b2016-01-11 23:59:1794 // Audio transport initialization
95 virtual int32_t PlayoutIsAvailable(bool& available);
96 virtual int32_t InitPlayout();
97 virtual bool PlayoutIsInitialized() const;
98 virtual int32_t RecordingIsAvailable(bool& available);
99 virtual int32_t InitRecording();
100 virtual bool RecordingIsInitialized() const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23101
andrew0cbc06b2016-01-11 23:59:17102 // Audio transport control
103 virtual int32_t StartPlayout();
104 virtual int32_t StopPlayout();
105 virtual bool Playing() const;
106 virtual int32_t StartRecording();
107 virtual int32_t StopRecording();
108 virtual bool Recording() const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23109
andrew0cbc06b2016-01-11 23:59:17110 // Microphone Automatic Gain Control (AGC)
111 virtual int32_t SetAGC(bool enable);
112 virtual bool AGC() const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23113
andrew0cbc06b2016-01-11 23:59:17114 // Audio mixer initialization
115 virtual int32_t InitSpeaker();
116 virtual bool SpeakerIsInitialized() const;
117 virtual int32_t InitMicrophone();
118 virtual bool MicrophoneIsInitialized() const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23119
andrew0cbc06b2016-01-11 23:59:17120 // Speaker volume controls
121 virtual int32_t SpeakerVolumeIsAvailable(bool& available);
122 virtual int32_t SetSpeakerVolume(uint32_t volume);
123 virtual int32_t SpeakerVolume(uint32_t& volume) const;
124 virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const;
125 virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23126
andrew0cbc06b2016-01-11 23:59:17127 // Microphone volume controls
128 virtual int32_t MicrophoneVolumeIsAvailable(bool& available);
129 virtual int32_t SetMicrophoneVolume(uint32_t volume);
130 virtual int32_t MicrophoneVolume(uint32_t& volume) const;
131 virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const;
132 virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23133
andrew0cbc06b2016-01-11 23:59:17134 // Microphone mute control
135 virtual int32_t MicrophoneMuteIsAvailable(bool& available);
136 virtual int32_t SetMicrophoneMute(bool enable);
137 virtual int32_t MicrophoneMute(bool& enabled) const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23138
andrew0cbc06b2016-01-11 23:59:17139 // Speaker mute control
140 virtual int32_t SpeakerMuteIsAvailable(bool& available);
141 virtual int32_t SetSpeakerMute(bool enable);
142 virtual int32_t SpeakerMute(bool& enabled) const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23143
andrew0cbc06b2016-01-11 23:59:17144 // Stereo support
145 virtual int32_t StereoPlayoutIsAvailable(bool& available);
146 virtual int32_t SetStereoPlayout(bool enable);
147 virtual int32_t StereoPlayout(bool& enabled) const;
148 virtual int32_t StereoRecordingIsAvailable(bool& available);
149 virtual int32_t SetStereoRecording(bool enable);
150 virtual int32_t StereoRecording(bool& enabled) const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23151
andrew0cbc06b2016-01-11 23:59:17152 // Delay information and control
andrew0cbc06b2016-01-11 23:59:17153 virtual int32_t PlayoutDelay(uint16_t& delayMS) const;
154 virtual int32_t RecordingDelay(uint16_t& delayMS) const;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23155
andrew0cbc06b2016-01-11 23:59:17156 virtual bool PlayoutWarning() const;
157 virtual bool PlayoutError() const;
158 virtual bool RecordingWarning() const;
159 virtual bool RecordingError() const;
160 virtual void ClearPlayoutWarning();
161 virtual void ClearPlayoutError();
162 virtual void ClearRecordingWarning();
163 virtual void ClearRecordingError();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23164
andrew0cbc06b2016-01-11 23:59:17165 virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23166
andrew0cbc06b2016-01-11 23:59:17167 private:
168 virtual int32_t MicrophoneIsAvailable(bool& available);
169 virtual int32_t SpeakerIsAvailable(bool& available);
andrew@webrtc.orgcceb3922014-04-02 16:49:26170
andrew0cbc06b2016-01-11 23:59:17171 static void AtomicSet32(int32_t* theValue, int32_t newValue);
172 static int32_t AtomicGet32(int32_t* theValue);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23173
sazaf7e08b22017-07-19 08:12:36174 static void logCAMsg(const rtc::LoggingSeverity sev,
andrew0cbc06b2016-01-11 23:59:17175 const char* msg,
176 const char* err);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23177
andrew0cbc06b2016-01-11 23:59:17178 int32_t GetNumberDevices(const AudioObjectPropertyScope scope,
179 AudioDeviceID scopedDeviceIds[],
180 const uint32_t deviceListLength);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23181
andrew0cbc06b2016-01-11 23:59:17182 int32_t GetDeviceName(const AudioObjectPropertyScope scope,
183 const uint16_t index,
184 char* name);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23185
andrew0cbc06b2016-01-11 23:59:17186 int32_t InitDevice(uint16_t userDeviceIndex,
187 AudioDeviceID& deviceId,
188 bool isInput);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23189
andrew0cbc06b2016-01-11 23:59:17190 // Always work with our preferred playout format inside VoE.
191 // Then convert the output to the OS setting using an AudioConverter.
192 OSStatus SetDesiredPlayoutFormat();
braveyao@webrtc.org462472f2015-03-21 01:05:56193
andrew0cbc06b2016-01-11 23:59:17194 static OSStatus objectListenerProc(
195 AudioObjectID objectId,
196 UInt32 numberAddresses,
197 const AudioObjectPropertyAddress addresses[],
198 void* clientData);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23199
andrew0cbc06b2016-01-11 23:59:17200 OSStatus implObjectListenerProc(AudioObjectID objectId,
201 UInt32 numberAddresses,
202 const AudioObjectPropertyAddress addresses[]);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23203
andrew0cbc06b2016-01-11 23:59:17204 int32_t HandleDeviceChange();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23205
andrew0cbc06b2016-01-11 23:59:17206 int32_t HandleStreamFormatChange(AudioObjectID objectId,
207 AudioObjectPropertyAddress propertyAddress);
208
209 int32_t HandleDataSourceChange(AudioObjectID objectId,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23210 AudioObjectPropertyAddress propertyAddress);
211
andrew0cbc06b2016-01-11 23:59:17212 int32_t HandleProcessorOverload(AudioObjectPropertyAddress propertyAddress);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23213
andrew0cbc06b2016-01-11 23:59:17214 static OSStatus deviceIOProc(AudioDeviceID device,
215 const AudioTimeStamp* now,
216 const AudioBufferList* inputData,
217 const AudioTimeStamp* inputTime,
218 AudioBufferList* outputData,
219 const AudioTimeStamp* outputTime,
220 void* clientData);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23221
andrew0cbc06b2016-01-11 23:59:17222 static OSStatus outConverterProc(
223 AudioConverterRef audioConverter,
224 UInt32* numberDataPackets,
225 AudioBufferList* data,
226 AudioStreamPacketDescription** dataPacketDescription,
227 void* userData);
228
229 static OSStatus inDeviceIOProc(AudioDeviceID device,
230 const AudioTimeStamp* now,
231 const AudioBufferList* inputData,
232 const AudioTimeStamp* inputTime,
233 AudioBufferList* outputData,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23234 const AudioTimeStamp* outputTime,
andrew0cbc06b2016-01-11 23:59:17235 void* clientData);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23236
andrew0cbc06b2016-01-11 23:59:17237 static OSStatus inConverterProc(
238 AudioConverterRef audioConverter,
239 UInt32* numberDataPackets,
240 AudioBufferList* data,
241 AudioStreamPacketDescription** dataPacketDescription,
242 void* inUserData);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23243
andrew0cbc06b2016-01-11 23:59:17244 OSStatus implDeviceIOProc(const AudioBufferList* inputData,
245 const AudioTimeStamp* inputTime,
246 AudioBufferList* outputData,
247 const AudioTimeStamp* outputTime);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23248
andrew0cbc06b2016-01-11 23:59:17249 OSStatus implOutConverterProc(UInt32* numberDataPackets,
250 AudioBufferList* data);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23251
andrew0cbc06b2016-01-11 23:59:17252 OSStatus implInDeviceIOProc(const AudioBufferList* inputData,
253 const AudioTimeStamp* inputTime);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23254
andrew0cbc06b2016-01-11 23:59:17255 OSStatus implInConverterProc(UInt32* numberDataPackets,
256 AudioBufferList* data);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23257
andrew0cbc06b2016-01-11 23:59:17258 static bool RunCapture(void*);
259 static bool RunRender(void*);
260 bool CaptureWorkerThread();
261 bool RenderWorkerThread();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23262
andrew0cbc06b2016-01-11 23:59:17263 bool KeyPressed();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23264
andrew0cbc06b2016-01-11 23:59:17265 AudioDeviceBuffer* _ptrAudioBuffer;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23266
kthelgason912e1cf2017-03-31 09:03:55267 rtc::CriticalSection _critSect;
niklas.enbom@webrtc.org28832e12013-05-07 21:04:24268
andrew0cbc06b2016-01-11 23:59:17269 EventWrapper& _stopEventRec;
270 EventWrapper& _stopEvent;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23271
andrew0cbc06b2016-01-11 23:59:17272 // TODO(pbos): Replace with direct members, just start/stop, no need to
273 // recreate the thread.
274 // Only valid/running between calls to StartRecording and StopRecording.
kwibergc0677bd2016-02-24 13:00:36275 std::unique_ptr<rtc::PlatformThread> capture_worker_thread_;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23276
andrew0cbc06b2016-01-11 23:59:17277 // Only valid/running between calls to StartPlayout and StopPlayout.
kwibergc0677bd2016-02-24 13:00:36278 std::unique_ptr<rtc::PlatformThread> render_worker_thread_;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23279
andrew0cbc06b2016-01-11 23:59:17280 AudioMixerManagerMac _mixerManager;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23281
andrew0cbc06b2016-01-11 23:59:17282 uint16_t _inputDeviceIndex;
283 uint16_t _outputDeviceIndex;
284 AudioDeviceID _inputDeviceID;
285 AudioDeviceID _outputDeviceID;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23286#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
andrew0cbc06b2016-01-11 23:59:17287 AudioDeviceIOProcID _inDeviceIOProcID;
288 AudioDeviceIOProcID _deviceIOProcID;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23289#endif
andrew0cbc06b2016-01-11 23:59:17290 bool _inputDeviceIsSpecified;
291 bool _outputDeviceIsSpecified;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23292
andrew0cbc06b2016-01-11 23:59:17293 uint8_t _recChannels;
294 uint8_t _playChannels;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23295
andrew0cbc06b2016-01-11 23:59:17296 Float32* _captureBufData;
297 SInt16* _renderBufData;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23298
andrew0cbc06b2016-01-11 23:59:17299 SInt16 _renderConvertData[PLAY_BUF_SIZE_IN_SAMPLES];
andrew@webrtc.orgb015cbe2012-10-22 18:19:23300
andrew0cbc06b2016-01-11 23:59:17301 bool _initialized;
302 bool _isShutDown;
303 bool _recording;
304 bool _playing;
305 bool _recIsInitialized;
306 bool _playIsInitialized;
307 bool _AGC;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23308
andrew0cbc06b2016-01-11 23:59:17309 // Atomically set varaibles
310 int32_t _renderDeviceIsAlive;
311 int32_t _captureDeviceIsAlive;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23312
andrew0cbc06b2016-01-11 23:59:17313 bool _twoDevices;
314 bool _doStop; // For play if not shared device or play+rec if shared device
315 bool _doStopRec; // For rec if not shared device
316 bool _macBookPro;
317 bool _macBookProPanRight;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23318
andrew0cbc06b2016-01-11 23:59:17319 AudioConverterRef _captureConverter;
320 AudioConverterRef _renderConverter;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23321
andrew0cbc06b2016-01-11 23:59:17322 AudioStreamBasicDescription _outStreamFormat;
323 AudioStreamBasicDescription _outDesiredFormat;
324 AudioStreamBasicDescription _inStreamFormat;
325 AudioStreamBasicDescription _inDesiredFormat;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23326
andrew0cbc06b2016-01-11 23:59:17327 uint32_t _captureLatencyUs;
328 uint32_t _renderLatencyUs;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23329
andrew0cbc06b2016-01-11 23:59:17330 // Atomically set variables
331 mutable int32_t _captureDelayUs;
332 mutable int32_t _renderDelayUs;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23333
andrew0cbc06b2016-01-11 23:59:17334 int32_t _renderDelayOffsetSamples;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23335
andrew0cbc06b2016-01-11 23:59:17336 uint16_t _playWarning;
337 uint16_t _playError;
338 uint16_t _recWarning;
339 uint16_t _recError;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23340
andrew0cbc06b2016-01-11 23:59:17341 PaUtilRingBuffer* _paCaptureBuffer;
342 PaUtilRingBuffer* _paRenderBuffer;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23343
andrew0cbc06b2016-01-11 23:59:17344 semaphore_t _renderSemaphore;
345 semaphore_t _captureSemaphore;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23346
andrew0cbc06b2016-01-11 23:59:17347 int _captureBufSizeSamples;
348 int _renderBufSizeSamples;
niklas.enbom@webrtc.orge807da92013-08-15 14:19:12349
andrew0cbc06b2016-01-11 23:59:17350 // Typing detection
351 // 0x5c is key "9", after that comes function keys.
352 bool prev_key_state_[0x5d];
andrewebe7b602016-01-08 09:16:17353
andrew0cbc06b2016-01-11 23:59:17354 int get_mic_volume_counter_ms_;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23355};
356
pbos@webrtc.org3b89e102013-07-03 15:12:26357} // namespace webrtc
andrew@webrtc.orgb015cbe2012-10-22 18:19:23358
359#endif // MODULES_AUDIO_DEVICE_MAIN_SOURCE_MAC_AUDIO_DEVICE_MAC_H_