fix: seek pauses playback

This commit is contained in:
Joakim Ramer 2023-02-09 02:38:56 +01:00
parent 40b2ff5a97
commit cbd74d08e1
No known key found for this signature in database
GPG key ID: 3DD9039EF02C0573
6 changed files with 49 additions and 47 deletions

View file

@ -783,8 +783,6 @@ export default {
console.log('received metadata update', data)
if (data.currentRate && data.currentRate > 0) this.playbackSpeed = data.currentRate
this.timeupdate()
},
// When a playback session is started the native android/ios will send the session

View file

@ -159,7 +159,7 @@ public class AbsAudioPlayer: CAPPlugin {
@objc func sendMetadata() {
self.notifyListeners("onPlayingUpdate", data: [ "value": !PlayerHandler.paused ])
if let metadata = PlayerHandler.getMetdata() {
if let metadata = try? PlayerHandler.getMetdata()?.asDictionary() {
self.notifyListeners("onMetadata", data: metadata)
}
}

View file

@ -7,8 +7,8 @@
import Foundation
class PlaybackMetadata: Codable {
var duration: Double = 0
var currentTime: Double = 0
var playerState: PlayerState = PlayerState.IDLE
struct PlaybackMetadata: Codable {
let duration: Double
let currentTime: Double
let playerState: PlayerState
}

View file

@ -7,9 +7,9 @@
import Foundation
enum PlayerState: Codable {
case IDLE
case BUFFERING
case READY
case ENDED
enum PlayerState: String, Codable {
case idle = "IDLE"
case buffering = "BUFFERING"
case ready = "READY"
case ended = "ENDED"
}

View file

@ -10,21 +10,26 @@ import AVFoundation
import UIKit
import MediaPlayer
enum PlayMethod:Int {
enum PlayMethod: Int {
case directplay = 0
case directstream = 1
case transcode = 2
case local = 3
}
enum PlayerStatus: Int {
case uninitialized = -1
case paused = 0
case playing = 1
}
class AudioPlayer: NSObject {
internal let queue = DispatchQueue(label: "ABSAudioPlayerQueue")
internal let logger = AppLogger(category: "AudioPlayer")
// enums and @objc are not compatible
@objc dynamic var status: Int
@objc dynamic var rate: Float
private var status: PlayerStatus
internal var rate: Float
private var tmpRate: Float = 1.0
private var playerContext = 0
@ -59,7 +64,7 @@ class AudioPlayer: NSObject {
self.audioPlayer = AVQueuePlayer()
self.audioPlayer.automaticallyWaitsToMinimizeStalling = false
self.sessionId = sessionId
self.status = -1
self.status = .uninitialized
self.rate = 0.0
self.tmpRate = playbackRate
@ -141,7 +146,7 @@ class AudioPlayer: NSObject {
}
public func isInitialized() -> Bool {
return self.status != -1
return self.status != .uninitialized
}
public func getPlaybackSession() -> PlaybackSession? {
@ -254,7 +259,7 @@ class AudioPlayer: NSObject {
logger.log("queueStatusObserver: Current Item Ready to play. PlayWhenReady: \(self.playWhenReady)")
// Seek the player before initializing, so a currentTime of 0 does not appear in MediaProgress / session
let firstReady = self.status < 0
let firstReady = self.status == .uninitialized
if firstReady && !self.playWhenReady {
// Seek is async, and if we call this when also pressing play, we will get weird jumps in the scrub bar depending on timing
// Seeking to the correct position happens during play()
@ -267,7 +272,7 @@ class AudioPlayer: NSObject {
self.play(allowSeekBack: false, isInitializing: true)
} else {
// Mark the player as ready
self.status = 0
self.status = .paused
}
} else if (playerItem.status == .failed) {
logger.error("queueStatusObserver: FAILED \(playerItem.error?.localizedDescription ?? "")")
@ -327,8 +332,8 @@ class AudioPlayer: NSObject {
self.audioPlayer.play()
self.audioPlayer.rate = self.tmpRate
}
self.status = 1
self.status = .playing
// Update the progress
self.updateNowPlaying()
@ -351,20 +356,16 @@ class AudioPlayer: NSObject {
}
}
self.status = 0
self.status = .paused
updateNowPlaying()
self.startPausedTimer()
}
public func seek(_ to: Double, from: String) {
let continuePlaying = rate > 0.0
self.pause()
logger.log("SEEK: Seek to \(to) from \(from) and continuePlaying(\(continuePlaying)")
logger.log("SEEK: Seek to \(to) from \(from)")
guard let playbackSession = self.getPlaybackSession() else { return }
let currentTrack = playbackSession.audioTracks[self.currentTrackIndex]
@ -383,8 +384,6 @@ class AudioPlayer: NSObject {
playbackSession.currentTime = to
}
self.playWhenReady = continuePlaying // Only playWhenReady if already playing
self.status = -1
let playerItems = self.allPlayerItems[indexOfSeek..<self.allPlayerItems.count]
DispatchQueue.runOnMainQueue {
@ -402,17 +401,13 @@ class AudioPlayer: NSObject {
DispatchQueue.runOnMainQueue {
self.audioPlayer.seek(to: CMTime(seconds: seekTime, preferredTimescale: 1000)) { [weak self] completed in
self?.logger.log("SEEK: Completion handler called and continuePlaying(\(continuePlaying)")
self?.logger.log("SEEK: Completion handler called")
guard completed else {
self?.logger.log("SEEK: WARNING: seeking not completed (to \(seekTime)")
return
}
guard let self = self else { return }
if continuePlaying {
self.resumePlayback()
}
self.updateNowPlaying()
}
}
@ -463,9 +458,19 @@ class AudioPlayer: NSObject {
}
public func isPlaying() -> Bool {
return self.status > 0
return self.status == .playing
}
public func getPlayerState() -> PlayerState {
// Other PlayerStates doesn't translate to player status
switch status {
case .uninitialized:
return PlayerState.buffering
default:
return PlayerState.ready
}
}
// MARK: - Private
private func createAsset(itemId:String, track:AudioTrack) -> AVAsset? {
guard let playbackSession = self.getPlaybackSession() else { return nil }

View file

@ -118,16 +118,15 @@ class PlayerHandler {
player.seek(amount, from: "handler")
}
public static func getMetdata() -> [String: Any]? {
public static func getMetdata() -> PlaybackMetadata? {
guard let player = player else { return nil }
guard player.isInitialized() else { return nil }
return [
"duration": player.getDuration(),
"currentTime": player.getCurrentTime(),
"playerState": !paused,
"currentRate": player.rate,
]
return PlaybackMetadata(
duration: player.getDuration() ?? 0,
currentTime: player.getCurrentTime() ?? 0,
playerState: player.getPlayerState()
)
}
// MARK: - Helper logic