1 | /* |
2 | * Copyright (C) 2014-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 | * 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 | #ifndef PlatformMediaSession_h |
27 | #define PlatformMediaSession_h |
28 | |
29 | #include "Timer.h" |
30 | #include <wtf/LoggerHelper.h> |
31 | #include <wtf/Noncopyable.h> |
32 | #include <wtf/text/WTFString.h> |
33 | |
34 | #if ENABLE(WIRELESS_PLAYBACK_TARGET) |
35 | #include "MediaPlaybackTargetClient.h" |
36 | #endif |
37 | |
38 | namespace WebCore { |
39 | |
40 | class Document; |
41 | class MediaPlaybackTarget; |
42 | class PlatformMediaSessionClient; |
43 | |
44 | class PlatformMediaSession |
45 | #if ENABLE(WIRELESS_PLAYBACK_TARGET) |
46 | : public MediaPlaybackTargetClient |
47 | #endif |
48 | #if !RELEASE_LOG_DISABLED |
49 | , private LoggerHelper |
50 | #endif |
51 | { |
52 | WTF_MAKE_FAST_ALLOCATED; |
53 | public: |
54 | static std::unique_ptr<PlatformMediaSession> create(PlatformMediaSessionClient&); |
55 | |
56 | PlatformMediaSession(PlatformMediaSessionClient&); |
57 | virtual ~PlatformMediaSession(); |
58 | |
59 | enum MediaType { |
60 | None = 0, |
61 | Video, |
62 | VideoAudio, |
63 | Audio, |
64 | WebAudio, |
65 | MediaStreamCapturingAudio, |
66 | }; |
67 | MediaType mediaType() const; |
68 | MediaType presentationType() const; |
69 | |
70 | enum State { |
71 | Idle, |
72 | Autoplaying, |
73 | Playing, |
74 | Paused, |
75 | Interrupted, |
76 | }; |
77 | State state() const { return m_state; } |
78 | void setState(State); |
79 | |
80 | enum InterruptionType { |
81 | NoInterruption, |
82 | SystemSleep, |
83 | EnteringBackground, |
84 | SystemInterruption, |
85 | SuspendedUnderLock, |
86 | InvisibleAutoplay, |
87 | ProcessInactive, |
88 | PlaybackSuspended, |
89 | }; |
90 | InterruptionType interruptionType() const { return m_interruptionType; } |
91 | |
92 | enum EndInterruptionFlags { |
93 | NoFlags = 0, |
94 | MayResumePlaying = 1 << 0, |
95 | }; |
96 | |
97 | enum Characteristics { |
98 | HasNothing = 0, |
99 | HasAudio = 1 << 0, |
100 | HasVideo = 1 << 1, |
101 | }; |
102 | typedef unsigned CharacteristicsFlags; |
103 | |
104 | CharacteristicsFlags characteristics() const; |
105 | void clientCharacteristicsChanged(); |
106 | |
107 | void beginInterruption(InterruptionType); |
108 | void endInterruption(EndInterruptionFlags); |
109 | |
110 | virtual void clientWillBeginAutoplaying(); |
111 | virtual bool clientWillBeginPlayback(); |
112 | virtual bool clientWillPausePlayback(); |
113 | |
114 | void pauseSession(); |
115 | void stopSession(); |
116 | |
117 | virtual void suspendBuffering() { } |
118 | virtual void resumeBuffering() { } |
119 | |
120 | #if ENABLE(VIDEO) |
121 | uint64_t uniqueIdentifier() const; |
122 | String title() const; |
123 | double duration() const; |
124 | double currentTime() const; |
125 | #endif |
126 | |
127 | typedef union { |
128 | double asDouble; |
129 | } RemoteCommandArgument; |
130 | |
131 | enum RemoteControlCommandType { |
132 | NoCommand, |
133 | PlayCommand, |
134 | PauseCommand, |
135 | StopCommand, |
136 | TogglePlayPauseCommand, |
137 | BeginSeekingBackwardCommand, |
138 | EndSeekingBackwardCommand, |
139 | BeginSeekingForwardCommand, |
140 | EndSeekingForwardCommand, |
141 | SeekToPlaybackPositionCommand, |
142 | }; |
143 | bool canReceiveRemoteControlCommands() const; |
144 | void didReceiveRemoteControlCommand(RemoteControlCommandType, const RemoteCommandArgument* argument = nullptr); |
145 | bool supportsSeeking() const; |
146 | |
147 | enum DisplayType { |
148 | Normal, |
149 | Fullscreen, |
150 | Optimized, |
151 | }; |
152 | DisplayType displayType() const; |
153 | |
154 | bool isHidden() const; |
155 | bool isSuspended() const; |
156 | |
157 | bool shouldOverrideBackgroundLoadingRestriction() const; |
158 | |
159 | virtual bool isPlayingToWirelessPlaybackTarget() const { return m_isPlayingToWirelessPlaybackTarget; } |
160 | void isPlayingToWirelessPlaybackTargetChanged(bool); |
161 | |
162 | #if ENABLE(WIRELESS_PLAYBACK_TARGET) |
163 | // MediaPlaybackTargetClient |
164 | void setPlaybackTarget(Ref<MediaPlaybackTarget>&&) override { } |
165 | void externalOutputDeviceAvailableDidChange(bool) override { } |
166 | void setShouldPlayToPlaybackTarget(bool) override { } |
167 | #endif |
168 | |
169 | #if PLATFORM(IOS_FAMILY) |
170 | virtual bool requiresPlaybackTargetRouteMonitoring() const { return false; } |
171 | #endif |
172 | |
173 | bool activeAudioSessionRequired(); |
174 | bool canProduceAudio() const; |
175 | void canProduceAudioChanged(); |
176 | |
177 | virtual void resetPlaybackSessionState() { } |
178 | String sourceApplicationIdentifier() const; |
179 | |
180 | virtual bool allowsNowPlayingControlsVisibility() const { return false; } |
181 | |
182 | bool hasPlayedSinceLastInterruption() const { return m_hasPlayedSinceLastInterruption; } |
183 | void clearHasPlayedSinceLastInterruption() { m_hasPlayedSinceLastInterruption = false; } |
184 | |
185 | #if !RELEASE_LOG_DISABLED |
186 | const Logger& logger() const final { return m_logger.get(); } |
187 | const void* logIdentifier() const override { return m_logIdentifier; } |
188 | const char* logClassName() const override { return "PlatformMediaSession" ; } |
189 | WTFLogChannel& logChannel() const final; |
190 | #endif |
191 | |
192 | protected: |
193 | PlatformMediaSessionClient& client() const { return m_client; } |
194 | |
195 | private: |
196 | PlatformMediaSessionClient& m_client; |
197 | State m_state; |
198 | State m_stateToRestore; |
199 | InterruptionType m_interruptionType { NoInterruption }; |
200 | int m_interruptionCount { 0 }; |
201 | bool m_notifyingClient; |
202 | bool m_isPlayingToWirelessPlaybackTarget { false }; |
203 | bool m_hasPlayedSinceLastInterruption { false }; |
204 | |
205 | #if !RELEASE_LOG_DISABLED |
206 | Ref<const Logger> m_logger; |
207 | const void* m_logIdentifier; |
208 | #endif |
209 | |
210 | friend class PlatformMediaSessionManager; |
211 | }; |
212 | |
213 | class PlatformMediaSessionClient { |
214 | WTF_MAKE_NONCOPYABLE(PlatformMediaSessionClient); |
215 | public: |
216 | PlatformMediaSessionClient() = default; |
217 | |
218 | virtual PlatformMediaSession::MediaType mediaType() const = 0; |
219 | virtual PlatformMediaSession::MediaType presentationType() const = 0; |
220 | virtual PlatformMediaSession::DisplayType displayType() const { return PlatformMediaSession::Normal; } |
221 | virtual PlatformMediaSession::CharacteristicsFlags characteristics() const = 0; |
222 | |
223 | virtual void resumeAutoplaying() { } |
224 | virtual void mayResumePlayback(bool shouldResume) = 0; |
225 | virtual void suspendPlayback() = 0; |
226 | |
227 | #if ENABLE(VIDEO) |
228 | virtual uint64_t mediaSessionUniqueIdentifier() const; |
229 | virtual String mediaSessionTitle() const; |
230 | virtual double mediaSessionDuration() const; |
231 | virtual double mediaSessionCurrentTime() const; |
232 | #endif |
233 | |
234 | virtual bool canReceiveRemoteControlCommands() const = 0; |
235 | virtual void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType, const PlatformMediaSession::RemoteCommandArgument*) = 0; |
236 | virtual bool supportsSeeking() const = 0; |
237 | |
238 | virtual bool canProduceAudio() const { return false; } |
239 | virtual bool isSuspended() const { return false; }; |
240 | |
241 | virtual bool shouldOverrideBackgroundPlaybackRestriction(PlatformMediaSession::InterruptionType) const = 0; |
242 | virtual bool shouldOverrideBackgroundLoadingRestriction() const { return false; } |
243 | |
244 | virtual void wirelessRoutesAvailableDidChange() { } |
245 | virtual void setWirelessPlaybackTarget(Ref<MediaPlaybackTarget>&&) { } |
246 | virtual bool isPlayingToWirelessPlaybackTarget() const { return false; } |
247 | virtual void setShouldPlayToPlaybackTarget(bool) { } |
248 | |
249 | virtual bool isPlayingOnSecondScreen() const { return false; } |
250 | |
251 | virtual Document* hostingDocument() const = 0; |
252 | virtual String sourceApplicationIdentifier() const = 0; |
253 | |
254 | virtual bool processingUserGestureForMedia() const = 0; |
255 | |
256 | protected: |
257 | virtual ~PlatformMediaSessionClient() = default; |
258 | }; |
259 | |
260 | String convertEnumerationToString(PlatformMediaSession::State); |
261 | String convertEnumerationToString(PlatformMediaSession::InterruptionType); |
262 | String convertEnumerationToString(PlatformMediaSession::RemoteControlCommandType); |
263 | } |
264 | |
265 | namespace WTF { |
266 | |
267 | template<typename Type> |
268 | struct LogArgument; |
269 | |
270 | template <> |
271 | struct LogArgument<WebCore::PlatformMediaSession::State> { |
272 | static String toString(const WebCore::PlatformMediaSession::State state) |
273 | { |
274 | return convertEnumerationToString(state); |
275 | } |
276 | }; |
277 | |
278 | template <> |
279 | struct LogArgument<WebCore::PlatformMediaSession::InterruptionType> { |
280 | static String toString(const WebCore::PlatformMediaSession::InterruptionType state) |
281 | { |
282 | return convertEnumerationToString(state); |
283 | } |
284 | }; |
285 | |
286 | template <> |
287 | struct LogArgument<WebCore::PlatformMediaSession::RemoteControlCommandType> { |
288 | static String toString(const WebCore::PlatformMediaSession::RemoteControlCommandType command) |
289 | { |
290 | return convertEnumerationToString(command); |
291 | } |
292 | }; |
293 | |
294 | } // namespace WTF |
295 | |
296 | #endif // PlatformMediaSession_h |
297 | |