Separate playback controls from blocked capture cleanup and gate stopping cores
This commit is contained in:
1 parent
b25766ae5a
commit
a9099a5ea7
2 files changed
+15
-10
No files matched your search
@@ -195,8 +195,9 @@ class AudioRecorderManager {
|
||||
if (captureMode == null) releaseCaptureDevice()
|
||||
return 0
|
||||
}
|
||||
@Synchronized fun cancelRecording() {
|
||||
if (captureMode == CaptureMode.RECORD) finishCapture(false) else if (captureMode == null) releaseCaptureDevice()
|
||||
fun cancelRecording() {
|
||||
if (closing.get()?.isDone == false) return
|
||||
synchronized(this) { if (captureMode == CaptureMode.RECORD) finishCapture(false) else if (captureMode == null) releaseCaptureDevice() }
|
||||
}
|
||||
fun isActive(): Boolean = captureMode == CaptureMode.RECORD && captureRunning
|
||||
|
||||
@@ -209,11 +210,13 @@ class AudioRecorderManager {
|
||||
}
|
||||
return synchronized(this) { if (isTesting) true else startCapture(CaptureMode.TEST, "__test__") }
|
||||
}
|
||||
@Synchronized fun stopMicTest() {
|
||||
if (captureMode == CaptureMode.TEST) finishCapture(false) else if (captureMode == null) releaseCaptureDevice()
|
||||
fun stopMicTest() {
|
||||
if (closing.get()?.isDone == false) return
|
||||
synchronized(this) { if (captureMode == CaptureMode.TEST) finishCapture(false) else if (captureMode == null) releaseCaptureDevice() }
|
||||
}
|
||||
|
||||
@Volatile private var playing = false
|
||||
private val playbackLock = Any()
|
||||
private var playThread: Thread? = null
|
||||
@Volatile private var playGeneration = 0
|
||||
|
||||
@@ -268,8 +271,9 @@ class AudioRecorderManager {
|
||||
|
||||
/** Запустить со startMs, округлённого вниз до 20 мс; seek декодирует и отбрасывает предшествующий PCM.
|
||||
* Отрицательный startMs ограничивается нулём; прогресс учитывает только принятые AudioTrack сэмплы. */
|
||||
@Synchronized fun playFromPosition(filePath: String, startMs: Int, onProgress: ((Float, Int) -> Unit)? = null, onComplete: () -> Unit = {}) {
|
||||
fun playFromPosition(filePath: String, startMs: Int, onProgress: ((Float, Int) -> Unit)? = null, onComplete: () -> Unit = {}) {
|
||||
if (closing.get()?.isDone == false) { LogManager.addLog("WARN", "AudioPlayer", "play rejected: cleanup pending"); return }
|
||||
synchronized(playbackLock) {
|
||||
stopPlayback()
|
||||
playing = true
|
||||
val myGen = playGeneration
|
||||
@@ -332,7 +336,7 @@ class AudioRecorderManager {
|
||||
}
|
||||
val total = (skippedSamples + readTotal).toFloat() / totalSamples.coerceAtLeast(1).toFloat()
|
||||
val eMs = ((skippedSamples + readTotal) * 1000 / (sampleRate * channels)).toInt()
|
||||
synchronized(this@AudioRecorderManager) {
|
||||
synchronized(playbackLock) {
|
||||
if (myGen == playGeneration) onProgress?.invoke(total, eMs)
|
||||
}
|
||||
}
|
||||
@@ -355,7 +359,7 @@ class AudioRecorderManager {
|
||||
try { if (handle != 0L) { NativeLib.voiceDecodeClose(handle); handle = 0 } }
|
||||
catch (e: Exception) { LogManager.addLog("ERROR", "AudioPlayer", "decode close failed generation=$myGen; retained: $e") }
|
||||
if (!notified) {
|
||||
synchronized(this@AudioRecorderManager) {
|
||||
synchronized(playbackLock) {
|
||||
if (playGeneration == myGen) {
|
||||
playing = false; playThread = null
|
||||
try { onComplete() }
|
||||
@@ -380,16 +384,17 @@ class AudioRecorderManager {
|
||||
LogManager.addLog("ERROR", "AudioPlayer", "Playback worker start failed: $e")
|
||||
onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Асинхронно остановить текущий worker; позицию для следующего playFromPosition хранит вызывающий код. */
|
||||
@Synchronized fun pausePlayback() {
|
||||
fun pausePlayback() = synchronized(playbackLock) {
|
||||
playGeneration++; playing = false
|
||||
playThread?.interrupt(); playThread = null
|
||||
}
|
||||
|
||||
/** Инвалидировать callbacks и прервать worker; собственные AudioTrack/decoder он освобождает в finally. */
|
||||
@Synchronized fun stopPlayback() {
|
||||
fun stopPlayback() = synchronized(playbackLock) {
|
||||
playGeneration++; playing = false
|
||||
playThread?.interrupt(); playThread = null
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ object NativeLib {
|
||||
return nativeUpdateSockets(configText)
|
||||
}
|
||||
|
||||
fun isReady(): Boolean = nativeIsRunning()
|
||||
fun isReady(): Boolean = !coreStopping && nativeIsRunning()
|
||||
|
||||
fun getMyNodeId(): Long = nativeGetMyNodeId()
|
||||
|
||||
|
||||
Reference in new issue
Block a user