diff --git a/Sources/KSPlayer/AVPlayer/KSPlayerLayer.swift b/Sources/KSPlayer/AVPlayer/KSPlayerLayer.swift index 6df93e9b4..a6cc3743b 100644 --- a/Sources/KSPlayer/AVPlayer/KSPlayerLayer.swift +++ b/Sources/KSPlayer/AVPlayer/KSPlayerLayer.swift @@ -50,7 +50,7 @@ public enum KSPlayerState: CustomStringConvertible { } } - public var isPlaying: Bool { self == .readyToPlay || self == .buffering || self == .bufferFinished } + public var isPlaying: Bool { self == .buffering || self == .bufferFinished } } public protocol KSPlayerLayerDelegate: AnyObject { @@ -459,13 +459,6 @@ extension KSPlayerLayer { startTime = CACurrentMediaTime() bufferedCount = 0 player.prepareToPlay() - if isAutoPlay { - DispatchQueue.main.async { - self.state = .buffering - } - } else { - state = .prepareToPlay - } if let view = player.view { addSubview(view) } @@ -521,7 +514,7 @@ extension KSPlayerLayer { } } - private func registerRemoteControllEvent() { + public func registerRemoteControllEvent() { let remoteCommand = MPRemoteCommandCenter.shared() remoteCommand.playCommand.addTarget { [weak self] _ in guard let self else { diff --git a/Sources/KSPlayer/AVPlayer/KSVideoPlayer.swift b/Sources/KSPlayer/AVPlayer/KSVideoPlayer.swift index 44a2431bf..57bd03517 100644 --- a/Sources/KSPlayer/AVPlayer/KSVideoPlayer.swift +++ b/Sources/KSPlayer/AVPlayer/KSVideoPlayer.swift @@ -113,7 +113,6 @@ extension KSVideoPlayer: UIViewRepresentable { didSet { oldValue?.delegate = nil oldValue?.pause() - subtitleModel.url = nil } } @@ -131,20 +130,23 @@ extension KSVideoPlayer: UIViewRepresentable { public init() {} public func makeView(url: URL, options: KSOptions) -> KSPlayerLayer { + defer { + DispatchQueue.main.async { [weak self] in + self?.subtitleModel.url = url + } + } if let playerLayer { if playerLayer.url == url { return playerLayer } playerLayer.delegate = nil playerLayer.set(url: url, options: options) - subtitleModel.url = url playerLayer.delegate = self return playerLayer } else { let playerLayer = KSPlayerLayer(url: url, options: options) playerLayer.delegate = self self.playerLayer = playerLayer - subtitleModel.url = url return playerLayer } } @@ -158,6 +160,9 @@ extension KSVideoPlayer: UIViewRepresentable { onSwipe = nil #endif playerLayer = nil + DispatchQueue.main.async { [weak self] in + self?.subtitleModel.url = nil + } } public func skip(interval: Int) { diff --git a/Sources/KSPlayer/Subtitle/KSSubtitle.swift b/Sources/KSPlayer/Subtitle/KSSubtitle.swift index be2d9261a..89fe22cf5 100644 --- a/Sources/KSPlayer/Subtitle/KSSubtitle.swift +++ b/Sources/KSPlayer/Subtitle/KSSubtitle.swift @@ -276,6 +276,7 @@ open class SubtitleModel: ObservableObject { public static var textItalic = false public static var textPosition = TextPosition() private var subtitleDataSouces: [SubtitleDataSouce] = KSOptions.subtitleDataSouces + @Published public private(set) var subtitleInfos = [any SubtitleInfo]() @Published public private(set) var parts = [SubtitlePart]() @@ -339,7 +340,7 @@ open class SubtitleModel: ObservableObject { $0 === info } } - Task { + Task { @MainActor in try? await dataSouce.searchSubtitle(query: query, languages: languages) subtitleInfos.append(contentsOf: dataSouce.infos) } @@ -349,7 +350,7 @@ open class SubtitleModel: ObservableObject { public func addSubtitle(dataSouce: SubtitleDataSouce) { if let dataSouce = dataSouce as? FileURLSubtitleDataSouce { - Task { + Task { @MainActor in try? await dataSouce.searchSubtitle(fileURL: url) subtitleInfos.append(contentsOf: dataSouce.infos) } diff --git a/Sources/KSPlayer/Subtitle/SubtitleDataSouce.swift b/Sources/KSPlayer/Subtitle/SubtitleDataSouce.swift index 6f376c438..020f8eba1 100644 --- a/Sources/KSPlayer/Subtitle/SubtitleDataSouce.swift +++ b/Sources/KSPlayer/Subtitle/SubtitleDataSouce.swift @@ -261,15 +261,15 @@ public class OpenSubtitleDataSouce: SearchSubtitleDataSouce { try await searchSubtitle(query: query, imdbID: 0, tmdbID: 0, languages: languages) } - public func searchSubtitle(query: String?, imdbID: Int?, tmdbID: Int?, languages: [String] = ["zh-cn"]) async throws { + public func searchSubtitle(query: String?, imdbID: Int, tmdbID: Int, languages: [String] = ["zh-cn"]) async throws { var queryItems = [String: String]() if let query { queryItems["query"] = query } - if let imdbID { + if imdbID != 0 { queryItems["imbd_id"] = String(imdbID) } - if let tmdbID { + if tmdbID != 0 { queryItems["tmdb_id"] = String(tmdbID) } if queryItems.isEmpty { @@ -278,6 +278,7 @@ public class OpenSubtitleDataSouce: SearchSubtitleDataSouce { queryItems["languages"] = languages.joined(separator: ",") } + // https://opensubtitles.stoplight.io/docs/opensubtitles-api/a172317bd5ccc-search-for-subtitles public func searchSubtitle(queryItems: [String: String]) async throws { infos = [any SubtitleInfo]() if queryItems.isEmpty { diff --git a/Sources/KSPlayer/SwiftUI/KSVideoPlayerView.swift b/Sources/KSPlayer/SwiftUI/KSVideoPlayerView.swift index b46aafae8..e661f16e1 100644 --- a/Sources/KSPlayer/SwiftUI/KSVideoPlayerView.swift +++ b/Sources/KSPlayer/SwiftUI/KSVideoPlayerView.swift @@ -440,8 +440,16 @@ struct VideoSettingView: View { fileprivate var config: KSVideoPlayer.Coordinator @ObservedObject fileprivate var subtitleModel: SubtitleModel + @State + fileprivate var subtitleTitle: String @Environment(\.dismiss) private var dismiss + init(config: KSVideoPlayer.Coordinator, subtitleModel: SubtitleModel) { + self.config = config + self.subtitleModel = subtitleModel + _subtitleTitle = .init(initialValue: subtitleModel.url?.deletingPathExtension().lastPathComponent ?? "") + } + var body: some View { PlatformView { Picker(selection: $config.playbackRate) { @@ -491,24 +499,26 @@ struct VideoSettingView: View { Label("Video track", systemImage: "video.fill") } } - if !config.subtitleModel.subtitleInfos.isEmpty { - Picker(selection: Binding { - subtitleModel.selectedSubtitleInfo?.subtitleID - } set: { value in - subtitleModel.selectedSubtitleInfo = subtitleModel.subtitleInfos.first { $0.subtitleID == value } - }) { - Text("Off").tag(nil as String?) - ForEach(subtitleModel.subtitleInfos, id: \.subtitleID) { track in - Text(track.name).tag(track.subtitleID as String?) - } - } label: { - Label("Sutitle", systemImage: "captions.bubble") + Picker(selection: Binding { + subtitleModel.selectedSubtitleInfo?.subtitleID + } set: { value in + subtitleModel.selectedSubtitleInfo = subtitleModel.subtitleInfos.first { $0.subtitleID == value } + }) { + Text("Off").tag(nil as String?) + ForEach(subtitleModel.subtitleInfos, id: \.subtitleID) { track in + Text(track.name).tag(track.subtitleID as String?) } - TextField("Sutitle delay", value: $subtitleModel.subtitleDelay, format: .number) + } label: { + Label("Sutitle", systemImage: "captions.bubble") + } + TextField("Get more Sutitle", text: $subtitleTitle) + Button("Search") { + subtitleModel.searchSubtitle(query: subtitleTitle, languages: ["zh-cn"]) } if let fileSize = config.playerLayer?.player.fileSize, fileSize > 0 { Text("File Size \(String(format: "%.1f", fileSize / 1_000_000))MB") } + TextField("Sutitle delay", value: $subtitleModel.subtitleDelay, format: .number) } .padding() #if os(macOS) || targetEnvironment(macCatalyst)