Skip to content
4 changes: 2 additions & 2 deletions Example/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import AVKit
struct ContentView: View {
var body: some View {
VStack {
let player = TPAVPlayer(assetID: "peBmzxeQ7Mf",
accessToken: "d7ebb4b2-8dee-4dff-bb00-e833195b0756")
let player = TPAVPlayer(assetID: "8eaHZjXt6km",
accessToken: "16b608ba-9979-45a0-94fb-b27c1a86b3c1")
TPStreamPlayerView(player: player)
.frame(height: 240)
Spacer()
Expand Down
2 changes: 1 addition & 1 deletion Source/Database/ObjectManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class ObjectManager<T: Object> {
}
}
}

func exists(id: Any) -> Bool {
let object = realm.object(ofType: T.self, forPrimaryKey: id)
return object != nil
Expand Down
2 changes: 1 addition & 1 deletion Source/Database/TPStreamsDownloadManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ internal class AssetDownloadDelegate: NSObject, AVAssetDownloadDelegate {
let percentageComplete = calculateDownloadPercentage(loadedTimeRanges, timeRangeExpectedToLoad)
OfflineAsset.manager.update(object: offlineAsset, with: ["status": Status.inProgress.rawValue, "percentageCompleted": percentageComplete])
}

private func updateDownloadCompleteStatus(_ error: Error?,_ offlineAsset: OfflineAsset) {
let status: Status = (error == nil) ? .finished : .failed
let updateValues: [String: Any] = ["status": status.rawValue, "downloadedAt": Date()]
Expand Down
3 changes: 3 additions & 0 deletions Source/Managers/TPStreamPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ class TPStreamPlayer: NSObject {
var currentVideoQuality: VideoQuality? {
return self.player.availableVideoQualities.first( where: {$0.bitrate == self.player.currentItem?.preferredPeakBitRate })
}
var asset: Asset? {
return self.player.asset
}

init(player: TPAVPlayer){
self.player = player
Expand Down
6 changes: 6 additions & 0 deletions Source/TPStreamPlayerConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public struct TPStreamPlayerConfiguration {
public var preferredRewindDuration: TimeInterval = 10.0
public var watchedProgressTrackColor: UIColor = .red
public var progressBarThumbColor: UIColor = .red
public var showDownloadOption: Bool = false
}


Expand Down Expand Up @@ -43,6 +44,11 @@ public class TPStreamPlayerConfigurationBuilder {
return self
}

public func showDownloadOption() -> Self {
configuration.showDownloadOption = true
return self
}

public func build() -> TPStreamPlayerConfiguration {
return configuration
}
Expand Down
30 changes: 28 additions & 2 deletions Source/Views/SwiftUI/PlayerSettingsButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct PlayerSettingsButton: View {
return ActionSheet(
title: Text("Settings"),
message: nil,
buttons: [playbackSpeedButton(), videoQualityButton(), .cancel()]
buttons: [playbackSpeedButton(), videoQualityButton(), downloadQualityButton(), .cancel()]
)
case .playbackSpeed:
return ActionSheet(
Expand All @@ -43,6 +43,12 @@ struct PlayerSettingsButton: View {
message: nil,
buttons: videoQualityOptions() + [.cancel()]
)
case .downloadQuality:
return ActionSheet(
title: Text("Download Quality"),
message: nil,
buttons: downloadQualityOptions() + [.cancel()]
)
}
}

Expand All @@ -64,6 +70,15 @@ struct PlayerSettingsButton: View {
}
}

private func downloadQualityButton() -> ActionSheet.Button {
return .default(Text("Download")) {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.showOptions = true
self.currentMenu = .downloadQuality
}
}
}

private func playbackSpeedOptions() -> [ActionSheet.Button] {
let playbackSpeeds = PlaybackSpeed.allCases
return playbackSpeeds.map { speed in
Expand All @@ -80,6 +95,17 @@ struct PlayerSettingsButton: View {
}
}
}

private func downloadQualityOptions() -> [ActionSheet.Button] {
var availableVideoQualities = player.availableVideoQualities
// Remove Auto Quality from the Array
availableVideoQualities.remove(at: 0)
return availableVideoQualities.map { downloadQuality in
.default(Text(downloadQuality.resolution)) {
TPStreamsDownloadManager.shared.startDownload(asset: player.asset!, videoQuality: downloadQuality)
}
}
}
}

enum SettingsMenu { case main, playbackSpeed, videoQuality }
enum SettingsMenu { case main, playbackSpeed, videoQuality, downloadQuality }
41 changes: 35 additions & 6 deletions Source/Views/UIKit/PlayerControlsUIView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,12 @@ class PlayerControlsUIView: UIView {
optionsMenu.addAction(UIAlertAction(title: "Playback Speed", style: .default) { _ in self.showPlaybackSpeedMenu()})
optionsMenu.addAction(UIAlertAction(title: "Video Quality", style: .default, handler: { action in self.showVideoQualityMenu()}))
optionsMenu.addAction(UIAlertAction(title: "Cancel", style: .cancel))
if playerConfig.showDownloadOption {
optionsMenu.addAction(UIAlertAction(title: "Download", style: .default, handler: { action in self.showDownloadQualityMenu()}))
}
parentViewController?.present(optionsMenu, animated: true, completion: nil)
}

func showPlaybackSpeedMenu(){
let playbackSpeedMenu = createPlaybackSpeedMenu()
parentViewController?.present(playbackSpeedMenu, animated: true, completion: nil)
Expand All @@ -132,14 +135,19 @@ class PlayerControlsUIView: UIView {
parentViewController?.present(videoQualityMenu, animated: true, completion: nil)
}

func showDownloadQualityMenu(){
let downloadQualityMenu = createDownloadQualityMenu()
parentViewController?.present(downloadQualityMenu, animated: true, completion: nil)
}

func createPlaybackSpeedMenu() -> UIAlertController {
let playbackSpeedMenu = UIAlertController(title: "Playback Speed", message: nil, preferredStyle: ACTION_SHEET_PREFERRED_STYLE)

for playbackSpeed in PlaybackSpeed.allCases {
let action = createActionForPlaybackSpeed(playbackSpeed)
playbackSpeedMenu.addAction(action)
}

playbackSpeedMenu.addAction(UIAlertAction(title: "Cancel", style: .cancel))
return playbackSpeedMenu
}
Expand All @@ -153,12 +161,25 @@ class PlayerControlsUIView: UIView {
qualityMenu.addAction(UIAlertAction(title: "Cancel", style: .cancel))
return qualityMenu
}


func createDownloadQualityMenu() -> UIAlertController {
let qualityMenu = UIAlertController(title: "Available resolutions", message: nil, preferredStyle: ACTION_SHEET_PREFERRED_STYLE)
var availableVideoQualities = player.availableVideoQualities
// Remove Auto Quality from the Array
availableVideoQualities.remove(at: 0)
for quality in availableVideoQualities {
let action = createActionForDownload(quality)
qualityMenu.addAction(action)
}
qualityMenu.addAction(UIAlertAction(title: "Cancel", style: .cancel))
return qualityMenu
}

func createActionForPlaybackSpeed(_ playbackSpeed: PlaybackSpeed) -> UIAlertAction {
let action = UIAlertAction(title: playbackSpeed.label, style: .default) { [weak self] _ in
self?.player.changePlaybackSpeed(playbackSpeed)
}

if playbackSpeed == .normal && self.player.currentPlaybackSpeed.rawValue == 0.0 || (playbackSpeed.rawValue == self.player.currentPlaybackSpeed.rawValue) {
action.setValue(UIImage(named: "checkmark", in: bundle, compatibleWith: nil), forKey: "image")
}
Expand All @@ -176,7 +197,15 @@ class PlayerControlsUIView: UIView {

return action
}


func createActionForDownload(_ quality: VideoQuality) -> UIAlertAction {
let action = UIAlertAction(title: quality.resolution, style: .default, handler: { (_) in
TPStreamsDownloadManager.shared.startDownload(asset: self.player.asset!, videoQuality: quality)
})

return action
}

@IBAction func toggleFullScreen(_ sender: Any) {
if isFullScreen {
fullScreenToggleDelegate?.exitFullScreen()
Expand Down
1 change: 1 addition & 0 deletions StoryboardExample/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class ViewController: UIViewController {
.setPreferredRewindDuration(5)
.setprogressBarThumbColor(.systemBlue)
.setwatchedProgressTrackColor(.systemBlue)
.showDownloadOption()
.build()

playerViewController?.config = config
Expand Down