commit 21/11/2025

This commit is contained in:
2025-11-21 13:33:37 +07:00
parent 46be98363a
commit 421ed661ad
7 changed files with 165 additions and 133 deletions

View File

@@ -55,7 +55,6 @@ function UpdateStreamerCard(values) {
const v = Number(value ?? 0); const v = Number(value ?? 0);
const pct = Math.max(0, Math.min(100, Math.round((v / max) * 100))); const pct = Math.max(0, Math.min(100, Math.round((v / max) * 100)));
//if (index!==1) return; // only update index 1 for testing //if (index!==1) return; // only update index 1 for testing
//console.log(`setProgress: index=${index}, value=${v}, pct=${pct}`);
$bar $bar
.attr('aria-valuenow', v) // semantic value .attr('aria-valuenow', v) // semantic value
.css('width', pct + '%') // visual width .css('width', pct + '%') // visual width
@@ -162,7 +161,6 @@ function fill_automaticqueuetablebody(vv) {
if (!Array.isArray(vv) || vv.length === 0) return; if (!Array.isArray(vv) || vv.length === 0) return;
vv.forEach(item => { vv.forEach(item => {
// fill index and description columns using item properties // fill index and description columns using item properties
//console.log("fill_automaticqueuetablebody: item", item);
$('#automaticqueuetable').append(`<tr> $('#automaticqueuetable').append(`<tr>
<td>${item.index}</td> <td>${item.index}</td>
<td>${item.date_Time}</td> <td>${item.date_Time}</td>
@@ -218,7 +216,6 @@ function reloadAutomaticQueue(APIURL = "QueueTable/") {
function RemovePagingQueueByIndex(index, APIURL = "QueuePaging/") { function RemovePagingQueueByIndex(index, APIURL = "QueuePaging/") {
fetchAPI(APIURL + "DeleteByIndex/" + index, "DELETE", {}, null, (okdata) => { fetchAPI(APIURL + "DeleteByIndex/" + index, "DELETE", {}, null, (okdata) => {
console.log("RemovePagingQueueByIndex: okdata", okdata);
reloadPagingQueue(APIURL); reloadPagingQueue(APIURL);
}, (errdata) => { }, (errdata) => {
console.log("RemovePagingQueueByIndex: errdata", errdata); console.log("RemovePagingQueueByIndex: errdata", errdata);
@@ -227,7 +224,6 @@ function RemovePagingQueueByIndex(index, APIURL = "QueuePaging/") {
function RemoveAutomaticQueueByIndex(index, APIURL = "QueueTable/") { function RemoveAutomaticQueueByIndex(index, APIURL = "QueueTable/") {
fetchAPI(APIURL + "DeleteByIndex/" + index, "DELETE", {}, null, (okdata) => { fetchAPI(APIURL + "DeleteByIndex/" + index, "DELETE", {}, null, (okdata) => {
console.log("RemoveAutomaticQueueByIndex: okdata", okdata);
reloadAutomaticQueue(APIURL); reloadAutomaticQueue(APIURL);
}, (errdata) => { }, (errdata) => {
console.log("RemoveAutomaticQueueByIndex: errdata", errdata); console.log("RemoveAutomaticQueueByIndex: errdata", errdata);
@@ -258,16 +254,16 @@ function GetListeningZones() {
* @param {Function} cbFail callback function on failure * @param {Function} cbFail callback function on failure
*/ */
function LiveAudioCommand(command, bz, cbOK = null, cbFail = null) { function LiveAudioCommand(command, bz, cbOK = null, cbFail = null) {
function raise_cbOK(value=null){ function raise_cbOK(value = null) {
if (cbOK) cbOK(value); if (cbOK) cbOK(value);
} }
function raise_cbFail(value){ function raise_cbFail(value) {
if (cbFail) cbFail(value); if (cbFail) cbFail(value);
} }
if (command && command.length>0){ if (command && command.length > 0) {
if (bz && bz.length>0){ if (bz && bz.length > 0) {
if (command === 'Open' || command === 'Close'){ if (command === 'Open' || command === 'Close') {
let url = `/api/LiveAudio`; let url = `/api/LiveAudio`;
let payload = { let payload = {
method: 'POST', method: 'POST',
@@ -281,22 +277,19 @@ function LiveAudioCommand(command, bz, cbOK = null, cbFail = null) {
}; };
fetch(url, payload) fetch(url, payload)
.then(response => { .then(response => {
console.log(`Fetch response for Live Audio Command ${command}:`, JSON.stringify(response));
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`); throw new Error(`HTTP error! status: ${response.status}`);
} }
return response.json(); return response.json();
}) })
.then(data => { .then(data => {
console.log(`Live Audio Command ${command} for Broadcast Zone: ${bz} executed on server.`, data);
raise_cbOK(data); raise_cbOK(data);
}) })
.catch(error => { .catch(error => {
console.log(`Error executing Live Audio Command ${command} for Broadcast Zone: ${bz} on server. ${error}`);
raise_cbFail(error); raise_cbFail(error);
}); });
} else raise_cbFail("LiveAudioCommand: Unknown command "+command); } else raise_cbFail("LiveAudioCommand: Unknown command " + command);
} else raise_cbFail("LiveAudioCommand: Broadcast Zone is empty"); } else raise_cbFail("LiveAudioCommand: Broadcast Zone is empty");
} else raise_cbFail("LiveAudioCommand: command is empty"); } else raise_cbFail("LiveAudioCommand: command is empty");
} }
@@ -308,7 +301,6 @@ let streamws = null;
let mediasource = null; let mediasource = null;
$(document).ready(function () { $(document).ready(function () {
console.log("overview.js loaded");
GetListeningZones(); GetListeningZones();
@@ -316,8 +308,10 @@ $(document).ready(function () {
let bz = $("#listenzone").val(); let bz = $("#listenzone").val();
let $icon = $(this).find('svg'); let $icon = $(this).find('svg');
if ($icon.hasClass('fa-stop')) { if ($icon.hasClass('fa-stop')) {
console.log("Stopping Live Audio for Broadcast Zone:", bz); LiveAudioCommand('Close', bz, (okdata) => {
LiveAudioCommand('Close', bz, (okdata) =>{ if (okdata.message && okdata.message.length > 0) {
console.log("Live Audio Session Closed:", okdata.message);
}
$icon.toggleClass('fa-stop fa-play'); $icon.toggleClass('fa-stop fa-play');
$("#listenzone").prop('disabled', false); $("#listenzone").prop('disabled', false);
if (streamws) { if (streamws) {
@@ -331,34 +325,37 @@ $(document).ready(function () {
let audio = document.getElementById('listenaudio'); let audio = document.getElementById('listenaudio');
audio.src = ""; audio.src = "";
}, (errdata) =>{ }, (errdata) => {
alert("Error stopping Live Audio: " + errdata); alert("Error stopping Live Audio: " + errdata);
}); });
} else { } else {
console.log("Starting Live Audio for Broadcast Zone:", bz); LiveAudioCommand('Open', bz, (okdata) => {
LiveAudioCommand('Open', bz, (okdata) =>{ if (okdata.message && okdata.message.length > 0) {
let uuid = okdata.message;
console.log("Live Audio Session UUID:", uuid);
}
$icon.toggleClass('fa-stop fa-play'); $icon.toggleClass('fa-stop fa-play');
$("#listenzone").prop('disabled', true); $("#listenzone").prop('disabled', true);
streamws = new WebSocket(`ws://${window.location.host}/LiveAudio/ws`); streamws = new WebSocket(`ws://${window.location.host}/api/LiveAudio/ws`);
streamws.binaryType = 'arraybuffer';
mediasource = new MediaSource(); mediasource = new MediaSource();
let audio = document.getElementById('listenaudio'); let audio = document.getElementById('listenaudio');
audio.src = URL.createObjectURL(mediasource); audio.src = URL.createObjectURL(mediasource);
mediasource.addEventListener('sourceopen', () => { mediasource.addEventListener('sourceopen', () => {
const sourceBuffer = mediasource.addSourceBuffer('audio/mpeg; codecs="mp3"'); const sourceBuffer = mediasource.addSourceBuffer('audio/mpeg');
streamws.binaryType = 'arraybuffer';
streamws.onmessage = (event) => { streamws.onmessage = (event) => {
if (event.data instanceof ArrayBuffer) { if (event.data instanceof ArrayBuffer) {
const chunk = new Uint8Array(event.data); const chunk = new Uint8Array(event.data);
sourceBuffer.appendBuffer(chunk); sourceBuffer.appendBuffer(chunk);
} }
}; };
}); });
}, (errdata) =>{ }, (errdata) => {
alert("Error starting Live Audio: " + errdata); alert("Error starting Live Audio: " + errdata);
}); });
} }
}); });
$('#clearpagingqueue').off('click').on('click', function () { $('#clearpagingqueue').off('click').on('click', function () {
DoClear("QueuePaging/", "Paging Queue", (okdata) => { DoClear("QueuePaging/", "Paging Queue", (okdata) => {
@@ -445,7 +442,6 @@ $(document).ready(function () {
switch (cmd) { switch (cmd) {
case "getPagingQueue": case "getPagingQueue":
let pq = JSON.parse(data); let pq = JSON.parse(data);
//console.log("getPagingQueue:", pq);
window.PagingQueue = []; window.PagingQueue = [];
if (Array.isArray(pq) && pq.length > 0) { if (Array.isArray(pq) && pq.length > 0) {
window.PagingQueue.push(...pq); window.PagingQueue.push(...pq);
@@ -454,7 +450,6 @@ $(document).ready(function () {
break; break;
case "getAASQueue": case "getAASQueue":
let aq = JSON.parse(data); let aq = JSON.parse(data);
//console.log("getAASQueue:", aq);
window.QueueTable = []; window.QueueTable = [];
if (Array.isArray(aq) && aq.length > 0) { if (Array.isArray(aq) && aq.length > 0) {
window.QueueTable.push(...aq); window.QueueTable.push(...aq);

View File

@@ -231,7 +231,8 @@ fun main() {
db.Add_Log("AAS"," Application started") db.Add_Log("AAS"," Application started")
// shutdown hook // shutdown hook
Runtime.getRuntime().addShutdownHook(Thread { Runtime.getRuntime().addShutdownHook(Thread ({
db.Add_Log("AAS"," Application stopping") db.Add_Log("AAS"," Application stopping")
Logger.info { "Shutdown hook called, stopping services..." } Logger.info { "Shutdown hook called, stopping services..." }
barixserver.StopTcpCommand() barixserver.StopTcpCommand()
@@ -240,11 +241,12 @@ fun main() {
web.Stop() web.Stop()
udpreceiver.Stop() udpreceiver.Stop()
tcpreceiver.Stop() tcpreceiver.Stop()
StreamerOutputs.values.forEach { it.close() }
audioPlayer.Close() audioPlayer.Close()
db.close() db.close()
Logger.info { "All services stopped, exiting application." } Logger.info { "All services stopped, exiting application." }
ProviderRegistry.getLoggingProvider().shutdown() ProviderRegistry.getLoggingProvider().shutdown()
}) },"ShutdownHook") )
} }

View File

@@ -48,9 +48,10 @@ class Mp3Encoder(val samplingrate: Int=44100, val channels: Int=1) {
push_handle = bass.BASS_StreamCreate(samplingrate, channels, Bass.BASS_STREAM_DECODE, Pointer(-1), null) push_handle = bass.BASS_StreamCreate(samplingrate, channels, Bass.BASS_STREAM_DECODE, Pointer(-1), null)
if (push_handle!=0){ if (push_handle!=0){
Logger.info{"MP3 Encoder initialized with sampling rate $samplingrate Hz and $channels channel(s)" } Logger.info{"MP3 Encoder initialized with sampling rate $samplingrate Hz and $channels channel(s)" }
//val options = "lame -b 128 --cbr --write-xing 0 --nohist --noid3v2 - -" val options = "lame -b 128 --cbr --write-xing 0 --nohist --noid3v2 - -"
val flag = BassEnc.BASS_ENCODE_AUTOFREE or BassEnc.BASS_ENCODE_NOHEAD //val flag = BassEnc.BASS_ENCODE_AUTOFREE or BassEnc.BASS_ENCODE_NOHEAD
mp3_handle = bassencmp3.BASS_Encode_MP3_Start(push_handle, null, flag,proc, null) val flag = BassEnc.BASS_ENCODE_AUTOFREE
mp3_handle = bassencmp3.BASS_Encode_MP3_Start(push_handle, options, flag,proc, null)
if (mp3_handle!=0){ if (mp3_handle!=0){
callback = cb callback = cb
@@ -100,7 +101,6 @@ class Mp3Encoder(val samplingrate: Int=44100, val channels: Int=1) {
Logger.error{"Failed to push data to MP3 Encoder. BASS error code: $err" } Logger.error{"Failed to push data to MP3 Encoder. BASS error code: $err" }
return 0 return 0
} }
//println("MP3 Encoder: Pushed $written bytes of PCM data.")
return written return written
} }
@@ -122,6 +122,5 @@ class Mp3Encoder(val samplingrate: Int=44100, val channels: Int=1) {
// auto close by BASS_ENCODE_AUTOFREE // auto close by BASS_ENCODE_AUTOFREE
mp3_handle = 0 mp3_handle = 0
callback = null callback = null
println("MP3 Encoder: Stopped.")
} }
} }

View File

@@ -16,7 +16,7 @@ import java.nio.ByteBuffer
import java.util.function.Consumer import java.util.function.Consumer
@Suppress("unused") @Suppress("unused")
class BarixConnection(val index: UInt, var channel: String, val ipaddress: String, val port: Int = 5002) { class BarixConnection(val index: UInt, var channel: String, val ipaddress: String, val port: Int = 5002) : AutoCloseable {
private var _bR: Int = 0 private var _bR: Int = 0
private var _sd: Int = 0 private var _sd: Int = 0
private var _vu: Int = 0 private var _vu: Int = 0
@@ -26,6 +26,13 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
private var _tcp: Socket? = null private var _tcp: Socket? = null
private val mp3encoder = Mp3Encoder() private val mp3encoder = Mp3Encoder()
private val mp3Consumer = mutableMapOf<String, Consumer<ByteArray>>() private val mp3Consumer = mutableMapOf<String, Consumer<ByteArray>>()
private val udp = DatagramSocket()
init {
mp3encoder.Start { data ->
mp3Consumer.values.forEach { it.accept(data) }
}
}
fun Add_Mp3_Consumer(key: String, cb: Consumer<ByteArray>) { fun Add_Mp3_Consumer(key: String, cb: Consumer<ByteArray>) {
mp3Consumer[key] = cb mp3Consumer[key] = cb
@@ -118,33 +125,26 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
fun SendData(data: ByteArray, cbOK: Consumer<String>, cbFail: Consumer<String>) { fun SendData(data: ByteArray, cbOK: Consumer<String>, cbFail: Consumer<String>) {
if (data.isNotEmpty()) { if (data.isNotEmpty()) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
DatagramSocket().use{ udp -> val bb = ByteBuffer.wrap(data)
val bb = ByteBuffer.wrap(data)
if (!mp3encoder.isStarted()) { while(bb.hasRemaining()){
mp3encoder.Start { data -> try {
mp3Consumer.values.forEach { it.accept(data) } val chunk = ByteArray(if (bb.remaining() > maxUDPsize) maxUDPsize else bb.remaining())
bb.get(chunk)
while(bufferRemain<chunk.size){
delay(10)
} }
} udp.send(DatagramPacket(chunk, chunk.size, inet))
while(bb.hasRemaining()){ mp3encoder.PushData(chunk)
try { delay(2)
val chunk = ByteArray(if (bb.remaining() > maxUDPsize) maxUDPsize else bb.remaining())
bb.get(chunk)
while(bufferRemain<chunk.size){
delay(10)
}
udp.send(DatagramPacket(chunk, chunk.size, inet))
mp3encoder.PushData(chunk)
delay(2)
} catch (e: Exception) { } catch (e: Exception) {
cbFail.accept("SendData to $ipaddress failed, message: ${e.message}") cbFail.accept("SendData to $ipaddress failed, message: ${e.message}")
return@launch return@launch
}
} }
mp3encoder.Stop()
cbOK.accept("SendData to $channel ($ipaddress) succeeded, ${data.size} bytes sent")
} }
cbOK.accept("SendData to $channel ($ipaddress) succeeded, ${data.size} bytes sent")
} }
} else cbFail.accept("SendData to $ipaddress failed, data is empty") } else cbFail.accept("SendData to $ipaddress failed, data is empty")
@@ -248,4 +248,18 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
} }
return false return false
} }
override fun close() {
try{
udp.close()
} catch (_ : Exception){
Logger.error { "Failed to close udp" }
}
try{
_tcp?.close()
} catch (_ : Exception){
Logger.error { "Failed to close tcp socket to $ipaddress" }
}
mp3encoder.Stop()
}
} }

View File

@@ -94,11 +94,11 @@ class TCP_Android_Command_Server {
} }
} catch (ex: Exception) { } catch (ex: Exception) {
logcb.accept("Failed accepting TCP Socket, Message : ${ex.message}") logcb.accept("Android TCP Server Failed accepting TCP Socket, Message : ${ex.message}")
} }
} }
logcb.accept("TCP server stopped") logcb.accept("Android TCP Command server stopped")
} }
return true return true
} catch (e: Exception) { } catch (e: Exception) {

View File

@@ -0,0 +1,6 @@
package web
import barix.BarixConnection
import io.javalin.websocket.WsContext
data class LiveListenData(val key: String, var bc : BarixConnection?, var ws : WsContext?)

View File

@@ -43,9 +43,10 @@ import java.nio.file.Files
import java.time.LocalDateTime import java.time.LocalDateTime
import codes.configKeys import codes.configKeys
import database.QueueTable import database.QueueTable
import io.javalin.websocket.WsContext import io.javalin.websocket.WsCloseStatus
import org.tinylog.Logger import org.tinylog.Logger
import java.io.File import java.io.File
import java.nio.ByteBuffer
import java.nio.file.Path import java.nio.file.Path
import java.util.UUID import java.util.UUID
@@ -56,7 +57,7 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
lateinit var app: Javalin lateinit var app: Javalin
lateinit var semiauto: Javalin lateinit var semiauto: Javalin
val objectmapper = jacksonObjectMapper() val objectmapper = jacksonObjectMapper()
val WsContextMap = mutableMapOf<String, WsContext>() val WsContextMap = mutableMapOf<String, LiveListenData>()
private fun SendReply(context: WsMessageContext, command: String, value: String) { private fun SendReply(context: WsMessageContext, command: String, value: String) {
try { try {
@@ -247,79 +248,100 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
path("api") { path("api") {
//TODO https://stackoverflow.com/questions/70002015/streaming-into-audio-element //TODO https://stackoverflow.com/questions/70002015/streaming-into-audio-element
path("LiveAudio") { path("LiveAudio") {
post{ post{ ctx->
val json : JsonNode = objectmapper.readTree(it.body()) val json : JsonNode = objectmapper.readTree(ctx.body())
val broadcastzone = json.get("broadcastzone")?.asText("") ?: "" val broadcastzone = json.get("broadcastzone")?.asText("") ?: ""
val command = json.get("command")?.asText("") ?: "" val command = json.get("command")?.asText("") ?: ""
println("LiveAudio command=$command for zone $broadcastzone from ${it.host()}" ) if (command == "Open" || command == "Close"){
if (broadcastzone.isNotEmpty()){
val bc = Get_Barix_Connection_by_ZoneName(broadcastzone)
if (bc!=null){
val key = ctx.cookie("client-stream-id")
if (command == "Open"){
// open command
if (key!=null && key.isNotEmpty()){
// ada connection sebelumnya, kemungkinan reconnect
val prev = WsContextMap[key]
if (prev!=null){
prev.bc?.Remove_Mp3_Consumer(key)
prev.ws?.closeSession(WsCloseStatus.NORMAL_CLOSURE, "Reopen Live Audio Stream")
}
WsContextMap.remove(key)
ctx.cookie("client-stream-id", "")
}
val newkey = UUID.randomUUID().toString()
.also { ctx.cookie("client-stream-id", it) }
WsContextMap[newkey] = LiveListenData(newkey, bc, null)
ResultMessageString(ctx, 200, newkey)
} else {
// close command
if (key!=null && key.isNotEmpty()){
// close connection
val prev = WsContextMap[key]
if (prev!=null){
prev.bc?.Remove_Mp3_Consumer(key)
prev.ws?.closeSession(WsCloseStatus.NORMAL_CLOSURE, "Close Live Audio Stream")
}
WsContextMap.remove(key)
ctx.cookie("client-stream-id", "")
ResultMessageString(ctx, 200, "OK")
} else ResultMessageString(ctx, 400, "No client-id cookie found")
}
} else ResultMessageString(ctx, 400, "Broadcastzone not found")
} else ResultMessageString(ctx, 400, "Invalid broadcastzone")
} else ResultMessageString(ctx, 400, "Invalid command")
} }
ws("/ws/{uuid}"){ws -> ws("ws"){ wscontext ->
ws.onConnect { wscontext.onConnect {
ctx -> val key = it.cookie("client-stream-id")
val uuid = ctx.pathParam("uuid") if (key!=null && key.isNotEmpty()){
val cookieresult = ctx.cookie("client-stream-id") val lld = WsContextMap[key]
println("Ws connected with uuid=$uuid, cookie=$cookieresult") if (lld!=null){
WsContextMap[uuid] = ctx it.enableAutomaticPings()
} lld.ws = it
lld.bc?.Add_Mp3_Consumer(key){ mp3data->
ws.onClose { try {
ctx -> if (it.session.isOpen){
val uuid = ctx.pathParam("uuid") it.send(ByteBuffer.wrap(mp3data))
println("Ws close on uuid=$uuid") }
WsContextMap.remove(uuid) } catch (e: Exception){
} Logger.error {"Error sending LiveAudio mp3 data for key $key, Message: ${e.message}"}
ws.onError { }
ctx -> }
val uuid = ctx.pathParam("uuid") } else {
println("Ws error on uuid=$uuid") it.closeSession(WsCloseStatus.POLICY_VIOLATION, "WsContextMap key not found")
WsContextMap.remove(uuid) Logger.info{"LiveAudio WebSocket connection rejected, WsContextMap key not found"}
}
}
get("Open/{broadcastzone}") { ctx ->
val param = ctx.pathParam("broadcastzone")
println("LiveAudio Open for zone $param from ${ctx.host()}" )
if (param.isNotEmpty()) {
val bc = Get_Barix_Connection_by_ZoneName(param)
if (bc != null) {
val key = ctx.cookie("client-stream-id") ?: UUID.randomUUID().toString()
.also { ctx.cookie("client-stream-id", it) }
bc.Add_Mp3_Consumer(key){ mp3data ->
WsContextMap[key]?.send(mp3data)
println("Send ${mp3data.size} to $key")
} }
} else {
ResultMessageString(ctx, 200, key) it.closeSession(WsCloseStatus.POLICY_VIOLATION, "Invalid client-stream-id")
} else ctx.status(400) Logger.info{"LiveAudio WebSocket connection rejected, invalid client-stream-id"}
.result(objectmapper.writeValueAsString(resultMessage("Broadcastzone not found"))) }
} else ctx.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid broadcastzone")))
}
get("Close/{broadcastzone}") { ctx ->
val param = ctx.pathParam("broadcastzone")
println("LiveAudio Close for zone $param")
val key = ctx.cookie("client-stream-id")
if (key != null && key.isNotEmpty()) {
if (param.isNotEmpty()) {
val bc = Get_Barix_Connection_by_ZoneName(param)
if (bc != null) {
bc.Remove_Mp3_Consumer(key)
WsContextMap.remove(key)
ResultMessageString(ctx, 200, "OK")
println("LiveAudio Close for zone $param SUCCESS")
} else ctx.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Broadcastzone not found")))
} else ctx.status(400)
.result(objectmapper.writeValueAsString(resultMessage("Invalid broadcastzone")))
} else {
ctx.status(400)
.result(objectmapper.writeValueAsString(resultMessage("No client-id cookie found")))
} }
wscontext.onClose {
val key = it.cookie("client-stream-id")
if (key!=null && key.isNotEmpty()){
val lld = WsContextMap[key]
lld?.bc?.Remove_Mp3_Consumer(key)
lld?.ws?.closeSession()
lld?.bc = null
lld?.ws= null
WsContextMap.remove(key)
Logger.info{"LiveAudio WebSocket closed for key $key"}
}
}
wscontext.onError {
val key = it.cookie("client-stream-id")
val msg = it.error()?.message ?: ""
Logger.info{"LiveAudio WebSocket error for key $key, Message: $msg"}
}
} }
} }
path("VoiceType") { path("VoiceType") {
get { get {
@@ -1876,7 +1898,6 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
val language = it.pathParam("language") val language = it.pathParam("language")
val voice = it.pathParam("voice") val voice = it.pathParam("voice")
val category = it.pathParam("category") val category = it.pathParam("category")
//println("ListSoundbank called with language=$language, voice=$voice, category=$category")
if (ValidString(language) && Language.entries.any { lang -> lang.name == language }) { if (ValidString(language) && Language.entries.any { lang -> lang.name == language }) {
if (ValidString(voice) && VoiceType.entries.any { vtype -> vtype.name == voice }) { if (ValidString(voice) && VoiceType.entries.any { vtype -> vtype.name == voice }) {
if (ValidString(category) && Category.entries.any { cat -> cat.name == category }) { if (ValidString(category) && Category.entries.any { cat -> cat.name == category }) {
@@ -1889,7 +1910,6 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
// just the filename, without path // just the filename, without path
mm.substring(mm.lastIndexOf(File.separator) + 1) mm.substring(mm.lastIndexOf(File.separator) + 1)
} }
//println("ListSoundbank result: $result")
it.result(objectmapper.writeValueAsString(result)) it.result(objectmapper.writeValueAsString(result))
} else { } else {
it.status(400) it.status(400)
@@ -1911,7 +1931,6 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
val category = it.pathParam("category") val category = it.pathParam("category")
val uploaded = it.uploadedFiles() val uploaded = it.uploadedFiles()
println("UploadSoundbank called with language=$language, voice=$voice, category=$category, uploaded files count=${uploaded.size}")
if (ValidString(language) && Language.entries.any { lang -> lang.name == language }) { if (ValidString(language) && Language.entries.any { lang -> lang.name == language }) {
if (ValidString(voice) && VoiceType.entries.any { vtype -> vtype.name == voice }) { if (ValidString(voice) && VoiceType.entries.any { vtype -> vtype.name == voice }) {
if (ValidString(category) && Category.entries.any { cat -> cat.name == category }) { if (ValidString(category) && Category.entries.any { cat -> cat.name == category }) {
@@ -2218,7 +2237,6 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
if (db.queuetableDB.Add(qt)) { if (db.queuetableDB.Add(qt)) {
db.queuetableDB.Resort() db.queuetableDB.Resort()
Logger.info { "SemiAutoWeb added to queue table: $qt" } Logger.info { "SemiAutoWeb added to queue table: $qt" }
//println("SemiAuto added to queue table: ${objectmapper.writeValueAsString(qt)}")
ctx.result(objectmapper.writeValueAsString(resultMessage("OK"))) ctx.result(objectmapper.writeValueAsString(resultMessage("OK")))
} else ResultMessageString(ctx, 500, "Failed to add to queue table") } else ResultMessageString(ctx, 500, "Failed to add to queue table")
} else ResultMessageString(ctx, 400, "Broadcast zones cannot be empty") } else ResultMessageString(ctx, 400, "Broadcast zones cannot be empty")
@@ -2232,10 +2250,8 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
get("/{datelog}") { ctx -> get("/{datelog}") { ctx ->
val datelog = ctx.pathParam("datelog") val datelog = ctx.pathParam("datelog")
if (ValidDate(datelog)) { if (ValidDate(datelog)) {
println("SemiAuto Get Log for date $datelog")
db.GetLogForHtml(datelog) { loghtml -> db.GetLogForHtml(datelog) { loghtml ->
val resultstring = objectmapper.writeValueAsString(loghtml) val resultstring = objectmapper.writeValueAsString(loghtml)
println("Log HTML for date $datelog: $resultstring")
ctx.result(resultstring) ctx.result(resultstring)
} }