4e772983af29fd4a77bff12f3eeab73521e65b0c
[WebKit-https.git] / Source / WebCore / platform / audio / MediaSessionManager.cpp
1 /*
2  * Copyright (C) 2013-2014 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 "MediaSessionManager.h"
28
29 #if ENABLE(VIDEO)
30
31 #include "Logging.h"
32 #include "NotImplemented.h"
33 #include "MediaSession.h"
34
35 namespace WebCore {
36
37 #if !PLATFORM(IOS)
38 MediaSessionManager& MediaSessionManager::sharedManager()
39 {
40     DEPRECATED_DEFINE_STATIC_LOCAL(MediaSessionManager, manager, ());
41     return manager;
42 }
43 #endif
44
45 MediaSessionManager::MediaSessionManager()
46     : m_systemSleepListener(SystemSleepListener::create(*this))
47     , m_interrupted(false)
48 {
49     resetRestrictions();
50 }
51
52 void MediaSessionManager::resetRestrictions()
53 {
54     m_restrictions[MediaSession::Video] = NoRestrictions;
55     m_restrictions[MediaSession::Audio] = NoRestrictions;
56     m_restrictions[MediaSession::WebAudio] = NoRestrictions;
57 }
58
59 bool MediaSessionManager::has(MediaSession::MediaType type) const
60 {
61     ASSERT(type >= MediaSession::None && type <= MediaSession::WebAudio);
62
63     for (auto* session : m_sessions) {
64         if (session->mediaType() == type)
65             return true;
66     }
67
68     return false;
69 }
70
71 int MediaSessionManager::count(MediaSession::MediaType type) const
72 {
73     ASSERT(type >= MediaSession::None && type <= MediaSession::WebAudio);
74
75     int count = 0;
76     for (auto* session : m_sessions) {
77         if (session->mediaType() == type)
78             ++count;
79     }
80
81     return count;
82 }
83
84 void MediaSessionManager::beginInterruption()
85 {
86     LOG(Media, "MediaSessionManager::beginInterruption");
87
88     m_interrupted = true;
89     Vector<MediaSession*> sessions = m_sessions;
90     for (auto* session : sessions)
91         session->beginInterruption();
92 }
93
94 void MediaSessionManager::endInterruption(MediaSession::EndInterruptionFlags flags)
95 {
96     LOG(Media, "MediaSessionManager::endInterruption");
97
98     m_interrupted = false;
99     Vector<MediaSession*> sessions = m_sessions;
100     for (auto* session : sessions)
101         session->endInterruption(flags);
102 }
103
104 void MediaSessionManager::addSession(MediaSession& session)
105 {
106     LOG(Media, "MediaSessionManager::addSession - %p", &session);
107     
108     m_sessions.append(&session);
109     if (m_interrupted)
110         session.setState(MediaSession::Interrupted);
111     updateSessionState();
112
113     if (!m_remoteCommandListener)
114         m_remoteCommandListener = RemoteCommandListener::create(*this);
115
116     if (m_clients.isEmpty() || !(session.mediaType() == MediaSession::Video || session.mediaType() == MediaSession::Audio))
117         return;
118
119     for (auto& client : m_clients)
120         client->startListeningForRemoteControlCommands();
121 }
122
123 void MediaSessionManager::removeSession(MediaSession& session)
124 {
125     LOG(Media, "MediaSessionManager::removeSession - %p", &session);
126     
127     size_t index = m_sessions.find(&session);
128     ASSERT(index != notFound);
129     if (index == notFound)
130         return;
131     
132     m_sessions.remove(index);
133     updateSessionState();
134
135     if (m_sessions.isEmpty())
136         m_remoteCommandListener = nullptr;
137
138     if (m_clients.isEmpty() || !(session.mediaType() == MediaSession::Video || session.mediaType() == MediaSession::Audio))
139         return;
140
141     for (auto& client : m_clients)
142         client->startListeningForRemoteControlCommands();
143 }
144
145 void MediaSessionManager::addRestriction(MediaSession::MediaType type, SessionRestrictions restriction)
146 {
147     ASSERT(type > MediaSession::None && type <= MediaSession::WebAudio);
148     m_restrictions[type] |= restriction;
149 }
150
151 void MediaSessionManager::removeRestriction(MediaSession::MediaType type, SessionRestrictions restriction)
152 {
153     ASSERT(type > MediaSession::None && type <= MediaSession::WebAudio);
154     m_restrictions[type] &= ~restriction;
155 }
156
157 MediaSessionManager::SessionRestrictions MediaSessionManager::restrictions(MediaSession::MediaType type)
158 {
159     ASSERT(type > MediaSession::None && type <= MediaSession::WebAudio);
160     return m_restrictions[type];
161 }
162
163 void MediaSessionManager::sessionWillBeginPlayback(MediaSession& session)
164 {
165     LOG(Media, "MediaSessionManager::sessionWillBeginPlayback - %p", &session);
166     
167     setCurrentSession(session);
168
169     if (!m_clients.isEmpty() && (session.mediaType() == MediaSession::Video || session.mediaType() == MediaSession::Audio)) {
170         for (auto& client : m_clients)
171             client->didBeginPlayback();
172     }
173
174     MediaSession::MediaType sessionType = session.mediaType();
175     SessionRestrictions restrictions = m_restrictions[sessionType];
176     if (!restrictions & ConcurrentPlaybackNotPermitted)
177         return;
178
179     Vector<MediaSession*> sessions = m_sessions;
180     for (auto* oneSession : sessions) {
181         if (oneSession == &session)
182             continue;
183         if (oneSession->mediaType() != sessionType)
184             continue;
185         if (restrictions & ConcurrentPlaybackNotPermitted)
186             oneSession->pauseSession();
187     }
188 }
189     
190 void MediaSessionManager::sessionWillEndPlayback(MediaSession& session)
191 {
192     LOG(Media, "MediaSessionManager::sessionWillEndPlayback - %p", &session);
193     
194     if (m_sessions.size() < 2)
195         return;
196     
197     size_t pausingSessionIndex = notFound;
198     size_t lastPlayingSessionIndex = notFound;
199     for (size_t i = 0; i < m_sessions.size(); ++i) {
200         MediaSession* oneSession = m_sessions[i];
201         
202         if (oneSession == &session) {
203             pausingSessionIndex = i;
204             continue;
205         }
206         if (oneSession->state() == MediaSession::Playing) {
207             lastPlayingSessionIndex = i;
208             continue;
209         }
210         if (oneSession->state() != MediaSession::Playing)
211             break;
212     }
213     if (lastPlayingSessionIndex == notFound || pausingSessionIndex == notFound)
214         return;
215     
216     if (pausingSessionIndex > lastPlayingSessionIndex)
217         return;
218     
219     m_sessions.remove(pausingSessionIndex);
220     m_sessions.insert(lastPlayingSessionIndex, &session);
221     
222     LOG(Media, "MediaSessionManager::sessionWillEndPlayback - session moved from index %zu to %zu", pausingSessionIndex, lastPlayingSessionIndex);
223 }
224
225 void MediaSessionManager::setCurrentSession(MediaSession& session)
226 {
227     LOG(Media, "MediaSessionManager::setCurrentSession - %p", &session);
228     
229     if (m_sessions.size() < 2)
230         return;
231     
232     size_t index = m_sessions.find(&session);
233     ASSERT(index != notFound);
234     if (!index || index == notFound)
235         return;
236
237     m_sessions.remove(index);
238     m_sessions.insert(0, &session);
239     
240     LOG(Media, "MediaSessionManager::setCurrentSession - session moved from index %zu to 0", index);
241 }
242     
243 MediaSession* MediaSessionManager::currentSession()
244 {
245     if (!m_sessions.size())
246         return nullptr;
247
248     return m_sessions[0];
249 }
250     
251 bool MediaSessionManager::sessionRestrictsInlineVideoPlayback(const MediaSession& session) const
252 {
253     MediaSession::MediaType sessionType = session.mediaType();
254     if (sessionType != MediaSession::Video)
255         return false;
256
257     return m_restrictions[sessionType] & InlineVideoPlaybackRestricted;
258 }
259
260 void MediaSessionManager::applicationWillEnterBackground() const
261 {
262     LOG(Media, "MediaSessionManager::applicationWillEnterBackground");
263     Vector<MediaSession*> sessions = m_sessions;
264     for (auto* session : sessions) {
265         if (m_restrictions[session->mediaType()] & BackgroundPlaybackNotPermitted)
266             session->beginInterruption();
267     }
268 }
269
270 void MediaSessionManager::applicationWillEnterForeground() const
271 {
272     LOG(Media, "MediaSessionManager::applicationWillEnterForeground");
273     Vector<MediaSession*> sessions = m_sessions;
274     for (auto* session : sessions) {
275         if (m_restrictions[session->mediaType()] & BackgroundPlaybackNotPermitted)
276             session->endInterruption(MediaSession::MayResumePlaying);
277     }
278 }
279
280 void MediaSessionManager::wirelessRoutesAvailableChanged()
281 {
282     notImplemented();
283 }
284
285 #if !PLATFORM(COCOA)
286 void MediaSessionManager::updateSessionState()
287 {
288 }
289 #endif
290
291 void MediaSessionManager::didReceiveRemoteControlCommand(MediaSession::RemoteControlCommandType command)
292 {
293     MediaSession* activeSession = currentSession();
294     if (!activeSession || !activeSession->canReceiveRemoteControlCommands())
295         return;
296     activeSession->didReceiveRemoteControlCommand(command);
297 }
298
299 void MediaSessionManager::addClient(MediaSessionManagerClient* client)
300 {
301     ASSERT(!m_clients.contains(client));
302     m_clients.append(client);
303 }
304
305 void MediaSessionManager::removeClient(MediaSessionManagerClient* client)
306 {
307     ASSERT(m_clients.contains(client));
308     m_clients.remove(m_clients.find(client));
309 }
310
311 void MediaSessionManager::systemWillSleep()
312 {
313     if (m_interrupted)
314         return;
315
316     for (auto session : m_sessions)
317         session->beginInterruption();
318 }
319
320 void MediaSessionManager::systemDidWake()
321 {
322     if (m_interrupted)
323         return;
324
325     for (auto session : m_sessions)
326         session->endInterruption(MediaSession::MayResumePlaying);
327 }
328
329 }
330
331 #endif