-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4ea71ae
commit 2ca2b5e
Showing
39 changed files
with
1,854 additions
and
331 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
14 changes: 0 additions & 14 deletions
14
rts-viewer-tvos/RTSViewer.xcworkspace/xcshareddata/swiftpm/Package.resolved
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
// | ||
// SourcedChannel.swift | ||
// | ||
|
||
import Combine | ||
import Foundation | ||
import os | ||
import MillicastSDK | ||
import RTSCore | ||
|
||
class Channel: ObservableObject, Identifiable, Hashable, Equatable { | ||
private static let logger = Logger( | ||
subsystem: Bundle.main.bundleIdentifier!, | ||
category: String(describing: Channel.self) | ||
) | ||
|
||
@Published var currentlyFocusedChannel: Channel? { | ||
didSet { | ||
guard let currentlyFocusedChannel else { return } | ||
isFocusedChannel = currentlyFocusedChannel.id == id | ||
} | ||
} | ||
|
||
@Published var isFocusedChannel: Bool = false { | ||
didSet { | ||
if isFocusedChannel { | ||
enableSound() | ||
} else { | ||
disableSound() | ||
} | ||
} | ||
} | ||
|
||
@Published private(set) var streamStatistics: StreamStatistics? | ||
@Published var showStatsView: Bool = false | ||
@Published var videoQualityList = [VideoQuality]() | ||
@Published var selectedVideoQuality: VideoQuality = .auto | ||
|
||
let id: UUID | ||
let streamConfig: StreamConfig | ||
let subscriptionManager: SubscriptionManager | ||
let source: StreamSource | ||
let rendererRegistry: RendererRegistry | ||
private var cancellables = [AnyCancellable]() | ||
private var layersEventsObserver: Task<Void, Never>? | ||
|
||
init(unsourcedChannel: UnsourcedChannel, | ||
source: StreamSource, | ||
rendererRegistry: RendererRegistry = RendererRegistry()) { | ||
self.id = unsourcedChannel.id | ||
self.streamConfig = unsourcedChannel.streamConfig | ||
self.subscriptionManager = unsourcedChannel.subscriptionManager | ||
self.source = source | ||
self.rendererRegistry = rendererRegistry | ||
|
||
observeStreamStatistics() | ||
observeLayerEvents() | ||
} | ||
|
||
func shouldShowStatsView(showStats: Bool) { | ||
showStatsView = showStats | ||
} | ||
|
||
func enableVideo(with quality: VideoQuality) { | ||
let displayLabel = source.sourceId.displayLabel | ||
let viewId = "\(ChannelGridView.self).\(displayLabel)" | ||
Task { | ||
Self.logger.debug("♼ Channel Grid view: Video view appear for \(self.source.sourceId)") | ||
self.selectedVideoQuality = quality | ||
if let layer = quality.layer { | ||
try await self.source.videoTrack.enable( | ||
renderer: rendererRegistry.sampleBufferRenderer(for: source).underlyingRenderer, | ||
layer: MCRTSRemoteVideoTrackLayer(layer: layer) | ||
) | ||
} else { | ||
try await self.source.videoTrack.enable(renderer: rendererRegistry.sampleBufferRenderer(for: source).underlyingRenderer) | ||
} | ||
} | ||
} | ||
|
||
func disableVideo() { | ||
let displayLabel = source.sourceId.displayLabel | ||
Task { | ||
Self.logger.debug("♼ Channel Grid view: Video view disappear for \(self.source.sourceId)") | ||
try await self.source.videoTrack.disable() | ||
} | ||
} | ||
|
||
func enableSound() { | ||
Task { | ||
try? await self.source.audioTrack?.enable() | ||
Self.logger.debug("♼ Channel \(self.source.sourceId) audio enabled") | ||
} | ||
} | ||
|
||
func disableSound() { | ||
Task { | ||
try? await self.source.audioTrack?.disable() | ||
Self.logger.debug("♼ Channel \(self.source.sourceId) audio disabled") | ||
} | ||
} | ||
|
||
func updateFocusedChannel(with channel: Channel) { | ||
currentlyFocusedChannel = channel | ||
} | ||
|
||
static func == (lhs: Channel, rhs: Channel) -> Bool { | ||
return lhs.id == rhs.id | ||
} | ||
|
||
func hash(into hasher: inout Hasher) { | ||
return hasher.combine(id) | ||
} | ||
} | ||
|
||
private extension Channel { | ||
func observeStreamStatistics() { | ||
Task { [weak self] in | ||
guard let self else { return } | ||
await subscriptionManager.$streamStatistics | ||
.sink { statistics in | ||
guard let statistics else { return } | ||
Task { | ||
self.streamStatistics = statistics | ||
} | ||
} | ||
.store(in: &cancellables) | ||
} | ||
} | ||
|
||
func observeLayerEvents() { | ||
Task { [weak self] in | ||
guard let self, | ||
layersEventsObserver == nil else { return } | ||
|
||
Self.logger.debug("♼ Registering layer events for \(source.sourceId)") | ||
let layerEventsObservationTask = Task { | ||
for await layerEvent in self.source.videoTrack.layers() { | ||
guard !Task.isCancelled else { return } | ||
|
||
let videoQualities = layerEvent.layers() | ||
.map(VideoQuality.init) | ||
.reduce([.auto]) { $0 + [$1] } | ||
Self.logger.debug("♼ Received layers \(videoQualities.count)") | ||
self.videoQualityList = videoQualities | ||
} | ||
} | ||
|
||
layersEventsObserver = layerEventsObservationTask | ||
|
||
_ = await layerEventsObservationTask.value | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// | ||
// PlayFromConfigs.swift | ||
// | ||
|
||
import Foundation | ||
|
||
struct StreamConfig { | ||
let apiUrl: String | ||
let streamName: String | ||
let accountId: String | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// | ||
// UnsourcedChannel.swift | ||
// | ||
|
||
import Foundation | ||
import RTSCore | ||
|
||
struct UnsourcedChannel: Identifiable, Hashable, Equatable { | ||
let id = UUID() | ||
let streamConfig: StreamConfig | ||
let subscriptionManager: SubscriptionManager | ||
|
||
static func == (lhs: UnsourcedChannel, rhs: UnsourcedChannel) -> Bool { | ||
return lhs.id == rhs.id | ||
} | ||
|
||
public func hash(into hasher: inout Hasher) { | ||
return hasher.combine(id) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.