This repository has been archived by the owner on Sep 1, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
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
Denpex
committed
Feb 9, 2022
1 parent
ec68c6c
commit 9384042
Showing
31 changed files
with
1,245 additions
and
8 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
Large diffs are not rendered by default.
Oops, something went wrong.
78 changes: 78 additions & 0 deletions
78
Example App/Example App.xcodeproj/xcshareddata/xcschemes/Example App.xcscheme
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,78 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<Scheme | ||
LastUpgradeVersion = "1320" | ||
version = "1.3"> | ||
<BuildAction | ||
parallelizeBuildables = "YES" | ||
buildImplicitDependencies = "YES"> | ||
<BuildActionEntries> | ||
<BuildActionEntry | ||
buildForTesting = "YES" | ||
buildForRunning = "YES" | ||
buildForProfiling = "YES" | ||
buildForArchiving = "YES" | ||
buildForAnalyzing = "YES"> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "E16FA8802746FAF70047ABE6" | ||
BuildableName = "Example App.app" | ||
BlueprintName = "Example App" | ||
ReferencedContainer = "container:Example App.xcodeproj"> | ||
</BuildableReference> | ||
</BuildActionEntry> | ||
</BuildActionEntries> | ||
</BuildAction> | ||
<TestAction | ||
buildConfiguration = "Debug" | ||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
shouldUseLaunchSchemeArgsEnv = "YES"> | ||
<Testables> | ||
</Testables> | ||
</TestAction> | ||
<LaunchAction | ||
buildConfiguration = "Debug" | ||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
launchStyle = "0" | ||
useCustomWorkingDirectory = "NO" | ||
ignoresPersistentStateOnLaunch = "NO" | ||
debugDocumentVersioning = "YES" | ||
debugServiceExtension = "internal" | ||
allowLocationSimulation = "YES"> | ||
<BuildableProductRunnable | ||
runnableDebuggingMode = "0"> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "E16FA8802746FAF70047ABE6" | ||
BuildableName = "Example App.app" | ||
BlueprintName = "Example App" | ||
ReferencedContainer = "container:Example App.xcodeproj"> | ||
</BuildableReference> | ||
</BuildableProductRunnable> | ||
</LaunchAction> | ||
<ProfileAction | ||
buildConfiguration = "Release" | ||
shouldUseLaunchSchemeArgsEnv = "YES" | ||
savedToolIdentifier = "" | ||
useCustomWorkingDirectory = "NO" | ||
debugDocumentVersioning = "YES"> | ||
<BuildableProductRunnable | ||
runnableDebuggingMode = "0"> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "E16FA8802746FAF70047ABE6" | ||
BuildableName = "Example App.app" | ||
BlueprintName = "Example App" | ||
ReferencedContainer = "container:Example App.xcodeproj"> | ||
</BuildableReference> | ||
</BuildableProductRunnable> | ||
</ProfileAction> | ||
<AnalyzeAction | ||
buildConfiguration = "Debug"> | ||
</AnalyzeAction> | ||
<ArchiveAction | ||
buildConfiguration = "Release" | ||
revealArchiveInOrganizer = "YES"> | ||
</ArchiveAction> | ||
</Scheme> |
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,30 @@ | ||
// | ||
// AppDelegate.swift | ||
// flowplayer-tvOS | ||
// | ||
// Created by Mehdi on 18. 11. 2021.. | ||
// | ||
|
||
import UIKit | ||
import AVFoundation | ||
|
||
@main | ||
class AppDelegate: UIResponder, UIApplicationDelegate { | ||
|
||
var window: UIWindow? | ||
|
||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { | ||
let audioSession = AVAudioSession.sharedInstance() | ||
|
||
do { | ||
// Required for audio & video playback on physical devices | ||
try audioSession.setCategory(.playback, mode: .moviePlayback) | ||
} catch { | ||
print("Setting category to AVAudioSessionCategoryPlayback failed.") | ||
} | ||
|
||
return true | ||
} | ||
|
||
} | ||
|
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,26 @@ | ||
// | ||
// Constants.swift | ||
// flowplayer-tvOS | ||
// | ||
// Created by Mehdi on 18. 11. 2021.. | ||
// | ||
|
||
import Foundation | ||
|
||
struct Constants { | ||
// - Videos | ||
static let DEMO_MEDIA_ID = "69891ec1-2d90-423c-9892-5a9ee87b6d86" | ||
static let DEMO_PLAYER_ID = "ac6dea7c-acf1-472a-bdab-efdd85f092f1" | ||
static let DEMO_URL_HLS = "https://wowzaec2demo.streamlock.net/vod-multitrack/_definst_/smil:ElephantsDream/ElephantsDream.smil/playlist.m3u8" | ||
static let DEMO_URL_MP4 = "https://edge.flowplayer.org/drive.mp4" | ||
static let DEMO_URL_HLS_SUBTITLES = "https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8" | ||
static let DEMO_MEDIA_ID_SUBTITLES = "279a8421-2488-4698-b0bd-2df15b2fabfe" | ||
static let DEMO_URL_VMAP = "https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpostpod&cmsid=496&vid=short_onecue&correlator=" | ||
|
||
// - Ads | ||
static let DEMO_URL_AD_PREROLL = "https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&vad_type=linear&vpos=preroll&pod=1&ppos=1&lip=true&min_ad_duration=0&max_ad_duration=30000&vrid=6376&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpostpod&url=&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0" | ||
static let DEMO_URL_AD_MIDROLL1 = "https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&cue=15000&vad_type=linear&vpos=midroll&pod=2&mridx=1&ppos=1&min_ad_duration=0&max_ad_duration=30000&vrid=6376&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpostpod&url=&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0" | ||
static let DEMO_URL_AD_MIDROLL2 = "https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&cue=15000&vad_type=linear&vpos=midroll&pod=2&mridx=1&ppos=2&min_ad_duration=0&max_ad_duration=30000&vrid=6376&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpostpod&url=&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0" | ||
static let DEMO_URL_AD_MIDROLL3 = "https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&cue=15000&vad_type=linear&vpos=midroll&pod=2&mridx=1&ppos=3&lip=true&min_ad_duration=0&max_ad_duration=30000&vrid=6376&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpostpod&url=&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0" | ||
static let DEMO_URL_AD_POSTROLL = "https://pubads.g.doubleclick.net/gampad/ads?slotname=/124319096/external/ad_rule_samples&sz=640x480&ciu_szs=300x250&unviewed_position_start=1&output=xml_vast3&impl=s&env=vp&gdfp_req=1&ad_rule=0&vad_type=linear&vpos=postroll&pod=3&ppos=1&lip=true&min_ad_duration=0&max_ad_duration=30000&vrid=6376&cust_params=deployment%3Ddevsite%26sample_ar%3Dpremidpostpod&url=&video_doc_id=short_onecue&cmsid=496&kfa=0&tfcd=0" | ||
} |
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,216 @@ | ||
// | ||
// MainController.swift | ||
// flowplayer-tvOS | ||
// | ||
// Created by Mehdi on 18. 11. 2021.. | ||
// | ||
|
||
import AVKit | ||
import Flowplayer | ||
|
||
// - Identifiers | ||
fileprivate let CELL_ID = "video-cell" | ||
|
||
class MainController: UIViewController { | ||
|
||
// - Views | ||
@IBOutlet weak var tableView: UITableView! | ||
|
||
// - Props | ||
private var flowplayer: FPFlowplayer! | ||
private let player = AVPlayer() | ||
private let playerController = AVPlayerViewController() | ||
|
||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
tableView.dataSource = self | ||
tableView.delegate = self | ||
|
||
playerController.player = player | ||
playerController.modalPresentationStyle = .fullScreen | ||
playerController.delegate = self | ||
flowplayer = FPFlowplayer(player: player, controller: playerController) | ||
flowplayer.delegate = self | ||
} | ||
|
||
} | ||
|
||
// MARK: - UITableViewDatasource | ||
extension MainController: UITableViewDataSource { | ||
|
||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | ||
return tableData.count | ||
} | ||
|
||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | ||
let cell = tableView.dequeueReusableCell(withIdentifier: CELL_ID, for: indexPath) | ||
cell.textLabel?.text = tableData[indexPath.row].title | ||
cell.accessoryType = .disclosureIndicator | ||
return cell | ||
} | ||
|
||
} | ||
|
||
// MARK: - UITableViewDelegate | ||
extension MainController: UITableViewDelegate { | ||
|
||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { | ||
let item = tableData[indexPath.row] | ||
|
||
present(playerController, animated: true) { [weak self] in | ||
// INFO: For the ADs to load, media needs to be loaded after the controller has been presented | ||
self?.onPlayControllerPresented(item: item) | ||
} | ||
} | ||
|
||
} | ||
|
||
// MARK: - Private | ||
extension MainController { | ||
|
||
private func onPlayControllerPresented(item: TableItem) { | ||
if let externalMedia = item.externalMedia { | ||
self.flowplayer.load(external: externalMedia, autoStart: true) | ||
} | ||
|
||
if let flowplayerMedia = item.flowplayerMedia { | ||
self.flowplayer.load(flowplayer: flowplayerMedia, autoStart: true) | ||
} | ||
} | ||
|
||
} | ||
|
||
// MARK: - AVPlayer | ||
extension MainController: AVPlayerViewControllerDelegate { | ||
|
||
func playerViewControllerWillBeginDismissalTransition(_ playerViewController: AVPlayerViewController) { | ||
// Stop flowplayer playback | ||
flowplayer.stop() | ||
} | ||
|
||
} | ||
|
||
// MARK: - FPFlowplayerDelegate | ||
extension MainController: FPFlowplayerDelegate { | ||
|
||
func onIdle(event: FPIdleEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onReady(event: FPReadyEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onPlay(event: FPPlayEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onPause(event: FPPauseEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onBuffer(event: FPBufferEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onComplete(event: FPCompleteEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onMute(event: FPMuteEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onVolume(event: FPVolumeEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onSpeed(event: FPSpeedEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onAudioTracksLoaded(event: FPAudioTracksEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onAudioTrackSelect(event: FPAudioTrackSelectEvent) { | ||
print(#function) | ||
print(event.audioTrack) | ||
} | ||
|
||
func onSubtitleTrackSelect(event: FPSubtitleTrackSelectEvent) { | ||
print(#function) | ||
dump(event.subtitleTrack) | ||
} | ||
|
||
func onSubtitleTracksLoaded(event: FPSubtitleTracksEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onOvpMetadata(event: FPOvpMetadataEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onError(event: FPErrorEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onAdBreakStart(event: FPAdBreakStartEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onAdBreakComplete(event: FPAdBreakCompleteEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onAdStart(event: FPAdStartEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onAdPause(event: FPAdPauseEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onAdResume(event: FPAdResumeEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onAdClick(event: FPAdClickEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onAdSkip(event: FPAdSkipEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onAdComplete(event: FPAdCompleteEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
func onAdError(event: FPAdErrorEvent) { | ||
print(#function) | ||
print(event) | ||
} | ||
|
||
} |
Oops, something went wrong.