1 // This file is part of Desktop App Toolkit,
2 // a set of libraries for developing nice desktop applications.
3 //
4 // For license and copyright information please follow this link:
5 // https://github.com/desktop-app/legal/blob/master/LEGAL
6 //
7 #pragma once
8 
9 #include "modules/audio_device/include/audio_device.h"
10 #include "modules/audio_device/audio_device_buffer.h"
11 
12 #include <crl/crl_time.h>
13 #include <al.h>
14 #include <alc.h>
15 #include <atomic>
16 
17 namespace rtc {
18 class Thread;
19 } // namespace rtc
20 
21 namespace Webrtc::details {
22 
23 class AudioDeviceOpenAL : public webrtc::AudioDeviceModule {
24 public:
25 	explicit AudioDeviceOpenAL(webrtc::TaskQueueFactory *taskQueueFactory);
26 	~AudioDeviceOpenAL();
27 
28 	int32_t ActiveAudioLayer(AudioLayer *audioLayer) const override;
29 	int32_t RegisterAudioCallback(
30 		webrtc::AudioTransport *audioCallback) override;
31 
32 	// Main initializaton and termination
33 	int32_t Init() override;
34 	int32_t Terminate() override;
35 	bool Initialized() const override;
36 
37 	// Device enumeration
38 	int16_t PlayoutDevices() override;
39 	int16_t RecordingDevices() override;
40 	int32_t PlayoutDeviceName(uint16_t index,
41 		char name[webrtc::kAdmMaxDeviceNameSize],
42 		char guid[webrtc::kAdmMaxGuidSize]) override;
43 	int32_t RecordingDeviceName(uint16_t index,
44 		char name[webrtc::kAdmMaxDeviceNameSize],
45 		char guid[webrtc::kAdmMaxGuidSize]) override;
46 
47 	// Device selection
48 	int32_t SetPlayoutDevice(uint16_t index) override;
49 	int32_t SetPlayoutDevice(WindowsDeviceType device) override;
50 	int32_t SetRecordingDevice(uint16_t index) override;
51 	int32_t SetRecordingDevice(WindowsDeviceType device) override;
52 
53 	// Audio transport initialization
54 	int32_t PlayoutIsAvailable(bool *available) override;
55 	int32_t InitPlayout() override;
56 	bool PlayoutIsInitialized() const override;
57 	int32_t RecordingIsAvailable(bool *available) override;
58 	int32_t InitRecording() override;
59 	bool RecordingIsInitialized() const override;
60 
61 	// Audio transport control
62 	int32_t StartPlayout() override;
63 	int32_t StopPlayout() override;
64 	bool Playing() const override;
65 	int32_t StartRecording() override;
66 	int32_t StopRecording() override;
67 	bool Recording() const override;
68 
69 	// Audio mixer initialization
70 	int32_t InitSpeaker() override;
71 	bool SpeakerIsInitialized() const override;
72 	int32_t InitMicrophone() override;
73 	bool MicrophoneIsInitialized() const override;
74 
75 	// Speaker volume controls
76 	int32_t SpeakerVolumeIsAvailable(bool *available) override;
77 	int32_t SetSpeakerVolume(uint32_t volume) override;
78 	int32_t SpeakerVolume(uint32_t *volume) const override;
79 	int32_t MaxSpeakerVolume(uint32_t *maxVolume) const override;
80 	int32_t MinSpeakerVolume(uint32_t *minVolume) const override;
81 
82 	// Microphone volume controls
83 	int32_t MicrophoneVolumeIsAvailable(bool *available) override;
84 	int32_t SetMicrophoneVolume(uint32_t volume) override;
85 	int32_t MicrophoneVolume(uint32_t *volume) const override;
86 	int32_t MaxMicrophoneVolume(uint32_t *maxVolume) const override;
87 	int32_t MinMicrophoneVolume(uint32_t *minVolume) const override;
88 
89 	// Microphone mute control
90 	int32_t MicrophoneMuteIsAvailable(bool *available) override;
91 	int32_t SetMicrophoneMute(bool enable) override;
92 	int32_t MicrophoneMute(bool *enabled) const override;
93 
94 	// Speaker mute control
95 	int32_t SpeakerMuteIsAvailable(bool *available) override;
96 	int32_t SetSpeakerMute(bool enable) override;
97 	int32_t SpeakerMute(bool *enabled) const override;
98 
99 	// Stereo support
100 	int32_t StereoPlayoutIsAvailable(bool *available) const override;
101 	int32_t SetStereoPlayout(bool enable) override;
102 	int32_t StereoPlayout(bool *enabled) const override;
103 	int32_t StereoRecordingIsAvailable(bool *available) const override;
104 	int32_t SetStereoRecording(bool enable) override;
105 	int32_t StereoRecording(bool *enabled) const override;
106 
107 	// Delay information and control
108 	int32_t PlayoutDelay(uint16_t *delayMS) const override;
109 
110 	// Only supported on Android.
111 	bool BuiltInAECIsAvailable() const override;
112 	bool BuiltInAGCIsAvailable() const override;
113 	bool BuiltInNSIsAvailable() const override;
114 
115 	// Enables the built-in audio effects. Only supported on Android.
116 	int32_t EnableBuiltInAEC(bool enable) override;
117 	int32_t EnableBuiltInAGC(bool enable) override;
118 	int32_t EnableBuiltInNS(bool enable) override;
119 
120 private:
121 	struct Data;
122 	struct ExactQueuedTime {
123 		crl::time now = 0;
124 		crl::time queued = 0;
125 	};
126 
127 	template <typename Callback>
128 	std::invoke_result_t<Callback> sync(Callback &&callback);
129 
130 	void openRecordingDevice();
131 	void openPlayoutDevice();
132 	void closeRecordingDevice();
133 
134 	// NB! stopPlayingOnThread should be called before this,
135 	// to clear the thread local context and event callback.
136 	void closePlayoutDevice();
137 
138 	int restartPlayout();
139 	int restartRecording();
140 	void restartRecordingQueued();
141 	void restartPlayoutQueued();
142 	bool validateRecordingDeviceId();
143 	bool validatePlayoutDeviceId();
144 
145 	void ensureThreadStarted();
146 	void startCaptureOnThread();
147 	void stopCaptureOnThread();
148 	void startPlayingOnThread();
149 
150 	// NB! closePlayoutDevice should be called after this, so that next time
151 	// we start playing, we set the thread local context and event callback.
152 	void stopPlayingOnThread();
153 
154 	void processData();
155 	void processRecordingData();
156 	void processPlayoutData();
157 	bool processRecordedPart(bool firstInCycle);
158 
159 	void clearProcessedBuffers();
160 	bool clearProcessedBuffer();
161 	void unqueueAllBuffers();
162 
163 	void handleEvent(
164 		ALenum eventType,
165 		ALuint object,
166 		ALuint param,
167 		ALsizei length,
168 		const ALchar *message);
169 
170 	[[nodiscard]] crl::time countExactQueuedMsForLatency(
171 		crl::time now,
172 		bool playing);
173 	[[nodiscard]] crl::time queryRecordingLatencyMs();
174 
175 	rtc::Thread *_thread = nullptr;
176 	webrtc::AudioDeviceBuffer _audioDeviceBuffer;
177 	std::unique_ptr<Data> _data;
178 
179 	ALCdevice *_playoutDevice = nullptr;
180 	ALCcontext *_playoutContext = nullptr;
181 	std::string _playoutDeviceId;
182 	crl::time _playoutLatency = 0;
183 	int _playoutChannels = 2;
184 	bool _playoutInitialized = false;
185 	bool _playoutFailed = false;
186 
187 	ALCdevice *_recordingDevice = nullptr;
188 	std::string _recordingDeviceId;
189 	crl::time _recordingLatency = 0;
190 	bool _recordingInitialized = false;
191 	bool _recordingFailed = false;
192 
193 	bool _speakerInitialized = false;
194 	bool _microphoneInitialized = false;
195 	bool _initialized = false;
196 
197 };
198 
199 } // namespace Webrtc::details
200