diff --git a/apps/ios/VMC.xcodeproj/project.pbxproj b/apps/ios/VMC.xcodeproj/project.pbxproj index 0113252..a1d1daa 100644 --- a/apps/ios/VMC.xcodeproj/project.pbxproj +++ b/apps/ios/VMC.xcodeproj/project.pbxproj @@ -345,7 +345,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 69; + CURRENT_PROJECT_VERSION = 70; DEVELOPMENT_TEAM = X25NYX3K49; ENABLE_BITCODE = NO; ENABLE_PREVIEWS = YES; @@ -360,7 +360,7 @@ "$(inherited)", "@executable_path/Frameworks" ); - MARKETING_VERSION = 0.5.56; + MARKETING_VERSION = 0.5.57; OTHER_LDFLAGS = ("$(inherited)", "-ObjC"); PRODUCT_BUNDLE_IDENTIFIER = nl.vonas.mediacluster.ios; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -378,7 +378,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 69; + CURRENT_PROJECT_VERSION = 70; DEVELOPMENT_TEAM = X25NYX3K49; ENABLE_BITCODE = NO; ENABLE_PREVIEWS = YES; @@ -393,7 +393,7 @@ "$(inherited)", "@executable_path/Frameworks" ); - MARKETING_VERSION = 0.5.56; + MARKETING_VERSION = 0.5.57; OTHER_LDFLAGS = ("$(inherited)", "-ObjC"); PRODUCT_BUNDLE_IDENTIFIER = nl.vonas.mediacluster.ios; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/apps/ios/VMC/Playback/AVLivePlayerController.swift b/apps/ios/VMC/Playback/AVLivePlayerController.swift index c82a8de..f98d9b9 100644 --- a/apps/ios/VMC/Playback/AVLivePlayerController.swift +++ b/apps/ios/VMC/Playback/AVLivePlayerController.swift @@ -47,7 +47,8 @@ final class AVLivePlayerController: NSObject, ObservableObject { url: URL, fallback: URL? = nil, format: String? = nil, - clearKeys: [ClearKeyEntry] = [] + clearKeys: [ClearKeyEntry] = [], + browserCdnHeaders: Bool = false ) async { generation &+= 1 let gen = generation @@ -78,7 +79,8 @@ final class AVLivePlayerController: NSObject, ObservableObject { let started = try await ClearKeyDashProxy.shared.start( manifestURL: url, keys: clearKeys, - preferHlsForAVPlayer: true + preferHlsForAVPlayer: true, + browserCdnHeaders: browserCdnHeaders ) guard gen == generation, !stopping else { return } playURL = started.url diff --git a/apps/ios/VMC/Playback/ClearKeyDashProxy.swift b/apps/ios/VMC/Playback/ClearKeyDashProxy.swift index 63eed36..f96998c 100644 --- a/apps/ios/VMC/Playback/ClearKeyDashProxy.swift +++ b/apps/ios/VMC/Playback/ClearKeyDashProxy.swift @@ -217,7 +217,8 @@ final class ClearKeyDashProxy { func start( manifestURL: URL, keys: [ClearKeyEntry], - preferHlsForAVPlayer: Bool = false + preferHlsForAVPlayer: Bool = false, + browserCdnHeaders: Bool = false ) async throws -> StartResult { let map = ClearKeyKeyMap(entries: keys) guard !map.isEmpty else { @@ -235,7 +236,11 @@ final class ClearKeyDashProxy { self.keyMap = map self.isHlsMode = hls self.preferHlsOutput = preferHlsForAVPlayer - self.useViaplayBrowserHeaders = ViaplayPlaybackHeaders.matches(manifestURL) + self.useViaplayBrowserHeaders = + browserCdnHeaders || ViaplayPlaybackHeaders.matches(manifestURL) + if self.useViaplayBrowserHeaders { + proxyLog.info("CDN headers=Chrome/122 for whole session") + } self.dashVideoRep = nil self.dashAudioRep = nil self.dashAudioReps = [] @@ -1112,7 +1117,7 @@ final class ClearKeyDashProxy { req.timeoutInterval = 15 req.cachePolicy = .reloadIgnoringLocalCacheData req.setValue("bytes", forHTTPHeaderField: "Accept-Ranges") - let browser = withState { useViaplayBrowserHeaders } || ViaplayPlaybackHeaders.matches(current) + let browser = withState { useViaplayBrowserHeaders } let session: URLSession if browser { ViaplayPlaybackHeaders.apply(to: &req) diff --git a/apps/ios/VMC/Playback/PlayerScreen.swift b/apps/ios/VMC/Playback/PlayerScreen.swift index ca8ef34..ed1f065 100644 --- a/apps/ios/VMC/Playback/PlayerScreen.swift +++ b/apps/ios/VMC/Playback/PlayerScreen.swift @@ -21,6 +21,12 @@ struct PlayRequest: Identifiable { /// Provider-/titel-logo voor laad-animatie (events, films, series). let logoUrl: String? + /// Zelfde Chrome/122-UA als de werkende losse MPD-speler, voor de hele CDN-sessie. + var usesViaplayCdn: Bool { + ViaplayPlaybackHeaders.matches(url) + || (watchId ?? "").localizedCaseInsensitiveContains("viaplay") + } + static func vod( url: URL, title: String, @@ -579,7 +585,8 @@ struct PlayerScreen: View { fallback: request.fallbackUrl, format: request.format, clearKeys: keys, - preferHls: true + preferHls: true, + browserCdnHeaders: request.usesViaplayCdn ) let maxWaitNs: UInt64 = 18_000_000_000 let stepNs: UInt64 = 200_000_000 @@ -597,7 +604,8 @@ struct PlayerScreen: View { url: request.url, fallback: request.fallbackUrl, format: request.format, - clearKeys: keys + clearKeys: keys, + browserCdnHeaders: request.usesViaplayCdn ) let maxWaitNs: UInt64 = 18_000_000_000 let stepNs: UInt64 = 200_000_000 @@ -620,7 +628,8 @@ struct PlayerScreen: View { fallback: request.fallbackUrl, format: request.format, clearKeys: keys, - preferHls: true + preferHls: true, + browserCdnHeaders: request.usesViaplayCdn ) waited = 0 while waited < 8_000_000_000 && !vlc.isPlaying && !vlc.hasError { @@ -638,7 +647,8 @@ struct PlayerScreen: View { url: request.url, fallback: request.fallbackUrl, format: request.format, - clearKeys: [] + clearKeys: [], + browserCdnHeaders: request.usesViaplayCdn ) let maxWaitNs: UInt64 = 4_000_000_000 let stepNs: UInt64 = 200_000_000 diff --git a/apps/ios/VMC/Playback/VLCPlayerController.swift b/apps/ios/VMC/Playback/VLCPlayerController.swift index a7cc789..decc9e9 100644 --- a/apps/ios/VMC/Playback/VLCPlayerController.swift +++ b/apps/ios/VMC/Playback/VLCPlayerController.swift @@ -278,7 +278,8 @@ final class VLCPlayerController: NSObject, ObservableObject, VLCMediaPlayerDeleg fallback: URL? = nil, format: String? = nil, clearKeys: [ClearKeyEntry] = [], - preferHls: Bool = false + preferHls: Bool = false, + browserCdnHeaders: Bool = false ) async { // Annuleer pending finishStop / delayed proxy-stop van vorige sessie. stopGeneration &+= 1 @@ -310,7 +311,8 @@ final class VLCPlayerController: NSObject, ObservableObject, VLCMediaPlayerDeleg let started = try await ClearKeyDashProxy.shared.start( manifestURL: url, keys: clearKeys, - preferHlsForAVPlayer: preferHls + preferHlsForAVPlayer: preferHls, + browserCdnHeaders: browserCdnHeaders ) playURL = started.url proxySession = started.session diff --git a/apps/ios/VMC/UI/EventHubsScreens.swift b/apps/ios/VMC/UI/EventHubsScreens.swift index 47cf8a4..2c502b3 100644 --- a/apps/ios/VMC/UI/EventHubsScreens.swift +++ b/apps/ios/VMC/UI/EventHubsScreens.swift @@ -768,6 +768,9 @@ private struct HubPlaybackModifier: ViewModifier { set: { if !$0 { playback.info = nil } } )) { if let info = playback.info, let url = URL(string: info.streamUrl) { + let sid = info.streamId + let viaplay = ViaplayPlaybackHeaders.matches(url) + || sid.localizedCaseInsensitiveContains("viaplay") PlayerScreen(request: .live( url: url, title: info.name, @@ -776,8 +779,9 @@ private struct HubPlaybackModifier: ViewModifier { drm: info.drm, watchSessionId: info.watchSessionId, watchKind: "event", - watchId: info.streamId.isEmpty ? nil : info.streamId, - logoUrl: info.logoUrl + watchId: viaplay ? (sid.isEmpty ? "viaplay" : sid) : (sid.isEmpty ? nil : sid), + logoUrl: info.logoUrl, + isLive: info.live ?? true )) .environmentObject(app) } diff --git a/apps/ios/VMC/UI/SettingsScreen.swift b/apps/ios/VMC/UI/SettingsScreen.swift index fdb13b0..45cfaef 100644 --- a/apps/ios/VMC/UI/SettingsScreen.swift +++ b/apps/ios/VMC/UI/SettingsScreen.swift @@ -96,7 +96,7 @@ struct SettingsScreen: View { Section("Info") { LabeledContent("App", value: "VMC iOS") - LabeledContent("Versie", value: "0.5.56") + LabeledContent("Versie", value: "0.5.57") LabeledContent("Live TV", value: app.iptvEnabled ? "Aan" : "Uit") LabeledContent("Events", value: app.eventsEnabled ? "Aan" : "Uit") }