commit 06/10/2025
This commit is contained in:
@@ -5,6 +5,7 @@ import codes.Somecodes.Companion.IsNumber
|
|||||||
import codes.Somecodes.Companion.Make_WAV_FileName
|
import codes.Somecodes.Companion.Make_WAV_FileName
|
||||||
import codes.Somecodes.Companion.SoundbankResult_directory
|
import codes.Somecodes.Companion.SoundbankResult_directory
|
||||||
import codes.Somecodes.Companion.ValidFile
|
import codes.Somecodes.Companion.ValidFile
|
||||||
|
import codes.Somecodes.Companion.ValidIPV4
|
||||||
import codes.Somecodes.Companion.ValidString
|
import codes.Somecodes.Companion.ValidString
|
||||||
import codes.Somecodes.Companion.dateformat1
|
import codes.Somecodes.Companion.dateformat1
|
||||||
import codes.Somecodes.Companion.datetimeformat1
|
import codes.Somecodes.Companion.datetimeformat1
|
||||||
@@ -12,6 +13,7 @@ import codes.Somecodes.Companion.timeformat2
|
|||||||
import content.Category
|
import content.Category
|
||||||
import content.Language
|
import content.Language
|
||||||
import content.ScheduleDay
|
import content.ScheduleDay
|
||||||
|
import database.BroadcastZones
|
||||||
import database.Messagebank
|
import database.Messagebank
|
||||||
import database.QueueTable
|
import database.QueueTable
|
||||||
import database.Soundbank
|
import database.Soundbank
|
||||||
@@ -34,49 +36,78 @@ class MainExtension01 {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Fungsi untuk cek apakah semua broadcast zone valid
|
* 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)
|
* @param bz List of broadcast zone (SoundChannel)
|
||||||
* @return true jika semua valid, false jika ada yang tidak valid
|
* @return true jika semua valid, false jika ada yang tidak valid
|
||||||
*/
|
*/
|
||||||
fun AllBroadcastZonesValid(bz: List<String>): Boolean {
|
fun AllBroadcastZonesValid(bz: List<String>): Boolean {
|
||||||
if (bz.isNotEmpty()) {
|
if (bz.isNotEmpty()) {
|
||||||
println("StreamerOutputs: $StreamerOutputs")
|
val validbz = mutableListOf<BroadcastZones>()
|
||||||
val validchannels = bz
|
db.broadcastDB.List.forEach { xx ->
|
||||||
// check apakah tiap zone ada di database broadcast zones
|
if (ValidString(xx.description) && ValidString(xx.SoundChannel)){
|
||||||
.filter { z1 ->
|
if (xx.description in bz) {
|
||||||
println("Checking broadcast zone $z1")
|
db.soundchannelDB.List.forEach { sc ->
|
||||||
val xx = db.broadcastDB.List.find { z2 -> z2.description == z1 }
|
if (sc.channel == xx.SoundChannel){
|
||||||
println("Found in DB: $xx")
|
if (ValidIPV4(sc.ip)){
|
||||||
xx != null
|
validbz.add(xx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fungsi untuk cek apakah semua broadcast zone idle
|
* Fungsi untuk cek apakah semua Streamer Output idle
|
||||||
* @param bz List of broadcast zone (SoundChannel)
|
* @param bz List of ip address
|
||||||
* @return true jika semua idle, false jika ada yang tidak idle
|
* @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()) {
|
if (bz.isNotEmpty()) {
|
||||||
return bz.all { z1 ->
|
if (StreamerOutputs.isNotEmpty()){
|
||||||
StreamerOutputs.any { sc -> sc.value.channel == z1 && sc.value.isIdle() }
|
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
|
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
|
* Fungsi untuk ambil messagebank berdasarkan ANN_ID, diurutkan berdasarkan urutan bahasa di urutan_bahasa
|
||||||
* @param id ANN_ID dari messagebank
|
* @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> {
|
fun Get_MessageBank_by_id(id: Int, languages: List<String> = urutan_bahasa): ArrayList<Messagebank> {
|
||||||
val mb_list = ArrayList<Messagebank>()
|
val mb_list = ArrayList<Messagebank>()
|
||||||
languages.forEach { lang ->
|
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 {
|
?.let {
|
||||||
mb_list.add(it)
|
mb_list.add(it)
|
||||||
}
|
}
|
||||||
@@ -181,8 +212,8 @@ class MainExtension01 {
|
|||||||
}
|
}
|
||||||
// dapatkan soundbank array berdasarkan VoiceType dan Language
|
// dapatkan soundbank array berdasarkan VoiceType dan Language
|
||||||
val sb = db.soundDB.List
|
val sb = db.soundDB.List
|
||||||
.filter { it.VoiceType == mb.Voice_Type }
|
.filter { it.VoiceType.equals(mb.Voice_Type, true) }
|
||||||
.filter { it.Language == mb.Language }
|
.filter { it.Language.equals(mb.Language, true) }
|
||||||
if (sb.isEmpty()) {
|
if (sb.isEmpty()) {
|
||||||
cbFail.accept("No soundbank found for voice type ${mb.Voice_Type} and language ${mb.Language}")
|
cbFail.accept("No soundbank found for voice type ${mb.Voice_Type} and language ${mb.Language}")
|
||||||
return
|
return
|
||||||
@@ -492,11 +523,13 @@ class MainExtension01 {
|
|||||||
fun Read_Queue_Paging(){
|
fun Read_Queue_Paging(){
|
||||||
db.queuepagingDB.Get()
|
db.queuepagingDB.Get()
|
||||||
for (qp in db.queuepagingDB.List) {
|
for (qp in db.queuepagingDB.List) {
|
||||||
println("Processing QueuePaging $qp")
|
println("Processing $qp")
|
||||||
if (qp.BroadcastZones.isNotBlank()) {
|
if (qp.BroadcastZones.isNotBlank()) {
|
||||||
val zz = qp.BroadcastZones.split(";")
|
val zz = qp.BroadcastZones.split(";")
|
||||||
if (AllBroadcastZonesValid(zz)) {
|
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") {
|
if (qp.Source == "PAGING") {
|
||||||
// nama file ada di Message
|
// nama file ada di Message
|
||||||
if (ValidFile(qp.Message)) {
|
if (ValidFile(qp.Message)) {
|
||||||
@@ -624,13 +657,15 @@ class MainExtension01 {
|
|||||||
fun Read_Queue_Table(){
|
fun Read_Queue_Table(){
|
||||||
db.queuetableDB.Get()
|
db.queuetableDB.Get()
|
||||||
db.queuetableDB.List.forEach { qa ->
|
db.queuetableDB.List.forEach { qa ->
|
||||||
println("Processing QueueTable $qa")
|
println("Processing $qa")
|
||||||
if (qa.BroadcastZones.isNotEmpty()) {
|
if (qa.BroadcastZones.isNotEmpty()) {
|
||||||
val zz = qa.BroadcastZones.split(";")
|
val zz = qa.BroadcastZones.split(";")
|
||||||
println("Broadcast zones: $zz")
|
|
||||||
if (AllBroadcastZonesValid(zz)) {
|
if (AllBroadcastZonesValid(zz)) {
|
||||||
println("All broadcast zones valid")
|
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")
|
println("All broadcast zones idle")
|
||||||
if (qa.Type == "SOUNDBANK") {
|
if (qa.Type == "SOUNDBANK") {
|
||||||
val variables = Get_Soundbank_Data(qa.SB_TAGS)
|
val variables = Get_Soundbank_Data(qa.SB_TAGS)
|
||||||
@@ -670,21 +705,36 @@ class MainExtension01 {
|
|||||||
|
|
||||||
val mblist = Get_MessageBank_by_id(ann_id, languages)
|
val mblist = Get_MessageBank_by_id(ann_id, languages)
|
||||||
if (mblist.isNotEmpty()) {
|
if (mblist.isNotEmpty()) {
|
||||||
|
val listafi = mutableListOf<AudioFileInfo>()
|
||||||
|
|
||||||
mblist.forEach { mb ->
|
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(), {
|
Get_Soundbank_Files(mb, variables ?: emptyMap(), {
|
||||||
listfile ->
|
listfile ->
|
||||||
val listafi = mutableListOf<AudioFileInfo>()
|
println("Got soundbank files: $listfile")
|
||||||
listfile.forEach { filenya ->
|
listfile.forEach { filenya ->
|
||||||
val afi = audioPlayer.LoadAudioFile(filenya)
|
val afi = audioPlayer.LoadAudioFile(filenya)
|
||||||
if (afi.isValid()) {
|
if (afi.isValid()) {
|
||||||
listafi.add(afi)
|
listafi.add(afi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
println("Loaded AudioFileInfo list: $listafi")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
err ->
|
||||||
|
db.Add_Log("AAS", err)
|
||||||
|
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listafi.isNotEmpty()){
|
||||||
val targetfile = SoundbankResult_directory.resolve(Make_WAV_FileName("Soundbank","")).toString()
|
val targetfile = SoundbankResult_directory.resolve(Make_WAV_FileName("Soundbank","")).toString()
|
||||||
|
println("Writing to target WAV file: $targetfile")
|
||||||
audioPlayer.WavWriter(listafi, targetfile
|
audioPlayer.WavWriter(listafi, targetfile
|
||||||
) { success, message ->
|
) { success, message ->
|
||||||
if (success) {
|
if (success) {
|
||||||
// file siap broadcast
|
// file siap broadcast
|
||||||
|
println("Successfully wrote WAV file: $targetfile")
|
||||||
val targetafi = audioPlayer.LoadAudioFile(targetfile)
|
val targetafi = audioPlayer.LoadAudioFile(targetfile)
|
||||||
if (targetafi.isValid()) {
|
if (targetafi.isValid()) {
|
||||||
zz.forEach { z1 ->
|
zz.forEach { z1 ->
|
||||||
@@ -701,15 +751,12 @@ class MainExtension01 {
|
|||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
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)
|
db.Add_Log("AAS", message)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
{
|
|
||||||
err ->
|
|
||||||
db.Add_Log("AAS", err)
|
|
||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// tidak ada messagebank dengan ann_id ini, delete from queue table
|
// tidak ada messagebank dengan ann_id ini, delete from queue table
|
||||||
@@ -783,7 +830,6 @@ class MainExtension01 {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ada broadcast zone yang tidak valid, delete from queue table
|
// ada broadcast zone yang tidak valid, delete from queue table
|
||||||
|
|||||||
@@ -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.
|
* @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>) {
|
fun WavWriter(sources: List<AudioFileInfo>, target: String, callback: BiConsumer<Boolean, String>) {
|
||||||
if (sources.isEmpty() || !ValidFile(target)) {
|
if (sources.isEmpty()) {
|
||||||
callback.accept(false, " Invalid sources")
|
callback.accept(false, " Invalid sources")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -324,9 +324,9 @@ class TCP_Android_Command_Server {
|
|||||||
VARMESSAGES.groupBy { it.ANN_ID }.forEach { (ann_id, value) ->
|
VARMESSAGES.groupBy { it.ANN_ID }.forEach { (ann_id, value) ->
|
||||||
result.append("MSG;").append(ann_id)
|
result.append("MSG;").append(ann_id)
|
||||||
result.append(";")
|
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(";")
|
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("@")
|
result.append("@")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ package content
|
|||||||
*/
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
enum class Language(name: String) {
|
enum class Language(name: String) {
|
||||||
INDONESIA("Indonesia"),
|
INDONESIA("INDONESIA"),
|
||||||
ENGLISH("English"),
|
ENGLISH("ENGLISH"),
|
||||||
LOCAL("Local"),
|
LOCAL("LOCAL"),
|
||||||
JAPANESE("Japanese"),
|
JAPANESE("JAPANESE"),
|
||||||
CHINESE("Chinese"),
|
CHINESE("CHINESE"),
|
||||||
ARABIC("Arabic");
|
ARABIC("ARABIC");
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user