🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@capgo/native-audio

Package Overview
Dependencies
Maintainers
1
Versions
256
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@capgo/native-audio - npm Package Compare versions

Comparing version
8.3.9
to
8.3.10
+35
-8
ios/Sources/NativeAudioPlugin/AudioAsset.swift

@@ -123,9 +123,20 @@ @preconcurrency import AVFoundation

func setCurrentTime(time: TimeInterval) {
owner?.executeOnAudioQueue { [weak self] in
guard let self else { return }
guard !channels.isEmpty, playIndex < channels.count else { return }
func setCurrentTime(time: TimeInterval, completion: (() -> Void)? = nil) {
guard let owner else {
completion?()
return
}
owner.executeOnAudioQueue { [weak self] in
guard let self else {
completion?()
return
}
guard !channels.isEmpty, playIndex < channels.count else {
completion?()
return
}
let player = channels[playIndex]
let validTime = min(max(time, 0), player.duration)
player.currentTime = validTime
completion?()
}

@@ -217,4 +228,3 @@ }

let player = channels[playIndex]
let timeOffset = player.deviceCurrentTime + 0.01
player.play(atTime: timeOffset)
player.play()
startCurrentTimeUpdates()

@@ -253,4 +263,21 @@ }

let player = channels[playIndex]
if player.isPlaying && player.volume > 0 {
fadeOut(audio: player, fadeOutDuration: fadeOutDuration, toPause: toPause)
if player.isPlaying {
if toPause {
if player.volume > 0 {
fadeOut(audio: player, fadeOutDuration: fadeOutDuration, toPause: true) { [weak self] elapsed, duration in
guard let self, let owner = self.owner else { return }
owner.recordPausePositionAfterFade(assetId: self.assetId, elapsedTime: elapsed, duration: duration)
}
} else {
cancelFade()
schedulePauseWithPositionRecording(audio: player) { [weak self] elapsed, duration in
guard let self, let owner = self.owner else { return }
owner.recordPausePositionAfterFade(assetId: self.assetId, elapsedTime: elapsed, duration: duration)
}
}
} else if player.volume > 0 {
fadeOut(audio: player, fadeOutDuration: fadeOutDuration, toPause: false)
} else {
stop()
}
} else if !toPause {

@@ -257,0 +284,0 @@ stop()

@@ -18,2 +18,33 @@ import AVFoundation

fileprivate func performLocalFadeOutPauseOnMain(audio: AVAudioPlayer, beforePause: ((TimeInterval, TimeInterval) -> Void)?) {
let elapsed = audio.currentTime
let duration = audio.duration.isFinite ? audio.duration : 0
beforePause?(elapsed, duration)
audio.pause()
}
fileprivate func scheduleLocalFadeOutPauseOnMain(audio: AVAudioPlayer, beforePause: ((TimeInterval, TimeInterval) -> Void)?) {
DispatchQueue.main.async { [weak self] in
guard let self else { return }
self.performLocalFadeOutPauseOnMain(audio: audio, beforePause: beforePause)
}
}
/// Same main-thread pause and `beforePause(elapsed, duration)` as fade-out-to-pause when no fade runs (e.g. volume already zero).
internal func schedulePauseWithPositionRecording(audio: AVAudioPlayer, beforePause: ((TimeInterval, TimeInterval) -> Void)?) {
scheduleLocalFadeOutPauseOnMain(audio: audio, beforePause: beforePause)
}
fileprivate func scheduleLocalFadeOutStopOnMain(audio: AVAudioPlayer) {
DispatchQueue.main.async { [weak self] in
guard let self else { return }
self.performLocalFadeOutStopOnMain(audio: audio)
}
}
fileprivate func performLocalFadeOutStopOnMain(audio: AVAudioPlayer) {
audio.stop()
dispatchComplete()
}
func fadeIn(audio: AVAudioPlayer, fadeInDuration: TimeInterval, targetVolume: Float) {

@@ -44,6 +75,20 @@ cancelFade()

func fadeOut(audio: AVAudioPlayer, fadeOutDuration: TimeInterval, toPause: Bool = false) {
/// - Parameter beforePause: Called on the main queue immediately before `pause()` when `toPause` is true,
/// so the plugin can persist `timeBeforePause` and update Now Playing at the actual stop position.
func fadeOut(
audio: AVAudioPlayer,
fadeOutDuration: TimeInterval,
toPause: Bool = false,
beforePause: ((TimeInterval, TimeInterval) -> Void)? = nil
) {
cancelFade()
let steps = Int(fadeOutDuration / TimeInterval(fadeDelaySecs))
guard steps > 0 else { return }
guard steps > 0 else {
if toPause {
scheduleLocalFadeOutPauseOnMain(audio: audio, beforePause: beforePause)
} else {
scheduleLocalFadeOutStopOnMain(audio: audio)
}
return
}
var currentVolume = audio.volume

@@ -66,6 +111,5 @@ let fadeStep = currentVolume / Float(steps)

if toPause {
audio.pause()
self.performLocalFadeOutPauseOnMain(audio: audio, beforePause: beforePause)
} else {
audio.stop()
self.dispatchComplete()
self.performLocalFadeOutStopOnMain(audio: audio)
}

@@ -72,0 +116,0 @@ }

@@ -135,2 +135,45 @@ @preconcurrency import AVFoundation

/// Timescale for seek targets; 600 is a common media default and avoids coarse rounding from timescale 1.
private static let seekPreferredTimescale: CMTimeScale = 600
override func setCurrentTime(time: TimeInterval, completion: (() -> Void)? = nil) {
guard let owner else {
completion?()
return
}
owner.executeOnAudioQueue { [weak self] in
guard let self else {
completion?()
return
}
guard !players.isEmpty && playIndex < players.count else {
completion?()
return
}
let player = players[playIndex]
let lowerBound = max(time, 0)
let validTime: TimeInterval
if let item = player.currentItem {
let d = item.duration
if d == .indefinite || !d.isValid {
validTime = lowerBound
} else {
let durationSeconds = d.seconds
if durationSeconds.isFinite && durationSeconds > 0 {
validTime = min(lowerBound, durationSeconds)
} else {
validTime = lowerBound
}
}
} else {
validTime = lowerBound
}
let target = CMTime(seconds: validTime, preferredTimescale: Self.seekPreferredTimescale)
player.seek(to: target, toleranceBefore: .zero, toleranceAfter: .zero) { finished in
guard finished else { return }
completion?()
}
}
}
override func resume() {

@@ -342,3 +385,10 @@ owner?.executeOnAudioQueue { [weak self] in

if player.timeControlStatus == .playing {
fadeOut(player: player, fadeOutDuration: fadeOutDuration, toPause: toPause)
if toPause {
fadeOut(player: player, fadeOutDuration: fadeOutDuration, toPause: true) { [weak self] elapsed, duration in
guard let self, let owner = self.owner else { return }
owner.recordPausePositionAfterFade(assetId: self.assetId, elapsedTime: elapsed, duration: duration)
}
} else {
fadeOut(player: player, fadeOutDuration: fadeOutDuration, toPause: false)
}
} else if !toPause {

@@ -345,0 +395,0 @@ stop()

@@ -5,2 +5,29 @@ import AVFoundation

/// Pause after sampling elapsed/duration for Now Playing. Caller must be on the main queue.
fileprivate func performRemoteFadeOutPauseOnMain(player: AVPlayer, beforePause: ((TimeInterval, TimeInterval) -> Void)?) {
let elapsed = player.currentTime().seconds
let rawDuration = player.currentItem?.duration ?? .zero
let duration = rawDuration.isNumeric && rawDuration.isValid ? rawDuration.seconds : 0
beforePause?(elapsed, duration.isFinite ? duration : 0)
player.pause()
}
fileprivate func scheduleRemoteFadeOutPauseOnMain(player: AVPlayer, beforePause: ((TimeInterval, TimeInterval) -> Void)?) {
DispatchQueue.main.async { [weak self] in
guard let self else { return }
self.performRemoteFadeOutPauseOnMain(player: player, beforePause: beforePause)
}
}
/// Pause, seek to start, then emit `complete` on the main queue after the seek finishes.
fileprivate func pauseSeekToStartThenDispatchComplete(on player: AVPlayer) {
player.pause()
player.seek(to: .zero) { [weak self] _ in
guard let self else { return }
DispatchQueue.main.async {
self.dispatchComplete()
}
}
}
func fadeIn(player: AVPlayer, fadeInDuration: TimeInterval, targetVolume: Float) {

@@ -31,6 +58,22 @@ cancelFade()

func fadeOut(player: AVPlayer, fadeOutDuration: TimeInterval, toPause: Bool = false) {
/// - Parameter beforePause: Called on the main queue immediately before `pause()` when `toPause` is true.
func fadeOut(
player: AVPlayer,
fadeOutDuration: TimeInterval,
toPause: Bool = false,
beforePause: ((TimeInterval, TimeInterval) -> Void)? = nil
) {
cancelFade()
let steps = Int(fadeOutDuration / TimeInterval(fadeDelaySecs))
guard steps > 0 else { return }
guard steps > 0 else {
if toPause {
scheduleRemoteFadeOutPauseOnMain(player: player, beforePause: beforePause)
} else {
DispatchQueue.main.async { [weak self] in
guard let self else { return }
self.pauseSeekToStartThenDispatchComplete(on: player)
}
}
return
}
let fadeStep = player.volume / Float(steps)

@@ -53,8 +96,5 @@ var currentVolume = player.volume

if toPause {
player.pause()
self.performRemoteFadeOutPauseOnMain(player: player, beforePause: beforePause)
} else {
player.pause()
player.seek(to: .zero)
self.owner?.notifyListeners("complete", data: ["assetId": self.assetId as Any])
self.dispatchedCompleteMap[self.assetId] = true
self.pauseSeekToStartThenDispatchComplete(on: player)
}

@@ -61,0 +101,0 @@ }

+1
-1
{
"name": "@capgo/native-audio",
"version": "8.3.9",
"version": "8.3.10",
"description": "A native plugin for native audio engine",

@@ -5,0 +5,0 @@ "license": "MPL-2.0",

Sorry, the diff of this file is too big to display