2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "AudioSession.h"
29 #if USE(AUDIO_SESSION) && PLATFORM(MAC)
31 #include "FloatConversion.h"
33 #include "NotImplemented.h"
34 #include <CoreAudio/AudioHardware.h>
35 #include <wtf/MainThread.h>
39 static AudioDeviceID defaultDevice()
41 AudioDeviceID deviceID = kAudioDeviceUnknown;
42 UInt32 infoSize = sizeof(deviceID);
44 AudioObjectPropertyAddress defaultOutputDeviceAddress = {
45 kAudioHardwarePropertyDefaultOutputDevice,
46 kAudioObjectPropertyScopeGlobal,
47 kAudioObjectPropertyElementMaster };
48 OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &defaultOutputDeviceAddress, 0, 0, &infoSize, (void*)&deviceID);
54 class AudioSessionPrivate {
56 AudioSessionPrivate(bool mutedState)
57 : lastMutedState(mutedState) { }
61 AudioSession::AudioSession()
62 : m_private(std::make_unique<AudioSessionPrivate>(isMuted()))
66 AudioSession::~AudioSession()
70 AudioSession::CategoryType AudioSession::category() const
76 void AudioSession::setCategory(CategoryType)
81 AudioSession::CategoryType AudioSession::categoryOverride() const
87 void AudioSession::setCategoryOverride(CategoryType)
92 float AudioSession::sampleRate() const
94 Float64 nominalSampleRate;
95 UInt32 nominalSampleRateSize = sizeof(Float64);
97 AudioObjectPropertyAddress nominalSampleRateAddress = {
98 kAudioDevicePropertyNominalSampleRate,
99 kAudioObjectPropertyScopeGlobal,
100 kAudioObjectPropertyElementMaster };
101 OSStatus result = AudioObjectGetPropertyData(defaultDevice(), &nominalSampleRateAddress, 0, 0, &nominalSampleRateSize, (void*)&nominalSampleRate);
105 return narrowPrecisionToFloat(nominalSampleRate);
108 size_t AudioSession::bufferSize() const
111 UInt32 bufferSizeSize = sizeof(bufferSize);
113 AudioObjectPropertyAddress bufferSizeAddress = {
114 kAudioDevicePropertyBufferFrameSize,
115 kAudioObjectPropertyScopeGlobal,
116 kAudioObjectPropertyElementMaster };
117 OSStatus result = AudioObjectGetPropertyData(defaultDevice(), &bufferSizeAddress, 0, 0, &bufferSizeSize, &bufferSize);
124 size_t AudioSession::numberOfOutputChannels() const
130 bool AudioSession::tryToSetActive(bool)
136 size_t AudioSession::preferredBufferSize() const
139 UInt32 bufferSizeSize = sizeof(bufferSize);
141 AudioObjectPropertyAddress preferredBufferSizeAddress = {
142 kAudioDevicePropertyBufferFrameSizeRange,
143 kAudioObjectPropertyScopeGlobal,
144 kAudioObjectPropertyElementMaster };
145 OSStatus result = AudioObjectGetPropertyData(defaultDevice(), &preferredBufferSizeAddress, 0, 0, &bufferSizeSize, &bufferSize);
152 void AudioSession::setPreferredBufferSize(size_t bufferSize)
154 AudioValueRange bufferSizeRange = {0, 0};
155 UInt32 bufferSizeRangeSize = sizeof(AudioValueRange);
156 AudioObjectPropertyAddress bufferSizeRangeAddress = {
157 kAudioDevicePropertyBufferFrameSizeRange,
158 kAudioObjectPropertyScopeGlobal,
159 kAudioObjectPropertyElementMaster
161 OSStatus result = AudioObjectGetPropertyData(defaultDevice(), &bufferSizeRangeAddress, 0, 0, &bufferSizeRangeSize, &bufferSizeRange);
165 size_t minBufferSize = static_cast<size_t>(bufferSizeRange.mMinimum);
166 size_t maxBufferSize = static_cast<size_t>(bufferSizeRange.mMaximum);
167 UInt32 bufferSizeOut = std::min(maxBufferSize, std::max(minBufferSize, bufferSize));
169 AudioObjectPropertyAddress preferredBufferSizeAddress = {
170 kAudioDevicePropertyBufferFrameSize,
171 kAudioObjectPropertyScopeGlobal,
172 kAudioObjectPropertyElementMaster };
174 result = AudioObjectSetPropertyData(defaultDevice(), &preferredBufferSizeAddress, 0, 0, sizeof(bufferSizeOut), (void*)&bufferSizeOut);
177 UNUSED_PARAM(result);
180 LOG(Media, "AudioSession::setPreferredBufferSize(%zu) - failed with error %d", bufferSize, static_cast<int>(result));
182 LOG(Media, "AudioSession::setPreferredBufferSize(%zu)", bufferSize);
186 bool AudioSession::isMuted() const
189 UInt32 muteSize = sizeof(mute);
190 AudioObjectPropertyAddress muteAddress = { kAudioDevicePropertyMute, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
191 AudioObjectGetPropertyData(defaultDevice(), &muteAddress, 0, nullptr, &muteSize, &mute);
199 ASSERT_NOT_REACHED();
204 static OSStatus handleMutePropertyChange(AudioObjectID, UInt32, const AudioObjectPropertyAddress*, void* inClientData)
206 callOnMainThread([inClientData] {
207 reinterpret_cast<AudioSession*>(inClientData)->handleMutedStateChange();
212 void AudioSession::handleMutedStateChange()
217 bool isCurrentlyMuted = isMuted();
218 if (m_private->lastMutedState == isCurrentlyMuted)
221 for (auto* observer : m_observers)
222 observer->hardwareMutedStateDidChange(this);
224 m_private->lastMutedState = isCurrentlyMuted;
227 void AudioSession::addMutedStateObserver(MutedStateObserver* observer)
229 m_observers.add(observer);
231 if (m_observers.size() > 1)
234 AudioObjectPropertyAddress muteAddress = { kAudioDevicePropertyMute, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
235 AudioObjectAddPropertyListener(defaultDevice(), &muteAddress, handleMutePropertyChange, this);
238 void AudioSession::removeMutedStateObserver(MutedStateObserver* observer)
240 if (m_observers.size() == 1) {
241 AudioObjectPropertyAddress muteAddress = { kAudioDevicePropertyMute, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
242 AudioObjectRemovePropertyListener(defaultDevice(), &muteAddress, handleMutePropertyChange, this);
245 m_observers.remove(observer);
250 #endif // USE(AUDIO_SESSION) && PLATFORM(MAC)