Skip to content

Commit

Permalink
[Mac] Adopt -setEligibleForBTSmartRoutingConsideration:error:
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=255343
rdar://107144097

Reviewed by Eric Carlson.

-[AVAudioSession setEligibleForBTSmartRoutingConsideration:error:] has been
available and in use on iOS for a while; adopt it (where available) on macOS
as well.

Add a new, common, base class to AVAudioSessionIOS and -Mac, AudioSessionCocoa.
Move tryToSetActive() and setEligibleForSmartRouting() into that new base class.

* Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h:
* Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm:
* Source/WebCore/PAL/pal/spi/cocoa/AVFoundationSPI.h:
* Source/WebCore/WebCore.xcodeproj/project.pbxproj:
* Source/WebCore/platform/audio/cocoa/AudioSessionCocoa.h: Copied from Source/WebCore/platform/audio/ios/AudioSessionIOS.h.
* Source/WebCore/platform/audio/cocoa/AudioSessionCocoa.mm: Added.
(WebCore::setEligibleForSmartRouting):
(WebCore::AudioSessionCocoa::AudioSessionCocoa):
(WebCore::AudioSessionCocoa::~AudioSessionCocoa):
(WebCore::AudioSessionCocoa::tryToSetActiveInternal):
* Source/WebCore/platform/audio/ios/AudioSessionIOS.h:
* Source/WebCore/platform/audio/ios/AudioSessionIOS.mm:
(WebCore::AudioSessionIOS::AudioSessionIOS):
(WebCore::setEligibleForSmartRouting): Deleted.
(WebCore::AudioSessionIOS::tryToSetActiveInternal): Deleted.
* Source/WebCore/platform/audio/mac/AudioSessionMac.h:
* Source/WebCore/platform/audio/mac/AudioSessionMac.mm:
(WebCore::AudioSessionMac::tryToSetActiveInternal): Deleted.

Canonical link: https://commits.webkit.org/262981@main
  • Loading branch information
jernoble committed Apr 14, 2023
1 parent 76179a5 commit 29cd887
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 68 deletions.
11 changes: 11 additions & 0 deletions Source/WTF/wtf/PlatformHave.h
Expand Up @@ -1440,3 +1440,14 @@
|| (PLATFORM(APPLETV) && __TV_OS_VERSION_MIN_REQUIRED >= 170000))
#define HAVE_CFNETWORK_SEPARATE_CREDENTIAL_STORAGE 1
#endif

#if ((PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000) \
|| (PLATFORM(IOS) || PLATFORM(MACCATALYST) || PLATFORM(WATCHOS) || PLATFORM(APPLETV)))
#define HAVE_AVAUDIOSESSION 1
#endif

#if ((PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000) \
|| (PLATFORM(MACCATALYST) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 170000) \
|| (PLATFORM(IOS) || PLATFORM(WATCHOS) || PLATFORM(APPLETV)))
#define HAVE_AVAUDIOSESSION_SMARTROUTING 1
#endif
5 changes: 4 additions & 1 deletion Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.h
Expand Up @@ -74,8 +74,11 @@ SOFT_LINK_CLASS_FOR_HEADER(PAL, AVURLAsset)
SOFT_LINK_CLASS_FOR_HEADER(PAL, AVDelegatingPlaybackCoordinator)
#endif

#if PLATFORM(IOS_FAMILY)
#if HAVE(AVAUDIOSESSION)
SOFT_LINK_CLASS_FOR_HEADER(PAL, AVAudioSession)
#endif

#if PLATFORM(IOS_FAMILY)
SOFT_LINK_CLASS_FOR_HEADER(PAL, AVPersistableContentKeyRequest)
#endif

Expand Down
5 changes: 4 additions & 1 deletion Source/WebCore/PAL/pal/cocoa/AVFoundationSoftLink.mm
Expand Up @@ -101,8 +101,11 @@ static BOOL justReturnsNO()
SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(PAL, AVFoundation, AVSampleBufferRenderSynchronizer, PAL_EXPORT)
SOFT_LINK_CLASS_FOR_SOURCE_OPTIONAL_WITH_EXPORT(PAL, AVFoundation, AVStreamDataParser, PAL_EXPORT)

#if PLATFORM(IOS_FAMILY)
#if HAVE(AVAUDIOSESSION)
SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVAudioSession, PAL_EXPORT)
#endif

#if PLATFORM(IOS_FAMILY)
SOFT_LINK_CLASS_FOR_SOURCE_WITH_EXPORT(PAL, AVFoundation, AVPersistableContentKeyRequest, PAL_EXPORT)
#endif

Expand Down
5 changes: 3 additions & 2 deletions Source/WebCore/PAL/pal/spi/cocoa/AVFoundationSPI.h
Expand Up @@ -54,8 +54,9 @@
#endif
#endif

#if PLATFORM(IOS_FAMILY)
#import <AVFoundation/AVAudioSession_Private.h>

#if PLATFORM(IOS_FAMILY)
NS_ASSUME_NONNULL_BEGIN
@interface AVAudioSession (AVAudioSessionWebKitPrivate)
- (BOOL)setAuditTokensForProcessAssertion:(NSArray<NSData *>*)inAuditTokens error:(NSError **)outError;
Expand Down Expand Up @@ -431,7 +432,7 @@ NS_ASSUME_NONNULL_END
@end
#endif

#if !USE(APPLE_INTERNAL_SDK) && PLATFORM(IOS_FAMILY) && !PLATFORM(MACCATALYST)
#if !USE(APPLE_INTERNAL_SDK) && HAVE(AVAUDIOSESSION) && !PLATFORM(MACCATALYST)
#import <AVFoundation/AVAudioSession.h>

NS_ASSUME_NONNULL_BEGIN
Expand Down
8 changes: 8 additions & 0 deletions Source/WebCore/WebCore.xcodeproj/project.pbxproj
Expand Up @@ -4902,6 +4902,8 @@
CDD08AC2277E554E00EA3755 /* PlatformVideoTrackConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = CDD08AC1277E554E00EA3755 /* PlatformVideoTrackConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; };
CDD7089718359F6F002B3DC6 /* SampleMap.h in Headers */ = {isa = PBXBuildFile; fileRef = CDD7089518359F6F002B3DC6 /* SampleMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
CDDC1E7A18A952F30027A9D4 /* MediaSourcePrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CDDC1E7918A952F30027A9D4 /* MediaSourcePrivateClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
CDE104F329E6220C00CBAE11 /* AudioSessionCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = CDE104F229E621F500CBAE11 /* AudioSessionCocoa.mm */; };
CDE104F429E6221500CBAE11 /* AudioSessionCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE104F129E621F500CBAE11 /* AudioSessionCocoa.h */; settings = {ATTRIBUTES = (Private, ); }; };
CDE3A85417F5FCE600C5BE20 /* AudioTrackPrivateAVF.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE3A85217F5FCE600C5BE20 /* AudioTrackPrivateAVF.h */; };
CDE3A85817F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE3A85617F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h */; };
CDE3AE1224B4916A00128E7E /* CDMUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = CDE3AE1024B4916900128E7E /* CDMUtilities.h */; };
Expand Down Expand Up @@ -17452,6 +17454,8 @@
CDDE02E918B3DFC700CF7FF1 /* LegacyCDMSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LegacyCDMSession.h; sourceTree = "<group>"; };
CDDE02EA18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDMSessionAVFoundationObjC.h; sourceTree = "<group>"; };
CDDE02EB18B3ED6D00CF7FF1 /* CDMSessionAVFoundationObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CDMSessionAVFoundationObjC.mm; sourceTree = "<group>"; };
CDE104F129E621F500CBAE11 /* AudioSessionCocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioSessionCocoa.h; sourceTree = "<group>"; };
CDE104F229E621F500CBAE11 /* AudioSessionCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AudioSessionCocoa.mm; sourceTree = "<group>"; };
CDE18C9E299613C9006FBD4B /* FormAssociatedElement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FormAssociatedElement.cpp; sourceTree = "<group>"; };
CDE3A85217F5FCE600C5BE20 /* AudioTrackPrivateAVF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioTrackPrivateAVF.h; sourceTree = "<group>"; };
CDE3A85517F6020400C5BE20 /* AudioTrackPrivateAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AudioTrackPrivateAVFObjC.mm; sourceTree = "<group>"; };
Expand Down Expand Up @@ -32488,6 +32492,8 @@
41FFD2C227563E0000501BBF /* AudioSampleDataConverter.mm */,
073B87651E43859D0071C0EC /* AudioSampleDataSource.h */,
073B87641E43859D0071C0EC /* AudioSampleDataSource.mm */,
CDE104F129E621F500CBAE11 /* AudioSessionCocoa.h */,
CDE104F229E621F500CBAE11 /* AudioSessionCocoa.mm */,
7BC9642D291E770300377DF1 /* AudioUtilitiesCocoa.cpp */,
7BC9642E291E770400377DF1 /* AudioUtilitiesCocoa.h */,
073B87571E40DCFD0071C0EC /* CAAudioStreamDescription.cpp */,
Expand Down Expand Up @@ -35881,6 +35887,7 @@
073B87691E4385AC0071C0EC /* AudioSampleDataSource.h in Headers */,
FD8C46EC154608E700A5910C /* AudioScheduledSourceNode.h in Headers */,
CDA7982A170A3D0000D45C55 /* AudioSession.h in Headers */,
CDE104F429E6221500CBAE11 /* AudioSessionCocoa.h in Headers */,
CD36C1622607E78600C8C529 /* AudioSessionIOS.h in Headers */,
FD31608912B026F700C1A359 /* AudioSourceProvider.h in Headers */,
CD8A7BBC197735FE00CBD643 /* AudioSourceProviderAVFObjC.h in Headers */,
Expand Down Expand Up @@ -41307,6 +41314,7 @@
7BE37F7D27BB86CD007A6CD3 /* ANGLEUtilities.cpp in Sources */,
7BE37F7C27BB86B8007A6CD3 /* ANGLEUtilitiesCocoa.mm in Sources */,
CD0EEE0E14743F39003EAFA2 /* AudioOutputUnitAdaptorIOS.cpp in Sources */,
CDE104F329E6220C00CBAE11 /* AudioSessionCocoa.mm in Sources */,
CDA79827170A279100D45C55 /* AudioSessionIOS.mm in Sources */,
CD8A7BBB197735FE00CBD643 /* AudioSourceProviderAVFObjC.mm in Sources */,
52B07441284680CA00511B65 /* AuthenticationExtensionsClientInputs.cpp in Sources */,
Expand Down
53 changes: 53 additions & 0 deletions Source/WebCore/platform/audio/cocoa/AudioSessionCocoa.h
@@ -0,0 +1,53 @@
/*
* Copyright (C) 2023 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.
*/

#pragma once

#if USE(AUDIO_SESSION) && PLATFORM(COCOA)

#include "AudioSession.h"

namespace WTF {
class WorkQueue;
}

namespace WebCore {

class AudioSessionCocoa : public AudioSession {
public:
virtual ~AudioSessionCocoa();

protected:
AudioSessionCocoa();

// AudioSession
bool tryToSetActiveInternal(bool) final;

Ref<WTF::WorkQueue> m_workQueue;
};

}

#endif
117 changes: 117 additions & 0 deletions Source/WebCore/platform/audio/cocoa/AudioSessionCocoa.mm
@@ -0,0 +1,117 @@
/*
* Copyright (C) 2023 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 "AudioSessionCocoa.h"

#if USE(AUDIO_SESSION) && PLATFORM(COCOA)

#import "Logging.h"
#import "NotImplemented.h"
#import <AVFoundation/AVAudioSession.h>
#import <pal/spi/cocoa/AVFoundationSPI.h>
#import <wtf/WorkQueue.h>

#import <pal/cocoa/AVFoundationSoftLink.h>

namespace WebCore {

static void setEligibleForSmartRouting(bool eligible)
{
#if HAVE(AVAUDIOSESSION_SMARTROUTING)
if (!AudioSession::shouldManageAudioSessionCategory())
return;

static bool supportsEligibleForBT = [PAL::getAVAudioSessionClass() instancesRespondToSelector:@selector(setEligibleForBTSmartRoutingConsideration:error:)]
&& [PAL::getAVAudioSessionClass() instancesRespondToSelector:@selector(eligibleForBTSmartRoutingConsideration)];
if (!supportsEligibleForBT)
return;

AVAudioSession *session = [PAL::getAVAudioSessionClass() sharedInstance];

if (session.eligibleForBTSmartRoutingConsideration == eligible)
return;

NSError *error = nil;
if (![session setEligibleForBTSmartRoutingConsideration:eligible error:&error])
RELEASE_LOG_ERROR(Media, "failed to set eligible to %d with error: %@", eligible, error.localizedDescription);
#else
UNUSED_PARAM(eligible);
#endif
}

AudioSessionCocoa::AudioSessionCocoa()
: m_workQueue(WorkQueue::create("AudioSession Activation Queue"))
{
m_workQueue->dispatch([] {
setEligibleForSmartRouting(false);
});

}

AudioSessionCocoa::~AudioSessionCocoa()
{
}

bool AudioSessionCocoa::tryToSetActiveInternal(bool active)
{
#if HAVE(AVAUDIOSESSION)
static bool supportsSharedInstance = [PAL::getAVAudioSessionClass() respondsToSelector:@selector(sharedInstance)];
static bool supportsSetActive = [PAL::getAVAudioSessionClass() instancesRespondToSelector:@selector(setActive:withOptions:error:)];

if (!supportsSharedInstance)
return true;

// We need to deactivate the session on another queue because the AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation option
// means that AVAudioSession may synchronously unduck previously ducked clients. Activation needs to complete before this method
// returns, so do it synchronously on the same serial queue.
if (active) {
bool success = false;
m_workQueue->dispatchSync([&success] {
NSError *error = nil;
setEligibleForSmartRouting(true);
if (supportsSetActive)
[[PAL::getAVAudioSessionClass() sharedInstance] setActive:YES withOptions:0 error:&error];
success = !error;
});
return success;
}

m_workQueue->dispatch([] {
NSError *error = nil;
if (supportsSetActive)
[[PAL::getAVAudioSessionClass() sharedInstance] setActive:NO withOptions:0 error:&error];
setEligibleForSmartRouting(false);
});
#else
UNUSED_PARAM(active);
notImplemented();
#endif
return true;
}

}

#endif // USE(AUDIO_SESSION) && PLATFORM(COCOA)
2 changes: 0 additions & 2 deletions Source/WebCore/platform/audio/ios/AudioSessionIOS.h
Expand Up @@ -56,7 +56,6 @@ class AudioSessionIOS final : public AudioSession {
size_t bufferSize() const final;
size_t numberOfOutputChannels() const final;
size_t maximumNumberOfOutputChannels() const final;
bool tryToSetActiveInternal(bool) final;
RouteSharingPolicy routeSharingPolicy() const final;
String routingContextUID() const final;
size_t preferredBufferSize() const final;
Expand All @@ -65,7 +64,6 @@ class AudioSessionIOS final : public AudioSession {
void handleMutedStateChange() final;

String m_lastSetPreferredAudioDeviceUID;
Ref<WTF::WorkQueue> m_workQueue;
RetainPtr<WebInterruptionObserverHelper> m_interruptionObserverHelper;
};

Expand Down
53 changes: 0 additions & 53 deletions Source/WebCore/platform/audio/ios/AudioSessionIOS.mm
Expand Up @@ -110,39 +110,11 @@ - (void)interruption:(NSNotification *)notification
observer(AudioSession::sharedSession(), AudioSession::sharedSession().category());
}

static void setEligibleForSmartRouting(bool eligible)
{
#if PLATFORM(IOS)
if (!AudioSession::shouldManageAudioSessionCategory())
return;

AVAudioSession *session = [PAL::getAVAudioSessionClass() sharedInstance];
if (![session respondsToSelector:@selector(setEligibleForBTSmartRoutingConsideration:error:)]
|| ![session respondsToSelector:@selector(eligibleForBTSmartRoutingConsideration)])
return;

if (session.eligibleForBTSmartRoutingConsideration == eligible)
return;

NSError *error = nil;
if (![session setEligibleForBTSmartRoutingConsideration:eligible error:&error])
RELEASE_LOG_ERROR(Media, "failed to set eligible to %d with error: %@", eligible, error.localizedDescription);
#else
UNUSED_PARAM(eligible);
#endif
}

AudioSessionIOS::AudioSessionIOS()
: m_workQueue(WorkQueue::create("AudioSession Activation Queue"))
{
BEGIN_BLOCK_OBJC_EXCEPTIONS
m_interruptionObserverHelper = adoptNS([[WebInterruptionObserverHelper alloc] initWithCallback:this]);
END_BLOCK_OBJC_EXCEPTIONS

m_workQueue->dispatch([] {
setEligibleForSmartRouting(false);
});

}

AudioSessionIOS::~AudioSessionIOS()
Expand Down Expand Up @@ -336,31 +308,6 @@ static void setEligibleForSmartRouting(bool eligible)
return [[PAL::getAVAudioSessionClass() sharedInstance] maximumOutputNumberOfChannels];
}

bool AudioSessionIOS::tryToSetActiveInternal(bool active)
{
// We need to deactivate the session on another queue because the AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation option
// means that AVAudioSession may synchronously unduck previously ducked clients. Activation needs to complete before this method
// returns, so do it synchronously on the same serial queue.
if (active) {
bool success = false;
m_workQueue->dispatchSync([&success] {
NSError *error = nil;
setEligibleForSmartRouting(true);
[[PAL::getAVAudioSessionClass() sharedInstance] setActive:YES withOptions:0 error:&error];
success = !error;
});
return success;
}

m_workQueue->dispatch([] {
NSError *error = nil;
[[PAL::getAVAudioSessionClass() sharedInstance] setActive:NO withOptions:0 error:&error];
setEligibleForSmartRouting(false);
});

return true;
}

size_t AudioSessionIOS::preferredBufferSize() const
{
return [[PAL::getAVAudioSessionClass() sharedInstance] preferredIOBufferDuration] * sampleRate();
Expand Down
5 changes: 2 additions & 3 deletions Source/WebCore/platform/audio/mac/AudioSessionMac.h
Expand Up @@ -27,15 +27,15 @@

#if USE(AUDIO_SESSION) && PLATFORM(MAC)

#include "AudioSession.h"
#include "AudioSessionCocoa.h"
#include <pal/spi/cf/CoreAudioSPI.h>

typedef UInt32 AudioObjectID;
typedef struct AudioObjectPropertyAddress AudioObjectPropertyAddress;

namespace WebCore {

class AudioSessionMac final : public AudioSession {
class AudioSessionMac final : public AudioSessionCocoa {
public:
AudioSessionMac() = default;
virtual ~AudioSessionMac() = default;
Expand Down Expand Up @@ -73,7 +73,6 @@ class AudioSessionMac final : public AudioSession {
size_t bufferSize() const final;
size_t numberOfOutputChannels() const final;
size_t maximumNumberOfOutputChannels() const final;
bool tryToSetActiveInternal(bool) final;
String routingContextUID() const final;
size_t preferredBufferSize() const final;
void setPreferredBufferSize(size_t) final;
Expand Down

0 comments on commit 29cd887

Please sign in to comment.