From 446f03153529bd99f3ed985d14bf43a8e5013d33 Mon Sep 17 00:00:00 2001 From: rdkartono Date: Wed, 6 Aug 2025 16:35:20 +0700 Subject: [PATCH] Commit 06/08/2025 --- config.json | 16 --- html/assets/js/prerecordedbroadcast.js | 117 ++++++++++------ html/assets/js/setting.js | 182 ++++++++++++++----------- html/prerecordedbroadcast.html | 16 +-- src/Main.kt | 62 ++++++--- src/audio/AudioFilePlayer.kt | 8 +- src/somecodes/Codes.kt | 22 ++- src/somecodes/configFile.kt | 44 +++--- src/web/webApp.java | 31 ++++- 9 files changed, 307 insertions(+), 191 deletions(-) delete mode 100644 config.json diff --git a/config.json b/config.json deleted file mode 100644 index c3166d8..0000000 --- a/config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "ZelloUsername": "gtcdevice01", - "ZelloPassword": "GtcDev2025", - "ZelloChannel": "GtcDev2025", - "ZelloServer": "community", - "ZelloWorkNetworkName": "", - "ZelloEnterpriseServerDomain": "", - "M1": "", - "M2": "", - "M3": "", - "M4": "", - "M5": "", - "M6": "", - "M7": "", - "M8": "" - } \ No newline at end of file diff --git a/html/assets/js/prerecordedbroadcast.js b/html/assets/js/prerecordedbroadcast.js index 4ccc430..22f7f57 100644 --- a/html/assets/js/prerecordedbroadcast.js +++ b/html/assets/js/prerecordedbroadcast.js @@ -1,79 +1,106 @@ -$(document).ready(function() { +$(document).ready(function () { // Your code here - console.log('precordedbroadcast.js is ready!'); + //console.log('precordedbroadcast.js is ready!'); const path = window.location.pathname; const ws = new WebSocket('ws://' + window.location.host + path + '/ws'); - for(let i = 1; i<=8; i++){ + for (let i = 1; i <= 8; i++) { $(`#fileM${i}`).val(''); $(`#playM${i}`).prop('disabled', true); $(`#stopM${i}`).prop('disabled', true); } - ws.onopen = function() { - console.log('WebSocket connection opened'); + ws.onopen = function () { + //console.log('WebSocket connection opened'); $('#indicatorDisconnected').addClass('visually-hidden'); $('#indicatorConnected').removeClass('visually-hidden'); sendCommand({ command: "getMessageConfig" }); - setInterval(function() { + setInterval(function () { sendCommand({ command: "getPlaybackStatus" }); - }, 5000); + }, 1000); // every second }; - ws.onmessage = function(event) { - console.log('WebSocket message received:', event.data); + ws.onmessage = function (event) { + //console.log('WebSocket message received:', event.data); let msg = {}; try { msg = JSON.parse(event.data); } catch (e) { return; } - if (msg.reply === "getMessageConfig" && msg.data !== undefined) { - const messageConfigdata = msg.data; - console.log('Message Config Data:', messageConfigdata); - for(let i=1; i<=8; i++){ - let filetitle = $(`#fileM${i}`); - let playButton = $(`#playM${i}`); - let stopButton = $(`#stopM${i}`); - let fileInput = messageConfigdata[`M${i}`] || ''; - filetitle.val(fileInput); - if (fileInput.length>0){ - playButton.prop('disabled', false); - stopButton.prop('disabled', false); - playButton.on('click', function() { - let cmd = { - command: "playMessage", - data: `M${i}` + + if (msg.reply && msg.reply.length > 0 && msg.data && msg.data.length > 0) { + switch (msg.reply) { + case "playMessage": + if (msg.data !== "success") + {alert(msg.data);} + else{ + $('#playbackStatus').text('Playback started'); } - - sendCommand(cmd); - }); - stopButton.on('click', function() { - let cmd = { - command: "stopMessage", - data: `M${i}` + break; + case "stopMessage": + if (msg.data !== "success") + {alert(msg.data);} + else{ + $('#playbackStatus').text('Playback stopped'); } - sendCommand(cmd); - }); - } else { - playButton.prop('disabled', true); - stopButton.prop('disabled', true); + break; + case "getMessageConfig": + const messageConfigdata = JSON.parse(msg.data); + //console.log('Message Config Data:', messageConfigdata); + for (let i = 1; i <= 8; i++) { + let filetitle = $(`#fileM${i}`); + let playButton = $(`#playM${i}`); + let stopButton = $(`#stopM${i}`); + let fileInput = messageConfigdata[`M${i}`]; + if (fileInput && fileInput.length > 0) { + filetitle.text(fileInput); + playButton.prop('disabled', false); + stopButton.prop('disabled', false); + playButton.removeClass('invisible'); + stopButton.removeClass('invisible'); + playButton.on('click', function () { + let cmd = { + command: "playMessage", + data: `M${i}` + } + + sendCommand(cmd); + }); + stopButton.on('click', function () { + let cmd = { + command: "stopMessage", + data: `M${i}` + } + sendCommand(cmd); + }); + } else { + filetitle.text('Not configured'); + playButton.addClass('invisible'); + stopButton.addClass('invisible'); + + } + + + } + break; + case "getPlaybackStatus": + $('#playbackStatus').text(msg.data); + break; } - } - - } else if (msg.reply === "getPlaybackStatus" && msg.data !== undefined && msg.data.length > 0) { - const playbackData = msg.data; - $('#playbackStatus').text(playbackData.status); } + + + }; - ws.onclose = function() { - console.log('WebSocket connection closed'); + ws.onclose = function () { + //console.log('WebSocket connection closed'); $('#indicatorDisconnected').removeClass('visually-hidden'); $('#indicatorConnected').addClass('visually-hidden'); }; - ws.onerror = function(error) { + ws.onerror = function (error) { console.error('WebSocket error:', error); }; diff --git a/html/assets/js/setting.js b/html/assets/js/setting.js index 0241a02..c079b59 100644 --- a/html/assets/js/setting.js +++ b/html/assets/js/setting.js @@ -1,6 +1,6 @@ -$(document).ready(function() { +$(document).ready(function () { // Your initialization code here - console.log('setting.js is ready!'); + //console.log('setting.js is ready!'); $('#dropdownM1 button').text(''); $('#dropdownM2 button').text(''); $('#dropdownM3 button').text(''); @@ -23,123 +23,150 @@ $(document).ready(function() { const path = window.location.pathname; const ws = new WebSocket('ws://' + window.location.host + path + '/ws'); - ws.onopen = function() { - console.log('WebSocket connection opened'); + ws.onopen = function () { + //console.log('WebSocket connection opened'); $('#indicatorDisconnected').addClass('visually-hidden'); $('#indicatorConnected').removeClass('visually-hidden'); sendCommand({ command: "getConfig" }); }; - ws.onmessage = function(event) { - console.log('WebSocket message received:', event.data); + ws.onmessage = function (event) { + //console.log('WebSocket message received:', event.data); let msg = {}; try { msg = JSON.parse(event.data); } catch (e) { return; } - if (msg.reply === "getConfig" && msg.data !== undefined ) { - const configData = JSON.parse(msg.data); - console.log('Config Data:', configData); - $('#zelloUsername').val(configData.zelloUsername || ''); - $('#zelloPassword').val(configData.zelloPassword || ''); - $('#zelloChannel').val(configData.zelloChannel || ''); - if ("community" === configData.zelloServer) { - $('#zellocommunity').prop('checked', true); - $('#zelloWorkNetworkName').val('').prop('disabled', true); - $('#zelloEnterpriseServerDomain').val('').prop('disabled', true); - } else if ("work" === configData.zelloServer) { - $('#zellowork').prop('checked', true); - $('#zelloWorkNetworkName').val(configData.zelloWorkNetworkName || '').prop('disabled', false); - $('#zelloEnterpriseServerDomain').val('').prop('disabled', true); - } else if ("enterprise" === configData.zelloServer) { - $('#zelloenterprise').prop('checked', true); - $('#zelloWorkNetworkName').val('').prop('disabled', true); - $('#zelloEnterpriseServerDomain').val(configData.zelloEnterpriseServerDomain || '').prop('disabled', false); - } + if (msg.reply && msg.reply.length > 0) { + switch (msg.reply) { + case "getConfig": + const configData = JSON.parse(msg.data); + //console.log('Config Data:', configData); + $('#zelloUsername').val(configData.zelloUsername || ''); + $('#zelloPassword').val(configData.zelloPassword || ''); + $('#zelloChannel').val(configData.zelloChannel || ''); + if ("community" === configData.zelloServer) { + $('#zellocommunity').prop('checked', true); + $('#zelloWorkNetworkName').val('').prop('disabled', true); + $('#zelloEnterpriseServerDomain').val('').prop('disabled', true); + } else if ("work" === configData.zelloServer) { + $('#zellowork').prop('checked', true); + $('#zelloWorkNetworkName').val(configData.zelloWorkNetworkName || '').prop('disabled', false); + $('#zelloEnterpriseServerDomain').val('').prop('disabled', true); + } else if ("enterprise" === configData.zelloServer) { + $('#zelloenterprise').prop('checked', true); + $('#zelloWorkNetworkName').val('').prop('disabled', true); + $('#zelloEnterpriseServerDomain').val(configData.zelloEnterpriseServerDomain || '').prop('disabled', false); + } - for (let i = 1; i <= 8; i++) { - const dropdownMenu = $(`#dropdownM${i} .dropdown-menu`); - const dropdownButton = $(`#dropdownM${i} button`); - dropdownMenu.empty(); - const messages = configData[`MessageList`] || []; - messages.forEach((msg, idx) => { - const item = $('').text(msg); - item.on('click', function() { - dropdownButton.text(msg); - }); - dropdownMenu.append(item); - }); - // Set button text to selected message if present - if (configData[`m${i}`]) { - dropdownButton.text(configData[`m${i}`]); - } else { - dropdownButton.text(''); - } + for (let i = 1; i <= 8; i++) { + const dropdownMenu = $(`#dropdownM${i} .dropdown-menu`); + const dropdownButton = $(`#dropdownM${i} button`); + dropdownMenu.empty(); + const messages = configData[`messageList`] || []; + messages.forEach((msg, idx) => { + const item = $('').text(msg); + item.on('click', function () { + dropdownButton.text(msg); + }); + dropdownMenu.append(item); + }); + // Set button text to selected message if present + if (configData[`m${i}`]) { + dropdownButton.text(configData[`m${i}`]); + } else { + dropdownButton.text(''); + } + } + break; + case "setZelloConfig": + if (msg.data === "success") { + alert('Zello configuration updated successfully.'); + } else { + alert('Failed to update Zello configuration: ' + msg.data); + } + sendCommand({ command: "getConfig" }); // Refresh config after update + break; + case "setMessageConfig": + if (msg.data === "success") { + alert('Message configuration updated successfully.'); + } else { + alert('Failed to update Message configuration: ' + msg.data); + } + sendCommand({ command: "getConfig" }); // Refresh config after update + break; } - } + + }; - ws.onclose = function() { - console.log('WebSocket connection closed'); + ws.onclose = function () { + //console.log('WebSocket connection closed'); $('#indicatorDisconnected').removeClass('visually-hidden'); $('#indicatorConnected').addClass('visually-hidden'); }; - ws.onerror = function(error) { + ws.onerror = function (error) { console.error('WebSocket error:', error); }; - $('#zellocommunity').on('click', function() { + $('#zellocommunity').on('click', function () { $('#zelloWorkNetworkName').val('').prop('disabled', true); $('#zelloEnterpriseServerDomain').val('').prop('disabled', true); }); - $('#zellowork').on('click', function() { + $('#zellowork').on('click', function () { $('#zelloWorkNetworkName').prop('disabled', false); $('#zelloEnterpriseServerDomain').val('').prop('disabled', true); }); - $('#zelloenterprise').on('click', function() { + $('#zelloenterprise').on('click', function () { $('#zelloWorkNetworkName').val('').prop('disabled', true); $('#zelloEnterpriseServerDomain').prop('disabled', false); }); - $('#btnApplyZello').on('click', function() { + $('#btnApplyZello').on('click', function () { if (ws.readyState === WebSocket.OPEN) { + let xx = { + command: "setZelloConfig" + }; let data = { - command: "setZelloConfig", ZelloUsername: $('#zelloUsername').val(), ZelloPassword: $('#zelloPassword').val(), ZelloChannel: $('#zelloChannel').val(), ZelloServer: $('#zellocommunity').is(':checked') ? 'community' : - $('#zellowork').is(':checked') ? 'work' : - $('#zelloenterprise').is(':checked') ? 'enterprise' : '' - }; + $('#zellowork').is(':checked') ? 'work' : + $('#zelloenterprise').is(':checked') ? 'enterprise' : '' + } if ($('#zellowork').is(':checked')) { data.ZelloWorkNetworkName = $('#zelloWorkNetworkName').val(); } if ($('#zelloenterprise').is(':checked')) { data.ZelloEnterpriseServerDomain = $('#zelloEnterpriseServerDomain').val(); } - sendCommand(data); + xx.data = JSON.stringify(data); + sendCommand(xx); } else { console.warn('WebSocket is not open.'); } }); - $('#btnApplyMessage').on('click', function() { + $('#btnApplyMessage').on('click', function () { if (ws.readyState === WebSocket.OPEN) { let data = { command: "setMessageConfig", - M1: $('#dropdownM1 button').text(), - M2: $('#dropdownM2 button').text(), - M3: $('#dropdownM3 button').text(), - M4: $('#dropdownM4 button').text(), - M5: $('#dropdownM5 button').text(), - M6: $('#dropdownM6 button').text(), - M7: $('#dropdownM7 button').text(), - M8: $('#dropdownM8 button').text() + data: JSON.stringify({ + M1: $('#dropdownM1 button').text(), + M2: $('#dropdownM2 button').text(), + M3: $('#dropdownM3 button').text(), + M4: $('#dropdownM4 button').text(), + M5: $('#dropdownM5 button').text(), + M6: $('#dropdownM6 button').text(), + M7: $('#dropdownM7 button').text(), + M8: $('#dropdownM8 button').text() + }) + }; sendCommand(data); } else { @@ -147,7 +174,7 @@ $(document).ready(function() { } }); - $('#btnUploadContent').on('click', function() { + $('#btnUploadContent').on('click', function () { const fileInput = document.getElementById('chosenFile'); if (!fileInput || !fileInput.files.length) { alert('Please select a file to upload.'); @@ -161,17 +188,18 @@ $(document).ready(function() { method: 'POST', body: formData }) - .then(response => { - if (response.ok) { - alert('File uploaded successfully.'); - } else { - alert('File upload failed.'); - } - }) - .catch(error => { - console.error('Upload error:', error); - alert('An error occurred during upload.'); - }); + .then(response => { + if (response.ok) { + alert('File uploaded successfully.'); + sendCommand({ command: "getConfig" }); // Refresh config after upload + } else { + alert('File upload failed.'); + } + }) + .catch(error => { + console.error('Upload error:', error); + alert('An error occurred during upload.'); + }); }); function sendCommand(cmd) { diff --git a/html/prerecordedbroadcast.html b/html/prerecordedbroadcast.html index 00b7eb4..013b41a 100644 --- a/html/prerecordedbroadcast.html +++ b/html/prerecordedbroadcast.html @@ -43,7 +43,7 @@

Message1

-

File 01

+

File 01

@@ -55,7 +55,7 @@

Message2

-

File 02

+

File 02

@@ -69,7 +69,7 @@

Message3

-

File 03

+

File 03

@@ -81,7 +81,7 @@

Message4

-

File 04

+

File 04

@@ -95,7 +95,7 @@

Message5

-

File 05

+

File 05

@@ -107,7 +107,7 @@

Message6

-

File 06

+

File 06

@@ -121,7 +121,7 @@

Message7

-

File 07

+

File 07

@@ -133,7 +133,7 @@

Message8

-

File 08

+

File 08

diff --git a/src/Main.kt b/src/Main.kt index 887871b..0b29c27 100644 --- a/src/Main.kt +++ b/src/Main.kt @@ -2,7 +2,7 @@ import audio.AudioFilePlayer import audio.AudioUtility import audio.OpusStreamReceiver import com.fasterxml.jackson.core.type.TypeReference -import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import somecodes.Codes.Companion.ValidString import somecodes.configFile import web.WsReply @@ -11,15 +11,17 @@ import zello.ZelloClient import zello.ZelloEvent import javafx.util.Pair import org.slf4j.LoggerFactory -import somecodes.Codes.Companion.ValidFile +import somecodes.Codes import web.WsCommand import java.util.function.BiFunction +import kotlin.io.path.isRegularFile +import kotlin.io.path.pathString //TIP To Run code, press or // click the icon in the gutter. fun main() { val logger = LoggerFactory.getLogger("Main") - val objectMapper = ObjectMapper() + val objectMapper = jacksonObjectMapper() val cfg = configFile() cfg.Load() @@ -33,7 +35,7 @@ fun main() { } } if (audioID!=0){ - val initsuccess = au.InitDevice(audioID) + val initsuccess = au.InitDevice(audioID,44100) println("Audio Device $audioID initialized: $initsuccess") } @@ -45,8 +47,25 @@ fun main() { when (source) { "setting" -> when(cmd.command){ "getConfig" ->{ - logger.info("Get Config") - WsReply(cmd.command,objectMapper.writeValueAsString(cfg) ) + val data = mapOf( + "zelloUsername" to cfg.ZelloUsername, + "zelloPassword" to cfg.ZelloPassword, + "zelloChannel" to cfg.ZelloChannel, + "zelloServer" to cfg.ZelloServer, + "zelloWorkNetworkName" to cfg.ZelloWorkNetworkName, + "zelloEnterpriseServerDomain" to cfg.ZelloEnterpriseServerDomain, + "m1" to cfg.M1, + "m2" to cfg.M2, + "m3" to cfg.M3, + "m4" to cfg.M4, + "m5" to cfg.M5, + "m6" to cfg.M6, + "m7" to cfg.M7, + "m8" to cfg.M8, + "messageList" to Codes.getAudioFiles() + ) + + WsReply(cmd.command, objectMapper.writeValueAsString(data).trim()) } "setZelloConfig" -> { try{ @@ -57,7 +76,7 @@ fun main() { cfg.ZelloServer = xx["ZelloServer"] cfg.ZelloWorkNetworkName = xx["ZelloWorkNetworkName"] cfg.ZelloEnterpriseServerDomain = xx["ZelloEnterpriseServerDomain"] - + cfg.Save() WsReply(cmd.command,"success") } catch (e: Exception){ WsReply(cmd.command,"failed: ${e.message}") @@ -76,6 +95,7 @@ fun main() { cfg.M6 = xx["M6"] cfg.M7 = xx["M7"] cfg.M8 = xx["M8"] + cfg.Save() WsReply(cmd.command,"success") } catch (e: Exception){ WsReply(cmd.command,"failed: ${e.message}") @@ -101,7 +121,7 @@ fun main() { } "getPlaybackStatus" ->{ if (afp!=null && true==afp?.isPlaying){ - WsReply(cmd.command, "Playing: ${afp?.filename}") + WsReply(cmd.command, "Playing: ${afp?.ShortFileName()}") } else { WsReply(cmd.command, "Idle") } @@ -120,17 +140,23 @@ fun main() { null } } - if (ValidFile(filename)){ - try{ - val player= AudioFilePlayer(audioID, filename) - player.Play { _ -> afp = null} - afp = player - WsReply(cmd.command,"success") + if (filename!=null){ + val completefilename = Codes.audioFilePath.resolve(filename) + if (completefilename.isRegularFile()){ + try{ + + val player= AudioFilePlayer(audioID, completefilename.pathString) + player.Play { _ -> afp = null} + afp = player + WsReply(cmd.command,"success") + + } catch (e: Exception){ + WsReply(cmd.command, "failed: ${e.message}") + } + } else WsReply(cmd.command,"File Not Found : $filename") + } else WsReply(cmd.command,"Invalid message name: ${cmd.data}") + - } catch (e: Exception){ - WsReply(cmd.command, "failed: ${e.message}") - } - } else WsReply(cmd.command,"Invalid file : $filename") diff --git a/src/audio/AudioFilePlayer.kt b/src/audio/AudioFilePlayer.kt index b2781da..7de5654 100644 --- a/src/audio/AudioFilePlayer.kt +++ b/src/audio/AudioFilePlayer.kt @@ -5,16 +5,18 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch import java.util.function.Consumer +import kotlin.io.path.Path /** * Audio Player for playing audio files. * Supported extensions : .wav, .mp3 */ @Suppress("unused") -class AudioFilePlayer(deviceID: Int, val filename: String?, device_samplingrate: Int = 48000) { +class AudioFilePlayer(deviceID: Int, filename: String, device_samplingrate: Int = 48000) { val bass: Bass = Bass.Instance var filehandle = 0 var isPlaying = false + private val filepath = Path(filename) init{ if (bass.BASS_SetDevice(deviceID)){ filehandle = bass.BASS_StreamCreateFile(false, filename, 0, 0, 0) @@ -32,6 +34,10 @@ class AudioFilePlayer(deviceID: Int, val filename: String?, device_samplingrate: } } + fun ShortFileName() : String { + return filepath.fileName.toString() + } + fun Play(finished: Consumer ) : Boolean{ if (bass.BASS_ChannelPlay(filehandle, false)){ diff --git a/src/somecodes/Codes.kt b/src/somecodes/Codes.kt index 598115f..d59929c 100644 --- a/src/somecodes/Codes.kt +++ b/src/somecodes/Codes.kt @@ -1,12 +1,30 @@ package somecodes -import com.fasterxml.jackson.databind.ObjectMapper import java.io.File +import kotlin.io.path.Path @Suppress("unused") class Codes { - private val objectMapper = ObjectMapper() + companion object{ + val audioFilePath = Path(System.getProperty("user.dir"), "audiofile") + private val validAudioExtensions = setOf("wav", "mp3") + fun getAudioFiles() : Array { + val audioDir = audioFilePath.toFile() + if (!audioDir.exists()) { + audioDir.mkdirs() // Create directory if it doesn't exist + } + val ll = audioDir.listFiles()?.filter { it.isFile && validAudioExtensions.contains(it.extension) }?.map { it.name } ?: emptyList() + return ll.toTypedArray() + } + + fun getaudioFileFullPath(filename: String) : String { + if (ValidString(filename)) { + val file = audioFilePath.resolve(filename) + return file.toAbsolutePath().toString() + } + return "" + } fun ValidFile(s: String?) : Boolean { if (s!=null){ diff --git a/src/somecodes/configFile.kt b/src/somecodes/configFile.kt index 4323876..313d77a 100644 --- a/src/somecodes/configFile.kt +++ b/src/somecodes/configFile.kt @@ -1,5 +1,6 @@ package somecodes +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import java.nio.file.Path import kotlin.io.path.Path @@ -21,15 +22,14 @@ class configFile { private val filepath : Path = Path(System.getProperty("user.dir"), "config.json") + @Suppress("UNCHECKED_CAST") fun Load(){ if (filepath.toFile().exists()){ // file found, then load the configuration to configFile object try{ val json = filepath.toFile().readText() - val configMap = json.split(",").associate { it -> - val (key, value) = it.split(":").map { it.trim().removeSurrounding("\"") } - key to value - } + val objectMapper = jacksonObjectMapper() + val configMap = objectMapper.readValue(json, Map::class.java) as Map ZelloUsername = configMap["ZelloUsername"] ZelloPassword = configMap["ZelloPassword"] @@ -72,23 +72,25 @@ class configFile { fun Save(){ try { // Convert the configFile object to JSON and write it to the file - val json = """{ - "ZelloUsername": "$ZelloUsername", - "ZelloPassword": "$ZelloPassword", - "ZelloChannel": "$ZelloChannel", - "ZelloServer": "$ZelloServer", - "ZelloWorkNetworkName": "$ZelloWorkNetworkName", - "ZelloEnterpriseServerDomain": "$ZelloEnterpriseServerDomain", - "M1": "$M1", - "M2": "$M2", - "M3": "$M3", - "M4": "$M4", - "M5": "$M5", - "M6": "$M6", - "M7": "$M7", - "M8": "$M8" - }""" - filepath.toFile().writeText(json) + val js = mapOf( + "ZelloUsername" to ZelloUsername, + "ZelloPassword" to ZelloPassword, + "ZelloChannel" to ZelloChannel, + "ZelloServer" to ZelloServer, + "ZelloWorkNetworkName" to ZelloWorkNetworkName, + "ZelloEnterpriseServerDomain" to ZelloEnterpriseServerDomain, + "M1" to M1, + "M2" to M2, + "M3" to M3, + "M4" to M4, + "M5" to M5, + "M6" to M6, + "M7" to M7, + "M8" to M8 + ) + + val mapper = jacksonObjectMapper() + mapper.writerWithDefaultPrettyPrinter().writeValue(filepath.toFile(), js) } catch (e: Exception) { println("Error saving configuration: ${e.message}") } diff --git a/src/web/webApp.java b/src/web/webApp.java index 396ba6a..d099041 100644 --- a/src/web/webApp.java +++ b/src/web/webApp.java @@ -2,10 +2,16 @@ package web; import com.fasterxml.jackson.databind.ObjectMapper; import io.javalin.Javalin; +import io.javalin.http.HttpStatus; import javafx.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import somecodes.Codes; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import java.util.HashMap; import java.util.Map; import java.util.function.BiFunction; @@ -85,7 +91,7 @@ public class webApp { String message = wsMessageContext.message(); try{ var command = objectMapper.readValue(message, WsCommand.class); - logger.info("Received command from prerecordedbroadcast.html/ws : {}", command); + //logger.info("Received command from prerecordedbroadcast.html/ws : {}", command); var reply = callback.apply("prerecordedbroadcast", command); wsMessageContext.send(reply); } catch (Exception e){ @@ -99,14 +105,33 @@ public class webApp { ctx.redirect("/index.html"); } }); + post("/upload", ctx -> { + // Handle file upload + var file = ctx.uploadedFile("file"); + if (file != null ) { + // Process the uploaded file + try(InputStream in = file.content()) { + var savetarget = Codes.Companion.getAudioFilePath().resolve(file.filename()); + Files.copy(in, savetarget, StandardCopyOption.REPLACE_EXISTING); + logger.info("File uploaded: {}", file.filename()); + ctx.status(HttpStatus.OK).result("File uploaded successfully: " + file.filename()); + } catch (Exception e){ + ctx.status(HttpStatus.INTERNAL_SERVER_ERROR).result("File upload failed: " + file.filename()); + } + + } else { + ctx.status(HttpStatus.BAD_REQUEST).result("No file uploaded"); + } + }); ws("/ws", wshandler -> wshandler.onMessage(wsMessageContext -> { // Handle incoming WebSocket messages String message = wsMessageContext.message(); + //logger.info("Received message from setting.html/ws: {}", message); try{ var command = objectMapper.readValue(message, WsCommand.class); - logger.info("Received command from setting.html/ws : {}", command); + //logger.info("Received command from setting.html/ws : {}", command); var reply = callback.apply("setting", command); - logger.info("Replying to setting.html/ws : {}", reply); + //logger.info("Replying to setting.html/ws : {}", reply); wsMessageContext.send(reply); } catch (Exception e){ logger.error("Error processing {} from setting.html/ws: {}", message, e.getMessage());