[FreeType] Incorrect application of glyph positioning in the Y direction
[WebKit-https.git] / Source / WebCore / platform / mac / WebPlaybackControlsManager.mm
1 /*
2  * Copyright (C) 2016-2019 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 #import "config.h"
27 #import "WebPlaybackControlsManager.h"
28
29 #if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE) && ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)
30
31 #import "MediaSelectionOption.h"
32 #import "PlaybackSessionInterfaceMac.h"
33 #import "PlaybackSessionModel.h"
34 #import <wtf/SoftLinking.h>
35 #import <wtf/text/WTFString.h>
36
37 IGNORE_WARNINGS_BEGIN("nullability-completeness")
38
39 SOFT_LINK_FRAMEWORK(AVKit)
40 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
41 SOFT_LINK_CLASS_OPTIONAL(AVKit, AVTouchBarMediaSelectionOption)
42 #else
43 SOFT_LINK_CLASS_OPTIONAL(AVKit, AVFunctionBarMediaSelectionOption)
44 #endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
45
46 using WebCore::MediaSelectionOption;
47 using WebCore::PlaybackSessionInterfaceMac;
48
49 @implementation WebPlaybackControlsManager
50
51 @synthesize contentDuration=_contentDuration;
52 @synthesize seekToTime=_seekToTime;
53 @synthesize hasEnabledAudio=_hasEnabledAudio;
54 @synthesize hasEnabledVideo=_hasEnabledVideo;
55 @synthesize rate=_rate;
56 @synthesize canTogglePlayback=_canTogglePlayback;
57 @synthesize allowsPictureInPicturePlayback;
58 @synthesize pictureInPictureActive;
59 @synthesize canTogglePictureInPicture;
60
61 - (void)dealloc
62 {
63     if (_playbackSessionInterfaceMac)
64         _playbackSessionInterfaceMac->setPlayBackControlsManager(nullptr);
65     [super dealloc];
66 }
67
68 - (AVValueTiming *)timing
69 {
70     return _timing.get();
71 }
72
73 - (void)setTiming:(AVValueTiming *)timing
74 {
75     _timing = timing;
76 }
77
78 - (NSArray *)seekableTimeRanges
79 {
80     return _seekableTimeRanges.get();
81 }
82
83 - (void)setSeekableTimeRanges:(NSArray *)timeRanges
84 {
85     _seekableTimeRanges = timeRanges;
86 }
87
88 - (BOOL)isSeeking
89 {
90     return NO;
91 }
92
93 - (void)seekToTime:(NSTimeInterval)time toleranceBefore:(NSTimeInterval)toleranceBefore toleranceAfter:(NSTimeInterval)toleranceAfter
94 {
95     UNUSED_PARAM(toleranceBefore);
96     UNUSED_PARAM(toleranceAfter);
97     if (auto* model = _playbackSessionInterfaceMac->playbackSessionModel())
98         model->seekToTime(time);
99 }
100
101 - (void)cancelThumbnailAndAudioAmplitudeSampleGeneration
102 {
103 }
104
105 - (void)generateTouchBarThumbnailsForTimes:(NSArray<NSNumber *> *)thumbnailTimes tolerance:(NSTimeInterval)tolerance size:(NSSize)size thumbnailHandler:(void (^)(NSArray<AVThumbnail *> *thumbnails, BOOL thumbnailGenerationFailed))thumbnailHandler
106 {
107     UNUSED_PARAM(thumbnailTimes);
108     UNUSED_PARAM(tolerance);
109     UNUSED_PARAM(size);
110     thumbnailHandler(@[ ], YES);
111 }
112
113 - (void)generateTouchBarAudioAmplitudeSamples:(NSInteger)numberOfSamples completionHandler:(void (^)(NSArray<NSNumber *> *audioAmplitudeSamples))completionHandler
114 {
115     UNUSED_PARAM(numberOfSamples);
116     completionHandler(@[ ]);
117 }
118
119 - (BOOL)canBeginTouchBarScrubbing
120 {
121     // At this time, we return YES for all media that is not a live stream and media that is not Netflix. (A Netflix
122     // quirk means we pretend Netflix is a live stream for Touch Bar.) It's not ideal to return YES all the time for
123     // other media. The intent of the API is that we return NO when the media is being scrubbed via the on-screen scrubber.
124     // But we can only possibly get the right answer for media that uses the default controls.
125     return std::isfinite(_contentDuration);;
126 }
127
128 - (void)beginTouchBarScrubbing
129 {
130     _playbackSessionInterfaceMac->beginScrubbing();
131 }
132
133 - (void)endTouchBarScrubbing
134 {
135     _playbackSessionInterfaceMac->endScrubbing();
136 }
137
138 #if __MAC_OS_X_VERSION_MIN_REQUIRED < 101300
139
140 - (void)generateFunctionBarThumbnailsForTimes:(NSArray<NSNumber *> *)thumbnailTimes size:(NSSize)size completionHandler:(void (^)(NSArray<AVThumbnail *> *thumbnails, NSError *error))completionHandler
141 {
142     UNUSED_PARAM(thumbnailTimes);
143     UNUSED_PARAM(size);
144     completionHandler(@[ ], nil);
145 }
146
147 - (void)generateFunctionBarAudioAmplitudeSamples:(NSInteger)numberOfSamples completionHandler:(void (^)(NSArray<NSNumber *> *audioAmplitudeSamples,  NSError *error))completionHandler
148 {
149     UNUSED_PARAM(numberOfSamples);
150     completionHandler(@[ ], nil);
151 }
152
153 - (BOOL)canBeginFunctionBarScrubbing
154 {
155     return [self canBeginTouchBarScrubbing];
156 }
157
158 - (void)beginFunctionBarScrubbing
159 {
160     [self beginTouchBarScrubbing];
161 }
162
163 - (void)endFunctionBarScrubbing
164 {
165     [self endTouchBarScrubbing];
166 }
167
168 #endif
169
170 - (NSArray<AVTouchBarMediaSelectionOption *> *)audioTouchBarMediaSelectionOptions
171 {
172     return _audioTouchBarMediaSelectionOptions.get();
173 }
174
175 - (void)setAudioTouchBarMediaSelectionOptions:(NSArray<AVTouchBarMediaSelectionOption *> *)audioOptions
176 {
177     _audioTouchBarMediaSelectionOptions = audioOptions;
178 }
179
180 - (AVTouchBarMediaSelectionOption *)currentAudioTouchBarMediaSelectionOption
181 {
182     return _currentAudioTouchBarMediaSelectionOption.get();
183 }
184
185 - (void)setCurrentAudioTouchBarMediaSelectionOption:(AVTouchBarMediaSelectionOption *)audioMediaSelectionOption
186 {
187     if (audioMediaSelectionOption == _currentAudioTouchBarMediaSelectionOption)
188         return;
189
190     _currentAudioTouchBarMediaSelectionOption = audioMediaSelectionOption;
191
192     NSInteger index = NSNotFound;
193
194     if (audioMediaSelectionOption && _audioTouchBarMediaSelectionOptions)
195         index = [_audioTouchBarMediaSelectionOptions indexOfObject:audioMediaSelectionOption];
196
197     if (auto* model = _playbackSessionInterfaceMac->playbackSessionModel())
198         model->selectAudioMediaOption(index != NSNotFound ? index : UINT64_MAX);
199 }
200
201 - (NSArray<AVTouchBarMediaSelectionOption *> *)legibleTouchBarMediaSelectionOptions
202 {
203     return _legibleTouchBarMediaSelectionOptions.get();
204 }
205
206 - (void)setLegibleTouchBarMediaSelectionOptions:(NSArray<AVTouchBarMediaSelectionOption *> *)legibleOptions
207 {
208     _legibleTouchBarMediaSelectionOptions = legibleOptions;
209 }
210
211 - (AVTouchBarMediaSelectionOption *)currentLegibleTouchBarMediaSelectionOption
212 {
213     return _currentLegibleTouchBarMediaSelectionOption.get();
214 }
215
216 - (void)setCurrentLegibleTouchBarMediaSelectionOption:(AVTouchBarMediaSelectionOption *)legibleMediaSelectionOption
217 {
218     if (legibleMediaSelectionOption == _currentLegibleTouchBarMediaSelectionOption)
219         return;
220
221     _currentLegibleTouchBarMediaSelectionOption = legibleMediaSelectionOption;
222
223     NSInteger index = NSNotFound;
224
225     if (legibleMediaSelectionOption && _legibleTouchBarMediaSelectionOptions)
226         index = [_legibleTouchBarMediaSelectionOptions indexOfObject:legibleMediaSelectionOption];
227
228     if (auto* model = _playbackSessionInterfaceMac->playbackSessionModel())
229         model->selectLegibleMediaOption(index != NSNotFound ? index : UINT64_MAX);
230 }
231
232 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
233 static AVTouchBarMediaSelectionOptionType toAVTouchBarMediaSelectionOptionType(MediaSelectionOption::Type type)
234 {
235     switch (type) {
236     case MediaSelectionOption::Type::Regular:
237         return AVTouchBarMediaSelectionOptionTypeRegular;
238     case MediaSelectionOption::Type::LegibleOff:
239         return AVTouchBarMediaSelectionOptionTypeLegibleOff;
240     case MediaSelectionOption::Type::LegibleAuto:
241         return AVTouchBarMediaSelectionOptionTypeLegibleAuto;
242     }
243
244     ASSERT_NOT_REACHED();
245     return AVTouchBarMediaSelectionOptionTypeRegular;
246 }
247 #endif
248
249 static RetainPtr<NSMutableArray> mediaSelectionOptions(const Vector<MediaSelectionOption>& options)
250 {
251     RetainPtr<NSMutableArray> webOptions = adoptNS([[NSMutableArray alloc] initWithCapacity:options.size()]);
252     for (auto& option : options) {
253 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
254         if (auto webOption = adoptNS([allocAVTouchBarMediaSelectionOptionInstance() initWithTitle:option.displayName type:toAVTouchBarMediaSelectionOptionType(option.type)]))
255 #else
256         if (auto webOption = adoptNS([allocAVFunctionBarMediaSelectionOptionInstance() initWithTitle:option.displayName]))
257 #endif // __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
258             [webOptions addObject:webOption.get()];
259     }
260     return webOptions;
261 }
262
263 - (void)setAudioMediaSelectionOptions:(const Vector<MediaSelectionOption>&)options withSelectedIndex:(NSUInteger)selectedIndex
264 {
265     RetainPtr<NSMutableArray> webOptions = mediaSelectionOptions(options);
266     [self setAudioTouchBarMediaSelectionOptions:webOptions.get()];
267     if (selectedIndex < [webOptions count])
268         [self setCurrentAudioTouchBarMediaSelectionOption:[webOptions objectAtIndex:selectedIndex]];
269 }
270
271 - (void)setLegibleMediaSelectionOptions:(const Vector<MediaSelectionOption>&)options withSelectedIndex:(NSUInteger)selectedIndex
272 {
273     RetainPtr<NSMutableArray> webOptions = mediaSelectionOptions(options);
274     [self setLegibleTouchBarMediaSelectionOptions:webOptions.get()];
275     if (selectedIndex < [webOptions count])
276         [self setCurrentLegibleTouchBarMediaSelectionOption:[webOptions objectAtIndex:selectedIndex]];
277 }
278
279 - (void)setAudioMediaSelectionIndex:(NSUInteger)selectedIndex
280 {
281     if (selectedIndex >= [_audioTouchBarMediaSelectionOptions count])
282         return;
283
284     [self willChangeValueForKey:@"currentAudioTouchBarMediaSelectionOption"];
285     _currentAudioTouchBarMediaSelectionOption = [_audioTouchBarMediaSelectionOptions objectAtIndex:selectedIndex];
286     [self didChangeValueForKey:@"currentAudioTouchBarMediaSelectionOption"];
287 }
288
289 - (void)setLegibleMediaSelectionIndex:(NSUInteger)selectedIndex
290 {
291     if (selectedIndex >= [_legibleTouchBarMediaSelectionOptions count])
292         return;
293
294     [self willChangeValueForKey:@"currentLegibleTouchBarMediaSelectionOption"];
295     _currentLegibleTouchBarMediaSelectionOption = [_legibleTouchBarMediaSelectionOptions objectAtIndex:selectedIndex];
296     [self didChangeValueForKey:@"currentLegibleTouchBarMediaSelectionOption"];
297 }
298
299 - (PlaybackSessionInterfaceMac*)playbackSessionInterfaceMac
300 {
301     return _playbackSessionInterfaceMac.get();
302 }
303
304 - (void)setPlaybackSessionInterfaceMac:(PlaybackSessionInterfaceMac*)playbackSessionInterfaceMac
305 {
306     if (_playbackSessionInterfaceMac == playbackSessionInterfaceMac)
307         return;
308
309     if (_playbackSessionInterfaceMac)
310         _playbackSessionInterfaceMac->setPlayBackControlsManager(nullptr);
311
312     _playbackSessionInterfaceMac = playbackSessionInterfaceMac;
313
314     if (_playbackSessionInterfaceMac)
315         _playbackSessionInterfaceMac->setPlayBackControlsManager(self);
316 }
317
318 - (void)togglePlayback
319 {
320     if (_playbackSessionInterfaceMac && _playbackSessionInterfaceMac->playbackSessionModel())
321         _playbackSessionInterfaceMac->playbackSessionModel()->togglePlayState();
322 }
323
324 - (void)setPlaying:(BOOL)playing
325 {
326     if (!_playbackSessionInterfaceMac || !_playbackSessionInterfaceMac->playbackSessionModel())
327         return;
328
329     BOOL isCurrentlyPlaying = self.playing;
330     if (!isCurrentlyPlaying && playing)
331         _playbackSessionInterfaceMac->playbackSessionModel()->play();
332     else if (isCurrentlyPlaying && !playing)
333         _playbackSessionInterfaceMac->playbackSessionModel()->pause();
334 }
335
336 - (BOOL)isPlaying
337 {
338     if (_playbackSessionInterfaceMac && _playbackSessionInterfaceMac->playbackSessionModel())
339         return _playbackSessionInterfaceMac->playbackSessionModel()->isPlaying();
340
341     return NO;
342 }
343
344 - (void)togglePictureInPicture
345 {
346     if (_playbackSessionInterfaceMac && _playbackSessionInterfaceMac->playbackSessionModel())
347         _playbackSessionInterfaceMac->playbackSessionModel()->togglePictureInPicture();
348 }
349
350 IGNORE_WARNINGS_END
351
352 @end
353
354 #endif // PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE) && ENABLE(WEB_PLAYBACK_CONTROLS_MANAGER)