diff --git a/Model/Player/Backends/MPVBackend.swift b/Model/Player/Backends/MPVBackend.swift index f616bef1..e4359673 100644 --- a/Model/Player/Backends/MPVBackend.swift +++ b/Model/Player/Backends/MPVBackend.swift @@ -4,9 +4,9 @@ import Defaults import Foundation import Logging import MediaPlayer +import MPVKit import Repeat import SwiftUI -import MPVKit final class MPVBackend: PlayerBackend { static var timeUpdateInterval = 0.5 @@ -464,6 +464,13 @@ final class MPVBackend: PlayerBackend { startClientUpdates() onFileLoaded = nil + case MPV_EVENT_PROPERTY_CHANGE: + let dataOpaquePtr = OpaquePointer(event.pointee.data) + if let property = UnsafePointer(dataOpaquePtr)?.pointee { + let propertyName = String(cString: property.name) + handlePropertyChange(propertyName, property) + } + case MPV_EVENT_PLAYBACK_RESTART: isLoadingVideo = false isSeeking = false @@ -584,4 +591,22 @@ final class MPVBackend: PlayerBackend { stopMusicMode() } } + + private func handlePropertyChange(_ name: String, _ property: mpv_event_property) { + switch name { + case "pause": + if let paused = UnsafePointer(OpaquePointer(property.data))?.pointee { + if paused { + DispatchQueue.main.async { [weak self] in self?.handleEndOfFile() } + } else { + isLoadingVideo = false + isSeeking = false + } + isPlaying = !paused + networkStateTimer.start() + } + default: + logger.info("MPV backend received unhandled property: \(name)") + } + } } diff --git a/Model/Player/Backends/MPVClient.swift b/Model/Player/Backends/MPVClient.swift index 32c51273..138fa052 100644 --- a/Model/Player/Backends/MPVClient.swift +++ b/Model/Player/Backends/MPVClient.swift @@ -107,9 +107,8 @@ final class MPVClient: ObservableObject { #endif } - queue!.async { - mpv_set_wakeup_callback(self.mpv, wakeUp, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())) - } + mpv_set_wakeup_callback(mpv, wakeUp, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())) + mpv_observe_property(mpv, 0, "pause", MPV_FORMAT_FLAG) } func readEvents() { @@ -431,6 +430,7 @@ final class MPVClient: ObservableObject { } func getString(_ name: String) -> String? { + guard mpv != nil else { return nil } let cstr = mpv_get_property_string(mpv, name) let str: String? = cstr == nil ? nil : String(cString: cstr!) mpv_free(cstr) diff --git a/Shared/Player/MPV/MPVOGLView.swift b/Shared/Player/MPV/MPVOGLView.swift index e5d57871..3311aa30 100644 --- a/Shared/Player/MPV/MPVOGLView.swift +++ b/Shared/Player/MPV/MPVOGLView.swift @@ -1,7 +1,7 @@ import GLKit import Logging -import OpenGLES import MPVKit +import OpenGLES final class MPVOGLView: GLKView { private var logger = Logger(label: "stream.yattee.mpv.oglview") diff --git a/Yattee.xcodeproj/project.pbxproj b/Yattee.xcodeproj/project.pbxproj index c03106fc..867eb2d0 100644 --- a/Yattee.xcodeproj/project.pbxproj +++ b/Yattee.xcodeproj/project.pbxproj @@ -72,6 +72,8 @@ 3703206627D2BB35007A0CB8 /* PINCache in Frameworks */ = {isa = PBXBuildFile; productRef = 3703206527D2BB35007A0CB8 /* PINCache */; }; 3703206827D2BB45007A0CB8 /* Defaults in Frameworks */ = {isa = PBXBuildFile; productRef = 3703206727D2BB45007A0CB8 /* Defaults */; }; 3703206A27D2BB49007A0CB8 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 3703206927D2BB49007A0CB8 /* Alamofire */; }; + 3704BDFF2ABF260C00370FF7 /* MPVKit in Frameworks */ = {isa = PBXBuildFile; productRef = 3704BDFE2ABF260C00370FF7 /* MPVKit */; }; + 3704BE012ABF263E00370FF7 /* MPVKit in Frameworks */ = {isa = PBXBuildFile; productRef = 3704BE002ABF263E00370FF7 /* MPVKit */; }; 3705B180267B4DFB00704544 /* TrendingCountry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B17F267B4DFB00704544 /* TrendingCountry.swift */; }; 3705B182267B4E4900704544 /* TrendingCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B181267B4E4900704544 /* TrendingCategory.swift */; }; 3705B183267B4E4900704544 /* TrendingCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B181267B4E4900704544 /* TrendingCategory.swift */; }; @@ -1444,6 +1446,7 @@ 375B8AB728B583BD00397B31 /* KeychainAccess in Frameworks */, 3703205E27D2BB12007A0CB8 /* SDWebImageWebPCoder in Frameworks */, 37CF8B8628535E5A00B71E37 /* SDWebImage in Frameworks */, + 3704BDFF2ABF260C00370FF7 /* MPVKit in Frameworks */, 3703205C27D2BAF3007A0CB8 /* SwiftyJSON in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1489,6 +1492,7 @@ 372915E42687E33E00F5A35B /* Defaults in Frameworks */, 3772003B27E8EEC800CB2475 /* libbz2.tbd in Frameworks */, 37BADCA9269A570B009BE4FB /* Alamofire in Frameworks */, + 3704BE012ABF263E00370FF7 /* MPVKit in Frameworks */, 37D4B19D2671817900C925CA /* SwiftyJSON in Frameworks */, 3797757D268922D100DD52A8 /* Siesta in Frameworks */, ); @@ -2338,6 +2342,7 @@ 371AC0B1294D1C230085989E /* CachedAsyncImage */, 379325D629A265AE00181CF1 /* Logging */, 379E7C352A2105B900AF8118 /* Introspect */, + 3704BDFE2ABF260C00370FF7 /* MPVKit */, ); productName = "Yattee (macOS)"; productReference = 37D4B0CF2671614900C925CA /* Yattee.app */; @@ -2415,6 +2420,7 @@ 377F9F75294403880043F856 /* Cache */, 371AC0B3294D1C290085989E /* CachedAsyncImage */, 379325D829A265B500181CF1 /* Logging */, + 3704BE002ABF263E00370FF7 /* MPVKit */, ); productName = Yattee; productReference = 37D4B158267164AE00C925CA /* Yattee.app */; @@ -4043,7 +4049,6 @@ ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/Vendor/mpv/macOS/lib", ); MACOSX_DEPLOYMENT_TARGET = 12.0; MARKETING_VERSION = 1.5; @@ -4086,7 +4091,6 @@ ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/Vendor/mpv/macOS/lib", ); MACOSX_DEPLOYMENT_TARGET = 12.0; MARKETING_VERSION = 1.5; @@ -4665,6 +4669,16 @@ package = 37BADCA32699FB72009BE4FB /* XCRemoteSwiftPackageReference "Alamofire" */; productName = Alamofire; }; + 3704BDFE2ABF260C00370FF7 /* MPVKit */ = { + isa = XCSwiftPackageProductDependency; + package = FA97174A2A494700001FF53D /* XCRemoteSwiftPackageReference "MPVKit" */; + productName = MPVKit; + }; + 3704BE002ABF263E00370FF7 /* MPVKit */ = { + isa = XCSwiftPackageProductDependency; + package = FA97174A2A494700001FF53D /* XCRemoteSwiftPackageReference "MPVKit" */; + productName = MPVKit; + }; 371AC0AB294D1A490085989E /* CachedAsyncImage */ = { isa = XCSwiftPackageProductDependency; package = 371AC0AA294D1A490085989E /* XCRemoteSwiftPackageReference "swiftui-cached-async-image" */; diff --git a/Yattee.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Yattee.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index e129a61a..bf2656de 100644 --- a/Yattee.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Yattee.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -59,8 +59,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/cxfksword/MPVKit.git", "state" : { - "revision" : "4c7109e35bafe7331da9db98949b7debd25ef0c8", - "version" : "0.35.1" + "revision" : "96825b3dc2b38e5550268156148d47798ce6aa74", + "version" : "0.36.0" } }, { diff --git a/macOS/BridgingHeader.h b/macOS/BridgingHeader.h index c181a4b9..7dc3efd5 100644 --- a/macOS/BridgingHeader.h +++ b/macOS/BridgingHeader.h @@ -1,6 +1,2 @@ #import #import -#import "../Vendor/mpv/include/client.h" -#import "../Vendor/mpv/include/render.h" -#import "../Vendor/mpv/include/render_gl.h" -#import "../Vendor/mpv/include/stream_cb.h" diff --git a/macOS/VideoLayer.swift b/macOS/VideoLayer.swift index 9f42637b..a3a83c55 100644 --- a/macOS/VideoLayer.swift +++ b/macOS/VideoLayer.swift @@ -1,4 +1,5 @@ import Cocoa +import MPVKit import OpenGL.GL import OpenGL.GL3 diff --git a/tvOS/BridgingHeader.h b/tvOS/BridgingHeader.h index 301e35c0..92846118 100644 --- a/tvOS/BridgingHeader.h +++ b/tvOS/BridgingHeader.h @@ -1,5 +1 @@ #import -#import "../Vendor/mpv/include/client.h" -#import "../Vendor/mpv/include/render.h" -#import "../Vendor/mpv/include/render_gl.h" -#import "../Vendor/mpv/include/stream_cb.h"