fix(music): convert SAF content:// downloads for gapless arming
setNext() appended raw content:// URIs that mpv cannot open, stalling playback at the SD-card-download track boundary. Convert to fdclose:// like open(), track the armed fd, and reclaim it via a new closeContentFd method when the entry is dropped unplayed (close only when provably unconsumed — playlist-pos 0 before and after the remove; leak on doubt). The playlist-pos pre-check also keeps the clear path from removing the playing entry when mpv rolls into the armed track mid-clear. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
4de38f4b17
commit
73be8ab1c8
@@ -5,6 +5,7 @@ import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.util.Log
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||
@@ -156,6 +157,7 @@ open class MpvPlayerPlugin(
|
||||
"requestAudioFocus" -> handleRequestAudioFocus(result)
|
||||
"abandonAudioFocus" -> handleAbandonAudioFocus(result)
|
||||
"openContentFd" -> handleOpenContentFd(call, result)
|
||||
"closeContentFd" -> handleCloseContentFd(call, result)
|
||||
"isInitialized" -> result.success(playerCore?.isInitialized ?: false)
|
||||
"setLogLevel" -> result.success(null)
|
||||
else -> result.notImplemented()
|
||||
@@ -454,6 +456,26 @@ open class MpvPlayerPlugin(
|
||||
}.start()
|
||||
}
|
||||
|
||||
// Reclaims a detached fd from handleOpenContentFd that mpv will never
|
||||
// consume (a gapless-armed entry dropped before mpv opened it). The Dart
|
||||
// side guarantees single-close and only calls this when the entry provably
|
||||
// never played.
|
||||
private fun handleCloseContentFd(call: MethodCall, result: MethodChannel.Result) {
|
||||
val fd = call.argument<Int>("fd")
|
||||
if (fd == null || fd < 0) {
|
||||
result.error("INVALID_ARGS", "Missing 'fd'", null)
|
||||
return
|
||||
}
|
||||
try {
|
||||
ParcelFileDescriptor.adoptFd(fd).close()
|
||||
Log.d(tag, "Closed content FD $fd")
|
||||
result.success(null)
|
||||
} catch (e: Exception) {
|
||||
Log.e(tag, "Failed to close content FD $fd: ${e.message}", e)
|
||||
result.error("CLOSE_FAILED", e.message, null)
|
||||
}
|
||||
}
|
||||
|
||||
// PlayerDelegate
|
||||
|
||||
override fun onPropertyChange(name: String, value: Any?) {
|
||||
|
||||
Reference in New Issue
Block a user