[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / platform / audio / mac / AudioSessionMac.cpp
1 /*
2  * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "AudioSession.h"
28
29 #if USE(AUDIO_SESSION) && PLATFORM(MAC)
30
31 #include "FloatConversion.h"
32 #include "Logging.h"
33 #include "NotImplemented.h"
34 #include <CoreAudio/AudioHardware.h>
35 #include <wtf/MainThread.h>
36 #include <wtf/text/WTFString.h>
37
38 namespace WebCore {
39
40 static AudioDeviceID defaultDevice()
41 {
42     AudioDeviceID deviceID = kAudioDeviceUnknown;
43     UInt32 infoSize = sizeof(deviceID);
44
45     AudioObjectPropertyAddress defaultOutputDeviceAddress = {
46         kAudioHardwarePropertyDefaultOutputDevice,
47         kAudioObjectPropertyScopeGlobal,
48         kAudioObjectPropertyElementMaster };
49     OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &defaultOutputDeviceAddress, 0, 0, &infoSize, (void*)&deviceID);
50     if (result)
51         return 0; // error
52     return deviceID;
53 }
54
55 class AudioSessionPrivate {
56     WTF_MAKE_FAST_ALLOCATED;
57 public:
58     explicit AudioSessionPrivate(bool mutedState)
59         : lastMutedState(mutedState) { }
60     bool lastMutedState;
61     AudioSession::CategoryType category { AudioSession::None };
62 };
63
64 AudioSession::AudioSession()
65     : m_private(makeUnique<AudioSessionPrivate>(isMuted()))
66 {
67 }
68
69 AudioSession::~AudioSession() = default;
70
71 AudioSession::CategoryType AudioSession::category() const
72 {
73     return m_private->category;
74 }
75
76 void AudioSession::setCategory(CategoryType category, RouteSharingPolicy)
77 {
78     m_private->category = category;
79 }
80
81 AudioSession::CategoryType AudioSession::categoryOverride() const
82 {
83     notImplemented();
84     return None;
85 }
86
87 void AudioSession::setCategoryOverride(CategoryType)
88 {
89     notImplemented();
90 }
91
92 float AudioSession::sampleRate() const
93 {
94     Float64 nominalSampleRate;
95     UInt32 nominalSampleRateSize = sizeof(Float64);
96
97     AudioObjectPropertyAddress nominalSampleRateAddress = {
98         kAudioDevicePropertyNominalSampleRate,
99         kAudioObjectPropertyScopeGlobal,
100         kAudioObjectPropertyElementMaster };
101     OSStatus result = AudioObjectGetPropertyData(defaultDevice(), &nominalSampleRateAddress, 0, 0, &nominalSampleRateSize, (void*)&nominalSampleRate);
102     if (result)
103         return 0;
104
105     return narrowPrecisionToFloat(nominalSampleRate);
106 }
107
108 size_t AudioSession::bufferSize() const
109 {
110     UInt32 bufferSize;
111     UInt32 bufferSizeSize = sizeof(bufferSize);
112
113     AudioObjectPropertyAddress bufferSizeAddress = {
114         kAudioDevicePropertyBufferFrameSize,
115         kAudioObjectPropertyScopeGlobal,
116         kAudioObjectPropertyElementMaster };
117     OSStatus result = AudioObjectGetPropertyData(defaultDevice(), &bufferSizeAddress, 0, 0, &bufferSizeSize, &bufferSize);
118
119     if (result)
120         return 0;
121     return bufferSize;
122 }
123
124 size_t AudioSession::numberOfOutputChannels() const
125 {
126     notImplemented();
127     return 0;
128 }
129
130 bool AudioSession::tryToSetActiveInternal(bool)
131 {
132     notImplemented();
133     return true;
134 }
135
136 RouteSharingPolicy AudioSession::routeSharingPolicy() const
137 {
138     return RouteSharingPolicy::Default;
139 }
140
141 String AudioSession::routingContextUID() const
142 {
143     return emptyString();
144 }
145
146 size_t AudioSession::preferredBufferSize() const
147 {
148     UInt32 bufferSize;
149     UInt32 bufferSizeSize = sizeof(bufferSize);
150
151     AudioObjectPropertyAddress preferredBufferSizeAddress = {
152         kAudioDevicePropertyBufferFrameSize,
153         kAudioObjectPropertyScopeGlobal,
154         kAudioObjectPropertyElementMaster };
155     OSStatus result = AudioObjectGetPropertyData(defaultDevice(), &preferredBufferSizeAddress, 0, 0, &bufferSizeSize, &bufferSize);
156
157     if (result)
158         return 0;
159     return bufferSize;
160 }
161
162 void AudioSession::setPreferredBufferSize(size_t bufferSize)
163 {
164     AudioValueRange bufferSizeRange = {0, 0};
165     UInt32 bufferSizeRangeSize = sizeof(AudioValueRange);
166     AudioObjectPropertyAddress bufferSizeRangeAddress = {
167         kAudioDevicePropertyBufferFrameSizeRange,
168         kAudioObjectPropertyScopeGlobal,
169         kAudioObjectPropertyElementMaster
170     };
171     OSStatus result = AudioObjectGetPropertyData(defaultDevice(), &bufferSizeRangeAddress, 0, 0, &bufferSizeRangeSize, &bufferSizeRange);
172     if (result)
173         return;
174
175     size_t minBufferSize = static_cast<size_t>(bufferSizeRange.mMinimum);
176     size_t maxBufferSize = static_cast<size_t>(bufferSizeRange.mMaximum);
177     UInt32 bufferSizeOut = std::min(maxBufferSize, std::max(minBufferSize, bufferSize));
178
179     AudioObjectPropertyAddress preferredBufferSizeAddress = {
180         kAudioDevicePropertyBufferFrameSize,
181         kAudioObjectPropertyScopeGlobal,
182         kAudioObjectPropertyElementMaster };
183
184     result = AudioObjectSetPropertyData(defaultDevice(), &preferredBufferSizeAddress, 0, 0, sizeof(bufferSizeOut), (void*)&bufferSizeOut);
185
186 #if LOG_DISABLED
187     UNUSED_PARAM(result);
188 #else
189     if (result)
190         LOG(Media, "AudioSession::setPreferredBufferSize(%zu) - failed with error %d", bufferSize, static_cast<int>(result));
191     else
192         LOG(Media, "AudioSession::setPreferredBufferSize(%zu)", bufferSize);
193 #endif
194 }
195
196 bool AudioSession::isMuted() const
197 {
198     UInt32 mute = 0;
199     UInt32 muteSize = sizeof(mute);
200     AudioObjectPropertyAddress muteAddress = { kAudioDevicePropertyMute, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
201     AudioObjectGetPropertyData(defaultDevice(), &muteAddress, 0, nullptr, &muteSize, &mute);
202     
203     switch (mute) {
204     case 0:
205         return false;
206     case 1:
207         return true;
208     default:
209         ASSERT_NOT_REACHED();
210         return false;
211     }
212 }
213
214 static OSStatus handleMutePropertyChange(AudioObjectID, UInt32, const AudioObjectPropertyAddress*, void* inClientData)
215 {
216     callOnMainThread([inClientData] {
217         reinterpret_cast<AudioSession*>(inClientData)->handleMutedStateChange();
218     });
219     return noErr;
220 }
221
222 void AudioSession::handleMutedStateChange()
223 {
224     if (!m_private)
225         return;
226
227     bool isCurrentlyMuted = isMuted();
228     if (m_private->lastMutedState == isCurrentlyMuted)
229         return;
230
231     for (auto* observer : m_observers)
232         observer->hardwareMutedStateDidChange(this);
233
234     m_private->lastMutedState = isCurrentlyMuted;
235 }
236
237 void AudioSession::addMutedStateObserver(MutedStateObserver* observer)
238 {
239     m_observers.add(observer);
240
241     if (m_observers.size() > 1)
242         return;
243
244     AudioObjectPropertyAddress muteAddress = { kAudioDevicePropertyMute, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
245     AudioObjectAddPropertyListener(defaultDevice(), &muteAddress, handleMutePropertyChange, this);
246 }
247
248 void AudioSession::removeMutedStateObserver(MutedStateObserver* observer)
249 {
250     if (m_observers.size() == 1) {
251         AudioObjectPropertyAddress muteAddress = { kAudioDevicePropertyMute, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
252         AudioObjectRemovePropertyListener(defaultDevice(), &muteAddress, handleMutePropertyChange, this);
253     }
254
255     m_observers.remove(observer);
256 }
257
258 }
259
260 #endif // USE(AUDIO_SESSION) && PLATFORM(MAC)