[iOS] Unset active media capture source when stopped capturing
[WebKit-https.git] / Source / WebCore / platform / mock / MockRealtimeAudioSource.cpp
1 /*
2  * Copyright (C) 2015 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  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer
12  *    in the documentation and/or other materials provided with the
13  *    distribution.
14  * 3. Neither the name of Google Inc. nor the names of its contributors
15  *    may be used to endorse or promote products derived from this
16  *    software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "MockRealtimeAudioSource.h"
33
34 #if ENABLE(MEDIA_STREAM)
35 #include "CaptureDevice.h"
36 #include "Logging.h"
37 #include "MediaConstraints.h"
38 #include "NotImplemented.h"
39 #include "RealtimeMediaSourceSettings.h"
40 #include <wtf/UUID.h>
41
42 namespace WebCore {
43
44 class MockRealtimeAudioSourceFactory : public RealtimeMediaSource::AudioCaptureFactory
45 #if PLATFORM(IOS)
46     , public RealtimeMediaSource::SingleSourceFactory<MockRealtimeAudioSource>
47 #endif
48 {
49 public:
50     CaptureSourceOrError createAudioCaptureSource(const String& deviceID, const MediaConstraints* constraints) final {
51         for (auto& device : MockRealtimeMediaSource::audioDevices()) {
52             if (device.persistentId() == deviceID)
53                 return MockRealtimeAudioSource::create(device.label(), constraints);
54         }
55         return { };
56     }
57 };
58
59 #if !PLATFORM(MAC) && !PLATFORM(IOS)
60 CaptureSourceOrError MockRealtimeAudioSource::create(const String& name, const MediaConstraints* constraints)
61 {
62     auto source = adoptRef(*new MockRealtimeAudioSource(name));
63     if (constraints && source->applyConstraints(*constraints))
64         return { };
65
66     return CaptureSourceOrError(WTFMove(source));
67 }
68
69 RefPtr<MockRealtimeAudioSource> MockRealtimeAudioSource::createMuted(const String& name)
70 {
71     auto source = adoptRef(new MockRealtimeAudioSource(name));
72     source->m_muted = true;
73     return source;
74 }
75 #endif
76
77 static MockRealtimeAudioSourceFactory& mockAudioCaptureSourceFactory()
78 {
79     static NeverDestroyed<MockRealtimeAudioSourceFactory> factory;
80     return factory.get();
81 }
82
83 RealtimeMediaSource::AudioCaptureFactory& MockRealtimeAudioSource::factory()
84 {
85     return mockAudioCaptureSourceFactory();
86 }
87
88 MockRealtimeAudioSource::MockRealtimeAudioSource(const String& name)
89     : MockRealtimeMediaSource(createCanonicalUUIDString(), RealtimeMediaSource::Type::Audio, name)
90     , m_timer(RunLoop::current(), this, &MockRealtimeAudioSource::tick)
91 {
92 }
93
94 MockRealtimeAudioSource::~MockRealtimeAudioSource()
95 {
96 #if PLATFORM(IOS)
97     mockAudioCaptureSourceFactory().unsetActiveSource(*this);
98 #endif
99 }
100
101 void MockRealtimeAudioSource::updateSettings(RealtimeMediaSourceSettings& settings)
102 {
103     settings.setVolume(volume());
104     settings.setEchoCancellation(echoCancellation());
105     settings.setSampleRate(sampleRate());
106 }
107
108 void MockRealtimeAudioSource::initializeCapabilities(RealtimeMediaSourceCapabilities& capabilities)
109 {
110     capabilities.setVolume(CapabilityValueOrRange(0.0, 1.0));
111     capabilities.setEchoCancellation(RealtimeMediaSourceCapabilities::EchoCancellation::ReadWrite);
112     capabilities.setSampleRate(CapabilityValueOrRange(44100, 48000));
113 }
114
115 void MockRealtimeAudioSource::initializeSupportedConstraints(RealtimeMediaSourceSupportedConstraints& supportedConstraints)
116 {
117     supportedConstraints.setSupportsVolume(true);
118     supportedConstraints.setSupportsEchoCancellation(true);
119     supportedConstraints.setSupportsSampleRate(true);
120 }
121
122 void MockRealtimeAudioSource::startProducingData()
123 {
124     if (m_isProducingData)
125         return;
126
127     m_isProducingData = true;
128
129 #if PLATFORM(IOS)
130     mockAudioCaptureSourceFactory().setActiveSource(*this);
131 #endif
132
133     if (!sampleRate())
134         setSampleRate(!deviceIndex() ? 44100 : 48000);
135
136     MockRealtimeMediaSource::startProducingData();
137
138     m_startTime = monotonicallyIncreasingTime();
139     m_timer.startRepeating(renderInterval());
140 }
141
142 void MockRealtimeAudioSource::stopProducingData()
143 {
144     if (!m_isProducingData)
145         return;
146
147     m_isProducingData = false;
148
149     MockRealtimeMediaSource::stopProducingData();
150     m_timer.stop();
151     m_elapsedTime += monotonicallyIncreasingTime() - m_startTime;
152     m_startTime = NAN;
153 }
154
155 double MockRealtimeAudioSource::elapsedTime()
156 {
157     if (std::isnan(m_startTime))
158         return m_elapsedTime;
159
160     return m_elapsedTime + (monotonicallyIncreasingTime() - m_startTime);
161 }
162
163 void MockRealtimeAudioSource::tick()
164 {
165     if (std::isnan(m_lastRenderTime))
166         m_lastRenderTime = monotonicallyIncreasingTime();
167
168     double now = monotonicallyIncreasingTime();
169     double delta = now - m_lastRenderTime;
170     m_lastRenderTime = now;
171     render(delta);
172 }
173
174 } // namespace WebCore
175
176 #endif // ENABLE(MEDIA_STREAM)