Only include those parts of AVFoundation.framework which are strictly needed.
[WebKit-https.git] / Source / WebCore / platform / mac / WebPlaybackSessionInterfaceMac.mm
1 /*
2  * Copyright (C) 2016 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 "WebPlaybackSessionInterfaceMac.h"
28
29 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
30
31 #import "AVKitSPI.h"
32 #import "IntRect.h"
33 #import "MediaTimeAVFoundation.h"
34 #import "TimeRanges.h"
35 #import "WebPlaybackControlsManager.h"
36 #import "WebPlaybackSessionModel.h"
37 #import <AVFoundation/AVTime.h>
38
39 #import "CoreMediaSoftLink.h"
40
41 SOFT_LINK_FRAMEWORK_OPTIONAL(AVKit)
42 SOFT_LINK_CLASS_OPTIONAL(AVKit, AVValueTiming)
43
44 using namespace WebCore;
45
46 namespace WebCore {
47
48 Ref<WebPlaybackSessionInterfaceMac> WebPlaybackSessionInterfaceMac::create(WebPlaybackSessionModel& model)
49 {
50     auto interface = adoptRef(*new WebPlaybackSessionInterfaceMac(model));
51     model.addClient(interface);
52     return interface;
53 }
54
55 WebPlaybackSessionInterfaceMac::WebPlaybackSessionInterfaceMac(WebPlaybackSessionModel& model)
56     : m_playbackSessionModel(&model)
57 {
58 }
59
60 WebPlaybackSessionInterfaceMac::~WebPlaybackSessionInterfaceMac()
61 {
62     invalidate();
63 }
64
65 void WebPlaybackSessionInterfaceMac::durationChanged(double duration)
66 {
67 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
68     WebPlaybackControlsManager* controlsManager = playBackControlsManager();
69
70     controlsManager.contentDuration = duration;
71
72     // FIXME: We take this as an indication that playback is ready, but that is not necessarily true.
73     controlsManager.hasEnabledAudio = YES;
74     controlsManager.hasEnabledVideo = YES;
75 #else
76     UNUSED_PARAM(duration);
77 #endif
78 }
79
80 void WebPlaybackSessionInterfaceMac::currentTimeChanged(double currentTime, double anchorTime)
81 {
82 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
83     WebPlaybackControlsManager* controlsManager = playBackControlsManager();
84     updatePlaybackControlsManagerTiming(currentTime, anchorTime, controlsManager.rate, controlsManager.playing);
85 #else
86     UNUSED_PARAM(currentTime);
87     UNUSED_PARAM(anchorTime);
88 #endif
89 }
90
91 void WebPlaybackSessionInterfaceMac::rateChanged(bool isPlaying, float playbackRate)
92 {
93 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
94     WebPlaybackControlsManager* controlsManager = playBackControlsManager();
95     [controlsManager setRate:isPlaying ? playbackRate : 0.];
96     [controlsManager setPlaying:isPlaying];
97     updatePlaybackControlsManagerTiming(m_playbackSessionModel ? m_playbackSessionModel->currentTime() : 0, [[NSProcessInfo processInfo] systemUptime], playbackRate, isPlaying);
98 #else
99     UNUSED_PARAM(isPlaying);
100     UNUSED_PARAM(playbackRate);
101 #endif
102 }
103
104 void WebPlaybackSessionInterfaceMac::beginScrubbing()
105 {
106 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
107     updatePlaybackControlsManagerTiming(m_playbackSessionModel ? m_playbackSessionModel->currentTime() : 0, [[NSProcessInfo processInfo] systemUptime], 0, false);
108 #endif
109     webPlaybackSessionModel()->beginScrubbing();
110 }
111
112 void WebPlaybackSessionInterfaceMac::endScrubbing()
113 {
114     webPlaybackSessionModel()->endScrubbing();
115 }
116
117 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
118 static RetainPtr<NSMutableArray> timeRangesToArray(const TimeRanges& timeRanges)
119 {
120     RetainPtr<NSMutableArray> rangeArray = adoptNS([[NSMutableArray alloc] init]);
121
122     for (unsigned i = 0; i < timeRanges.length(); i++) {
123         const PlatformTimeRanges& ranges = timeRanges.ranges();
124         CMTimeRange range = CMTimeRangeMake(toCMTime(ranges.start(i)), toCMTime(ranges.end(i)));
125         [rangeArray addObject:[NSValue valueWithCMTimeRange:range]];
126     }
127
128     return rangeArray;
129 }
130 #endif
131
132 void WebPlaybackSessionInterfaceMac::seekableRangesChanged(const TimeRanges& timeRanges)
133 {
134 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
135     [playBackControlsManager() setSeekableTimeRanges:timeRangesToArray(timeRanges).get()];
136 #else
137     UNUSED_PARAM(timeRanges);
138 #endif
139 }
140
141 void WebPlaybackSessionInterfaceMac::audioMediaSelectionOptionsChanged(const Vector<WTF::String>& options, uint64_t selectedIndex)
142 {
143 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
144     [playBackControlsManager() setAudioMediaSelectionOptions:options withSelectedIndex:static_cast<NSUInteger>(selectedIndex)];
145 #else
146     UNUSED_PARAM(options);
147     UNUSED_PARAM(selectedIndex);
148 #endif
149 }
150
151 void WebPlaybackSessionInterfaceMac::legibleMediaSelectionOptionsChanged(const Vector<WTF::String>& options, uint64_t selectedIndex)
152 {
153 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
154     [playBackControlsManager() setLegibleMediaSelectionOptions:options withSelectedIndex:static_cast<NSUInteger>(selectedIndex)];
155 #else
156     UNUSED_PARAM(options);
157     UNUSED_PARAM(selectedIndex);
158 #endif
159 }
160
161 void WebPlaybackSessionInterfaceMac::invalidate()
162 {
163     if (!m_playbackSessionModel)
164         return;
165
166     m_playbackSessionModel->removeClient(*this);
167     m_playbackSessionModel = nullptr;
168 }
169
170 void WebPlaybackSessionInterfaceMac::ensureControlsManager()
171 {
172 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
173     playBackControlsManager();
174 #endif
175 }
176
177 #if ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
178
179 WebPlaybackControlsManager *WebPlaybackSessionInterfaceMac::playBackControlsManager()
180 {
181     return m_playbackControlsManager;
182 }
183
184 void WebPlaybackSessionInterfaceMac::setPlayBackControlsManager(WebPlaybackControlsManager *manager)
185 {
186     m_playbackControlsManager = manager;
187
188     if (!manager || !m_playbackSessionModel)
189         return;
190
191     NSTimeInterval anchorTimeStamp = ![manager rate] ? NAN : [[NSProcessInfo processInfo] systemUptime];
192     manager.timing = [getAVValueTimingClass() valueTimingWithAnchorValue:m_playbackSessionModel->currentTime() anchorTimeStamp:anchorTimeStamp rate:0];
193     double duration = m_playbackSessionModel->duration();
194     manager.contentDuration = duration;
195     manager.hasEnabledAudio = duration > 0;
196     manager.hasEnabledVideo = duration > 0;
197     manager.rate = m_playbackSessionModel->isPlaying() ? m_playbackSessionModel->playbackRate() : 0.;
198     manager.seekableTimeRanges = timeRangesToArray(m_playbackSessionModel->seekableRanges()).get();
199     manager.canTogglePlayback = YES;
200     manager.playing = m_playbackSessionModel->isPlaying();
201     [manager setAudioMediaSelectionOptions:m_playbackSessionModel->audioMediaSelectionOptions() withSelectedIndex:static_cast<NSUInteger>(m_playbackSessionModel->audioMediaSelectedIndex())];
202     [manager setLegibleMediaSelectionOptions:m_playbackSessionModel->legibleMediaSelectionOptions() withSelectedIndex:static_cast<NSUInteger>(m_playbackSessionModel->legibleMediaSelectedIndex())];
203 }
204
205 void WebPlaybackSessionInterfaceMac::updatePlaybackControlsManagerTiming(double currentTime, double anchorTime, double playbackRate, bool isPlaying)
206 {
207     WebPlaybackControlsManager *manager = playBackControlsManager();
208     if (!manager)
209         return;
210
211     WebPlaybackSessionModel *model = webPlaybackSessionModel();
212     if (!model)
213         return;
214
215     double effectiveAnchorTime = playbackRate ? anchorTime : NAN;
216     double effectivePlaybackRate = playbackRate;
217     if (!isPlaying
218         || model->isScrubbing()
219         || (manager.rate > 0 && model->playbackStartedTime() >= currentTime)
220         || (manager.rate < 0 && model->playbackStartedTime() <= currentTime))
221         effectivePlaybackRate = 0;
222
223     manager.timing = [getAVValueTimingClass() valueTimingWithAnchorValue:currentTime anchorTimeStamp:effectiveAnchorTime rate:effectivePlaybackRate];
224 }
225
226 #endif // ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
227
228 }
229
230 #endif // PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)