2 * Copyright (C) 2013-2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "MediaSessionManager.h"
32 #include "NotImplemented.h"
33 #include "MediaSession.h"
38 MediaSessionManager& MediaSessionManager::sharedManager()
40 DEPRECATED_DEFINE_STATIC_LOCAL(MediaSessionManager, manager, ());
45 MediaSessionManager::MediaSessionManager()
46 : m_systemSleepListener(SystemSleepListener::create(*this))
47 , m_interrupted(false)
52 void MediaSessionManager::resetRestrictions()
54 m_restrictions[MediaSession::Video] = NoRestrictions;
55 m_restrictions[MediaSession::Audio] = NoRestrictions;
56 m_restrictions[MediaSession::WebAudio] = NoRestrictions;
59 bool MediaSessionManager::has(MediaSession::MediaType type) const
61 ASSERT(type >= MediaSession::None && type <= MediaSession::WebAudio);
63 for (auto* session : m_sessions) {
64 if (session->mediaType() == type)
71 int MediaSessionManager::count(MediaSession::MediaType type) const
73 ASSERT(type >= MediaSession::None && type <= MediaSession::WebAudio);
76 for (auto* session : m_sessions) {
77 if (session->mediaType() == type)
84 void MediaSessionManager::beginInterruption()
86 LOG(Media, "MediaSessionManager::beginInterruption");
89 Vector<MediaSession*> sessions = m_sessions;
90 for (auto* session : sessions)
91 session->beginInterruption();
94 void MediaSessionManager::endInterruption(MediaSession::EndInterruptionFlags flags)
96 LOG(Media, "MediaSessionManager::endInterruption");
98 m_interrupted = false;
99 Vector<MediaSession*> sessions = m_sessions;
100 for (auto* session : sessions)
101 session->endInterruption(flags);
104 void MediaSessionManager::addSession(MediaSession& session)
106 LOG(Media, "MediaSessionManager::addSession - %p", &session);
108 m_sessions.append(&session);
110 session.setState(MediaSession::Interrupted);
111 updateSessionState();
113 if (!m_remoteCommandListener)
114 m_remoteCommandListener = RemoteCommandListener::create(*this);
116 if (m_clients.isEmpty() || !(session.mediaType() == MediaSession::Video || session.mediaType() == MediaSession::Audio))
119 for (auto& client : m_clients)
120 client->startListeningForRemoteControlCommands();
123 void MediaSessionManager::removeSession(MediaSession& session)
125 LOG(Media, "MediaSessionManager::removeSession - %p", &session);
127 size_t index = m_sessions.find(&session);
128 ASSERT(index != notFound);
129 if (index == notFound)
132 m_sessions.remove(index);
133 updateSessionState();
135 if (m_sessions.isEmpty())
136 m_remoteCommandListener = nullptr;
138 if (m_clients.isEmpty() || !(session.mediaType() == MediaSession::Video || session.mediaType() == MediaSession::Audio))
141 for (auto& client : m_clients)
142 client->startListeningForRemoteControlCommands();
145 void MediaSessionManager::addRestriction(MediaSession::MediaType type, SessionRestrictions restriction)
147 ASSERT(type > MediaSession::None && type <= MediaSession::WebAudio);
148 m_restrictions[type] |= restriction;
151 void MediaSessionManager::removeRestriction(MediaSession::MediaType type, SessionRestrictions restriction)
153 ASSERT(type > MediaSession::None && type <= MediaSession::WebAudio);
154 m_restrictions[type] &= ~restriction;
157 MediaSessionManager::SessionRestrictions MediaSessionManager::restrictions(MediaSession::MediaType type)
159 ASSERT(type > MediaSession::None && type <= MediaSession::WebAudio);
160 return m_restrictions[type];
163 void MediaSessionManager::sessionWillBeginPlayback(MediaSession& session)
165 LOG(Media, "MediaSessionManager::sessionWillBeginPlayback - %p", &session);
167 setCurrentSession(session);
169 if (!m_clients.isEmpty() && (session.mediaType() == MediaSession::Video || session.mediaType() == MediaSession::Audio)) {
170 for (auto& client : m_clients)
171 client->didBeginPlayback();
174 MediaSession::MediaType sessionType = session.mediaType();
175 SessionRestrictions restrictions = m_restrictions[sessionType];
176 if (!restrictions & ConcurrentPlaybackNotPermitted)
179 Vector<MediaSession*> sessions = m_sessions;
180 for (auto* oneSession : sessions) {
181 if (oneSession == &session)
183 if (oneSession->mediaType() != sessionType)
185 if (restrictions & ConcurrentPlaybackNotPermitted)
186 oneSession->pauseSession();
190 void MediaSessionManager::sessionWillEndPlayback(MediaSession& session)
192 LOG(Media, "MediaSessionManager::sessionWillEndPlayback - %p", &session);
194 if (m_sessions.size() < 2)
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];
202 if (oneSession == &session) {
203 pausingSessionIndex = i;
206 if (oneSession->state() == MediaSession::Playing) {
207 lastPlayingSessionIndex = i;
210 if (oneSession->state() != MediaSession::Playing)
213 if (lastPlayingSessionIndex == notFound || pausingSessionIndex == notFound)
216 if (pausingSessionIndex > lastPlayingSessionIndex)
219 m_sessions.remove(pausingSessionIndex);
220 m_sessions.insert(lastPlayingSessionIndex, &session);
222 LOG(Media, "MediaSessionManager::sessionWillEndPlayback - session moved from index %zu to %zu", pausingSessionIndex, lastPlayingSessionIndex);
225 void MediaSessionManager::setCurrentSession(MediaSession& session)
227 LOG(Media, "MediaSessionManager::setCurrentSession - %p", &session);
229 if (m_sessions.size() < 2)
232 size_t index = m_sessions.find(&session);
233 ASSERT(index != notFound);
234 if (!index || index == notFound)
237 m_sessions.remove(index);
238 m_sessions.insert(0, &session);
240 LOG(Media, "MediaSessionManager::setCurrentSession - session moved from index %zu to 0", index);
243 MediaSession* MediaSessionManager::currentSession()
245 if (!m_sessions.size())
248 return m_sessions[0];
251 bool MediaSessionManager::sessionRestrictsInlineVideoPlayback(const MediaSession& session) const
253 MediaSession::MediaType sessionType = session.mediaType();
254 if (sessionType != MediaSession::Video)
257 return m_restrictions[sessionType] & InlineVideoPlaybackRestricted;
260 void MediaSessionManager::applicationWillEnterBackground() const
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();
270 void MediaSessionManager::applicationWillEnterForeground() const
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);
280 void MediaSessionManager::wirelessRoutesAvailableChanged()
286 void MediaSessionManager::updateSessionState()
291 void MediaSessionManager::didReceiveRemoteControlCommand(MediaSession::RemoteControlCommandType command)
293 MediaSession* activeSession = currentSession();
294 if (!activeSession || !activeSession->canReceiveRemoteControlCommands())
296 activeSession->didReceiveRemoteControlCommand(command);
299 void MediaSessionManager::addClient(MediaSessionManagerClient* client)
301 ASSERT(!m_clients.contains(client));
302 m_clients.append(client);
305 void MediaSessionManager::removeClient(MediaSessionManagerClient* client)
307 ASSERT(m_clients.contains(client));
308 m_clients.remove(m_clients.find(client));
311 void MediaSessionManager::systemWillSleep()
316 for (auto session : m_sessions)
317 session->beginInterruption();
320 void MediaSessionManager::systemDidWake()
325 for (auto session : m_sessions)
326 session->endInterruption(MediaSession::MayResumePlaying);