2 * Copyright (C) 2016-2017 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 #import "PlaybackSessionManagerProxy.h"
29 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
31 #import "PlaybackSessionManagerMessages.h"
32 #import "PlaybackSessionManagerProxyMessages.h"
33 #import "WebPageProxy.h"
34 #import "WebProcessProxy.h"
37 using namespace WebCore;
39 #pragma mark - PlaybackSessionModelContext
41 void PlaybackSessionModelContext::addClient(PlaybackSessionModelClient& client)
43 ASSERT(!m_clients.contains(&client));
44 m_clients.add(&client);
47 void PlaybackSessionModelContext::removeClient(PlaybackSessionModelClient& client)
49 ASSERT(m_clients.contains(&client));
50 m_clients.remove(&client);
53 void PlaybackSessionModelContext::play()
56 m_manager->play(m_contextId);
59 void PlaybackSessionModelContext::pause()
62 m_manager->pause(m_contextId);
65 void PlaybackSessionModelContext::togglePlayState()
68 m_manager->togglePlayState(m_contextId);
71 void PlaybackSessionModelContext::beginScrubbing()
74 m_manager->beginScrubbing(m_contextId);
79 void PlaybackSessionModelContext::endScrubbing()
82 m_manager->endScrubbing(m_contextId);
84 m_isScrubbing = false;
85 m_playbackStartedTimeNeedsUpdate = isPlaying();
88 void PlaybackSessionModelContext::seekToTime(double time, double toleranceBefore, double toleranceAfter)
91 m_manager->seekToTime(m_contextId, time, toleranceBefore, toleranceAfter);
94 void PlaybackSessionModelContext::fastSeek(double time)
97 m_manager->fastSeek(m_contextId, time);
100 void PlaybackSessionModelContext::beginScanningForward()
103 m_manager->beginScanningForward(m_contextId);
106 void PlaybackSessionModelContext::beginScanningBackward()
109 m_manager->beginScanningBackward(m_contextId);
112 void PlaybackSessionModelContext::endScanning()
115 m_manager->endScanning(m_contextId);
118 void PlaybackSessionModelContext::selectAudioMediaOption(uint64_t optionId)
121 m_manager->selectAudioMediaOption(m_contextId, optionId);
124 void PlaybackSessionModelContext::selectLegibleMediaOption(uint64_t optionId)
127 m_manager->selectLegibleMediaOption(m_contextId, optionId);
130 void PlaybackSessionModelContext::togglePictureInPicture()
133 m_manager->togglePictureInPicture(m_contextId);
136 void PlaybackSessionModelContext::toggleMuted()
139 m_manager->toggleMuted(m_contextId);
142 void PlaybackSessionModelContext::setMuted(bool muted)
145 m_manager->setMuted(m_contextId, muted);
148 void PlaybackSessionModelContext::setVolume(double volume)
151 m_manager->setVolume(m_contextId, volume);
154 void PlaybackSessionModelContext::setPlayingOnSecondScreen(bool value)
157 m_manager->setPlayingOnSecondScreen(m_contextId, value);
160 void PlaybackSessionModelContext::playbackStartedTimeChanged(double playbackStartedTime)
162 m_playbackStartedTime = playbackStartedTime;
163 m_playbackStartedTimeNeedsUpdate = false;
166 void PlaybackSessionModelContext::durationChanged(double duration)
168 m_duration = duration;
169 for (auto* client : m_clients)
170 client->durationChanged(duration);
173 void PlaybackSessionModelContext::currentTimeChanged(double currentTime)
175 m_currentTime = currentTime;
176 auto anchorTime = [[NSProcessInfo processInfo] systemUptime];
177 if (m_playbackStartedTimeNeedsUpdate)
178 playbackStartedTimeChanged(currentTime);
180 for (auto* client : m_clients)
181 client->currentTimeChanged(currentTime, anchorTime);
184 void PlaybackSessionModelContext::bufferedTimeChanged(double bufferedTime)
186 m_bufferedTime = bufferedTime;
187 for (auto* client : m_clients)
188 client->bufferedTimeChanged(bufferedTime);
191 void PlaybackSessionModelContext::rateChanged(bool isPlaying, float playbackRate)
193 m_isPlaying = isPlaying;
194 m_playbackRate = playbackRate;
195 for (auto* client : m_clients)
196 client->rateChanged(isPlaying, playbackRate);
199 void PlaybackSessionModelContext::seekableRangesChanged(WebCore::TimeRanges& seekableRanges, double lastModifiedTime, double liveUpdateInterval)
201 m_seekableRanges = seekableRanges;
202 m_seekableTimeRangesLastModifiedTime = lastModifiedTime;
203 m_liveUpdateInterval = liveUpdateInterval;
204 for (auto* client : m_clients)
205 client->seekableRangesChanged(seekableRanges, lastModifiedTime, liveUpdateInterval);
208 void PlaybackSessionModelContext::canPlayFastReverseChanged(bool canPlayFastReverse)
210 m_canPlayFastReverse = canPlayFastReverse;
211 for (auto* client : m_clients)
212 client->canPlayFastReverseChanged(canPlayFastReverse);
215 void PlaybackSessionModelContext::audioMediaSelectionOptionsChanged(const Vector<MediaSelectionOption>& audioMediaSelectionOptions, uint64_t audioMediaSelectedIndex)
217 m_audioMediaSelectionOptions = audioMediaSelectionOptions;
218 m_audioMediaSelectedIndex = audioMediaSelectedIndex;
219 for (auto* client : m_clients)
220 client->audioMediaSelectionOptionsChanged(audioMediaSelectionOptions, audioMediaSelectedIndex);
223 void PlaybackSessionModelContext::legibleMediaSelectionOptionsChanged(const Vector<MediaSelectionOption>& legibleMediaSelectionOptions, uint64_t legibleMediaSelectedIndex)
225 m_legibleMediaSelectionOptions = legibleMediaSelectionOptions;
226 m_legibleMediaSelectedIndex = legibleMediaSelectedIndex;
228 for (auto* client : m_clients)
229 client->legibleMediaSelectionOptionsChanged(legibleMediaSelectionOptions, legibleMediaSelectedIndex);
232 void PlaybackSessionModelContext::audioMediaSelectionIndexChanged(uint64_t selectedIndex)
234 m_audioMediaSelectedIndex = selectedIndex;
236 for (auto* client : m_clients)
237 client->audioMediaSelectionIndexChanged(selectedIndex);
240 void PlaybackSessionModelContext::legibleMediaSelectionIndexChanged(uint64_t selectedIndex)
242 m_legibleMediaSelectedIndex = selectedIndex;
244 for (auto* client : m_clients)
245 client->legibleMediaSelectionIndexChanged(selectedIndex);
248 void PlaybackSessionModelContext::externalPlaybackChanged(bool enabled, PlaybackSessionModel::ExternalPlaybackTargetType type, const String& localizedName)
250 m_externalPlaybackEnabled = enabled;
251 m_externalPlaybackTargetType = type;
252 m_externalPlaybackLocalizedDeviceName = localizedName;
254 for (auto* client : m_clients)
255 client->externalPlaybackChanged(enabled, type, localizedName);
258 void PlaybackSessionModelContext::wirelessVideoPlaybackDisabledChanged(bool wirelessVideoPlaybackDisabled)
260 m_wirelessVideoPlaybackDisabled = wirelessVideoPlaybackDisabled;
261 for (auto* client : m_clients)
262 client->wirelessVideoPlaybackDisabledChanged(wirelessVideoPlaybackDisabled);
265 void PlaybackSessionModelContext::mutedChanged(bool muted)
268 for (auto* client : m_clients)
269 client->mutedChanged(muted);
272 void PlaybackSessionModelContext::volumeChanged(double volume)
275 for (auto* client : m_clients)
276 client->volumeChanged(volume);
279 void PlaybackSessionModelContext::pictureInPictureSupportedChanged(bool supported)
281 m_pictureInPictureSupported = supported;
282 for (auto* client : m_clients)
283 client->isPictureInPictureSupportedChanged(supported);
286 void PlaybackSessionModelContext::pictureInPictureActiveChanged(bool active)
288 m_pictureInPictureActive = active;
289 for (auto* client : m_clients)
290 client->pictureInPictureActiveChanged(active);
293 #pragma mark - PlaybackSessionManagerProxy
295 RefPtr<PlaybackSessionManagerProxy> PlaybackSessionManagerProxy::create(WebPageProxy& page)
297 return adoptRef(new PlaybackSessionManagerProxy(page));
300 PlaybackSessionManagerProxy::PlaybackSessionManagerProxy(WebPageProxy& page)
303 m_page->process().addMessageReceiver(Messages::PlaybackSessionManagerProxy::messageReceiverName(), m_page->pageID(), *this);
306 PlaybackSessionManagerProxy::~PlaybackSessionManagerProxy()
313 void PlaybackSessionManagerProxy::invalidate()
315 m_page->process().removeMessageReceiver(Messages::PlaybackSessionManagerProxy::messageReceiverName(), m_page->pageID());
318 auto contextMap = WTFMove(m_contextMap);
319 m_clientCounts.clear();
321 for (auto& tuple : contextMap.values()) {
322 RefPtr<PlaybackSessionModelContext> model;
323 RefPtr<PlatformPlaybackSessionInterface> interface;
324 std::tie(model, interface) = tuple;
326 interface->invalidate();
330 PlaybackSessionManagerProxy::ModelInterfaceTuple PlaybackSessionManagerProxy::createModelAndInterface(uint64_t contextId)
332 Ref<PlaybackSessionModelContext> model = PlaybackSessionModelContext::create(*this, contextId);
333 Ref<PlatformPlaybackSessionInterface> interface = PlatformPlaybackSessionInterface::create(model);
335 return std::make_tuple(WTFMove(model), WTFMove(interface));
338 PlaybackSessionManagerProxy::ModelInterfaceTuple& PlaybackSessionManagerProxy::ensureModelAndInterface(uint64_t contextId)
340 auto addResult = m_contextMap.add(contextId, ModelInterfaceTuple());
341 if (addResult.isNewEntry)
342 addResult.iterator->value = createModelAndInterface(contextId);
343 return addResult.iterator->value;
346 PlaybackSessionModelContext& PlaybackSessionManagerProxy::ensureModel(uint64_t contextId)
348 return *std::get<0>(ensureModelAndInterface(contextId));
351 PlatformPlaybackSessionInterface& PlaybackSessionManagerProxy::ensureInterface(uint64_t contextId)
353 return *std::get<1>(ensureModelAndInterface(contextId));
356 void PlaybackSessionManagerProxy::addClientForContext(uint64_t contextId)
358 m_clientCounts.add(contextId);
361 void PlaybackSessionManagerProxy::removeClientForContext(uint64_t contextId)
363 if (!m_clientCounts.remove(contextId))
366 ensureInterface(contextId).invalidate();
367 m_contextMap.remove(contextId);
370 #pragma mark Messages from PlaybackSessionManager
372 void PlaybackSessionManagerProxy::setUpPlaybackControlsManagerWithID(uint64_t contextId)
374 if (m_controlsManagerContextId == contextId)
377 if (m_controlsManagerContextId)
378 removeClientForContext(m_controlsManagerContextId);
380 m_controlsManagerContextId = contextId;
381 ensureInterface(m_controlsManagerContextId).ensureControlsManager();
382 addClientForContext(m_controlsManagerContextId);
384 m_page->videoControlsManagerDidChange();
387 void PlaybackSessionManagerProxy::clearPlaybackControlsManager()
389 if (!m_controlsManagerContextId)
392 removeClientForContext(m_controlsManagerContextId);
393 m_controlsManagerContextId = 0;
394 m_page->videoControlsManagerDidChange();
397 void PlaybackSessionManagerProxy::currentTimeChanged(uint64_t contextId, double currentTime, double hostTime)
399 ensureModel(contextId).currentTimeChanged(currentTime);
402 void PlaybackSessionManagerProxy::bufferedTimeChanged(uint64_t contextId, double bufferedTime)
404 ensureModel(contextId).bufferedTimeChanged(bufferedTime);
407 void PlaybackSessionManagerProxy::seekableRangesVectorChanged(uint64_t contextId, Vector<std::pair<double, double>> ranges, double lastModifiedTime, double liveUpdateInterval)
409 Ref<TimeRanges> timeRanges = TimeRanges::create();
410 for (const auto& range : ranges) {
411 ASSERT(isfinite(range.first));
412 ASSERT(isfinite(range.second));
413 ASSERT(range.second >= range.first);
414 timeRanges->add(range.first, range.second);
417 ensureModel(contextId).seekableRangesChanged(timeRanges, lastModifiedTime, liveUpdateInterval);
420 void PlaybackSessionManagerProxy::canPlayFastReverseChanged(uint64_t contextId, bool value)
422 ensureModel(contextId).canPlayFastReverseChanged(value);
425 void PlaybackSessionManagerProxy::audioMediaSelectionOptionsChanged(uint64_t contextId, Vector<MediaSelectionOption> options, uint64_t selectedIndex)
427 ensureModel(contextId).audioMediaSelectionOptionsChanged(options, selectedIndex);
430 void PlaybackSessionManagerProxy::legibleMediaSelectionOptionsChanged(uint64_t contextId, Vector<MediaSelectionOption> options, uint64_t selectedIndex)
432 ensureModel(contextId).legibleMediaSelectionOptionsChanged(options, selectedIndex);
435 void PlaybackSessionManagerProxy::audioMediaSelectionIndexChanged(uint64_t contextId, uint64_t selectedIndex)
437 ensureModel(contextId).audioMediaSelectionIndexChanged(selectedIndex);
440 void PlaybackSessionManagerProxy::legibleMediaSelectionIndexChanged(uint64_t contextId, uint64_t selectedIndex)
442 ensureModel(contextId).legibleMediaSelectionIndexChanged(selectedIndex);
445 void PlaybackSessionManagerProxy::externalPlaybackPropertiesChanged(uint64_t contextId, bool enabled, uint32_t targetType, String localizedDeviceName)
447 PlaybackSessionModel::ExternalPlaybackTargetType type = static_cast<PlaybackSessionModel::ExternalPlaybackTargetType>(targetType);
448 ASSERT(type == PlaybackSessionModel::TargetTypeAirPlay || type == PlaybackSessionModel::TargetTypeTVOut || type == PlaybackSessionModel::TargetTypeNone);
450 ensureModel(contextId).externalPlaybackChanged(enabled, type, localizedDeviceName);
453 void PlaybackSessionManagerProxy::wirelessVideoPlaybackDisabledChanged(uint64_t contextId, bool disabled)
455 ensureModel(contextId).wirelessVideoPlaybackDisabledChanged(disabled);
458 void PlaybackSessionManagerProxy::mutedChanged(uint64_t contextId, bool muted)
460 ensureModel(contextId).mutedChanged(muted);
463 void PlaybackSessionManagerProxy::volumeChanged(uint64_t contextId, double volume)
465 ensureModel(contextId).volumeChanged(volume);
468 void PlaybackSessionManagerProxy::durationChanged(uint64_t contextId, double duration)
470 ensureModel(contextId).durationChanged(duration);
473 void PlaybackSessionManagerProxy::playbackStartedTimeChanged(uint64_t contextId, double playbackStartedTime)
475 ensureModel(contextId).playbackStartedTimeChanged(playbackStartedTime);
478 void PlaybackSessionManagerProxy::rateChanged(uint64_t contextId, bool isPlaying, double rate)
480 ensureModel(contextId).rateChanged(isPlaying, rate);
483 void PlaybackSessionManagerProxy::pictureInPictureSupportedChanged(uint64_t contextId, bool supported)
485 ensureModel(contextId).pictureInPictureSupportedChanged(supported);
488 void PlaybackSessionManagerProxy::pictureInPictureActiveChanged(uint64_t contextId, bool active)
490 ensureModel(contextId).pictureInPictureActiveChanged(active);
493 void PlaybackSessionManagerProxy::handleControlledElementIDResponse(uint64_t contextId, String identifier) const
496 if (contextId == m_controlsManagerContextId)
497 m_page->handleControlledElementIDResponse(identifier);
499 UNUSED_PARAM(contextId);
500 UNUSED_PARAM(identifier);
505 #pragma mark Messages to PlaybackSessionManager
507 void PlaybackSessionManagerProxy::play(uint64_t contextId)
509 m_page->send(Messages::PlaybackSessionManager::Play(contextId), m_page->pageID());
512 void PlaybackSessionManagerProxy::pause(uint64_t contextId)
514 m_page->send(Messages::PlaybackSessionManager::Pause(contextId), m_page->pageID());
517 void PlaybackSessionManagerProxy::togglePlayState(uint64_t contextId)
519 m_page->send(Messages::PlaybackSessionManager::TogglePlayState(contextId), m_page->pageID());
522 void PlaybackSessionManagerProxy::beginScrubbing(uint64_t contextId)
524 m_page->send(Messages::PlaybackSessionManager::BeginScrubbing(contextId), m_page->pageID());
527 void PlaybackSessionManagerProxy::endScrubbing(uint64_t contextId)
529 m_page->send(Messages::PlaybackSessionManager::EndScrubbing(contextId), m_page->pageID());
532 void PlaybackSessionManagerProxy::seekToTime(uint64_t contextId, double time, double toleranceBefore, double toleranceAfter)
534 m_page->send(Messages::PlaybackSessionManager::SeekToTime(contextId, time, toleranceBefore, toleranceAfter), m_page->pageID());
537 void PlaybackSessionManagerProxy::fastSeek(uint64_t contextId, double time)
539 m_page->send(Messages::PlaybackSessionManager::FastSeek(contextId, time), m_page->pageID());
542 void PlaybackSessionManagerProxy::beginScanningForward(uint64_t contextId)
544 m_page->send(Messages::PlaybackSessionManager::BeginScanningForward(contextId), m_page->pageID());
547 void PlaybackSessionManagerProxy::beginScanningBackward(uint64_t contextId)
549 m_page->send(Messages::PlaybackSessionManager::BeginScanningBackward(contextId), m_page->pageID());
552 void PlaybackSessionManagerProxy::endScanning(uint64_t contextId)
554 m_page->send(Messages::PlaybackSessionManager::EndScanning(contextId), m_page->pageID());
557 void PlaybackSessionManagerProxy::selectAudioMediaOption(uint64_t contextId, uint64_t index)
559 m_page->send(Messages::PlaybackSessionManager::SelectAudioMediaOption(contextId, index), m_page->pageID());
562 void PlaybackSessionManagerProxy::selectLegibleMediaOption(uint64_t contextId, uint64_t index)
564 m_page->send(Messages::PlaybackSessionManager::SelectLegibleMediaOption(contextId, index), m_page->pageID());
567 void PlaybackSessionManagerProxy::togglePictureInPicture(uint64_t contextId)
569 m_page->send(Messages::PlaybackSessionManager::TogglePictureInPicture(contextId), m_page->pageID());
572 void PlaybackSessionManagerProxy::toggleMuted(uint64_t contextId)
574 m_page->send(Messages::PlaybackSessionManager::ToggleMuted(contextId), m_page->pageID());
577 void PlaybackSessionManagerProxy::setMuted(uint64_t contextId, bool muted)
579 m_page->send(Messages::PlaybackSessionManager::SetMuted(contextId, muted), m_page->pageID());
582 void PlaybackSessionManagerProxy::setVolume(uint64_t contextId, double volume)
584 m_page->send(Messages::PlaybackSessionManager::SetVolume(contextId, volume), m_page->pageID());
587 void PlaybackSessionManagerProxy::setPlayingOnSecondScreen(uint64_t contextId, bool value)
590 m_page->send(Messages::PlaybackSessionManager::SetPlayingOnSecondScreen(contextId, value), m_page->pageID());
593 void PlaybackSessionManagerProxy::requestControlledElementID()
595 if (m_controlsManagerContextId)
596 m_page->send(Messages::PlaybackSessionManager::HandleControlledElementIDRequest(m_controlsManagerContextId), m_page->pageID());
599 PlatformPlaybackSessionInterface* PlaybackSessionManagerProxy::controlsManagerInterface()
601 if (!m_controlsManagerContextId)
604 auto& interface = ensureInterface(m_controlsManagerContextId);
608 } // namespace WebKit
610 #endif // PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))