mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-06-04 04:58:30 +01:00
fix: IOS video player black screens
- restores player view when re-entering apps foreground - added logger
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"platforms": ["ios", "tvos", "android", "web"],
|
"platforms": ["ios", "tvos", "android", "web"],
|
||||||
"ios": {
|
"ios": {
|
||||||
"modules": ["VlcPlayerModule"]
|
"modules": ["VlcPlayerModule"],
|
||||||
|
"appDelegateSubscribers": ["AppLifecycleDelegate"]
|
||||||
},
|
},
|
||||||
"android": {
|
"android": {
|
||||||
"modules": ["expo.modules.vlcplayer.VlcPlayerModule"]
|
"modules": ["expo.modules.vlcplayer.VlcPlayerModule"]
|
||||||
|
|||||||
32
modules/vlc-player/ios/AppLifecycleDelegate.swift
Normal file
32
modules/vlc-player/ios/AppLifecycleDelegate.swift
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import ExpoModulesCore
|
||||||
|
|
||||||
|
protocol SimpleAppLifecycleListener {
|
||||||
|
func applicationDidEnterBackground() -> Void
|
||||||
|
func applicationDidEnterForeground() -> Void
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AppLifecycleDelegate: ExpoAppDelegateSubscriber {
|
||||||
|
public func applicationDidBecomeActive(_ application: UIApplication) {
|
||||||
|
// The app has become active.
|
||||||
|
}
|
||||||
|
|
||||||
|
public func applicationWillResignActive(_ application: UIApplication) {
|
||||||
|
// The app is about to become inactive.
|
||||||
|
}
|
||||||
|
|
||||||
|
public func applicationDidEnterBackground(_ application: UIApplication) {
|
||||||
|
VLCManager.shared.listeners.forEach { listener in
|
||||||
|
listener.applicationDidEnterBackground()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func applicationWillEnterForeground(_ application: UIApplication) {
|
||||||
|
VLCManager.shared.listeners.forEach { listener in
|
||||||
|
listener.applicationDidEnterForeground()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func applicationWillTerminate(_ application: UIApplication) {
|
||||||
|
// The app is about to terminate.
|
||||||
|
}
|
||||||
|
}
|
||||||
4
modules/vlc-player/ios/VLCManager.swift
Normal file
4
modules/vlc-player/ios/VLCManager.swift
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
class VLCManager {
|
||||||
|
static let shared = VLCManager()
|
||||||
|
var listeners: [SimpleAppLifecycleListener] = []
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import ExpoModulesCore
|
import ExpoModulesCore
|
||||||
import UIKit
|
import UIKit
|
||||||
import VLCKit
|
import VLCKit
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
public class VLCPlayerView: UIView {
|
public class VLCPlayerView: UIView {
|
||||||
func setupView(parent: UIView) {
|
func setupView(parent: UIView) {
|
||||||
@@ -142,6 +144,8 @@ extension VLCPlayerWrapper: VLCMediaDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class VlcPlayerView: ExpoView {
|
class VlcPlayerView: ExpoView {
|
||||||
|
let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "VlcPlayerView")
|
||||||
|
|
||||||
private var vlc: VLCPlayerWrapper = VLCPlayerWrapper()
|
private var vlc: VLCPlayerWrapper = VLCPlayerWrapper()
|
||||||
private var progressUpdateInterval: TimeInterval = 1.0 // Update interval set to 1 second
|
private var progressUpdateInterval: TimeInterval = 1.0 // Update interval set to 1 second
|
||||||
private var isPaused: Bool = false
|
private var isPaused: Bool = false
|
||||||
@@ -157,6 +161,7 @@ class VlcPlayerView: ExpoView {
|
|||||||
super.init(appContext: appContext)
|
super.init(appContext: appContext)
|
||||||
setupVLC()
|
setupVLC()
|
||||||
setupNotifications()
|
setupNotifications()
|
||||||
|
VLCManager.shared.listeners.append(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Setup
|
// MARK: - Setup
|
||||||
@@ -188,7 +193,7 @@ class VlcPlayerView: ExpoView {
|
|||||||
@objc func play() {
|
@objc func play() {
|
||||||
self.vlc.player.play()
|
self.vlc.player.play()
|
||||||
self.isPaused = false
|
self.isPaused = false
|
||||||
print("Play")
|
logger.debug("Play")
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func pause() {
|
@objc func pause() {
|
||||||
@@ -203,7 +208,7 @@ class VlcPlayerView: ExpoView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let duration = vlc.player.media?.length.intValue {
|
if let duration = vlc.player.media?.length.intValue {
|
||||||
print("Seeking to time: \(time) Video Duration \(duration)")
|
logger.debug("Seeking to time: \(time) Video Duration \(duration)")
|
||||||
|
|
||||||
// If the specified time is greater than the duration, seek to the end
|
// If the specified time is greater than the duration, seek to the end
|
||||||
let seekTime = time > duration ? duration - 1000 : time
|
let seekTime = time > duration ? duration - 1000 : time
|
||||||
@@ -217,11 +222,12 @@ class VlcPlayerView: ExpoView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print("Error: Unable to retrieve video duration")
|
logger.error("Unable to retrieve video duration")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func setSource(_ source: [String: Any]) {
|
@objc func setSource(_ source: [String: Any]) {
|
||||||
|
logger.debug("Setting source...")
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
if self.hasSource {
|
if self.hasSource {
|
||||||
@@ -241,7 +247,7 @@ class VlcPlayerView: ExpoView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard let uri = source["uri"] as? String, !uri.isEmpty else {
|
guard let uri = source["uri"] as? String, !uri.isEmpty else {
|
||||||
print("Error: Invalid or empty URI")
|
logger.error("Invalid or empty URI")
|
||||||
self.onVideoError?(["error": "Invalid or empty URI"])
|
self.onVideoError?(["error": "Invalid or empty URI"])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -253,10 +259,10 @@ class VlcPlayerView: ExpoView {
|
|||||||
|
|
||||||
let media: VLCMedia!
|
let media: VLCMedia!
|
||||||
if isNetwork {
|
if isNetwork {
|
||||||
print("Loading network file: \(uri)")
|
logger.debug("Loading network file: \(uri)")
|
||||||
media = VLCMedia(url: URL(string: uri)!)
|
media = VLCMedia(url: URL(string: uri)!)
|
||||||
} else {
|
} else {
|
||||||
print("Loading local file: \(uri)")
|
logger.debug("Loading local file: \(uri)")
|
||||||
if uri.starts(with: "file://"), let url = URL(string: uri) {
|
if uri.starts(with: "file://"), let url = URL(string: uri) {
|
||||||
media = VLCMedia(url: url)
|
media = VLCMedia(url: url)
|
||||||
} else {
|
} else {
|
||||||
@@ -264,14 +270,14 @@ class VlcPlayerView: ExpoView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print("Debug: Media options: \(mediaOptions)")
|
logger.debug("Media options: \(mediaOptions)")
|
||||||
media.addOptions(mediaOptions)
|
media.addOptions(mediaOptions)
|
||||||
|
|
||||||
self.vlc.player.media = media
|
self.vlc.player.media = media
|
||||||
self.setInitialExternalSubtitles()
|
self.setInitialExternalSubtitles()
|
||||||
self.hasSource = true
|
self.hasSource = true
|
||||||
if autoplay {
|
if autoplay {
|
||||||
print("Playing...")
|
logger.info("Playing...")
|
||||||
self.play()
|
self.play()
|
||||||
self.vlc.player.time = VLCTime(number: NSNumber(value: self.startPosition * 1000))
|
self.vlc.player.time = VLCTime(number: NSNumber(value: self.startPosition * 1000))
|
||||||
}
|
}
|
||||||
@@ -291,31 +297,31 @@ class VlcPlayerView: ExpoView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc func setSubtitleTrack(_ trackIndex: Int) {
|
@objc func setSubtitleTrack(_ trackIndex: Int) {
|
||||||
print("Debug: Attempting to set subtitle track to index: \(trackIndex)")
|
logger.debug("Attempting to set subtitle track to index: \(trackIndex)")
|
||||||
if trackIndex == -1 {
|
if trackIndex == -1 {
|
||||||
print("Debug: Disabling all subtitles")
|
logger.debug("Disabling all subtitles")
|
||||||
for track in self.vlc.player.textTracks {
|
for track in self.vlc.player.textTracks {
|
||||||
track.isSelected = false
|
track.isSelected = false
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let track = self.vlc.player.textTracks[trackIndex]
|
let track = self.vlc.player.textTracks[trackIndex]
|
||||||
track.isSelectedExclusively = true
|
track.isSelectedExclusively = true;
|
||||||
print("Debug: Current subtitle track index after setting: \(track.trackName)")
|
logger.debug("Current subtitle track index after setting: \(track.trackName)")
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func setSubtitleURL(_ subtitleURL: String, name: String) {
|
@objc func setSubtitleURL(_ subtitleURL: String, name: String) {
|
||||||
guard let url = URL(string: subtitleURL) else {
|
guard let url = URL(string: subtitleURL) else {
|
||||||
print("Error: Invalid subtitle URL")
|
logger.error("Invalid subtitle URL")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let result = self.vlc.player.addPlaybackSlave(url, type: .subtitle, enforce: false)
|
let result = self.vlc.player.addPlaybackSlave(url, type: .subtitle, enforce: false)
|
||||||
if result == 0 {
|
if result == 0 {
|
||||||
let internalName = "Track \(self.customSubtitles.count)"
|
let internalName = "Track \(self.customSubtitles.count)"
|
||||||
self.customSubtitles.append((internalName: internalName, originalName: name))
|
self.customSubtitles.append((internalName: internalName, originalName: name))
|
||||||
print("Subtitle added with result: \(result) \(internalName)")
|
logger.debug("Subtitle added with result: \(result) \(internalName)")
|
||||||
} else {
|
} else {
|
||||||
print("Failed to add subtitle")
|
logger.debug("Failed to add subtitle")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +330,8 @@ class VlcPlayerView: ExpoView {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
print("Debug: Number of subtitle tracks: \(self.vlc.player.textTracks.count)")
|
logger.debug("Number of subtitle tracks: \(self.vlc.player.textTracks.count)")
|
||||||
|
|
||||||
let tracks = self.vlc.player.textTracks.enumerated().map { (index, track) in
|
let tracks = self.vlc.player.textTracks.enumerated().map { (index, track) in
|
||||||
if let customSubtitle = customSubtitles.first(where: {
|
if let customSubtitle = customSubtitles.first(where: {
|
||||||
$0.internalName == track.trackName
|
$0.internalName == track.trackName
|
||||||
@@ -334,11 +341,13 @@ class VlcPlayerView: ExpoView {
|
|||||||
return ["name": track.trackName, "index": index]
|
return ["name": track.trackName, "index": index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print("Debug: Subtitle tracks: \(tracks)")
|
|
||||||
return tracks
|
logger.debug("Subtitle tracks: \(tracks)")
|
||||||
|
return tracks
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func stop(completion: (() -> Void)? = nil) {
|
@objc func stop(completion: (() -> Void)? = nil) {
|
||||||
|
logger.debug("Stopping media...")
|
||||||
guard !isStopping else {
|
guard !isStopping else {
|
||||||
completion?()
|
completion?()
|
||||||
return
|
return
|
||||||
@@ -398,7 +407,7 @@ class VlcPlayerView: ExpoView {
|
|||||||
let currentTimeMs = self.vlc.player.time.intValue
|
let currentTimeMs = self.vlc.player.time.intValue
|
||||||
let durationMs = self.vlc.player.media?.length.intValue ?? 0
|
let durationMs = self.vlc.player.media?.length.intValue ?? 0
|
||||||
|
|
||||||
print("Debug: Current time: \(currentTimeMs)")
|
logger.debug("Current time: \(currentTimeMs)")
|
||||||
self.onVideoProgress?([
|
self.onVideoProgress?([
|
||||||
"currentTime": currentTimeMs,
|
"currentTime": currentTimeMs,
|
||||||
"duration": durationMs,
|
"duration": durationMs,
|
||||||
@@ -430,7 +439,24 @@ class VlcPlayerView: ExpoView {
|
|||||||
// MARK: - Deinitialization
|
// MARK: - Deinitialization
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
logger.debug("Deinitialization")
|
||||||
performStop()
|
performStop()
|
||||||
|
VLCManager.shared.listeners.removeAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - SimpleAppLifecycleListener
|
||||||
|
extension VlcPlayerView: SimpleAppLifecycleListener {
|
||||||
|
func applicationDidEnterBackground() {
|
||||||
|
logger.debug("Entering background")
|
||||||
|
}
|
||||||
|
|
||||||
|
func applicationDidEnterForeground() {
|
||||||
|
logger.debug("Entering foreground")
|
||||||
|
if !self.vlc.getPlayerView().isDescendant(of: self) {
|
||||||
|
logger.debug("Player view is missing. Adding back as subview")
|
||||||
|
self.addSubview(self.vlc.getPlayerView())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user