/
NowPlayingService.swift
104 lines (87 loc) · 3.96 KB
/
NowPlayingService.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// The MIT License (MIT)
//
// ModernAVPlayer
// Copyright (c) 2018 Raphael Ankierman <raphael.ankierman@radiofrance.com>
//
// NowPlayingService.swift
// Created by raphael ankierman on 17/03/2018.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
import MediaPlayer
//sourcery: AutoMockable
protocol NowPlaying {
func update(metadata: PlayerMediaMetadata?)
func update(metadata: PlayerMediaMetadata?, duration: Double?, isLive: Bool)
func overrideInfoCenter(for key: String, value: Any)
}
/*
Because of race condition, we have to share infos property when updating
*/
final class ModernAVPlayerNowPlayingService: NowPlaying {
private var infos = [String: Any]()
private var session: URLSession { return URLSession.shared }
private var task: URLSessionTask?
func update(metadata: PlayerMediaMetadata?) {
infos[MPMediaItemPropertyTitle] = metadata?.title ?? ""
infos[MPMediaItemPropertyArtist] = metadata?.artist ?? ""
infos[MPMediaItemPropertyAlbumTitle] = metadata?.albumTitle ?? ""
infos[MPNowPlayingInfoPropertyPlaybackRate] = 1.0
if let imageData = metadata?.image, let image = UIImage(data: imageData) {
let artwork = getArtwork(image: image)
infos[MPMediaItemPropertyArtwork] = artwork
} else {
infos.removeValue(forKey: MPMediaItemPropertyArtwork)
}
MPNowPlayingInfoCenter.default().nowPlayingInfo = infos
if let imageUrl = metadata?.remoteImageUrl {
updateRemoteImage(url: imageUrl)
}
ModernAVPlayerLogger.instance.log(message: "Update now playing dictionnary", domain: .service)
}
func update(metadata: PlayerMediaMetadata?, duration: Double?, isLive: Bool) {
infos[MPNowPlayingInfoPropertyIsLiveStream] = isLive
if let duration = duration, duration.isNormal {
infos[MPMediaItemPropertyPlaybackDuration] = duration
} else {
infos.removeValue(forKey: MPMediaItemPropertyPlaybackDuration)
}
update(metadata: metadata)
}
func overrideInfoCenter(for key: String, value: Any) {
infos[key] = value
MPNowPlayingInfoCenter.default().nowPlayingInfo = infos
ModernAVPlayerLogger.instance.log(message: "Update nowPlayingInfo \(key):\(value)", domain: .service)
}
private func getArtwork(image: UIImage) -> MPMediaItemArtwork {
return MPMediaItemArtwork(boundsSize: image.size) { _ in image }
}
private func updateRemoteImage(url: URL) {
task?.cancel()
task = session.dataTask(with: url) { [weak self] data, _, _ in
guard let self = self, let imageData = data, let image = UIImage(data: imageData)
else { return }
DispatchQueue.main.async {
let artwork = self.getArtwork(image: image)
self.overrideInfoCenter(for: MPMediaItemPropertyArtwork, value: artwork)
}
}
task?.resume()
}
}