Skip to content

Commit

Permalink
Deliver player metadata (#808)
Browse files Browse the repository at this point in the history
Co-authored-by: Samuel Défago <[email protected]>
  • Loading branch information
waliid and defagos authored Mar 26, 2024
1 parent edfcb80 commit b82fd13
Show file tree
Hide file tree
Showing 66 changed files with 1,128 additions and 1,150 deletions.
1 change: 0 additions & 1 deletion Demo/Sources/Analytics/DemoTracker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// License information is available from the LICENSE file.
//

import Combine
import Foundation
import os
import PillarboxPlayer
Expand Down
13 changes: 8 additions & 5 deletions Demo/Sources/Model/Media.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,7 @@ struct Media: Hashable {
}
}

extension Media: AssetMetadata {
func nowPlayingMetadata() -> NowPlayingMetadata {
.init(title: title, subtitle: description, image: image)
}

extension Media {
private func playerItem(for url: URL, configuration: @escaping (AVPlayerItem) -> Void = { _ in }) -> PlayerItem {
.init(
publisher: imagePublisher()
Expand All @@ -99,6 +95,13 @@ extension Media: AssetMetadata {
configuration: configuration
)
},
metadataAdapter: StandardMetadata.adapter { metadata in
.init(
title: metadata.title,
subtitle: metadata.description,
image: metadata.image
)
},
trackerAdapters: [
DemoTracker.adapter { media in
DemoTracker.Metadata(title: media.title)
Expand Down
1 change: 0 additions & 1 deletion Demo/Sources/Settings/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// License information is available from the LICENSE file.
//

import AVFoundation
import PillarboxPlayer
import SwiftUI

Expand Down
1 change: 0 additions & 1 deletion Demo/Sources/Settings/UserDefaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// License information is available from the LICENSE file.
//

import AVFoundation
import Foundation
import PillarboxPlayer

Expand Down
1 change: 0 additions & 1 deletion Demo/Sources/Tools/MotionManager~ios.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import Combine
import CoreMotion
import PillarboxPlayer

final class MotionManager: ObservableObject {
@Published private(set) var attitude: CMAttitude?
Expand Down
1 change: 0 additions & 1 deletion Demo/Sources/Views/CloseButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
//

import SwiftUI
import UIKit

struct CloseButton: View {
@Environment(\.dismiss) private var dismiss
Expand Down
35 changes: 33 additions & 2 deletions Sources/Core/Publisher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,14 @@ public extension Publisher {
func weakCapture<T>(_ other: T?) -> AnyPublisher<(Output, T), Failure> where T: AnyObject {
weakCapture(other, at: \T.self)
}
}

public extension Publisher {
/// Safely receives elements from the upstream on the main thread.
///
/// - Returns: A publisher delivering elements on the main thread.
func receiveOnMainThread() -> AnyPublisher<Output, Failure> {
map { output in
flatMap { output in
// `receive(on: DispatchQueue.main)` defers execution if already on the main thread. Do nothing in this case.
if Thread.isMainThread {
return Just(output)
Expand All @@ -94,7 +96,36 @@ public extension Publisher {
.eraseToAnyPublisher()
}
}
.switchToLatest()
.eraseToAnyPublisher()
}

/// Delays delivery of all output to the downstream receiver by a specified amount of time on a particular scheduler.
///
/// - Parameters:
/// - interval: The amount of time to delay.
/// - tolerance: The allowed tolerance in delivering delayed events. The `Delay` publisher may deliver elements
/// this much sooner or later than the interval specifies.
/// - scheduler: The scheduler to deliver the delayed events.
/// - options: Options relevant to the scheduler’s behavior.
/// - Returns: A publisher that delays delivery of elements and completion to the downstream receiver.
///
/// If the `interval` is zero the value is published synchronously, not on the specified scheduler.
func delayIfNeeded<S>(
for interval: S.SchedulerTimeType.Stride,
tolerance: S.SchedulerTimeType.Stride? = nil,
scheduler: S,
options: S.SchedulerOptions? = nil
) -> AnyPublisher<Output, Failure> where S: Scheduler {
flatMap { output in
if interval != 0 {
return Just(output)
.delay(for: interval, tolerance: tolerance, scheduler: scheduler, options: options)
.eraseToAnyPublisher()
}
else {
return Just(output).eraseToAnyPublisher()
}
}
.eraseToAnyPublisher()
}
}
Expand Down
1 change: 0 additions & 1 deletion Sources/Core/ReplaySubscription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
//

import Combine
import Foundation

final class ReplaySubscription<Output, Failure>: Subscription where Failure: Error {
var onCancel: (() -> Void)?
Expand Down
19 changes: 19 additions & 0 deletions Sources/CoreBusiness/Extensions/MetadataAdapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Copyright (c) SRG SSR. All rights reserved.
//
// License information is available from the LICENSE file.
//

import PillarboxPlayer

public extension MetadataAdapter where M == MediaMetadata {
/// A metadata adapter displaying standard media metadata.
static let standard: Self = StandardMetadata.adapter { metadata in
.init(
title: metadata.title,
subtitle: metadata.subtitle,
description: metadata.description,
image: metadata.image
)
}
}
6 changes: 1 addition & 5 deletions Sources/CoreBusiness/Model/MediaMetadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import PillarboxPlayer
import UIKit

/// Metadata associated with content loaded from a URN.
public struct MediaMetadata: AssetMetadata {
public struct MediaMetadata {
private static let dateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(identifier: "Europe/Zurich")
Expand Down Expand Up @@ -82,8 +82,4 @@ public struct MediaMetadata: AssetMetadata {
private static func areRedundant(chapter: Chapter, show: Show) -> Bool {
chapter.title.lowercased() == show.title.lowercased()
}

public func nowPlayingMetadata() -> NowPlayingMetadata {
.init(title: title, subtitle: subtitle, description: description, image: image)
}
}
4 changes: 3 additions & 1 deletion Sources/CoreBusiness/PlayerItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ public extension PlayerItem {
/// - Parameters:
/// - urn: The URN to play.
/// - server: The server which the URN is played from.
/// - metadataAdapter: A `MetadataAdapter` converting item metadata into player metadata.
/// - trackerAdapters: An array of `TrackerAdapter` instances to use for tracking playback events.
/// - configuration: A closure to configure player items created from the receiver.
///
/// In addition the item is automatically tracked according to SRG SSR analytics standards.
static func urn(
_ urn: String,
server: Server = .production,
metadataAdapter: MetadataAdapter<MediaMetadata> = .standard,
trackerAdapters: [TrackerAdapter<MediaMetadata>] = [],
configuration: @escaping (AVPlayerItem) -> Void = { _ in }
) -> Self {
Expand All @@ -43,7 +45,7 @@ public extension PlayerItem {
}
.switchToLatest()
.eraseToAnyPublisher()
return .init(publisher: publisher, trackerAdapters: [
return .init(publisher: publisher, metadataAdapter: metadataAdapter, trackerAdapters: [
ComScoreTracker.adapter { $0.analyticsData },
CommandersActTracker.adapter { $0.analyticsMetadata }
] + trackerAdapters)
Expand Down
Loading

0 comments on commit b82fd13

Please sign in to comment.