1/*
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
14#include "webrtc/modules/audio_device/audio_device_generic.h"
15#include "webrtc/modules/audio_device/mac/audio_mixer_manager_mac.h"
16#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
17
18#include <AudioToolbox/AudioConverter.h>
19#include <CoreAudio/CoreAudio.h>
20#include <mach/semaphore.h>
21
22struct PaUtilRingBuffer;
23
24namespace webrtc
25{
26class EventWrapper;
27class ThreadWrapper;
28
29const uint32_t N_REC_SAMPLES_PER_SEC = 48000;
30const uint32_t N_PLAY_SAMPLES_PER_SEC = 48000;
31
32const uint32_t N_REC_CHANNELS = 1; // default is mono recording
33const uint32_t N_PLAY_CHANNELS = 2; // default is stereo playout
34const uint32_t N_DEVICE_CHANNELS = 64;
35
36const uint32_t ENGINE_REC_BUF_SIZE_IN_SAMPLES = (N_REC_SAMPLES_PER_SEC / 100);
37const uint32_t ENGINE_PLAY_BUF_SIZE_IN_SAMPLES = (N_PLAY_SAMPLES_PER_SEC / 100);
38
39const int N_BLOCKS_IO = 2;
40const int N_BUFFERS_IN = 2;  // Must be at least N_BLOCKS_IO.
41const int N_BUFFERS_OUT = 3;  // Must be at least N_BLOCKS_IO.
42
43const uint32_t TIMER_PERIOD_MS = (2 * 10 * N_BLOCKS_IO * 1000000);
44
45const uint32_t REC_BUF_SIZE_IN_SAMPLES =
46    ENGINE_REC_BUF_SIZE_IN_SAMPLES * N_DEVICE_CHANNELS * N_BUFFERS_IN;
47const uint32_t PLAY_BUF_SIZE_IN_SAMPLES =
48    ENGINE_PLAY_BUF_SIZE_IN_SAMPLES * N_PLAY_CHANNELS * N_BUFFERS_OUT;
49
50class AudioDeviceMac: public AudioDeviceGeneric
51{
52public:
53    AudioDeviceMac(const int32_t id);
54    ~AudioDeviceMac();
55
56    // Retrieve the currently utilized audio layer
57    virtual int32_t
58        ActiveAudioLayer(AudioDeviceModule::AudioLayer& audioLayer) const;
59
60    // Main initializaton and termination
61    virtual int32_t Init();
62    virtual int32_t Terminate();
63    virtual bool Initialized() const;
64
65    // Device enumeration
66    virtual int16_t PlayoutDevices();
67    virtual int16_t RecordingDevices();
68    virtual int32_t PlayoutDeviceName(
69        uint16_t index,
70        char name[kAdmMaxDeviceNameSize],
71        char guid[kAdmMaxGuidSize]);
72    virtual int32_t RecordingDeviceName(
73        uint16_t index,
74        char name[kAdmMaxDeviceNameSize],
75        char guid[kAdmMaxGuidSize]);
76
77    // Device selection
78    virtual int32_t SetPlayoutDevice(uint16_t index);
79    virtual int32_t SetPlayoutDevice(
80        AudioDeviceModule::WindowsDeviceType device);
81    virtual int32_t SetRecordingDevice(uint16_t index);
82    virtual int32_t SetRecordingDevice(
83        AudioDeviceModule::WindowsDeviceType device);
84
85    // Audio transport initialization
86    virtual int32_t PlayoutIsAvailable(bool& available);
87    virtual int32_t InitPlayout();
88    virtual bool PlayoutIsInitialized() const;
89    virtual int32_t RecordingIsAvailable(bool& available);
90    virtual int32_t InitRecording();
91    virtual bool RecordingIsInitialized() const;
92
93    // Audio transport control
94    virtual int32_t StartPlayout();
95    virtual int32_t StopPlayout();
96    virtual bool Playing() const;
97    virtual int32_t StartRecording();
98    virtual int32_t StopRecording();
99    virtual bool Recording() const;
100
101    // Microphone Automatic Gain Control (AGC)
102    virtual int32_t SetAGC(bool enable);
103    virtual bool AGC() const;
104
105    // Volume control based on the Windows Wave API (Windows only)
106    virtual int32_t SetWaveOutVolume(uint16_t volumeLeft, uint16_t volumeRight);
107    virtual int32_t WaveOutVolume(uint16_t& volumeLeft,
108                                  uint16_t& volumeRight) const;
109
110    // Audio mixer initialization
111    virtual int32_t InitSpeaker();
112    virtual bool SpeakerIsInitialized() const;
113    virtual int32_t InitMicrophone();
114    virtual bool MicrophoneIsInitialized() const;
115
116    // Speaker volume controls
117    virtual int32_t SpeakerVolumeIsAvailable(bool& available);
118    virtual int32_t SetSpeakerVolume(uint32_t volume);
119    virtual int32_t SpeakerVolume(uint32_t& volume) const;
120    virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const;
121    virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const;
122    virtual int32_t SpeakerVolumeStepSize(uint16_t& stepSize) const;
123
124    // Microphone volume controls
125    virtual int32_t MicrophoneVolumeIsAvailable(bool& available);
126    virtual int32_t SetMicrophoneVolume(uint32_t volume);
127    virtual int32_t MicrophoneVolume(uint32_t& volume) const;
128    virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const;
129    virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const;
130    virtual int32_t
131        MicrophoneVolumeStepSize(uint16_t& stepSize) const;
132
133    // Microphone mute control
134    virtual int32_t MicrophoneMuteIsAvailable(bool& available);
135    virtual int32_t SetMicrophoneMute(bool enable);
136    virtual int32_t MicrophoneMute(bool& enabled) const;
137
138    // Speaker mute control
139    virtual int32_t SpeakerMuteIsAvailable(bool& available);
140    virtual int32_t SetSpeakerMute(bool enable);
141    virtual int32_t SpeakerMute(bool& enabled) const;
142
143    // Microphone boost control
144    virtual int32_t MicrophoneBoostIsAvailable(bool& available);
145    virtual int32_t SetMicrophoneBoost(bool enable);
146    virtual int32_t MicrophoneBoost(bool& enabled) const;
147
148    // Stereo support
149    virtual int32_t StereoPlayoutIsAvailable(bool& available);
150    virtual int32_t SetStereoPlayout(bool enable);
151    virtual int32_t StereoPlayout(bool& enabled) const;
152    virtual int32_t StereoRecordingIsAvailable(bool& available);
153    virtual int32_t SetStereoRecording(bool enable);
154    virtual int32_t StereoRecording(bool& enabled) const;
155
156    // Delay information and control
157    virtual int32_t
158        SetPlayoutBuffer(const AudioDeviceModule::BufferType type,
159                         uint16_t sizeMS);
160    virtual int32_t PlayoutBuffer(AudioDeviceModule::BufferType& type,
161                                  uint16_t& sizeMS) const;
162    virtual int32_t PlayoutDelay(uint16_t& delayMS) const;
163    virtual int32_t RecordingDelay(uint16_t& delayMS) const;
164
165    // CPU load
166    virtual int32_t CPULoad(uint16_t& load) const;
167
168    virtual bool PlayoutWarning() const;
169    virtual bool PlayoutError() const;
170    virtual bool RecordingWarning() const;
171    virtual bool RecordingError() const;
172    virtual void ClearPlayoutWarning();
173    virtual void ClearPlayoutError();
174    virtual void ClearRecordingWarning();
175    virtual void ClearRecordingError();
176
177    virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer);
178
179private:
180    virtual int32_t MicrophoneIsAvailable(bool& available);
181    virtual int32_t SpeakerIsAvailable(bool& available);
182
183    void Lock()
184    {
185        _critSect.Enter();
186    }
187    ;
188    void UnLock()
189    {
190        _critSect.Leave();
191    }
192    ;
193    int32_t Id()
194    {
195        return _id;
196    }
197
198    static void AtomicSet32(int32_t* theValue, int32_t newValue);
199    static int32_t AtomicGet32(int32_t* theValue);
200
201    static void logCAMsg(const TraceLevel level,
202                         const TraceModule module,
203                         const int32_t id, const char *msg,
204                         const char *err);
205
206    int32_t GetNumberDevices(const AudioObjectPropertyScope scope,
207                             AudioDeviceID scopedDeviceIds[],
208                             const uint32_t deviceListLength);
209
210    int32_t GetDeviceName(const AudioObjectPropertyScope scope,
211                          const uint16_t index, char* name);
212
213    int32_t InitDevice(uint16_t userDeviceIndex,
214                       AudioDeviceID& deviceId, bool isInput);
215
216    static OSStatus
217        objectListenerProc(AudioObjectID objectId, UInt32 numberAddresses,
218                           const AudioObjectPropertyAddress addresses[],
219                           void* clientData);
220
221    OSStatus
222        implObjectListenerProc(AudioObjectID objectId, UInt32 numberAddresses,
223                               const AudioObjectPropertyAddress addresses[]);
224
225    int32_t HandleDeviceChange();
226
227    int32_t
228        HandleStreamFormatChange(AudioObjectID objectId,
229                                 AudioObjectPropertyAddress propertyAddress);
230
231    int32_t
232        HandleDataSourceChange(AudioObjectID objectId,
233                               AudioObjectPropertyAddress propertyAddress);
234
235    int32_t
236        HandleProcessorOverload(AudioObjectPropertyAddress propertyAddress);
237
238    static OSStatus deviceIOProc(AudioDeviceID device,
239                                 const AudioTimeStamp *now,
240                                 const AudioBufferList *inputData,
241                                 const AudioTimeStamp *inputTime,
242                                 AudioBufferList *outputData,
243                                 const AudioTimeStamp* outputTime,
244                                 void *clientData);
245
246    static OSStatus
247        outConverterProc(AudioConverterRef audioConverter,
248                         UInt32 *numberDataPackets, AudioBufferList *data,
249                         AudioStreamPacketDescription **dataPacketDescription,
250                         void *userData);
251
252    static OSStatus inDeviceIOProc(AudioDeviceID device,
253                                   const AudioTimeStamp *now,
254                                   const AudioBufferList *inputData,
255                                   const AudioTimeStamp *inputTime,
256                                   AudioBufferList *outputData,
257                                   const AudioTimeStamp *outputTime,
258                                   void *clientData);
259
260    static OSStatus
261        inConverterProc(AudioConverterRef audioConverter,
262                        UInt32 *numberDataPackets, AudioBufferList *data,
263                        AudioStreamPacketDescription **dataPacketDescription,
264                        void *inUserData);
265
266    OSStatus implDeviceIOProc(const AudioBufferList *inputData,
267                              const AudioTimeStamp *inputTime,
268                              AudioBufferList *outputData,
269                              const AudioTimeStamp *outputTime);
270
271    OSStatus implOutConverterProc(UInt32 *numberDataPackets,
272                                  AudioBufferList *data);
273
274    OSStatus implInDeviceIOProc(const AudioBufferList *inputData,
275                                const AudioTimeStamp *inputTime);
276
277    OSStatus implInConverterProc(UInt32 *numberDataPackets,
278                                 AudioBufferList *data);
279
280    static bool RunCapture(void*);
281    static bool RunRender(void*);
282    bool CaptureWorkerThread();
283    bool RenderWorkerThread();
284
285    bool KeyPressed();
286
287    AudioDeviceBuffer* _ptrAudioBuffer;
288
289    CriticalSectionWrapper& _critSect;
290
291    EventWrapper& _stopEventRec;
292    EventWrapper& _stopEvent;
293
294    ThreadWrapper* _captureWorkerThread;
295    ThreadWrapper* _renderWorkerThread;
296    uint32_t _captureWorkerThreadId;
297    uint32_t _renderWorkerThreadId;
298
299    int32_t _id;
300
301    AudioMixerManagerMac _mixerManager;
302
303    uint16_t _inputDeviceIndex;
304    uint16_t _outputDeviceIndex;
305    AudioDeviceID _inputDeviceID;
306    AudioDeviceID _outputDeviceID;
307#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
308    AudioDeviceIOProcID _inDeviceIOProcID;
309    AudioDeviceIOProcID _deviceIOProcID;
310#endif
311    bool _inputDeviceIsSpecified;
312    bool _outputDeviceIsSpecified;
313
314    uint8_t _recChannels;
315    uint8_t _playChannels;
316
317    Float32* _captureBufData;
318    SInt16* _renderBufData;
319
320    SInt16 _renderConvertData[PLAY_BUF_SIZE_IN_SAMPLES];
321
322    AudioDeviceModule::BufferType _playBufType;
323
324    bool _initialized;
325    bool _isShutDown;
326    bool _recording;
327    bool _playing;
328    bool _recIsInitialized;
329    bool _playIsInitialized;
330    bool _AGC;
331
332    // Atomically set varaibles
333    int32_t _renderDeviceIsAlive;
334    int32_t _captureDeviceIsAlive;
335
336    bool _twoDevices;
337    bool _doStop; // For play if not shared device or play+rec if shared device
338    bool _doStopRec; // For rec if not shared device
339    bool _macBookPro;
340    bool _macBookProPanRight;
341
342    AudioConverterRef _captureConverter;
343    AudioConverterRef _renderConverter;
344
345    AudioStreamBasicDescription _outStreamFormat;
346    AudioStreamBasicDescription _outDesiredFormat;
347    AudioStreamBasicDescription _inStreamFormat;
348    AudioStreamBasicDescription _inDesiredFormat;
349
350    uint32_t _captureLatencyUs;
351    uint32_t _renderLatencyUs;
352
353    // Atomically set variables
354    mutable int32_t _captureDelayUs;
355    mutable int32_t _renderDelayUs;
356
357    int32_t _renderDelayOffsetSamples;
358
359    uint16_t _playBufDelayFixed; // fixed playback delay
360
361    uint16_t _playWarning;
362    uint16_t _playError;
363    uint16_t _recWarning;
364    uint16_t _recError;
365
366    PaUtilRingBuffer* _paCaptureBuffer;
367    PaUtilRingBuffer* _paRenderBuffer;
368
369    semaphore_t _renderSemaphore;
370    semaphore_t _captureSemaphore;
371
372    int _captureBufSizeSamples;
373    int _renderBufSizeSamples;
374
375    // Typing detection
376    // 0x5c is key "9", after that comes function keys.
377    bool prev_key_state_[0x5d];
378};
379
380}  // namespace webrtc
381
382#endif  // MODULES_AUDIO_DEVICE_MAIN_SOURCE_MAC_AUDIO_DEVICE_MAC_H_
383