Diff
Modified: trunk/Source/WebCore/ChangeLog (147493 => 147494)
--- trunk/Source/WebCore/ChangeLog 2013-04-02 20:47:12 UTC (rev 147493)
+++ trunk/Source/WebCore/ChangeLog 2013-04-02 20:49:19 UTC (rev 147494)
@@ -1,5 +1,72 @@
2013-04-02 Jer Noble <[email protected]>
+ Add platform AudioSession and iOS platform-specific code.
+ https://bugs.webkit.org/show_bug.cgi?id=113813
+ <rdar://problem/11701792>
+
+ Reviewed by Eric Carlson.
+
+ Replace the deprecated AudioToolbox AudioSession APIs with the new AVAudioSession API.
+ To protect against exposing platform specific intrinsics to cross-platform code, add a
+ platform generic class AudioSession, with port-specific implementations. A default
+ implementation is provided.
+
+ Add a new listener interface to receive interruption notifications:
+ * platform/audio/AudioSessionListener.h: Added.
+ (WebCore::AudioSessionListener::AudioSessionListener):
+ (WebCore::AudioSessionListener::~AudioSessionListener):
+
+ Add a platform generic AudioSession class:
+ * platform/audio/AudioSession.cpp: Added.
+ (AudioSession::sharedSession): AudioSession is a singleton object, and this is its accessor.
+ (AudioSession::addListener): Add the parameter to the listeners set.
+ (AudioSession::removeListener): Remove the parameter from the listers set.
+ (AudioSession::beganAudioInterruption): Iterate over the parameters.
+ (AudioSession::endedAudioInterruption): Ditto.
+ (AudioSession::AudioSession): Empty stub.
+ (AudioSession::~AudioSession): Ditto.
+ (AudioSession::setCategory): Ditto.
+ (AudioSession::category): Ditto.
+ (AudioSession::sampleRate): Ditto.
+ (AudioSession::numberOfOutputChannels): Ditto.
+ (AudioSession::setActive): Ditto.
+ (AudioSession::preferredBufferDuration): Ditto.
+ (AudioSession::setPreferredBufferDuration): Ditto.
+ * platform/audio/AudioSession.h: Added.
+
+ Add IOS-specific AudioSession implementation:
+ * platform/audio/ios/AudioSessionIOS.mm: Added.
+ (-[WebAudioSessionHelper initWithCallback:WebCore::]): Register for interruption notifications.
+ (-[WebAudioSessionHelper dealloc]): Unregister for interruption notifications.
+ (-[WebAudioSessionHelper interruption:]): Pass to AudioSession.
+ (WebCore::AudioSessionPrivate::AudioSessionPrivate): Private storage for AudioSessionIOS.
+ (WebCore::AudioSession::AudioSession): Create AudioSessionPrivate and WebAudioSessionHelper.
+ (WebCore::AudioSession::~AudioSession): Simple destructor.
+ (WebCore::AudioSession::setCategory): Check the current categoryOverride, and refuse to overwrite
+ "MediaPlayback" with "AmbientSound".
+ (WebCore::AudioSession::setCategoryOverride): Simple setter.
+ (WebCore::AudioSession::categoryOverride): Simple getter.
+ (WebCore::AudioSession::category): Pass to AVAudioSession.
+ (WebCore::AudioSession::sampleRate): Ditto.
+ (WebCore::AudioSession::numberOfOutputChannels): Ditto.
+ (WebCore::AudioSession::setActive): Ditto.
+ (WebCore::AudioSession::preferredBufferDuration): Ditto.
+ (WebCore::AudioSession::setPreferredBufferDuration): Ditto.
+
+ Use the new AudioSession class in place of explicit AudioToolbox or AVAudioSession calls:
+ * platform/audio/ios/AudioDestinationIOS.cpp:
+ (WebCore::AudioDestination::hardwareSampleRate): Pass to AudioSession.
+ (WebCore::AudioDestination::maxChannelCount): Ditto.
+ (WebCore::AudioDestinationIOS::AudioDestinationIOS): Register for listeners and activate.
+ (WebCore::AudioDestinationIOS::~AudioDestinationIOS): Unregister and deactivate.
+ (WebCore::AudioDestinationIOS::configure): Use AudioSession to set the buffer length.
+ * platform/audio/ios/AudioDestinationIOS.h:
+
+ Add the new files to the project:
+ * WebCore.xcodeproj/project.pbxproj:
+
+2013-04-02 Jer Noble <[email protected]>
+
Upstream AudioDestinationIOS.
https://bugs.webkit.org/show_bug.cgi?id=113806
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (147493 => 147494)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2013-04-02 20:47:12 UTC (rev 147493)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2013-04-02 20:49:19 UTC (rev 147494)
@@ -6037,6 +6037,9 @@
CD82030D1395AB6A00F956C6 /* WebVideoFullscreenHUDWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD8203091395AB6A00F956C6 /* WebVideoFullscreenHUDWindowController.mm */; };
CD8203101395ACE700F956C6 /* WebWindowAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = CD82030E1395ACE700F956C6 /* WebWindowAnimation.h */; settings = {ATTRIBUTES = (Private, ); }; };
CD8203111395ACE700F956C6 /* WebWindowAnimation.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD82030F1395ACE700F956C6 /* WebWindowAnimation.mm */; };
+ CDA79824170A258300D45C55 /* AudioSession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDA79823170A258300D45C55 /* AudioSession.cpp */; };
+ CDA79827170A279100D45C55 /* AudioSessionIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDA79825170A279000D45C55 /* AudioSessionIOS.mm */; };
+ CDA7982A170A3D0000D45C55 /* AudioSession.h in Headers */ = {isa = PBXBuildFile; fileRef = CDA79821170A22DC00D45C55 /* AudioSession.h */; settings = {ATTRIBUTES = (Private, ); }; };
CDA98DA31601464100FEA3B1 /* JSMediaKeyError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDA98D9B160128A500FEA3B1 /* JSMediaKeyError.cpp */; };
CDA98DD816025BEF00FEA3B1 /* MediaKeyMessageEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDA98DD516025BED00FEA3B1 /* MediaKeyMessageEvent.cpp */; };
CDA98DDF16026A3700FEA3B1 /* JSMediaKeyMessageEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDA98DDB16026A1800FEA3B1 /* JSMediaKeyMessageEvent.cpp */; };
@@ -13724,6 +13727,10 @@
CD8203091395AB6A00F956C6 /* WebVideoFullscreenHUDWindowController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebVideoFullscreenHUDWindowController.mm; sourceTree = "<group>"; };
CD82030E1395ACE700F956C6 /* WebWindowAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebWindowAnimation.h; sourceTree = "<group>"; };
CD82030F1395ACE700F956C6 /* WebWindowAnimation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebWindowAnimation.mm; sourceTree = "<group>"; };
+ CDA79821170A22DC00D45C55 /* AudioSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioSession.h; sourceTree = "<group>"; };
+ CDA79822170A24F400D45C55 /* AudioSessionListener.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioSessionListener.h; sourceTree = "<group>"; };
+ CDA79823170A258300D45C55 /* AudioSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioSession.cpp; sourceTree = "<group>"; };
+ CDA79825170A279000D45C55 /* AudioSessionIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AudioSessionIOS.mm; path = ios/AudioSessionIOS.mm; sourceTree = "<group>"; };
CDA98D9B160128A500FEA3B1 /* JSMediaKeyError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMediaKeyError.cpp; sourceTree = "<group>"; };
CDA98D9C160128A500FEA3B1 /* JSMediaKeyError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSMediaKeyError.h; sourceTree = "<group>"; };
CDA98DC216014EEE00FEA3B1 /* MediaKeyNeededEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MediaKeyNeededEvent.cpp; path = Modules/encryptedmedia/MediaKeyNeededEvent.cpp; sourceTree = "<group>"; };
@@ -21887,6 +21894,7 @@
children = (
CD0EEE0B14743E35003EAFA2 /* AudioDestinationIOS.cpp */,
CD0EEE0A14743E34003EAFA2 /* AudioDestinationIOS.h */,
+ CDA79825170A279000D45C55 /* AudioSessionIOS.mm */,
);
name = ios;
sourceTree = "<group>";
@@ -23222,6 +23230,9 @@
FD31605012B026F700C1A359 /* AudioResampler.h */,
FD31605112B026F700C1A359 /* AudioResamplerKernel.cpp */,
FD31605212B026F700C1A359 /* AudioResamplerKernel.h */,
+ CDA79821170A22DC00D45C55 /* AudioSession.h */,
+ CDA79823170A258300D45C55 /* AudioSession.cpp */,
+ CDA79822170A24F400D45C55 /* AudioSessionListener.h */,
FD31605312B026F700C1A359 /* AudioSourceProvider.h */,
FD62F52D145898D80094B0ED /* AudioSourceProviderClient.h */,
FD31605412B026F700C1A359 /* AudioUtilities.cpp */,
@@ -23472,6 +23483,7 @@
FD31608612B026F700C1A359 /* AudioResampler.h in Headers */,
FD31608812B026F700C1A359 /* AudioResamplerKernel.h in Headers */,
FD8C46EC154608E700A5910C /* AudioScheduledSourceNode.h in Headers */,
+ CDA7982A170A3D0000D45C55 /* AudioSession.h in Headers */,
FD31602212B0267600C1A359 /* AudioSourceNode.h in Headers */,
FD31608912B026F700C1A359 /* AudioSourceProvider.h in Headers */,
FD62F52E145898D80094B0ED /* AudioSourceProviderClient.h in Headers */,
@@ -27216,6 +27228,8 @@
FD31608512B026F700C1A359 /* AudioResampler.cpp in Sources */,
FD31608712B026F700C1A359 /* AudioResamplerKernel.cpp in Sources */,
FD8C46EB154608E700A5910C /* AudioScheduledSourceNode.cpp in Sources */,
+ CDA79824170A258300D45C55 /* AudioSession.cpp in Sources */,
+ CDA79827170A279100D45C55 /* AudioSessionIOS.mm in Sources */,
FDB052DF1561A42C00B500D6 /* AudioSummingJunction.cpp in Sources */,
FD31608A12B026F700C1A359 /* AudioUtilities.cpp in Sources */,
7EE6845F12D26E3800E79415 /* AuthenticationCF.cpp in Sources */,
Added: trunk/Source/WebCore/platform/audio/AudioSession.cpp (0 => 147494)
--- trunk/Source/WebCore/platform/audio/AudioSession.cpp (rev 0)
+++ trunk/Source/WebCore/platform/audio/AudioSession.cpp 2013-04-02 20:49:19 UTC (rev 147494)
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "AudioSession.h"
+
+#include "AudioSessionListener.h"
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+AudioSession& AudioSession::sharedSession()
+{
+ DEFINE_STATIC_LOCAL(AudioSession, session, ());
+ return session;
+}
+
+void AudioSession::addListener(AudioSessionListener* listener)
+{
+ m_listeners.add(listener);
+}
+
+void AudioSession::removeListener(AudioSessionListener* listener)
+{
+ m_listeners.remove(listener);
+}
+
+void AudioSession::beganAudioInterruption()
+{
+ for (HashSet<AudioSessionListener*>::iterator i = m_listeners.begin(); i != m_listeners.end(); ++i)
+ (*i)->beganAudioInterruption();
+}
+
+void AudioSession::endedAudioInterruption()
+{
+ for (HashSet<AudioSessionListener*>::iterator i = m_listeners.begin(); i != m_listeners.end(); ++i)
+ (*i)->endedAudioInterruption();
+}
+
+#if !PLATFORM(IOS)
+class AudioSessionPrivate {
+};
+
+AudioSession::AudioSession()
+ : m_private(0)
+{
+ notImplemented();
+}
+
+AudioSession::~AudioSession()
+{
+}
+
+void AudioSession::setCategory(CategoryType)
+{
+ notImplemented();
+}
+
+AudioSession::CategoryType AudioSession::categoryOverride() const
+{
+ notImplemented();
+ return None;
+}
+
+void AudioSession::setCategoryOverride(CategoryType)
+{
+ notImplemented();
+}
+
+AudioSession::CategoryType AudioSession::category() const
+{
+ notImplemented();
+ return None;
+}
+
+float AudioSession::sampleRate() const
+{
+ notImplemented();
+ return 0;
+}
+
+size_t AudioSession::numberOfOutputChannels() const
+{
+ notImplemented();
+ return 0;
+}
+
+void AudioSession::setActive(bool)
+{
+ notImplemented();
+}
+
+float AudioSession::preferredBufferDuration() const
+{
+ notImplemented();
+ return 0;
+}
+
+void AudioSession::setPreferredBufferDuration(float)
+{
+ notImplemented();
+}
+#endif // !PLATFORM(IOS)
+
+}
Added: trunk/Source/WebCore/platform/audio/AudioSession.h (0 => 147494)
--- trunk/Source/WebCore/platform/audio/AudioSession.h (rev 0)
+++ trunk/Source/WebCore/platform/audio/AudioSession.h 2013-04-02 20:49:19 UTC (rev 147494)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AudioSession_h
+#define AudioSession_h
+
+#include <wtf/HashSet.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class AudioSessionListener;
+class AudioSessionPrivate;
+
+class AudioSession {
+ WTF_MAKE_NONCOPYABLE(AudioSession);
+public:
+ static AudioSession& sharedSession();
+
+ enum CategoryType {
+ None,
+ AmbientSound,
+ SoloAmbientSound,
+ MediaPlayback,
+ RecordAudio,
+ PlayAndRecord,
+ AudioProcessing,
+ };
+ void setCategory(CategoryType);
+ CategoryType category() const;
+
+ void setCategoryOverride(CategoryType);
+ CategoryType categoryOverride() const;
+
+ void addListener(AudioSessionListener*);
+ void removeListener(AudioSessionListener*);
+
+ float sampleRate() const;
+ size_t numberOfOutputChannels() const;
+
+ void setActive(bool);
+
+ float preferredBufferDuration() const;
+ void setPreferredBufferDuration(float seconds);
+
+ void beganAudioInterruption();
+ void endedAudioInterruption();
+
+private:
+ AudioSession();
+ ~AudioSession();
+
+ OwnPtr<AudioSessionPrivate> m_private;
+ HashSet<AudioSessionListener*> m_listeners;
+};
+
+}
+
+#endif // AudioSession_h
Added: trunk/Source/WebCore/platform/audio/AudioSessionListener.h (0 => 147494)
--- trunk/Source/WebCore/platform/audio/AudioSessionListener.h (rev 0)
+++ trunk/Source/WebCore/platform/audio/AudioSessionListener.h 2013-04-02 20:49:19 UTC (rev 147494)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AudioSessionListener_h
+#define AudioSessionListener_h
+
+namespace WebCore {
+
+class AudioSessionListener {
+ WTF_MAKE_NONCOPYABLE(AudioSessionListener)
+public:
+ virtual void beganAudioInterruption() = 0;
+ virtual void endedAudioInterruption() = 0;
+protected:
+ AudioSessionListener() { }
+ virtual ~AudioSessionListener() { }
+};
+
+}
+
+#endif // AudioSessionListener_h
Modified: trunk/Source/WebCore/platform/audio/ios/AudioDestinationIOS.cpp (147493 => 147494)
--- trunk/Source/WebCore/platform/audio/ios/AudioDestinationIOS.cpp 2013-04-02 20:47:12 UTC (rev 147493)
+++ trunk/Source/WebCore/platform/audio/ios/AudioDestinationIOS.cpp 2013-04-02 20:49:19 UTC (rev 147494)
@@ -36,11 +36,11 @@
#include "AudioDestinationIOS.h"
#include "AudioIOCallback.h"
+#include "AudioSession.h"
#include "FloatConversion.h"
#include "Logging.h"
#include "Page.h"
#include "SoftLinking.h"
-#include <CoreAudio/AudioHardware.h>
#include <AudioToolbox/AudioServices.h>
#include <WebCore/RuntimeApplicationChecksIOS.h>
#include <wtf/HashSet.h>
@@ -51,10 +51,6 @@
SOFT_LINK(AudioToolbox, AudioComponentInstanceNew, OSStatus, (AudioComponent inComponent, AudioComponentInstance *outInstance), (inComponent, outInstance))
SOFT_LINK(AudioToolbox, AudioOutputUnitStart, OSStatus, (AudioUnit ci), (ci))
SOFT_LINK(AudioToolbox, AudioOutputUnitStop, OSStatus, (AudioUnit ci), (ci))
-SOFT_LINK(AudioToolbox, AudioSessionInitialize, OSStatus, (CFRunLoopRef inRunLoop, CFStringRef inRunLoopMode, AudioSessionInterruptionListener inInterruptionListener, void *inClientData), (inRunLoop, inRunLoopMode, inInterruptionListener, inClientData))
-SOFT_LINK(AudioToolbox, AudioSessionGetProperty, OSStatus, (AudioSessionPropertyID inID, UInt32 *ioDataSize, void *outData), (inID, ioDataSize, outData))
-SOFT_LINK(AudioToolbox, AudioSessionSetActive, OSStatus, (Boolean active), (active))
-SOFT_LINK(AudioToolbox, AudioSessionSetProperty, OSStatus, (AudioSessionPropertyID inID, UInt32 inDataSize, const void *inData), (inID, inDataSize, inData))
SOFT_LINK(AudioToolbox, AudioUnitAddPropertyListener, OSStatus, (AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitPropertyListenerProc inProc, void *inProcUserData), (inUnit, inID, inProc, inProcUserData))
SOFT_LINK(AudioToolbox, AudioUnitGetProperty, OSStatus, (AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void *outData, UInt32 *ioDataSize), (inUnit, inID, inScope, inElement, outData, ioDataSize))
SOFT_LINK(AudioToolbox, AudioUnitInitialize, OSStatus, (AudioUnit inUnit), (inUnit))
@@ -88,20 +84,9 @@
return adoptPtr(new AudioDestinationIOS(callback, sampleRate));
}
-// iOS 7.0/Innsbruck will deprecate AudioSession APIs. For now continue to use the old API.
-// <rdar://problem/11701792> AudioSession should move to using AVAudioSession (Innsbruck)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-
float AudioDestination::hardwareSampleRate()
{
- AudioDestinationIOS::initializeAudioSession();
-
- double sampleRate = 0;
- UInt32 sampleRateSize = sizeof(sampleRate);
-
- AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &sampleRateSize, &sampleRate);
- return sampleRate;
+ return AudioSession::sharedSession().sampleRate();
}
unsigned long AudioDestination::maxChannelCount()
@@ -121,11 +106,13 @@
, m_isPlaying(false)
, m_interruptedOnPlayback(false)
{
- initializeAudioSession();
+ AudioSession& session = AudioSession::sharedSession();
+ session.addListener(this);
+ session.setCategory(AudioSession::AmbientSound);
audioDestinations().add(this);
if (audioDestinations().size() == 1)
- AudioSessionSetActive(true);
+ session.setActive(1);
// Open and initialize DefaultOutputUnit
AudioComponent comp;
@@ -145,11 +132,11 @@
UInt32 flag = 1;
result = AudioUnitSetProperty(m_outputUnit,
- kAudioOutputUnitProperty_EnableIO,
- kAudioUnitScope_Output,
- 0,
- &flag,
- sizeof(flag));
+ kAudioOutputUnitProperty_EnableIO,
+ kAudioUnitScope_Output,
+ 0,
+ &flag,
+ sizeof(flag));
ASSERT(!result);
result = AudioUnitAddPropertyListener(m_outputUnit, kAudioUnitProperty_MaximumFramesPerSlice, frameSizeChangedProc, this);
@@ -164,8 +151,8 @@
AudioDestinationIOS::~AudioDestinationIOS()
{
audioDestinations().remove(this);
- if (audioDestinations().size() == 0)
- AudioSessionSetActive(false);
+ if (!audioDestinations().size())
+ AudioSession::sharedSession().setActive(0);
if (m_outputUnit)
AudioComponentInstanceDispose(m_outputUnit);
@@ -201,34 +188,9 @@
result = AudioUnitSetProperty(m_outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, (void*)&streamFormat, sizeof(AudioStreamBasicDescription));
ASSERT(!result);
- Float32 duration = narrowPrecisionToFloat(kPreferredBufferSize / m_sampleRate);
- AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(duration), &duration);
+ AudioSession::sharedSession().setPreferredBufferDuration(narrowPrecisionToFloat(kPreferredBufferSize / m_sampleRate));
}
-void AudioDestinationIOS::audioDestinationInterruptionListener(void *userData, UInt32 interruptionState)
-{
- ASSERT_UNUSED(userData, userData);
- for (AudioDestinationSet::iterator i = audioDestinations().begin(); i != audioDestinations().end(); ++i) {
- if (interruptionState == kAudioSessionBeginInterruption)
- (*i)->beganAudioInterruption();
- else
- (*i)->endedAudioInterruption();
- }
-}
-
-void AudioDestinationIOS::initializeAudioSession()
-{
- static bool audioSessionWasInitialized = false;
- if (audioSessionWasInitialized)
- return;
-
- audioSessionWasInitialized = true;
- AudioSessionInitialize(0, 0, &audioDestinationInterruptionListener, 0);
- Page::setAudioSessionCategory(kAudioSessionCategory_AmbientSound);
-}
-
-#pragma GCC diagnostic pop
-
void AudioDestinationIOS::start()
{
OSStatus result = AudioOutputUnitStart(m_outputUnit);
@@ -268,7 +230,7 @@
{
AudioBuffer* buffers = ioData->mBuffers;
for (UInt32 frameOffset = 0; frameOffset + kRenderBufferSize <= numberOfFrames; frameOffset += kRenderBufferSize) {
- UInt32 remainingFrames = MIN(kRenderBufferSize, numberOfFrames - frameOffset);
+ UInt32 remainingFrames = std::min<UInt32>(kRenderBufferSize, numberOfFrames - frameOffset);
for (UInt32 i = 0; i < ioData->mNumberBuffers; ++i) {
UInt32 bytesPerFrame = buffers[i].mDataByteSize / numberOfFrames;
UInt32 byteOffset = frameOffset * bytesPerFrame;
Added: trunk/Source/WebCore/platform/audio/ios/AudioSessionIOS.mm (0 => 147494)
--- trunk/Source/WebCore/platform/audio/ios/AudioSessionIOS.mm (rev 0)
+++ trunk/Source/WebCore/platform/audio/ios/AudioSessionIOS.mm 2013-04-02 20:49:19 UTC (rev 147494)
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "AudioSession.h"
+
+#if PLATFORM(IOS)
+
+#import "SoftLinking.h"
+#import <AVFoundation/AVAudioSession.h>
+#import <objc/runtime.h>
+#import <wtf/RetainPtr.h>
+
+SOFT_LINK_FRAMEWORK(AVFoundation)
+SOFT_LINK_CLASS(AVFoundation, AVAudioSession)
+
+SOFT_LINK_POINTER(AVFoundation, AVAudioSessionCategoryAmbient, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVAudioSessionCategorySoloAmbient, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVAudioSessionCategoryPlayback, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVAudioSessionCategoryRecord, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVAudioSessionCategoryPlayAndRecord, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVAudioSessionCategoryAudioProcessing, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVAudioSessionInterruptionNotification, NSString *)
+SOFT_LINK_POINTER(AVFoundation, AVAudioSessionInterruptionTypeKey, NSString *)
+
+#define AVAudioSession getAVAudioSessionClass()
+#define AVAudioSessionCategoryAmbient getAVAudioSessionCategoryAmbient()
+#define AVAudioSessionCategorySoloAmbient getAVAudioSessionCategorySoloAmbient()
+#define AVAudioSessionCategoryPlayback getAVAudioSessionCategoryPlayback()
+#define AVAudioSessionCategoryRecord getAVAudioSessionCategoryRecord()
+#define AVAudioSessionCategoryPlayAndRecord getAVAudioSessionCategoryPlayAndRecord()
+#define AVAudioSessionCategoryAudioProcessing getAVAudioSessionCategoryAudioProcessing()
+#define AVAudioSessionInterruptionNotification getAVAudioSessionInterruptionNotification()
+#define AVAudioSessionInterruptionTypeKey getAVAudioSessionInterruptionTypeKey()
+
+@interface WebAudioSessionHelper : NSObject {
+ WebCore::AudioSession* _callback;
+}
+- (id)initWithCallback:(WebCore::AudioSession*)callback;
+- (void)interruption:(NSNotification*)notification;
+@end
+
+@implementation WebAudioSessionHelper
+- (id)initWithCallback:(WebCore::AudioSession*)callback
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ _callback = callback;
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(interruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [super dealloc];
+}
+
+- (void)interruption:(NSNotification *)notification
+{
+ NSUInteger type = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
+ if (type == AVAudioSessionInterruptionTypeBegan)
+ _callback->beganAudioInterruption();
+ else
+ _callback->endedAudioInterruption();
+}
+@end
+
+namespace WebCore {
+
+class AudioSessionPrivate {
+public:
+ AudioSessionPrivate(AudioSession*);
+ RetainPtr<WebAudioSessionHelper> m_helper;
+ AudioSession::CategoryType m_categoryOverride;
+};
+
+AudioSessionPrivate::AudioSessionPrivate(AudioSession* session)
+ : m_helper(adoptNS([[WebAudioSessionHelper alloc] initWithCallback:session]))
+ , m_categoryOverride(AudioSession::None)
+{
+}
+
+AudioSession::AudioSession()
+ : m_private(adoptPtr(new AudioSessionPrivate(this)))
+{
+}
+
+AudioSession::~AudioSession()
+{
+}
+
+void AudioSession::setCategory(CategoryType newCategory)
+{
+ if (categoryOverride() && categoryOverride() != newCategory)
+ return;
+
+ if (!categoryOverride()) {
+ // If a page plays only WebAudio we set the audio category to "ambient" so it is muted by the ringer switch.
+ // However, audio from an HTML5 media element or from a plug-in should always play as "media" so don't change the
+ // category once it has already been set to media.
+ if (newCategory == AudioSession::AmbientSound && category() == AudioSession::MediaPlayback)
+ return;
+ }
+
+ NSString* categoryString;
+ switch (newCategory) {
+ case AmbientSound:
+ categoryString = AVAudioSessionCategoryAmbient;
+ case SoloAmbientSound:
+ categoryString = AVAudioSessionCategorySoloAmbient;
+ case MediaPlayback:
+ categoryString = AVAudioSessionCategoryPlayback;
+ case RecordAudio:
+ categoryString = AVAudioSessionCategoryRecord;
+ case PlayAndRecord:
+ categoryString = AVAudioSessionCategoryPlayAndRecord;
+ case AudioProcessing:
+ categoryString = AVAudioSessionCategoryAudioProcessing;
+ case None:
+ default:
+ categoryString = nil;
+ }
+ NSError *error = nil;
+ [[AVAudioSession sharedInstance] setCategory:categoryString error:error];
+ ASSERT(!error);
+}
+
+AudioSession::CategoryType AudioSession::category() const
+{
+ NSString* categoryString = [[AVAudioSession sharedInstance] category];
+ if ([categoryString isEqual:AVAudioSessionCategoryAmbient])
+ return AmbientSound;
+ if ([categoryString isEqual:AVAudioSessionCategorySoloAmbient])
+ return SoloAmbientSound;
+ if ([categoryString isEqual:AVAudioSessionCategoryPlayback])
+ return MediaPlayback;
+ if ([categoryString isEqual:AVAudioSessionCategoryRecord])
+ return RecordAudio;
+ if ([categoryString isEqual:AVAudioSessionCategoryPlayAndRecord])
+ return PlayAndRecord;
+ if ([categoryString isEqual:AVAudioSessionCategoryAudioProcessing])
+ return AudioProcessing;
+ return None;
+}
+
+void AudioSession::setCategoryOverride(CategoryType category)
+{
+ if (m_private->m_categoryOverride == category)
+ return;
+
+ m_private->m_categoryOverride = category;
+ setCategory(category);
+}
+
+AudioSession::CategoryType AudioSession::categoryOverride() const
+{
+ return m_private->m_categoryOverride;
+}
+
+float AudioSession::sampleRate() const
+{
+ return [[AVAudioSession sharedInstance] sampleRate];
+}
+
+size_t AudioSession::numberOfOutputChannels() const
+{
+ return [[AVAudioSession sharedInstance] outputNumberOfChannels];
+}
+
+void AudioSession::setActive(bool active)
+{
+ NSError *error = nil;
+ [[AVAudioSession sharedInstance] setActive:active error:&error];
+ ASSERT(!error);
+}
+
+float AudioSession::preferredBufferDuration() const
+{
+ return [[AVAudioSession sharedInstance] preferredIOBufferDuration];
+}
+
+void AudioSession::setPreferredBufferDuration(float duration)
+{
+ NSError *error = nil;
+ [[AVAudioSession sharedInstance] setPreferredIOBufferDuration:duration error:&error];
+ ASSERT(!error);
+}
+
+}
+
+#endif // PLATFORM(IOS)