79834f7aa1518f1cbae8cba38e4ecd530a36c37d
[WebKit-https.git] / Source / WebCore / platform / audio / MediaSessionManager.cpp
1 /*
2  * Copyright (C) 2013 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 #include "Logging.h"
30 #include "MediaSession.h"
31
32 namespace WebCore {
33
34 #if !PLATFORM(IOS)
35 MediaSessionManager& MediaSessionManager::sharedManager()
36 {
37     DEPRECATED_DEFINE_STATIC_LOCAL(MediaSessionManager, manager, ());
38     return manager;
39 }
40 #endif
41
42 MediaSessionManager::MediaSessionManager()
43     : m_activeSession(nullptr)
44     , m_interrupted(false)
45 {
46     resetRestrictions();
47 }
48
49 void MediaSessionManager::resetRestrictions()
50 {
51     m_restrictions[MediaSession::Video] = NoRestrictions;
52     m_restrictions[MediaSession::Audio] = NoRestrictions;
53     m_restrictions[MediaSession::WebAudio] = NoRestrictions;
54 }
55
56 bool MediaSessionManager::has(MediaSession::MediaType type) const
57 {
58     ASSERT(type >= MediaSession::None && type <= MediaSession::WebAudio);
59
60     for (auto* session : m_sessions) {
61         if (session->mediaType() == type)
62             return true;
63     }
64
65     return false;
66 }
67
68 int MediaSessionManager::count(MediaSession::MediaType type) const
69 {
70     ASSERT(type >= MediaSession::None && type <= MediaSession::WebAudio);
71     
72     int count = 0;
73     for (auto* session : m_sessions) {
74         if (session->mediaType() == type)
75             ++count;
76     }
77
78     return count;
79 }
80
81 void MediaSessionManager::beginInterruption()
82 {
83     LOG(Media, "MediaSessionManager::beginInterruption");
84
85     m_interrupted = true;
86     for (auto* session : m_sessions)
87         session->beginInterruption();
88 }
89
90 void MediaSessionManager::endInterruption(MediaSession::EndInterruptionFlags flags)
91 {
92     LOG(Media, "MediaSessionManager::endInterruption");
93
94     m_interrupted = false;
95     for (auto* session : m_sessions)
96         session->endInterruption(flags);
97 }
98
99 void MediaSessionManager::addSession(MediaSession& session)
100 {
101     m_sessions.append(&session);
102     if (m_interrupted)
103         session.setState(MediaSession::Interrupted);
104     updateSessionState();
105
106     if (!m_remoteCommandListener)
107         m_remoteCommandListener = RemoteCommandListener::create(*this);
108
109     if (m_clients.isEmpty() || !(session.mediaType() == MediaSession::Video || session.mediaType() == MediaSession::Audio))
110         return;
111
112     for (auto& client : m_clients)
113         client->startListeningForRemoteControlCommands();
114 }
115
116 void MediaSessionManager::removeSession(MediaSession& session)
117 {
118     size_t index = m_sessions.find(&session);
119     ASSERT(index != notFound);
120     if (index == notFound)
121         return;
122     
123     if (m_activeSession == &session)
124         setCurrentSession(nullptr);
125     
126     m_sessions.remove(index);
127     updateSessionState();
128
129     if (m_sessions.isEmpty())
130         m_remoteCommandListener = nullptr;
131
132     if (m_clients.isEmpty() || !(session.mediaType() == MediaSession::Video || session.mediaType() == MediaSession::Audio))
133         return;
134
135     for (auto& client : m_clients)
136         client->startListeningForRemoteControlCommands();
137 }
138
139 void MediaSessionManager::addRestriction(MediaSession::MediaType type, SessionRestrictions restriction)
140 {
141     ASSERT(type > MediaSession::None && type <= MediaSession::WebAudio);
142     m_restrictions[type] |= restriction;
143 }
144
145 void MediaSessionManager::removeRestriction(MediaSession::MediaType type, SessionRestrictions restriction)
146 {
147     ASSERT(type > MediaSession::None && type <= MediaSession::WebAudio);
148     m_restrictions[type] &= ~restriction;
149 }
150
151 MediaSessionManager::SessionRestrictions MediaSessionManager::restrictions(MediaSession::MediaType type)
152 {
153     ASSERT(type > MediaSession::None && type <= MediaSession::WebAudio);
154     return m_restrictions[type];
155 }
156
157 void MediaSessionManager::sessionWillBeginPlayback(MediaSession& session)
158 {
159     setCurrentSession(&session);
160
161     if (!m_clients.isEmpty() && (session.mediaType() == MediaSession::Video || session.mediaType() == MediaSession::Audio)) {
162         for (auto& client : m_clients)
163             client->didBeginPlayback();
164     }
165
166     MediaSession::MediaType sessionType = session.mediaType();
167     SessionRestrictions restrictions = m_restrictions[sessionType];
168     if (!restrictions & ConcurrentPlaybackNotPermitted)
169         return;
170
171     for (auto* oneSession : m_sessions) {
172         if (oneSession == &session)
173             continue;
174         if (oneSession->mediaType() != sessionType)
175             continue;
176         if (restrictions & ConcurrentPlaybackNotPermitted)
177             oneSession->pauseSession();
178     }
179 }
180
181 bool MediaSessionManager::sessionRestrictsInlineVideoPlayback(const MediaSession& session) const
182 {
183     MediaSession::MediaType sessionType = session.mediaType();
184     if (sessionType != MediaSession::Video)
185         return false;
186
187     return m_restrictions[sessionType] & InlineVideoPlaybackRestricted;
188 }
189
190 void MediaSessionManager::applicationWillEnterBackground() const
191 {
192     LOG(Media, "MediaSessionManager::applicationWillEnterBackground");
193     for (auto* session : m_sessions) {
194         if (m_restrictions[session->mediaType()] & BackgroundPlaybackNotPermitted)
195             session->beginInterruption();
196     }
197 }
198
199 void MediaSessionManager::applicationWillEnterForeground() const
200 {
201     LOG(Media, "MediaSessionManager::applicationWillEnterForeground");
202     for (auto* session : m_sessions) {
203         if (m_restrictions[session->mediaType()] & BackgroundPlaybackNotPermitted)
204             session->endInterruption(MediaSession::MayResumePlaying);
205     }
206 }
207
208 #if !PLATFORM(COCOA)
209 void MediaSessionManager::updateSessionState()
210 {
211 }
212 #endif
213
214 void MediaSessionManager::didReceiveRemoteControlCommand(MediaSession::RemoteControlCommandType command)
215 {
216     if (!m_activeSession || !m_activeSession->canReceiveRemoteControlCommands())
217         return;
218     m_activeSession->didReceiveRemoteControlCommand(command);
219 }
220
221 void MediaSessionManager::addClient(MediaSessionManagerClient* client)
222 {
223     ASSERT(!m_clients.contains(client));
224     m_clients.append(client);
225 }
226
227 void MediaSessionManager::removeClient(MediaSessionManagerClient* client)
228 {
229     ASSERT(m_clients.contains(client));
230     m_clients.remove(m_clients.find(client));
231 }
232
233 }