6fb3dad39c2d9e978dc521b7bb83f699a93253ff
[WebKit-https.git] / Source / WebCore / platform / mediastream / ios / CoreAudioCaptureSourceIOS.mm
1 /*
2  * Copyright (C) 2017 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 "CoreAudioCaptureSourceIOS.h"
28
29 #if ENABLE(MEDIA_STREAM) && PLATFORM(IOS_FAMILY)
30
31 #import "Logging.h"
32 #import <AVFoundation/AVAudioSession.h>
33 #import <wtf/MainThread.h>
34
35 #import <pal/cocoa/AVFoundationSoftLink.h>
36
37 using namespace WebCore;
38
39 @interface WebCoreAudioCaptureSourceIOSListener : NSObject {
40     CoreAudioCaptureSourceFactoryIOS* _callback;
41 }
42
43 - (void)invalidate;
44 - (void)handleInterruption:(NSNotification*)notification;
45 - (void)sessionMediaServicesWereReset:(NSNotification*)notification;
46 @end
47
48 @implementation WebCoreAudioCaptureSourceIOSListener
49 - (id)initWithCallback:(CoreAudioCaptureSourceFactoryIOS*)callback
50 {
51     self = [super init];
52     if (!self)
53         return nil;
54
55     _callback = callback;
56
57     NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
58     AVAudioSession* session = [PAL::getAVAudioSessionClass() sharedInstance];
59
60     [center addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:session];
61     [center addObserver:self selector:@selector(sessionMediaServicesWereReset:) name:AVAudioSessionMediaServicesWereResetNotification object:session];
62
63     return self;
64 }
65
66 - (void)invalidate
67 {
68     _callback = nullptr;
69     [[NSNotificationCenter defaultCenter] removeObserver:self];
70 }
71
72 - (void)handleInterruption:(NSNotification*)notification
73 {
74     ASSERT(_callback);
75     if (!_callback)
76         return;
77
78     if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] intValue] == AVAudioSessionInterruptionTypeBegan) {
79         _callback->beginInterruption();
80         return;
81     }
82
83     if ([[notification.userInfo valueForKey:AVAudioSessionInterruptionTypeKey] intValue] == AVAudioSessionInterruptionTypeEnded) {
84         NSError *error = nil;
85         [[PAL::getAVAudioSessionClass() sharedInstance] setActive:YES error:&error];
86
87 #if !LOG_DISABLED
88         if (error)
89             LOG(Media, "-[WebCoreAudioCaptureSourceIOSListener handleInterruption] (%p) - error = %s", self, [[error localizedDescription] UTF8String]);
90 #endif
91
92         _callback->endInterruption();
93     }
94 }
95
96 - (void)sessionMediaServicesWereReset:(NSNotification*)notification
97 {
98     UNUSED_PARAM(notification);
99     ASSERT(_callback);
100
101     if (!_callback)
102         return;
103
104     // mediaserverd crashed and was relaunched, rebuild everything. See
105     // https://developer.apple.com/library/content/qa/qa1749/_index.html.
106     _callback->scheduleReconfiguration();
107 }
108 @end
109
110 namespace WebCore {
111
112 CoreAudioCaptureSourceFactoryIOS::CoreAudioCaptureSourceFactoryIOS()
113     : m_listener(adoptNS([[WebCoreAudioCaptureSourceIOSListener alloc] initWithCallback:this]))
114 {
115 }
116
117 CoreAudioCaptureSourceFactoryIOS::~CoreAudioCaptureSourceFactoryIOS()
118 {
119     [m_listener invalidate];
120     m_listener = nullptr;
121 }
122
123 CoreAudioCaptureSourceFactory& CoreAudioCaptureSourceFactory::singleton()
124 {
125     static NeverDestroyed<CoreAudioCaptureSourceFactoryIOS> factory;
126     return factory.get();
127 }
128
129 }
130
131 #endif // ENABLE(MEDIA_STREAM) && PLATFORM(IOS_FAMILY)