mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-16 01:14:04 +09:00
vmgui now exits on exit
This commit is contained in:
@@ -16,46 +16,46 @@ private class RenderRunnable(val playhead: AudioAdapter.Playhead) : Runnable {
|
|||||||
private fun printdbg(msg: Any) {
|
private fun printdbg(msg: Any) {
|
||||||
if (AudioAdapter.DBGPRN) println("[AudioAdapter] $msg")
|
if (AudioAdapter.DBGPRN) println("[AudioAdapter] $msg")
|
||||||
}
|
}
|
||||||
@Volatile private var exit = false
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
while (!exit) {
|
while (!Thread.currentThread().isInterrupted) {
|
||||||
if (playhead.isPcmMode) {
|
try {
|
||||||
|
if (playhead.isPcmMode) {
|
||||||
|
|
||||||
val writeQueue = playhead.pcmQueue
|
val writeQueue = playhead.pcmQueue
|
||||||
|
|
||||||
if (playhead.isPlaying && writeQueue.notEmpty()) {
|
if (playhead.isPlaying && writeQueue.notEmpty()) {
|
||||||
|
|
||||||
printdbg("Taking samples from queue (queue size: ${writeQueue.size}/${playhead.getPcmQueueCapacity()})")
|
printdbg("Taking samples from queue (queue size: ${writeQueue.size}/${playhead.getPcmQueueCapacity()})")
|
||||||
|
|
||||||
val samples = writeQueue.removeFirst()
|
val samples = writeQueue.removeFirst()
|
||||||
playhead.position = writeQueue.size
|
playhead.position = writeQueue.size
|
||||||
|
|
||||||
// printdbg("P${playhead.index+1} Vol ${playhead.masterVolume}; LpP ${playhead.pcmUploadLength}; start playback...")
|
// printdbg("P${playhead.index+1} Vol ${playhead.masterVolume}; LpP ${playhead.pcmUploadLength}; start playback...")
|
||||||
// printdbg(""+(0..42).joinToString { String.format("%.2f", samples[it]) })
|
// printdbg(""+(0..42).joinToString { String.format("%.2f", samples[it]) })
|
||||||
|
|
||||||
playhead.audioDevice.writeSamplesUI8(samples, 0, samples.size)
|
playhead.audioDevice.writeSamplesUI8(samples, 0, samples.size)
|
||||||
|
|
||||||
// printdbg("P${playhead.index+1} go back to spinning")
|
// printdbg("P${playhead.index+1} go back to spinning")
|
||||||
|
|
||||||
Thread.sleep(12)
|
Thread.sleep(12)
|
||||||
}
|
}
|
||||||
else if (playhead.isPlaying && writeQueue.isEmpty) {
|
else if (playhead.isPlaying && writeQueue.isEmpty) {
|
||||||
printdbg("!! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED ")
|
printdbg("!! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED !! QUEUE EXHAUSTED ")
|
||||||
|
|
||||||
// TODO: wait for 1-2 seconds then finally stop the device
|
// TODO: wait for 1-2 seconds then finally stop the device
|
||||||
// playhead.audioDevice.stop()
|
// playhead.audioDevice.stop()
|
||||||
|
|
||||||
Thread.sleep(12)
|
Thread.sleep(12)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Thread.sleep(1)
|
||||||
|
}
|
||||||
|
catch (_: InterruptedException) {
|
||||||
|
Thread.currentThread().interrupt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Thread.sleep(1)
|
|
||||||
}
|
}
|
||||||
playhead.audioDevice.dispose()
|
|
||||||
}
|
|
||||||
fun stop() {
|
|
||||||
exit = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,35 +63,40 @@ private class WriteQueueingRunnable(val playhead: AudioAdapter.Playhead, val pcm
|
|||||||
private fun printdbg(msg: Any) {
|
private fun printdbg(msg: Any) {
|
||||||
if (AudioAdapter.DBGPRN) println("[AudioAdapter] $msg")
|
if (AudioAdapter.DBGPRN) println("[AudioAdapter] $msg")
|
||||||
}
|
}
|
||||||
@Volatile private var exit = false
|
|
||||||
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
while (!exit) {
|
while (!Thread.currentThread().isInterrupted) {
|
||||||
|
try {
|
||||||
|
playhead.let {
|
||||||
|
if (/*it.pcmQueue.size < it.getPcmQueueCapacity() &&*/ it.pcmUpload && it.pcmUploadLength > 0) {
|
||||||
|
printdbg("Downloading samples ${it.pcmUploadLength}")
|
||||||
|
|
||||||
playhead.let {
|
val samples = ByteArray(it.pcmUploadLength)
|
||||||
if (/*it.pcmQueue.size < it.getPcmQueueCapacity() &&*/ it.pcmUpload && it.pcmUploadLength > 0) {
|
UnsafeHelper.memcpyRaw(
|
||||||
printdbg("Downloading samples ${it.pcmUploadLength}")
|
null,
|
||||||
|
pcmBin.ptr,
|
||||||
|
samples,
|
||||||
|
UnsafeHelper.getArrayOffset(samples),
|
||||||
|
it.pcmUploadLength.toLong()
|
||||||
|
)
|
||||||
|
it.pcmQueue.addLast(samples)
|
||||||
|
|
||||||
val samples = ByteArray(it.pcmUploadLength)
|
it.pcmUploadLength = 0
|
||||||
UnsafeHelper.memcpyRaw(null, pcmBin.ptr, samples, UnsafeHelper.getArrayOffset(samples), it.pcmUploadLength.toLong())
|
it.position = it.pcmQueue.size
|
||||||
it.pcmQueue.addLast(samples)
|
Thread.sleep(6)
|
||||||
|
}
|
||||||
it.pcmUploadLength = 0
|
else if (it.pcmUpload) {
|
||||||
it.position = it.pcmQueue.size
|
|
||||||
Thread.sleep(6)
|
|
||||||
}
|
|
||||||
else if (it.pcmUpload) {
|
|
||||||
// printdbg("Rejecting samples (queueSize: ${it.pcmQueue.size}, uploadLength: ${it.pcmUploadLength})")
|
// printdbg("Rejecting samples (queueSize: ${it.pcmQueue.size}, uploadLength: ${it.pcmUploadLength})")
|
||||||
Thread.sleep(6)
|
Thread.sleep(6)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Thread.sleep(1)
|
Thread.sleep(1)
|
||||||
|
}
|
||||||
|
catch (_: InterruptedException) {
|
||||||
|
Thread.currentThread().interrupt()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun stop() {
|
|
||||||
exit = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,6 +130,9 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
|||||||
private val writeQueueingRunnables: Array<WriteQueueingRunnable>
|
private val writeQueueingRunnables: Array<WriteQueueingRunnable>
|
||||||
private val writeQueueingThreads: Array<Thread>
|
private val writeQueueingThreads: Array<Thread>
|
||||||
|
|
||||||
|
private val renderThreadGroup = ThreadGroup("AudioRenderThreadGroup")
|
||||||
|
private val writeQueueingGroup = ThreadGroup("AudioQriteQueueingThreadGroup")
|
||||||
|
|
||||||
private val threadExceptionHandler = Thread.UncaughtExceptionHandler { thread, throwable ->
|
private val threadExceptionHandler = Thread.UncaughtExceptionHandler { thread, throwable ->
|
||||||
throwable.printStackTrace()
|
throwable.printStackTrace()
|
||||||
}
|
}
|
||||||
@@ -163,9 +171,9 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
|||||||
|
|
||||||
|
|
||||||
renderRunnables = Array(4) { RenderRunnable(playheads[it]) }
|
renderRunnables = Array(4) { RenderRunnable(playheads[it]) }
|
||||||
renderThreads = Array(4) { Thread(renderRunnables[it], "AudioRenderHead${it+1}!$hash") }
|
renderThreads = Array(4) { Thread(renderThreadGroup, renderRunnables[it], "AudioRenderHead${it+1}!$hash") }
|
||||||
writeQueueingRunnables = Array(4) { WriteQueueingRunnable(playheads[it], pcmBin) }
|
writeQueueingRunnables = Array(4) { WriteQueueingRunnable(playheads[it], pcmBin) }
|
||||||
writeQueueingThreads = Array(4) { Thread(writeQueueingRunnables[it], "AudioQueueingHead${it+1}!$hash") }
|
writeQueueingThreads = Array(4) { Thread(writeQueueingGroup, writeQueueingRunnables[it], "AudioQueueingHead${it+1}!$hash") }
|
||||||
|
|
||||||
// printdbg("AudioAdapter latency: ${audioDevice.latency}")
|
// printdbg("AudioAdapter latency: ${audioDevice.latency}")
|
||||||
renderThreads.forEach { it.uncaughtExceptionHandler = threadExceptionHandler; it.start() }
|
renderThreads.forEach { it.uncaughtExceptionHandler = threadExceptionHandler; it.start() }
|
||||||
@@ -266,17 +274,23 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var disposed = false
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
System.err.println("Dispose AudioAdapter")
|
if (!disposed) {
|
||||||
renderRunnables.forEach { it.stop() }
|
disposed = true
|
||||||
renderThreads.forEach { it.interrupt() }
|
System.err.println("Dispose AudioAdapter")
|
||||||
writeQueueingRunnables.forEach { it.stop() }
|
renderThreadGroup.interrupt()
|
||||||
writeQueueingThreads.forEach { it.interrupt() }
|
writeQueueingGroup.interrupt()
|
||||||
playheads.forEach { it.dispose() }
|
playheads.forEach { it.dispose() }
|
||||||
sampleBin.destroy()
|
sampleBin.destroy()
|
||||||
pcmBin.destroy()
|
pcmBin.destroy()
|
||||||
mediaFrameBin.destroy()
|
mediaFrameBin.destroy()
|
||||||
mediaDecodedBin.destroy()
|
mediaDecodedBin.destroy()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.err.println("AudioAdapter already disposed")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getVM(): VM {
|
override fun getVM(): VM {
|
||||||
@@ -435,7 +449,7 @@ class AudioAdapter(val vm: VM) : PeriBase(VM.PERITYPE_SOUND) {
|
|||||||
fun dispose() {
|
fun dispose() {
|
||||||
// audioDevice.dispose() is called by RenderRunnable.stop()
|
// audioDevice.dispose() is called by RenderRunnable.stop()
|
||||||
System.err.println("AudioDevice dispose ${parent.renderThreads[index]}")
|
System.err.println("AudioDevice dispose ${parent.renderThreads[index]}")
|
||||||
try { audioDevice.dispose() } catch (e: GdxRuntimeException) { println(" "+ e.message) }
|
try { audioDevice.dispose() } catch (e: GdxRuntimeException) { System.err.println(" "+ e.message) }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class VMEmuExecutableWrapper(val windowWidth: Int, val windowHeight: Int, var pa
|
|||||||
// println("App Dispose")
|
// println("App Dispose")
|
||||||
executable.dispose()
|
executable.dispose()
|
||||||
SQTEX.dispose()
|
SQTEX.dispose()
|
||||||
exitProcess(1)
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import java.util.*
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
import kotlin.coroutines.*
|
import kotlin.coroutines.*
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
|
||||||
class EmulInstance(
|
class EmulInstance(
|
||||||
@@ -320,6 +321,9 @@ class VMGUI(val loaderInfo: EmulInstance, val viewportWidth: Int, val viewportHe
|
|||||||
crtShader.dispose()
|
crtShader.dispose()
|
||||||
gpuFBO.dispose()
|
gpuFBO.dispose()
|
||||||
vm.dispose()
|
vm.dispose()
|
||||||
|
|
||||||
|
System.err.println("VM disposed: ${vm.id}")
|
||||||
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
Reference in New Issue
Block a user