commit 24/09/2025
This commit is contained in:
25
src/Main.kt
25
src/Main.kt
@@ -18,6 +18,7 @@ import web.WebApp
|
|||||||
import java.time.DayOfWeek
|
import java.time.DayOfWeek
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
|
import kotlin.concurrent.fixedRateTimer
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
@@ -141,7 +142,7 @@ fun main() {
|
|||||||
listOf(
|
listOf(
|
||||||
Pair("admin", "password"),
|
Pair("admin", "password"),
|
||||||
Pair("user", "password")
|
Pair("user", "password")
|
||||||
), db
|
), db, StreamerOutputs
|
||||||
)
|
)
|
||||||
web.Start()
|
web.Start()
|
||||||
|
|
||||||
@@ -154,7 +155,7 @@ fun main() {
|
|||||||
// belum create BarixConnection untuk ipaddress ini
|
// belum create BarixConnection untuk ipaddress ini
|
||||||
Logger.info{"New Streamer Output connection from ${cmd.ipaddress}"}
|
Logger.info{"New Streamer Output connection from ${cmd.ipaddress}"}
|
||||||
if (_sc!=null){
|
if (_sc!=null){
|
||||||
val _bc = BarixConnection(_sc.channel,cmd.ipaddress)
|
val _bc = BarixConnection(_sc.index,_sc.channel,cmd.ipaddress)
|
||||||
_bc.vu = cmd.vu
|
_bc.vu = cmd.vu
|
||||||
_bc.bufferRemain = cmd.buffremain
|
_bc.bufferRemain = cmd.buffremain
|
||||||
_bc.statusData = cmd.statusdata
|
_bc.statusData = cmd.statusdata
|
||||||
@@ -163,7 +164,7 @@ fun main() {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// sudah ada, update data
|
// sudah ada, update data
|
||||||
if (_sc !=null && !_sc.channel.equals(_streamer.channel)) {
|
if (_sc !=null && _sc.channel != _streamer.channel) {
|
||||||
_streamer.channel = _sc.channel
|
_streamer.channel = _sc.channel
|
||||||
}
|
}
|
||||||
_streamer.vu = cmd.vu
|
_streamer.vu = cmd.vu
|
||||||
@@ -173,5 +174,23 @@ fun main() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val onlinechecker = fixedRateTimer(name="onlinecheck", initialDelay = 1000, period = 1000) {
|
||||||
|
// cek setiap 1 detik, decrement online counter semua BarixConnection
|
||||||
|
StreamerOutputs.values.forEach {
|
||||||
|
it.decrementOnlineCounter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// shutdown hook
|
||||||
|
Runtime.getRuntime().addShutdownHook(Thread {
|
||||||
|
Logger.info{"Shutdown hook called, stopping services..."}
|
||||||
|
barixserver.StopTcpCommand()
|
||||||
|
onlinechecker.cancel()
|
||||||
|
web.Stop()
|
||||||
|
audioPlayer.Close()
|
||||||
|
db.close()
|
||||||
|
Logger.info{"All services stopped, exiting application."}
|
||||||
|
} )
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ class AudioPlayer (var samplingrate: Int) {
|
|||||||
/**
|
/**
|
||||||
* Uninitializes the audio system if it was previously initialized.
|
* Uninitializes the audio system if it was previously initialized.
|
||||||
*/
|
*/
|
||||||
fun UnInitAudio(){
|
fun Close(){
|
||||||
if (initedDevice != -1) {
|
if (initedDevice != -1) {
|
||||||
bass.BASS_SetDevice(initedDevice)
|
bass.BASS_SetDevice(initedDevice)
|
||||||
if (bass.BASS_Free()) {
|
if (bass.BASS_Free()) {
|
||||||
|
|||||||
@@ -1,26 +1,74 @@
|
|||||||
package barix
|
package barix
|
||||||
|
|
||||||
|
import codes.Somecodes
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
import org.tinylog.Logger
|
import org.tinylog.Logger
|
||||||
import java.net.DatagramPacket
|
import java.net.DatagramPacket
|
||||||
import java.net.DatagramSocket
|
import java.net.DatagramSocket
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class BarixConnection(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) {
|
||||||
var bufferRemain: Int = 0
|
private var _bR: Int = 0
|
||||||
var statusData: Int = 0
|
private var _sd: Int = 0
|
||||||
var vu: Int = 0
|
private var _vu: Int = 0
|
||||||
|
private var _onlinecounter = 0
|
||||||
private val udp = DatagramSocket(0)
|
private val udp = DatagramSocket(0)
|
||||||
private val inet = InetSocketAddress(ipaddress, port)
|
private val inet = InetSocketAddress(ipaddress, port)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer remain in bytes
|
||||||
|
*/
|
||||||
|
var bufferRemain: Int
|
||||||
|
get() = _bR
|
||||||
|
set(value) {
|
||||||
|
_bR = value
|
||||||
|
_onlinecounter = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status data, 0 = playback idle, 1 = playback running
|
||||||
|
*/
|
||||||
|
var statusData: Int
|
||||||
|
get() = _sd
|
||||||
|
set(value) {
|
||||||
|
_sd = if (value < 0) 0 else if (value > 1) 1 else value
|
||||||
|
_onlinecounter = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VU level 0-100
|
||||||
|
*/
|
||||||
|
var vu: Int
|
||||||
|
get() = _vu
|
||||||
|
set(value) {
|
||||||
|
_vu = if (value < 0) 0 else if (value > 100) 100 else value
|
||||||
|
_onlinecounter = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrement online counter, if counter reaches 0, the device is considered offline
|
||||||
|
*/
|
||||||
|
fun decrementOnlineCounter() {
|
||||||
|
if (_onlinecounter > 0) {
|
||||||
|
_onlinecounter--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isOnline(): Boolean {
|
||||||
|
return _onlinecounter > 0
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send data to Barix device via UDP
|
* Send data to Barix device via UDP
|
||||||
* @param data The data to send
|
* @param data The data to send
|
||||||
* @return true if successful
|
* @return true if successful
|
||||||
*/
|
*/
|
||||||
fun SendData(data: ByteArray): Boolean {
|
fun SendData(data: ByteArray): Boolean {
|
||||||
if (data.isNotEmpty()){
|
if (data.isNotEmpty()) {
|
||||||
try{
|
try {
|
||||||
udp.send(DatagramPacket(data, data.size, inet))
|
udp.send(DatagramPacket(data, data.size, inet))
|
||||||
return true
|
return true
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -30,4 +78,30 @@ class BarixConnection(var channel: String, val ipaddress: String, val port: Int
|
|||||||
return false
|
return false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert BarixConnection to JsonNode
|
||||||
|
* @return JsonNode representation of BarixConnection
|
||||||
|
*/
|
||||||
|
fun toJsonNode(): JsonNode {
|
||||||
|
// make json node from index, channel, ipaddress, port, bufferRemain, statusData, vu
|
||||||
|
return Somecodes.objectmapper.createObjectNode().apply {
|
||||||
|
put("index", index.toInt())
|
||||||
|
put("channel", channel)
|
||||||
|
put("ipaddress", ipaddress)
|
||||||
|
put("port", port)
|
||||||
|
put("bufferRemain", bufferRemain)
|
||||||
|
put("statusData", statusData)
|
||||||
|
put("vu", vu)
|
||||||
|
put("isOnline", isOnline())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert BarixConnection to JSON string
|
||||||
|
* @return JSON string representation of BarixConnection
|
||||||
|
*/
|
||||||
|
fun toJsonString(): String {
|
||||||
|
return Somecodes.toJsonString(toJsonNode())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,8 +13,9 @@ class TCP_Barix_Command_Server {
|
|||||||
private var job: Job? = null
|
private var job: Job? = null
|
||||||
private val socketMap = mutableMapOf<String, Socket>()
|
private val socketMap = mutableMapOf<String, Socket>()
|
||||||
|
|
||||||
private val regex: String = "\\$\\\"STATUSBARIX;(\\d+);(\\d+);?(\\d)?\\\"\\$"
|
private val regex = """\$\\"STATUSBARIX;(\d+);(\d+);?(\d)?\\"$"""
|
||||||
private val pattern = Regex(regex)
|
private val pattern = Regex(regex)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start TCP Command Server
|
* Start TCP Command Server
|
||||||
* @param port The port number to listen on (default is 5001)
|
* @param port The port number to listen on (default is 5001)
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package codes
|
package codes
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
import content.ScheduleDay
|
import content.ScheduleDay
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -31,6 +33,47 @@ class Somecodes {
|
|||||||
const val MB_threshold = KB_threshold * 1024.0
|
const val MB_threshold = KB_threshold * 1024.0
|
||||||
const val GB_threshold = MB_threshold * 1024.0
|
const val GB_threshold = MB_threshold * 1024.0
|
||||||
const val TB_threshold = GB_threshold * 1024.0
|
const val TB_threshold = GB_threshold * 1024.0
|
||||||
|
val objectmapper = jacksonObjectMapper()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an object to a JSON string.
|
||||||
|
* @param data The object to convert.
|
||||||
|
* @return A JSON string representation of the object, or "{}" if conversion fails.
|
||||||
|
*/
|
||||||
|
fun toJsonString(data: Any) : String {
|
||||||
|
return try {
|
||||||
|
objectmapper.writeValueAsString(data)
|
||||||
|
} catch (e: Exception){
|
||||||
|
"{}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a JSON string to an object of the specified class.
|
||||||
|
* @param json The JSON string to convert.
|
||||||
|
* @param clazz The class of the object to convert to.
|
||||||
|
* @return An object of the specified class, or null if conversion fails.
|
||||||
|
*/
|
||||||
|
fun <T> fromJsonString(json: String, clazz: Class<T>) : T? {
|
||||||
|
return try {
|
||||||
|
objectmapper.readValue(json, clazz)
|
||||||
|
} catch (e: Exception){
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a JSON string to a JsonNode.
|
||||||
|
* @param data The JSON string to convert.
|
||||||
|
* @return A JsonNode representation of the JSON string, or empty JsonNode if conversion fails.
|
||||||
|
*/
|
||||||
|
fun toJsonNode(data: String) : JsonNode {
|
||||||
|
return try {
|
||||||
|
objectmapper.readTree(data)
|
||||||
|
} catch (e: Exception){
|
||||||
|
objectmapper.createObjectNode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List all audio files (.mp3 and .wav) in the specified directory and its subdirectories.
|
* List all audio files (.mp3 and .wav) in the specified directory and its subdirectories.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import codes.Somecodes.Companion.ValiDateForLogHtml
|
import codes.Somecodes.Companion.ValiDateForLogHtml
|
||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
import codes.Somecodes.Companion.toJsonString
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@@ -50,7 +50,6 @@ class MariaDB(
|
|||||||
return regex.matches(time)
|
return regex.matches(time)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val objectMapper = jacksonObjectMapper()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert SoundbankList, MessagebankList, LanguageLinkList, or SchedulebankList to a JSON String.
|
* Convert SoundbankList, MessagebankList, LanguageLinkList, or SchedulebankList to a JSON String.
|
||||||
@@ -59,7 +58,7 @@ class MariaDB(
|
|||||||
*/
|
*/
|
||||||
fun <T> ArrayListtoString(list: ArrayList<T>): String {
|
fun <T> ArrayListtoString(list: ArrayList<T>): String {
|
||||||
return try {
|
return try {
|
||||||
objectMapper.writeValueAsString(list)
|
toJsonString(list)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Logger.error("Error converting list to JSON: ${e.message}" as Any)
|
Logger.error("Error converting list to JSON: ${e.message}" as Any)
|
||||||
"[]"
|
"[]"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package web
|
package web
|
||||||
|
|
||||||
|
import barix.BarixConnection
|
||||||
import codes.Somecodes
|
import codes.Somecodes
|
||||||
import codes.Somecodes.Companion.ListAudioFiles
|
import codes.Somecodes.Companion.ListAudioFiles
|
||||||
import codes.Somecodes.Companion.ValiDateForLogHtml
|
import codes.Somecodes.Companion.ValiDateForLogHtml
|
||||||
@@ -35,7 +36,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook
|
|||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val db: MariaDB) {
|
class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val db: MariaDB, val StreamerOutputs : MutableMap<String, BarixConnection> ) {
|
||||||
|
|
||||||
var app: Javalin? = null
|
var app: Javalin? = null
|
||||||
val objectmapper = jacksonObjectMapper()
|
val objectmapper = jacksonObjectMapper()
|
||||||
@@ -134,6 +135,10 @@ class WebApp(val listenPort: Int, val userlist: List<Pair<String, String>>, val
|
|||||||
SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(db.Read_Queue_Table()))
|
SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(db.Read_Queue_Table()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"getStreamerOutputs" -> {
|
||||||
|
SendReply(wsMessageContext, cmd.command, objectmapper.writeValueAsString(StreamerOutputs.values.toList()))
|
||||||
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
SendReply(wsMessageContext, cmd.command, "Unknown command")
|
SendReply(wsMessageContext, cmd.command, "Unknown command")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user