diff --git a/src/MainExtension01.kt b/src/MainExtension01.kt index dabaaa9..dc69652 100644 --- a/src/MainExtension01.kt +++ b/src/MainExtension01.kt @@ -5,6 +5,7 @@ import codes.Somecodes.Companion.IsNumber import codes.Somecodes.Companion.Make_WAV_FileName import codes.Somecodes.Companion.SoundbankResult_directory import codes.Somecodes.Companion.ValidFile +import codes.Somecodes.Companion.ValidIPV4 import codes.Somecodes.Companion.ValidString import codes.Somecodes.Companion.dateformat1 import codes.Somecodes.Companion.datetimeformat1 @@ -12,6 +13,7 @@ import codes.Somecodes.Companion.timeformat2 import content.Category import content.Language import content.ScheduleDay +import database.BroadcastZones import database.Messagebank import database.QueueTable import database.Soundbank @@ -34,49 +36,78 @@ class MainExtension01 { /** * Fungsi untuk cek apakah semua broadcast zone valid + * Valid berarti nama broadcast zone ada di tabel BroadcastZones, dan SoundChannel-nya ada di tabel SoundChannel, dan IP-nya valid * @param bz List of broadcast zone (SoundChannel) * @return true jika semua valid, false jika ada yang tidak valid */ fun AllBroadcastZonesValid(bz: List): Boolean { if (bz.isNotEmpty()) { - println("StreamerOutputs: $StreamerOutputs") - val validchannels = bz - // check apakah tiap zone ada di database broadcast zones - .filter { z1 -> - println("Checking broadcast zone $z1") - val xx = db.broadcastDB.List.find { z2 -> z2.description == z1 } - println("Found in DB: $xx") - xx != null - } - // check apakah tiap zone ada di SoundChannelList dan Online - .filter { z3 -> - println("Checking if zone $z3 is in StreamerOutputs and online") - val xx = StreamerOutputs.values.find { it.channel == z3 } - println("Is online: $xx") - xx!= null + val validbz = mutableListOf() + db.broadcastDB.List.forEach { xx -> + if (ValidString(xx.description) && ValidString(xx.SoundChannel)){ + if (xx.description in bz) { + db.soundchannelDB.List.forEach { sc -> + if (sc.channel == xx.SoundChannel){ + if (ValidIPV4(sc.ip)){ + validbz.add(xx) + } + } + } + } } - println("Valid channels: $validchannels") - // kalau jumlah valid channel sama dengan jumlah broadcast zone, berarti semua valid - return validchannels.size == bz.size - } + } + if (validbz.size == bz.size) { + return true + } else Logger.error { "Some requested broadcast zones are not registered in BroadcastZone table" } + } else Logger.error { "No Broadcast Zones checked for validity" } return false } /** - * Fungsi untuk cek apakah semua broadcast zone idle - * @param bz List of broadcast zone (SoundChannel) + * Fungsi untuk cek apakah semua Streamer Output idle + * @param bz List of ip address * @return true jika semua idle, false jika ada yang tidak idle */ - fun AllBroadcastZoneIdle(bz: List): Boolean { + fun AllStreamerOutputIdle(bz: List): Boolean { if (bz.isNotEmpty()) { - return bz.all { z1 -> - StreamerOutputs.any { sc -> sc.value.channel == z1 && sc.value.isIdle() } - } - } + if (StreamerOutputs.isNotEmpty()){ + val idlebz = mutableListOf() + bz.forEach { z1 -> + val so = StreamerOutputs.values.find { it.ipaddress == z1 } + if (so != null) { + if (so.isIdle()) { + idlebz.add(z1) + } + } + } + if (idlebz.size == bz.size) { + return true + } else Logger.warn { "Some requested Streamer Outputs are not idle" } + } else Logger.error { "Streamer Outputs empty, Idle Broadcast Zones not available" } + } else Logger.error { "No Broadcast Zones checked for idle" } return false } + /** + * find SoundChannel IP from BroadcastZones description + * @param bz List of BroadcastZones description + * @return List of SoundChannel IP + */ + fun BroadcastZones_to_SoundChannel_IP(bz: List) : List{ + val result = mutableListOf() + if (bz.isNotEmpty()) { + val l1 = db.broadcastDB.List.filter { bz.contains(it.description) } + if (l1.size==bz.size){ + l1.forEach { xx -> + val yy = db.soundchannelDB.List.find { it.channel == xx.SoundChannel } + if (yy!=null) result.add(yy.ip) + } + } else Logger.error { "Some requested broadcast zones are not registered in BroadcastZone table" } + } else Logger.error { "No Broadcast Zones to convert to SoundChannel IP" } + return result + } + /** * Fungsi untuk ambil messagebank berdasarkan ANN_ID, diurutkan berdasarkan urutan bahasa di urutan_bahasa * @param id ANN_ID dari messagebank @@ -86,7 +117,7 @@ class MainExtension01 { fun Get_MessageBank_by_id(id: Int, languages: List = urutan_bahasa): ArrayList { val mb_list = ArrayList() languages.forEach { lang -> - db.messageDB.List.find { mb -> mb.ANN_ID == id.toUInt() && mb.Language == lang && mb.Voice_Type == selected_voice } + db.messageDB.List.find { mb -> mb.ANN_ID == id.toUInt() && mb.Language.equals(lang, true) && mb.Voice_Type.equals(selected_voice, true) } ?.let { mb_list.add(it) } @@ -181,8 +212,8 @@ class MainExtension01 { } // dapatkan soundbank array berdasarkan VoiceType dan Language val sb = db.soundDB.List - .filter { it.VoiceType == mb.Voice_Type } - .filter { it.Language == mb.Language } + .filter { it.VoiceType.equals(mb.Voice_Type, true) } + .filter { it.Language.equals(mb.Language, true) } if (sb.isEmpty()) { cbFail.accept("No soundbank found for voice type ${mb.Voice_Type} and language ${mb.Language}") return @@ -492,11 +523,13 @@ class MainExtension01 { fun Read_Queue_Paging(){ db.queuepagingDB.Get() for (qp in db.queuepagingDB.List) { - println("Processing QueuePaging $qp") + println("Processing $qp") if (qp.BroadcastZones.isNotBlank()) { val zz = qp.BroadcastZones.split(";") if (AllBroadcastZonesValid(zz)) { - if (AllBroadcastZoneIdle(zz)) { + val ips = BroadcastZones_to_SoundChannel_IP(zz) + println("Broadcast zones $zz converted to SoundChannel IPs: $ips") + if (AllStreamerOutputIdle(ips)) { if (qp.Source == "PAGING") { // nama file ada di Message if (ValidFile(qp.Message)) { @@ -624,13 +657,15 @@ class MainExtension01 { fun Read_Queue_Table(){ db.queuetableDB.Get() db.queuetableDB.List.forEach { qa -> - println("Processing QueueTable $qa") + println("Processing $qa") if (qa.BroadcastZones.isNotEmpty()) { val zz = qa.BroadcastZones.split(";") - println("Broadcast zones: $zz") + if (AllBroadcastZonesValid(zz)) { println("All broadcast zones valid") - if (AllBroadcastZoneIdle(zz)) { + val ips = BroadcastZones_to_SoundChannel_IP(zz) + println("Broadcast zones $zz converted to SoundChannel IPs: $ips") + if (AllStreamerOutputIdle(ips)) { println("All broadcast zones idle") if (qa.Type == "SOUNDBANK") { val variables = Get_Soundbank_Data(qa.SB_TAGS) @@ -670,40 +705,20 @@ class MainExtension01 { val mblist = Get_MessageBank_by_id(ann_id, languages) if (mblist.isNotEmpty()) { + val listafi = mutableListOf() + mblist.forEach { mb -> + println("Getting soundbank files for messagebank id ${mb.ANN_ID} voice=${mb.Voice_Type} lang=${mb.Language}, variables=$variables") Get_Soundbank_Files(mb, variables ?: emptyMap(), { listfile -> - val listafi = mutableListOf() + println("Got soundbank files: $listfile") listfile.forEach { filenya -> val afi = audioPlayer.LoadAudioFile(filenya) if (afi.isValid()) { listafi.add(afi) } } - val targetfile = SoundbankResult_directory.resolve(Make_WAV_FileName("Soundbank","")).toString() - audioPlayer.WavWriter(listafi, targetfile - ) { success, message -> - if (success) { - // file siap broadcast - val targetafi = audioPlayer.LoadAudioFile(targetfile) - if (targetafi.isValid()) { - zz.forEach { z1 -> - StreamerOutputs.values.find { it.channel == z1 } - ?.SendData( - targetafi.bytes, - { db.Add_Log("AAS", it) }, - { db.Add_Log("AAS", it) }) - } - val logmsg = - "Broadcast started SOUNDBANK message with generated file '$targetfile' to zones: ${qa.BroadcastZones}" - Logger.info { logmsg } - db.Add_Log("AAS", logmsg) - db.queuetableDB.DeleteByIndex(qa.index.toInt()) - - } - } - db.Add_Log("AAS", message) - } + println("Loaded AudioFileInfo list: $listafi") }, { err -> @@ -711,6 +726,38 @@ class MainExtension01 { db.queuetableDB.DeleteByIndex(qa.index.toInt()) }) } + + if (listafi.isNotEmpty()){ + val targetfile = SoundbankResult_directory.resolve(Make_WAV_FileName("Soundbank","")).toString() + println("Writing to target WAV file: $targetfile") + audioPlayer.WavWriter(listafi, targetfile + ) { success, message -> + if (success) { + // file siap broadcast + println("Successfully wrote WAV file: $targetfile") + val targetafi = audioPlayer.LoadAudioFile(targetfile) + if (targetafi.isValid()) { + zz.forEach { z1 -> + StreamerOutputs.values.find { it.channel == z1 } + ?.SendData( + targetafi.bytes, + { db.Add_Log("AAS", it) }, + { db.Add_Log("AAS", it) }) + } + val logmsg = + "Broadcast started SOUNDBANK message with generated file '$targetfile' to zones: ${qa.BroadcastZones}" + Logger.info { logmsg } + db.Add_Log("AAS", logmsg) + db.queuetableDB.DeleteByIndex(qa.index.toInt()) + + } + } else { + println("Failed to write WAV file: $message") + db.queuetableDB.DeleteByIndex(qa.index.toInt()) + db.Add_Log("AAS", message) + } + } + } } else { // tidak ada messagebank dengan ann_id ini, delete from queue table db.queuetableDB.DeleteByIndex(qa.index.toInt()) @@ -783,7 +830,6 @@ class MainExtension01 { ) } } - } } else { // ada broadcast zone yang tidak valid, delete from queue table diff --git a/src/audio/AudioPlayer.kt b/src/audio/AudioPlayer.kt index af96e6c..13adaf8 100644 --- a/src/audio/AudioPlayer.kt +++ b/src/audio/AudioPlayer.kt @@ -141,7 +141,7 @@ class AudioPlayer (var samplingrate: Int) { * @param callback A BiConsumer that accepts a Boolean indicating success or failure and a String message. */ fun WavWriter(sources: List, target: String, callback: BiConsumer) { - if (sources.isEmpty() || !ValidFile(target)) { + if (sources.isEmpty()) { callback.accept(false, " Invalid sources") return } diff --git a/src/barix/BarixConnection.kt b/src/barix/BarixConnection.kt index 18789f4..b70ada0 100644 --- a/src/barix/BarixConnection.kt +++ b/src/barix/BarixConnection.kt @@ -109,7 +109,7 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin } - } + } else cbFail.accept("SendData to $ipaddress:$port failed, data is empty") } diff --git a/src/commandServer/TCP_Android_Command_Server.kt b/src/commandServer/TCP_Android_Command_Server.kt index cdd5959..1ecbc91 100644 --- a/src/commandServer/TCP_Android_Command_Server.kt +++ b/src/commandServer/TCP_Android_Command_Server.kt @@ -324,9 +324,9 @@ class TCP_Android_Command_Server { VARMESSAGES.groupBy { it.ANN_ID }.forEach { (ann_id, value) -> result.append("MSG;").append(ann_id) result.append(";") - value.find { it.Language== Language.INDONESIA.name }?.let {result.append(it.Message_Detail)} ?: result.append("NA") + value.find { it.Language.equals(Language.INDONESIA.name, true) }?.let {result.append(it.Message_Detail)} ?: result.append("NA") result.append(";") - value.find {it.Language== Language.ENGLISH.name }?.let {result.append(it.Message_Detail)} ?: result.append("NA") + value.find {it.Language.equals(Language.ENGLISH.name, true) }?.let {result.append(it.Message_Detail)} ?: result.append("NA") result.append("@") } diff --git a/src/content/Language.kt b/src/content/Language.kt index 9308031..97780d0 100644 --- a/src/content/Language.kt +++ b/src/content/Language.kt @@ -7,10 +7,10 @@ package content */ @Suppress("unused") enum class Language(name: String) { - INDONESIA("Indonesia"), - ENGLISH("English"), - LOCAL("Local"), - JAPANESE("Japanese"), - CHINESE("Chinese"), - ARABIC("Arabic"); + INDONESIA("INDONESIA"), + ENGLISH("ENGLISH"), + LOCAL("LOCAL"), + JAPANESE("JAPANESE"), + CHINESE("CHINESE"), + ARABIC("ARABIC"); } \ No newline at end of file