commit 06/10/2025

This commit is contained in:
2025-10-06 11:06:32 +07:00
parent cf69c72f3c
commit 13a45b706b
5 changed files with 116 additions and 70 deletions

View File

@@ -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<String>): 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<BroadcastZones>()
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<String>): Boolean {
fun AllStreamerOutputIdle(bz: List<String>): Boolean {
if (bz.isNotEmpty()) {
return bz.all { z1 ->
StreamerOutputs.any { sc -> sc.value.channel == z1 && sc.value.isIdle() }
}
}
if (StreamerOutputs.isNotEmpty()){
val idlebz = mutableListOf<String>()
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<String>) : List<String>{
val result = mutableListOf<String>()
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<String> = urutan_bahasa): ArrayList<Messagebank> {
val mb_list = ArrayList<Messagebank>()
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<AudioFileInfo>()
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<AudioFileInfo>()
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

View File

@@ -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<AudioFileInfo>, target: String, callback: BiConsumer<Boolean, String>) {
if (sources.isEmpty() || !ValidFile(target)) {
if (sources.isEmpty()) {
callback.accept(false, " Invalid sources")
return
}

View File

@@ -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")
}

View File

@@ -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("@")
}

View File

@@ -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");
}