commit 05/02/2026
This commit is contained in:
@@ -240,6 +240,7 @@ fun main(args: Array<String>) {
|
|||||||
_bc.bufferRemain = cmd.buffremain
|
_bc.bufferRemain = cmd.buffremain
|
||||||
_bc.statusData = cmd.statusdata
|
_bc.statusData = cmd.statusdata
|
||||||
_bc.commandsocket = _tcp
|
_bc.commandsocket = _tcp
|
||||||
|
_bc.BarixMode = cmd.isBarix
|
||||||
|
|
||||||
StreamerOutputs[cmd.ipaddress] = _bc
|
StreamerOutputs[cmd.ipaddress] = _bc
|
||||||
Logger.info { "Created new Streamer Output for channel ${_sc.channel} with IP ${cmd.ipaddress}" }
|
Logger.info { "Created new Streamer Output for channel ${_sc.channel} with IP ${cmd.ipaddress}" }
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import database.BroadcastZones
|
|||||||
import database.Messagebank
|
import database.Messagebank
|
||||||
import database.QueueTable
|
import database.QueueTable
|
||||||
import database.Soundbank
|
import database.Soundbank
|
||||||
|
|
||||||
import org.tinylog.Logger
|
import org.tinylog.Logger
|
||||||
import java.time.DayOfWeek
|
import java.time.DayOfWeek
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
@@ -37,60 +38,94 @@ import java.time.LocalTime
|
|||||||
*/
|
*/
|
||||||
class MainExtension01 {
|
class MainExtension01 {
|
||||||
|
|
||||||
|
data class InvalidZoneDetail(val zonename: String, val reason: String)
|
||||||
|
class CheckBroadcastZoneResult{
|
||||||
|
var allvalid: Boolean = false
|
||||||
|
var message : String? = null
|
||||||
|
var invalidzones: MutableList<InvalidZoneDetail> = mutableListOf()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* 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 CheckBroadcastZoneResult object containing allvalid flag and list of invalid zones
|
||||||
*/
|
*/
|
||||||
fun AllBroadcastZonesValid(bz: List<String>): Boolean {
|
fun AllBroadcastZonesValid(bz: List<String>): CheckBroadcastZoneResult {
|
||||||
|
val result = CheckBroadcastZoneResult()
|
||||||
if (bz.isNotEmpty()) {
|
if (bz.isNotEmpty()) {
|
||||||
val validbz = mutableListOf<BroadcastZones>()
|
val validbz = mutableListOf<BroadcastZones>()
|
||||||
db.broadcastDB.List.forEach { xx ->
|
bz.forEach { zz ->
|
||||||
if (ValidString(xx.description) && ValidString(xx.SoundChannel)){
|
if (ValidString(zz)){ // string tidak kosong
|
||||||
if (xx.description in bz) {
|
val findzone = db.broadcastDB.List.find { ValidString(it.description) && ValidString(it.SoundChannel) && zz.equals(it.description, true) }
|
||||||
db.soundchannelDB.List.forEach { sc ->
|
if (findzone!=null){ // ketemu zona dengan deskripsi sesuai
|
||||||
if (sc.channel == xx.SoundChannel){
|
val findsc = db.soundchannelDB.List.find { findzone.SoundChannel.equals(it.channel, true) && ValidIPV4(it.ip) }
|
||||||
if (ValidIPV4(sc.ip)){
|
if (findsc!=null){ // ketemu soundchannel dengan channel sesuai dan IP valid
|
||||||
validbz.add(xx)
|
// check apakah offline atau online
|
||||||
}
|
if (StreamerOutputs.containsKey(findsc.ip)){
|
||||||
}
|
val bc = StreamerOutputs[findsc.ip]
|
||||||
}
|
if (bc!=null && bc.isOnline()){
|
||||||
}
|
validbz.add(findzone)
|
||||||
|
} else result.invalidzones.add(InvalidZoneDetail(zz,"SoundChannel ${findzone.SoundChannel} with IP ${findsc.ip} is offline") )
|
||||||
|
} else result.invalidzones.add(InvalidZoneDetail(zz,"SoundChannel ${findzone.SoundChannel} with IP ${findsc.ip} is not connected in StreamerOutputs") )
|
||||||
|
} else result.invalidzones.add(InvalidZoneDetail(zz,"SoundChannel ${findzone.SoundChannel} not found or has invalid IP in SoundChannel table") )
|
||||||
|
} else result.invalidzones.add(InvalidZoneDetail(zz,"Zone $zz not found in BroadcastZones table") )
|
||||||
|
} else result.invalidzones.add(InvalidZoneDetail(zz,"Invalid broadcast zone string") )
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// db.broadcastDB.List.forEach { xx ->
|
||||||
//TODO buat log lebih informatif
|
// 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)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else result.invalidzones.add(InvalidZoneDetail(xx.description,"Invalid description or SoundChannel") )
|
||||||
|
// }
|
||||||
if (validbz.size == bz.size) {
|
if (validbz.size == bz.size) {
|
||||||
return true
|
result.allvalid = true
|
||||||
} else Logger.error { "Some requested broadcast zones are not registered in BroadcastZone table" }
|
result.message = "All requested broadcast zones are valid"
|
||||||
} else Logger.error { "No Broadcast Zones checked for validity" }
|
} else {
|
||||||
return false
|
result.message = "Some requested broadcast zones are not registered in BroadcastZone table"
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
result.message = "No Broadcast Zones checked for validity"
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fungsi untuk cek apakah semua Streamer Output idle
|
* Fungsi untuk cek apakah semua Streamer Output idle
|
||||||
* @param bz List of ip address
|
* @param bz List of ip address
|
||||||
* @return true jika semua idle, false jika ada yang tidak idle
|
* @return ChannelIdleResult object containing allidle flag and message
|
||||||
*/
|
*/
|
||||||
fun AllStreamerOutputIdle(bz: List<String>): Boolean {
|
fun AllStreamerOutputIdle(bz: List<String>) : Boolean {
|
||||||
if (bz.isNotEmpty()) {
|
if (bz.isNotEmpty()) {
|
||||||
if (StreamerOutputs.isNotEmpty()){
|
val idlebz = mutableSetOf<String>()
|
||||||
val idlebz = mutableListOf<String>()
|
val missingbz = mutableSetOf<String>()
|
||||||
|
fun add_idle(ip: String) {
|
||||||
|
idlebz.add(ip)
|
||||||
|
missingbz.remove(ip)
|
||||||
|
}
|
||||||
|
fun add_missing(ip: String) {
|
||||||
|
idlebz.remove(ip)
|
||||||
|
missingbz.add(ip)
|
||||||
|
}
|
||||||
|
|
||||||
bz.forEach { z1 ->
|
bz.forEach { z1 ->
|
||||||
val so = StreamerOutputs.values.find { it.ipaddress == z1 }
|
val so = StreamerOutputs.values.find { it.ipaddress == z1 }
|
||||||
if (so != null) {
|
if (so != null) {
|
||||||
if (so.isIdle()) {
|
if (so.isIdle()) add_idle(z1) else add_missing(z1)
|
||||||
idlebz.add(z1)
|
} else add_missing(z1)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
return idlebz.size == bz.size
|
||||||
if (idlebz.size == bz.size) {
|
} else return false
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -561,7 +596,7 @@ class MainExtension01 {
|
|||||||
return Result_GetSoundbankFiles(true, "Success", files)
|
return Result_GetSoundbankFiles(true, "Success", files)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Read_Queue_Paging() : Boolean{
|
fun Read_Queue_Paging() {
|
||||||
db.queuepagingDB.Get()
|
db.queuepagingDB.Get()
|
||||||
val list = db.queuepagingDB.List
|
val list = db.queuepagingDB.List
|
||||||
.filter { it.Type.equals("PAGING",true) }
|
.filter { it.Type.equals("PAGING",true) }
|
||||||
@@ -571,7 +606,8 @@ class MainExtension01 {
|
|||||||
if (qp.BroadcastZones.isNotBlank()){
|
if (qp.BroadcastZones.isNotBlank()){
|
||||||
if (ValidFile(qp.Message)){
|
if (ValidFile(qp.Message)){
|
||||||
val zz = qp.BroadcastZones.split(";")
|
val zz = qp.BroadcastZones.split(";")
|
||||||
if (AllBroadcastZonesValid(zz)){
|
AllBroadcastZonesValid(zz).let{ checkresult ->
|
||||||
|
if (checkresult.allvalid){
|
||||||
val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
||||||
if (AllStreamerOutputIdle(ips)){
|
if (AllStreamerOutputIdle(ips)){
|
||||||
val afi = audioPlayer.LoadAudioFile(qp.Message)
|
val afi = audioPlayer.LoadAudioFile(qp.Message)
|
||||||
@@ -595,25 +631,69 @@ class MainExtension01 {
|
|||||||
db.logDB.Add("AAS", logmessage)
|
db.logDB.Add("AAS", logmessage)
|
||||||
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
db.queuepagingDB.Resort()
|
db.queuepagingDB.Resort()
|
||||||
return true
|
|
||||||
} else {
|
} else {
|
||||||
// file tidak valid, delete from queue paging
|
// file tidak valid, delete from queue paging
|
||||||
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
db.queuepagingDB.Resort()
|
db.queuepagingDB.Resort()
|
||||||
db.logDB.Add(
|
db.logDB.Add(
|
||||||
"AAS",
|
"AAS",
|
||||||
"Cancelled paging message $qp due to invalid audio file"
|
"Canceled paging message $qp due to invalid audio file"
|
||||||
)
|
)
|
||||||
Logger.error { "Cancelled paging message $qp due to invalid audio file" }
|
Logger.error { "Canceled paging message $qp due to invalid audio file" }
|
||||||
}
|
}
|
||||||
} // kalau enggak semua streamer idle, skip dulu
|
} // kalau enggak semua streamer idle, skip dulu
|
||||||
} else {
|
} else {
|
||||||
// ada broadcast zone yang tidak valid, delete from queue paging
|
checkresult.invalidzones.forEach { iz ->
|
||||||
|
Logger.error { "Cancelled paging message $qp due to invalid broadcast zone '${iz.zonename}': ${iz.reason}" }
|
||||||
|
}
|
||||||
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
db.queuepagingDB.Resort()
|
db.queuepagingDB.Resort()
|
||||||
db.logDB.Add("AAS", "Cancelled paging message $qp due to invalid broadcast zone")
|
return@forEach
|
||||||
Logger.error { "Cancelled paging message $qp due to invalid broadcast zone" }
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// if (AllBroadcastZonesValid(zz)){
|
||||||
|
// val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
||||||
|
// if (AllStreamerOutputIdle(ips)){
|
||||||
|
// val afi = audioPlayer.LoadAudioFile(qp.Message)
|
||||||
|
// if (afi.isValid()){
|
||||||
|
// // file bisa di load, kirim ke masing-masing Streamer Output by IP address
|
||||||
|
// Activate_Relays(zz)
|
||||||
|
// ips.forEach { ip ->
|
||||||
|
// // send byte array to streamer output
|
||||||
|
// StreamerOutputs[ip]?.SendData(afi.bytes,
|
||||||
|
// {
|
||||||
|
// Deactivate_Relays(zz)
|
||||||
|
// db.logDB.Add("AAS", it) },
|
||||||
|
// {
|
||||||
|
// Deactivate_Relays(zz)
|
||||||
|
// db.logDB.Add("AAS", it) })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val logmessage =
|
||||||
|
// "Broadcast started PAGING with Filename '${qp.Message}' to zones: ${qp.BroadcastZones}"
|
||||||
|
// Logger.info { logmessage }
|
||||||
|
// db.logDB.Add("AAS", logmessage)
|
||||||
|
// db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
|
// db.queuepagingDB.Resort()
|
||||||
|
// return true
|
||||||
|
// } else {
|
||||||
|
// // file tidak valid, delete from queue paging
|
||||||
|
// db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
|
// db.queuepagingDB.Resort()
|
||||||
|
// db.logDB.Add(
|
||||||
|
// "AAS",
|
||||||
|
// "Canceled paging message $qp due to invalid audio file"
|
||||||
|
// )
|
||||||
|
// Logger.error { "Canceled paging message $qp due to invalid audio file" }
|
||||||
|
// }
|
||||||
|
// } // kalau enggak semua streamer idle, skip dulu
|
||||||
|
// } else {
|
||||||
|
// // ada broadcast zone yang tidak valid, delete from queue paging
|
||||||
|
// db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
|
// db.queuepagingDB.Resort()
|
||||||
|
// db.logDB.Add("AAS", "Cancelled paging message $qp due to invalid broadcast zone")
|
||||||
|
// Logger.error { "Canceled paging message $qp due to invalid broadcast zone" }
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
// file tidak valid, delete from queue paging
|
// file tidak valid, delete from queue paging
|
||||||
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
@@ -632,10 +712,9 @@ class MainExtension01 {
|
|||||||
Logger.error { "Cancelled paging message $qp due to empty broadcast zone" }
|
Logger.error { "Cancelled paging message $qp due to empty broadcast zone" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Read_Queue_Shalat() : Boolean{
|
fun Read_Queue_Shalat() {
|
||||||
db.queuepagingDB.Get()
|
db.queuepagingDB.Get()
|
||||||
val list = db.queuepagingDB.List
|
val list = db.queuepagingDB.List
|
||||||
.filter { it.Type.equals("SHALAT",true) }
|
.filter { it.Type.equals("SHALAT",true) }
|
||||||
@@ -643,10 +722,12 @@ class MainExtension01 {
|
|||||||
//println("Processing $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)){
|
AllBroadcastZonesValid(zz).let { checkresult ->
|
||||||
|
if (checkresult.allvalid){
|
||||||
val ann_id = Get_ANN_ID(qp.Message)
|
val ann_id = Get_ANN_ID(qp.Message)
|
||||||
if (ann_id>0){
|
if (ann_id>0){
|
||||||
val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
||||||
|
|
||||||
if (AllStreamerOutputIdle(ips)){
|
if (AllStreamerOutputIdle(ips)){
|
||||||
val mblist = Get_MessageBank_by_id(ann_id, listOf(Language.INDONESIA.name))
|
val mblist = Get_MessageBank_by_id(ann_id, listOf(Language.INDONESIA.name))
|
||||||
if (mblist.isNotEmpty()) {
|
if (mblist.isNotEmpty()) {
|
||||||
@@ -701,7 +782,6 @@ class MainExtension01 {
|
|||||||
db.logDB.Add("AAS", logmsg)
|
db.logDB.Add("AAS", logmsg)
|
||||||
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
db.queuepagingDB.Resort()
|
db.queuepagingDB.Resort()
|
||||||
return true
|
|
||||||
} else {
|
} else {
|
||||||
db.logDB.Add(
|
db.logDB.Add(
|
||||||
"AAS",
|
"AAS",
|
||||||
@@ -737,12 +817,113 @@ class MainExtension01 {
|
|||||||
Logger.error { "Cancelled shalat message $qp due to invalid ANN_ID" }
|
Logger.error { "Cancelled shalat message $qp due to invalid ANN_ID" }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ada broadcast zone yang tidak valid, delete from queue paging
|
checkresult.invalidzones.forEach { iz ->
|
||||||
|
Logger.error { "Cancelled shalat message $qp due to invalid broadcast zone '${iz.zonename}': ${iz.reason}" }
|
||||||
|
}
|
||||||
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
db.queuepagingDB.Resort()
|
db.queuepagingDB.Resort()
|
||||||
db.logDB.Add("AAS", "Cancelled shalat message $qp due to invalid broadcast zone")
|
|
||||||
Logger.error { "Cancelled shalat message $qp due to invalid broadcast zone" }
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// if (AllBroadcastZonesValid(zz)){
|
||||||
|
// val ann_id = Get_ANN_ID(qp.Message)
|
||||||
|
// if (ann_id>0){
|
||||||
|
// val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
||||||
|
// if (AllStreamerOutputIdle(ips)){
|
||||||
|
// val mblist = Get_MessageBank_by_id(ann_id, listOf(Language.INDONESIA.name))
|
||||||
|
// if (mblist.isNotEmpty()) {
|
||||||
|
// mblist.forEach { mb ->
|
||||||
|
// val result = Get_Soundbank_Files(mb, emptyMap())
|
||||||
|
// if (result.success){
|
||||||
|
// val listafi = mutableListOf<AudioFileInfo>()
|
||||||
|
// result.files.forEach { filenya ->
|
||||||
|
// val afi = contentCache.getAudioFile(filenya)
|
||||||
|
// if (afi!=null && afi.isValid()){
|
||||||
|
// listafi.add(afi)
|
||||||
|
// } else {
|
||||||
|
// val afi = audioPlayer.LoadAudioFile(filenya)
|
||||||
|
// if (afi.isValid()) {
|
||||||
|
// listafi.add(afi)
|
||||||
|
// contentCache.addAudioFile(filenya, afi)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// val targetfile = SoundbankResult_directory.resolve(
|
||||||
|
// Make_WAV_FileName(
|
||||||
|
// "Shalat",
|
||||||
|
// ""
|
||||||
|
// )
|
||||||
|
// ).toString()
|
||||||
|
//
|
||||||
|
// val result =audioPlayer.WavWriter(
|
||||||
|
// listafi,
|
||||||
|
// targetfile, true,
|
||||||
|
// )
|
||||||
|
// db.logDB.Add("AAS", result.message)
|
||||||
|
// if (result.success) {
|
||||||
|
// // file siap broadcast
|
||||||
|
// val targetafi = audioPlayer.LoadAudioFile(targetfile)
|
||||||
|
// if (targetafi.isValid()) {
|
||||||
|
// // activate relays from broadcast zone
|
||||||
|
// Activate_Relays(zz)
|
||||||
|
// ips.forEach { ip ->
|
||||||
|
// // send byte array to streamer output
|
||||||
|
// StreamerOutputs[ip]?.SendData(targetafi.bytes,
|
||||||
|
// {
|
||||||
|
// Deactivate_Relays(zz)
|
||||||
|
// db.logDB.Add("AAS", it) },
|
||||||
|
// {
|
||||||
|
// Deactivate_Relays(zz)
|
||||||
|
// db.logDB.Add("AAS", it) })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val logmsg =
|
||||||
|
// "Broadcast started SHALAT message with generated file '$targetfile' to zones: ${qp.BroadcastZones}"
|
||||||
|
// Logger.info { logmsg }
|
||||||
|
// db.logDB.Add("AAS", logmsg)
|
||||||
|
// db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
|
// db.queuepagingDB.Resort()
|
||||||
|
// return true
|
||||||
|
// } else {
|
||||||
|
// db.logDB.Add(
|
||||||
|
// "AAS",
|
||||||
|
// "Failed to load generated Shalat WAV file $targetfile"
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else{
|
||||||
|
// db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
|
// db.queuepagingDB.Resort()
|
||||||
|
// db.logDB.Add("AAS", result.message)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
// // tidak ada messagebank dengan ann_id ini, delete from queue paging
|
||||||
|
// db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
|
// db.queuepagingDB.Resort()
|
||||||
|
// db.logDB.Add(
|
||||||
|
// "AAS",
|
||||||
|
// "Canceled Shalat message $qp due to ANN_ID $ann_id not found in Messagebank"
|
||||||
|
// )
|
||||||
|
// Logger.error { "Canceled Shalat message $qp due to ANN_ID $ann_id not found in Messagebank" }
|
||||||
|
// }
|
||||||
|
// } // kalau enggak semua streamer idle, skip dulu
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
// // invalid ann_id, delete from queue paging
|
||||||
|
// db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
|
// db.queuepagingDB.Resort()
|
||||||
|
// db.logDB.Add("AAS", "Cancelled shalat message $qp due to invalid ANN_ID")
|
||||||
|
// Logger.error { "Canceled shalat message $qp due to invalid ANN_ID" }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // ada broadcast zone yang tidak valid, delete from queue paging
|
||||||
|
// db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
|
// db.queuepagingDB.Resort()
|
||||||
|
// db.logDB.Add("AAS", "Cancelled shalat message $qp due to invalid broadcast zone")
|
||||||
|
// Logger.error { "Canceled shalat message $qp due to invalid broadcast zone" }
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
// invalid broadcast zone, delete from queue paging
|
// invalid broadcast zone, delete from queue paging
|
||||||
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
db.queuepagingDB.DeleteByIndex(qp.index.toInt())
|
||||||
@@ -751,20 +932,21 @@ class MainExtension01 {
|
|||||||
Logger.error { "Cancelled shalat message $qp due to empty broadcast zone" }
|
Logger.error { "Cancelled shalat message $qp due to empty broadcast zone" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Read_Queue_Timer() : Boolean{
|
fun Read_Queue_Timer() {
|
||||||
db.queuetableDB.Get()
|
db.queuetableDB.Get()
|
||||||
val list = db.queuetableDB.List.filter { it.Type.equals("TIMER",true) }
|
val list = db.queuetableDB.List.filter { it.Type.equals("TIMER",true) }
|
||||||
list.forEach { qa ->
|
list.forEach { qa ->
|
||||||
//println("Processing $qa")
|
//println("Processing $qa")
|
||||||
if (qa.BroadcastZones.isNotEmpty()){
|
if (qa.BroadcastZones.isNotEmpty()){
|
||||||
val zz = qa.BroadcastZones.split(";")
|
val zz = qa.BroadcastZones.split(";")
|
||||||
if (AllBroadcastZonesValid(zz)){
|
AllBroadcastZonesValid(zz).let { checkresult ->
|
||||||
|
if (checkresult.allvalid){
|
||||||
val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
||||||
val ann_id = Get_ANN_ID(qa.SB_TAGS)
|
val ann_id = Get_ANN_ID(qa.SB_TAGS)
|
||||||
if (ann_id>0){
|
if (ann_id>0){
|
||||||
|
|
||||||
if (AllStreamerOutputIdle(ips)){
|
if (AllStreamerOutputIdle(ips)){
|
||||||
val mblist = Get_MessageBank_by_id(ann_id, qa.Language.split(";"))
|
val mblist = Get_MessageBank_by_id(ann_id, qa.Language.split(";"))
|
||||||
if (mblist.isNotEmpty()) {
|
if (mblist.isNotEmpty()) {
|
||||||
@@ -812,7 +994,6 @@ class MainExtension01 {
|
|||||||
db.logDB.Add("AAS", logmsg)
|
db.logDB.Add("AAS", logmsg)
|
||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
db.queuetableDB.Resort()
|
db.queuetableDB.Resort()
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
} else{
|
} else{
|
||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
@@ -846,12 +1027,105 @@ class MainExtension01 {
|
|||||||
Logger.error { "Cancelled TIMER message $qa due to invalid ANN_ID" }
|
Logger.error { "Cancelled TIMER message $qa due to invalid ANN_ID" }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ada broadcast zone yang tidak valid, delete from queue table
|
checkresult.invalidzones.forEach { iz ->
|
||||||
|
Logger.error { "Cancelled TIMER message $qa due to invalid broadcast zone '${iz.zonename}': ${iz.reason}" }
|
||||||
|
}
|
||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
db.queuetableDB.Resort()
|
db.queuetableDB.Resort()
|
||||||
db.logDB.Add("AAS", "Cancelled TIMER message $qa due to invalid broadcast zone")
|
return@forEach
|
||||||
Logger.error {"Cancelled TIMER message $qa due to invalid broadcast zone"}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// if (AllBroadcastZonesValid(zz)){
|
||||||
|
// val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
||||||
|
// val ann_id = Get_ANN_ID(qa.SB_TAGS)
|
||||||
|
// if (ann_id>0){
|
||||||
|
// if (AllStreamerOutputIdle(ips)){
|
||||||
|
// val mblist = Get_MessageBank_by_id(ann_id, qa.Language.split(";"))
|
||||||
|
// if (mblist.isNotEmpty()) {
|
||||||
|
// mblist.forEach {
|
||||||
|
// mb ->
|
||||||
|
// val result = Get_Soundbank_Files(mb, emptyMap())
|
||||||
|
// if (result.success){
|
||||||
|
// val listafi = mutableListOf<AudioFileInfo>()
|
||||||
|
// result.files.forEach { filenya ->
|
||||||
|
// val afi = contentCache.getAudioFile(filenya)
|
||||||
|
// if (afi!=null && afi.isValid()){
|
||||||
|
// listafi.add(afi)
|
||||||
|
// } else {
|
||||||
|
// val afi = audioPlayer.LoadAudioFile(filenya)
|
||||||
|
// if (afi.isValid()) {
|
||||||
|
// listafi.add(afi)
|
||||||
|
// contentCache.addAudioFile(filenya, afi)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// val targetfile = SoundbankResult_directory.resolve(Make_WAV_FileName("Timer","")).toString()
|
||||||
|
// val result = audioPlayer.WavWriter(listafi, targetfile, true)
|
||||||
|
// db.logDB.Add("AAS", result.message)
|
||||||
|
// if (result.success){
|
||||||
|
// // file siap broadcast
|
||||||
|
// val targetafi = audioPlayer.LoadAudioFile(targetfile)
|
||||||
|
// if (targetafi.isValid()) {
|
||||||
|
// // activate relays from broadcast zone
|
||||||
|
// Activate_Relays(zz)
|
||||||
|
// ips.forEach { ip ->
|
||||||
|
// // send byte array to streamer output
|
||||||
|
// StreamerOutputs[ip]?.SendData(targetafi.bytes,
|
||||||
|
// {
|
||||||
|
// Deactivate_Relays(zz)
|
||||||
|
// db.logDB.Add("AAS", it) },
|
||||||
|
// {
|
||||||
|
// Deactivate_Relays(zz)
|
||||||
|
// db.logDB.Add("AAS", it) })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val logmsg =
|
||||||
|
// "Broadcast started TIMER message with generated file '$targetfile' to zones: ${qa.BroadcastZones}"
|
||||||
|
// Logger.info { logmsg }
|
||||||
|
// db.logDB.Add("AAS", logmsg)
|
||||||
|
// db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// db.queuetableDB.Resort()
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
// } else{
|
||||||
|
// db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// db.queuetableDB.Resort()
|
||||||
|
// db.logDB.Add("AAS", result.message)
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// db.queuetableDB.Resort()
|
||||||
|
// db.logDB.Add("AAS", result.message)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
// // tidak ada messagebank dengan ann_id ini, delete from queue table
|
||||||
|
// db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// db.queuetableDB.Resort()
|
||||||
|
// db.logDB.Add(
|
||||||
|
// "AAS",
|
||||||
|
// "Cancelled TIMER $qa due to ANN_ID $ann_id not found in Messagebank"
|
||||||
|
// )
|
||||||
|
// Logger.error { "Cancelled TIMER $qa due to ANN_ID $ann_id not found in Messagebank" }
|
||||||
|
// }
|
||||||
|
// } // kalau enggak semua streamer idle, skip dulu
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
// // invalid ann_id, delete from queue table
|
||||||
|
// db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// db.queuetableDB.Resort()
|
||||||
|
// db.logDB.Add("AAS", "Cancelled TIMER message $qa due to invalid ANN_ID")
|
||||||
|
// Logger.error { "Cancelled TIMER message $qa due to invalid ANN_ID" }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // ada broadcast zone yang tidak valid, delete from queue table
|
||||||
|
// db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// db.queuetableDB.Resort()
|
||||||
|
// db.logDB.Add("AAS", "Cancelled TIMER message $qa due to invalid broadcast zone")
|
||||||
|
// Logger.error {"Cancelled TIMER message $qa due to invalid broadcast zone"}
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
// invalid broadcast zone, delete from queue table
|
// invalid broadcast zone, delete from queue table
|
||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
@@ -860,7 +1134,6 @@ class MainExtension01 {
|
|||||||
Logger.error { "Cancelled TIMER message $qa due to empty broadcast zone" }
|
Logger.error { "Cancelled TIMER message $qa due to empty broadcast zone" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Activate_Relays(zz: List<String>){
|
fun Activate_Relays(zz: List<String>){
|
||||||
@@ -897,15 +1170,17 @@ class MainExtension01 {
|
|||||||
/**
|
/**
|
||||||
* Read and process Queue_Table table for SOUNDBANK type messages.
|
* Read and process Queue_Table table for SOUNDBANK type messages.
|
||||||
*/
|
*/
|
||||||
fun Read_Queue_Soundbank() : Boolean{
|
fun Read_Queue_Soundbank() {
|
||||||
db.queuetableDB.Get()
|
db.queuetableDB.Get()
|
||||||
val list = db.queuetableDB.List.filter { it.Type.equals("SOUNDBANK",true) }
|
val list = db.queuetableDB.List.filter { it.Type.equals("SOUNDBANK",true) }
|
||||||
list.forEach { qa ->
|
list.forEach { qa ->
|
||||||
//println("Processing $qa")
|
//println("Processing $qa")
|
||||||
if (qa.BroadcastZones.isNotEmpty()){
|
if (qa.BroadcastZones.isNotEmpty()){
|
||||||
val zz = qa.BroadcastZones.split(";")
|
val zz = qa.BroadcastZones.split(";")
|
||||||
if (AllBroadcastZonesValid(zz)){
|
AllBroadcastZonesValid(zz).let { checkresult ->
|
||||||
|
if (checkresult.allvalid){
|
||||||
val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
||||||
|
|
||||||
if (AllStreamerOutputIdle(ips)) {
|
if (AllStreamerOutputIdle(ips)) {
|
||||||
val variables = Get_Soundbank_Data(qa.SB_TAGS)
|
val variables = Get_Soundbank_Data(qa.SB_TAGS)
|
||||||
val languages = qa.Language.split(";")
|
val languages = qa.Language.split(";")
|
||||||
@@ -986,16 +1261,18 @@ class MainExtension01 {
|
|||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Logger.error{"Failed to get soundbank files for ANN_ID $ann_id: ${result.message}"}
|
||||||
db.logDB.Add("AAS", result.message)
|
db.logDB.Add("AAS", result.message)
|
||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
|
||||||
db.queuetableDB.Resort()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
db.queuetableDB.Resort()
|
||||||
|
|
||||||
if (listafi.isNotEmpty()){
|
if (listafi.isNotEmpty()){
|
||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
|
||||||
db.queuetableDB.Resort()
|
|
||||||
// bikin nama file ada postifx nya dari SB_TAGS, tapi spasi diganti underscore
|
// bikin nama file ada postifx nya dari SB_TAGS, tapi spasi diganti underscore
|
||||||
// dan titik dua diganti dash
|
// dan titik dua diganti dash
|
||||||
val postfix = qa.SB_TAGS.replace(" ","_").replace(":","-")
|
val postfix = qa.SB_TAGS.replace(" ","_").replace(":","-")
|
||||||
@@ -1027,7 +1304,6 @@ class MainExtension01 {
|
|||||||
Logger.info { logmsg }
|
Logger.info { logmsg }
|
||||||
db.logDB.Add("AAS", logmsg)
|
db.logDB.Add("AAS", logmsg)
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
@@ -1035,6 +1311,12 @@ class MainExtension01 {
|
|||||||
db.logDB.Add("AAS", result.message)
|
db.logDB.Add("AAS", result.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
db.logDB.Add(
|
||||||
|
"AAS",
|
||||||
|
"Cancelled SOUNDBANK message $qa due to no valid soundbank files generated for ANN_ID $ann_id"
|
||||||
|
)
|
||||||
|
Logger.error { "Cancelled SOUNDBANK message $qa due to no valid soundbank files generated for ANN_ID $ann_id" }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// tidak ada messagebank dengan ann_id ini, delete from queue table
|
// tidak ada messagebank dengan ann_id ini, delete from queue table
|
||||||
@@ -1045,17 +1327,180 @@ class MainExtension01 {
|
|||||||
"Cancelled SOUNDBANK message $qa due to ANN_ID $ann_id not found in Messagebank"
|
"Cancelled SOUNDBANK message $qa due to ANN_ID $ann_id not found in Messagebank"
|
||||||
)
|
)
|
||||||
Logger.error { "Cancelled SOUNDBANK message $qa due to ANN_ID $ann_id not found in Messagebank" }
|
Logger.error { "Cancelled SOUNDBANK message $qa due to ANN_ID $ann_id not found in Messagebank" }
|
||||||
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// ada broadcast zone yang tidak valid, delete from queue table
|
checkresult.invalidzones.forEach { iz ->
|
||||||
|
Logger.error { "Cancelled SOUNDBANK message $qa due to invalid broadcast zone '${iz.zonename}': ${iz.reason}" }
|
||||||
|
}
|
||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
db.queuetableDB.Resort()
|
db.queuetableDB.Resort()
|
||||||
db.logDB.Add("AAS", "Cancelled SOUNDBANK message $qa due to invalid broadcast zone")
|
return@forEach
|
||||||
Logger.error { "Cancelled SOUNDBANK message $qa due to invalid broadcast zone" }
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// if (AllBroadcastZonesValid(zz)){
|
||||||
|
// val ips = BroadcastZones_to_SoundChannel_IP(zz)
|
||||||
|
// if (AllStreamerOutputIdle(ips)) {
|
||||||
|
// val variables = Get_Soundbank_Data(qa.SB_TAGS)
|
||||||
|
// val languages = qa.Language.split(";")
|
||||||
|
// // cek apakah ANN_ID ada di SB_TAGS
|
||||||
|
// if (variables!=null){
|
||||||
|
// Logger.info{"SB_TAGS variables: $variables"}
|
||||||
|
// } else{
|
||||||
|
// Logger.info{"No SB_TAGS variables found"}
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// var ann_id = variables?.get("ANN_ID")?.toIntOrNull() ?: 0
|
||||||
|
//
|
||||||
|
// if (ann_id==0){
|
||||||
|
// // not available from variables, try to get from Message column
|
||||||
|
// // ada ini, karena protokol FIS dulu tidak ada ANN_ID tapi pake Remark
|
||||||
|
// val remark = variables?.get("REMARK").orEmpty()
|
||||||
|
// db.logDB.Add("AAS", "Trying to get ANN_ID from REMARK field: $remark")
|
||||||
|
// Logger.info{ "Trying to get ANN_ID from REMARK field: $remark" }
|
||||||
|
// when(remark){
|
||||||
|
// "GOP" -> {
|
||||||
|
// val remarkMsg = config.Get(configKeys.REMARK_GOP.key)
|
||||||
|
// Logger.info{"Remark message for GOP: $remarkMsg"}
|
||||||
|
// ann_id = Regex("\\[(\\d+)]").find(remarkMsg)?.value?.toIntOrNull() ?: 0
|
||||||
|
// }
|
||||||
|
// "GBD" ->{
|
||||||
|
// val remarkMsg = config.Get(configKeys.REMARK_GBD.key)
|
||||||
|
// Logger.info{"Remark message for GBD: $remarkMsg"}
|
||||||
|
// ann_id = Regex("\\[(\\d+)]").find(remarkMsg)?.value?.toIntOrNull() ?: 0
|
||||||
|
// }
|
||||||
|
// "GFC" ->{
|
||||||
|
// val remarkMsg = config.Get(configKeys.REMARK_GFC.key)
|
||||||
|
// Logger.info{"Remark message for GFC: $remarkMsg"}
|
||||||
|
// ann_id = Regex("\\[(\\d+)]").find(remarkMsg)?.value?.toIntOrNull() ?: 0
|
||||||
|
// }
|
||||||
|
// "FLD" ->{
|
||||||
|
// val remarkMsg = config.Get(configKeys.REMARK_FLD.key)
|
||||||
|
// Logger.info{"Remark message for FLD: $remarkMsg"}
|
||||||
|
// ann_id = Regex("\\[(\\d+)]").find(remarkMsg)?.value?.toIntOrNull() ?: 0
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Logger.info{"Found ANN_ID from REMARK field: $ann_id" }
|
||||||
|
// db.logDB.Add("AAS", "Found ANN_ID from REMARK field: $ann_id")
|
||||||
|
// } else {
|
||||||
|
// db.logDB.Add("AAS", "Found ANN_ID from SB_TAGS variables: $ann_id")
|
||||||
|
// Logger.info{ "Found ANN_ID from SB_TAGS variables: $ann_id" }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // recheck again
|
||||||
|
// if (ann_id == 0) {
|
||||||
|
// db.logDB.Add(
|
||||||
|
// "AAS",
|
||||||
|
// "Cancelled SOUNDBANK message $qa due to missing or invalid ANN_ID in SB_TAGS"
|
||||||
|
// )
|
||||||
|
// db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// db.queuetableDB.Resort()
|
||||||
|
// return@forEach
|
||||||
|
// }
|
||||||
|
// // sampe sini punya ann_id valid
|
||||||
|
//
|
||||||
|
// val mblist = Get_MessageBank_by_id(ann_id, languages)
|
||||||
|
// if (mblist.isNotEmpty()) {
|
||||||
|
// val listafi = mutableListOf<AudioFileInfo>()
|
||||||
|
//
|
||||||
|
// mblist.forEach { mb ->
|
||||||
|
// val result = Get_Soundbank_Files(mb, variables ?: emptyMap())
|
||||||
|
// if (result.success){
|
||||||
|
// result.files.forEach { filenya ->
|
||||||
|
// val afi = contentCache.getAudioFile(filenya)
|
||||||
|
// if (afi!=null && afi.isValid()){
|
||||||
|
// listafi.add(afi)
|
||||||
|
// } else {
|
||||||
|
// val afi = audioPlayer.LoadAudioFile(filenya)
|
||||||
|
// if (afi.isValid()) {
|
||||||
|
// listafi.add(afi)
|
||||||
|
// contentCache.addAudioFile(filenya, afi)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// Logger.error{"Failed to get soundbank files for ANN_ID $ann_id: ${result.message}"}
|
||||||
|
// db.logDB.Add("AAS", result.message)
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// db.queuetableDB.Resort()
|
||||||
|
//
|
||||||
|
// if (listafi.isNotEmpty()){
|
||||||
|
//
|
||||||
|
// // bikin nama file ada postifx nya dari SB_TAGS, tapi spasi diganti underscore
|
||||||
|
// // dan titik dua diganti dash
|
||||||
|
// val postfix = qa.SB_TAGS.replace(" ","_").replace(":","-")
|
||||||
|
// val targetfile = SoundbankResult_directory.resolve(Make_WAV_FileName("${qa.Source}_${qa.Type}",postfix)).toString()
|
||||||
|
// //println("Writing to target WAV file: $targetfile")
|
||||||
|
// val result = audioPlayer.WavWriter(listafi, targetfile, true)
|
||||||
|
// if (result.success){
|
||||||
|
// // file siap broadcast
|
||||||
|
// //println("Successfully wrote WAV file: $targetfile")
|
||||||
|
// val targetafi = audioPlayer.LoadAudioFile(targetfile)
|
||||||
|
// if (targetafi.isValid()) {
|
||||||
|
// // activate relays from broadcast zone
|
||||||
|
// Activate_Relays(zz)
|
||||||
|
// ips.forEach { ip ->
|
||||||
|
// // send byte array to streamer output
|
||||||
|
// StreamerOutputs[ip]?.SendData(targetafi.bytes,
|
||||||
|
// {
|
||||||
|
// Deactivate_Relays(zz)
|
||||||
|
// db.logDB.Add("AAS", it)
|
||||||
|
//
|
||||||
|
// }, {
|
||||||
|
// Deactivate_Relays(zz)
|
||||||
|
// db.logDB.Add("AAS", it)
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val logmsg =
|
||||||
|
// "Broadcast started SOUNDBANK message with generated file '$targetfile' to zones: ${qa.BroadcastZones}"
|
||||||
|
// Logger.info { logmsg }
|
||||||
|
// db.logDB.Add("AAS", logmsg)
|
||||||
|
//
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// db.queuetableDB.Resort()
|
||||||
|
// db.logDB.Add("AAS", result.message)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
// db.logDB.Add(
|
||||||
|
// "AAS",
|
||||||
|
// "Cancelled SOUNDBANK message $qa due to no valid soundbank files generated for ANN_ID $ann_id"
|
||||||
|
// )
|
||||||
|
// Logger.error { "Cancelled SOUNDBANK message $qa due to no valid soundbank files generated for ANN_ID $ann_id" }
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// // tidak ada messagebank dengan ann_id ini, delete from queue table
|
||||||
|
// db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// db.queuetableDB.Resort()
|
||||||
|
// db.logDB.Add(
|
||||||
|
// "AAS",
|
||||||
|
// "Cancelled SOUNDBANK message $qa due to ANN_ID $ann_id not found in Messagebank"
|
||||||
|
// )
|
||||||
|
// Logger.error { "Cancelled SOUNDBANK message $qa due to ANN_ID $ann_id not found in Messagebank" }
|
||||||
|
// return@forEach
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } else {
|
||||||
|
// // ada broadcast zone yang tidak valid, delete from queue table
|
||||||
|
// db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
|
// db.queuetableDB.Resort()
|
||||||
|
// db.logDB.Add("AAS", "Cancelled SOUNDBANK message $qa due to invalid broadcast zone")
|
||||||
|
// Logger.error { "Cancelled SOUNDBANK message $qa due to invalid broadcast zone" }
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
// invalid broadcast zone, delete from queue table
|
// invalid broadcast zone, delete from queue table
|
||||||
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
db.queuetableDB.DeleteByIndex(qa.index.toInt())
|
||||||
@@ -1064,7 +1509,6 @@ class MainExtension01 {
|
|||||||
Logger.error { "Cancelled SOUNDBANK message $qa due to empty broadcast zone" }
|
Logger.error { "Cancelled SOUNDBANK message $qa due to empty broadcast zone" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import java.net.InetSocketAddress
|
|||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
|
import kotlin.experimental.or
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class BarixConnection(val index: UInt, var channel: String, val ipaddress: String, val port: Int = 5002) : AutoCloseable {
|
class BarixConnection(val index: UInt, var channel: String, val ipaddress: String, val port: Int = 5002) : AutoCloseable {
|
||||||
@@ -27,6 +28,16 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
|
|||||||
private val mp3encoder = Mp3Encoder()
|
private val mp3encoder = Mp3Encoder()
|
||||||
private val mp3Consumer = mutableMapOf<String, Consumer<ByteArray>>()
|
private val mp3Consumer = mutableMapOf<String, Consumer<ByteArray>>()
|
||||||
private val udp = DatagramSocket()
|
private val udp = DatagramSocket()
|
||||||
|
private var _barixmode: Boolean = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Barix mode flag
|
||||||
|
*/
|
||||||
|
var BarixMode: Boolean
|
||||||
|
get() = _barixmode
|
||||||
|
set(value) {
|
||||||
|
_barixmode = value
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
mp3encoder.Start { data ->
|
mp3encoder.Start { data ->
|
||||||
@@ -132,11 +143,12 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
|
|||||||
val chunk = ByteArray(if (bb.remaining() > maxUDPsize) maxUDPsize else bb.remaining())
|
val chunk = ByteArray(if (bb.remaining() > maxUDPsize) maxUDPsize else bb.remaining())
|
||||||
bb.get(chunk)
|
bb.get(chunk)
|
||||||
while(bufferRemain<chunk.size){
|
while(bufferRemain<chunk.size){
|
||||||
delay(5)
|
delay(10)
|
||||||
}
|
}
|
||||||
udp.send(DatagramPacket(chunk, chunk.size, inet))
|
udp.send(DatagramPacket(chunk, chunk.size, inet))
|
||||||
|
|
||||||
mp3encoder.PushData(chunk)
|
mp3encoder.PushData(chunk)
|
||||||
delay(1)
|
if (_barixmode) delay(10) else delay(1)
|
||||||
|
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -177,40 +189,62 @@ class BarixConnection(val index: UInt, var channel: String, val ipaddress: Strin
|
|||||||
return Somecodes.toJsonString(toJsonNode())
|
return Somecodes.toJsonString(toJsonNode())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ActivateRelay(relays: List<Int>){
|
||||||
|
if (relays.isNotEmpty()){
|
||||||
|
var value : Byte = 0
|
||||||
|
for (r in relays){
|
||||||
|
if (r in 1..8){
|
||||||
|
value = value or (1 shl (r - 1)).toByte()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SendSimpleCommand(byteArrayOf(0x1A, value, 0x61))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activate relay on Barix device
|
* Activate relay on Barix device
|
||||||
* @param relays The relay numbers to activate (1-8)
|
* @param relays The relay numbers to activate (1-8)
|
||||||
* @return true if successful
|
|
||||||
*/
|
*/
|
||||||
fun ActivateRelay(vararg relays: Int){
|
fun ActivateRelay(vararg relays: Int){
|
||||||
val command = StringBuilder("RELAY;")
|
if (relays.isNotEmpty()){
|
||||||
var binary = 0
|
var value : Byte = 0
|
||||||
relays.forEach {
|
for (r in relays){
|
||||||
if (it in 1..8) {
|
if (r in 1..8){
|
||||||
binary = binary or (1 shl (it - 1))
|
value = value or (1 shl (r - 1)).toByte()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
command.append(binary.toString()).append("@")
|
SendSimpleCommand(byteArrayOf(0x1A, value, 0x61))
|
||||||
SendCommand(command.toString())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ActivateRelay(relays: List<Int>){
|
|
||||||
val command = StringBuilder("RELAY;")
|
|
||||||
var binary = 0
|
|
||||||
relays.forEach {
|
|
||||||
if (it in 1..8) {
|
|
||||||
binary = binary or (1 shl (it - 1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
command.append(binary.toString()).append("@")
|
|
||||||
SendCommand(command.toString())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivate relay on Barix device
|
* Deactivate relay on Barix device
|
||||||
*/
|
*/
|
||||||
fun DeactivateRelay(){
|
fun DeactivateRelay(){
|
||||||
SendCommand("RELAY;0@")
|
SendSimpleCommand(byteArrayOf(0x1A, 0, 0x61))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send simple command to Barix device
|
||||||
|
* @param command The command to send
|
||||||
|
* @return true if successful
|
||||||
|
*/
|
||||||
|
fun SendSimpleCommand(command: ByteArray) : Boolean {
|
||||||
|
try {
|
||||||
|
if (_tcp !=null){
|
||||||
|
if (_tcp!!.isConnected){
|
||||||
|
val out = _tcp!!.getOutputStream()
|
||||||
|
out.write(command)
|
||||||
|
out.flush()
|
||||||
|
return true
|
||||||
|
} else throw Exception("Socket to $ipaddress is not connected")
|
||||||
|
} else throw Exception("Socket to $ipaddress is null")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
if (e.message != null && e.message!!.isNotEmpty()) {
|
||||||
|
Logger.error { "Failed to send command, message : ${e.message}" }
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package barix
|
package barix
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
data class BarixStatus(val ipaddress: String, val vu: Int, val buffremain: Int, val statusdata: Int){
|
data class BarixStatus(val ipaddress: String, val vu: Int, val buffremain: Int, val statusdata: Int, val isBarix: Boolean){
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "BarixStatus(ipaddress='$ipaddress', vu=$vu, buffremain=$buffremain, statusdata=$statusdata)"
|
return "BarixStatus(ipaddress='$ipaddress', vu=$vu, buffremain=$buffremain, statusdata=$statusdata)"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package barix
|
package barix
|
||||||
|
|
||||||
|
import codes.Somecodes.Companion.LitteEndianToInt
|
||||||
import codes.Somecodes.Companion.ValidString
|
import codes.Somecodes.Companion.ValidString
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import org.tinylog.Logger
|
import org.tinylog.Logger
|
||||||
@@ -15,7 +16,7 @@ class TCP_Barix_Command_Server {
|
|||||||
lateinit var job: Job
|
lateinit var job: Job
|
||||||
private val socketMap = mutableMapOf<String, Socket>()
|
private val socketMap = mutableMapOf<String, Socket>()
|
||||||
|
|
||||||
private val regex = """STATUSBARIX;(\d+);(\d+);?(\d)?"""
|
private val regex = """STATUSBARIX;(\d+);(\d+)(;(\d+))?"""
|
||||||
private val pattern = Regex(regex)
|
private val pattern = Regex(regex)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,15 +44,25 @@ class TCP_Barix_Command_Server {
|
|||||||
|
|
||||||
val din = DataInputStream(socket.getInputStream())
|
val din = DataInputStream(socket.getInputStream())
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
val length = ByteArray(4)
|
|
||||||
din.readFully(length)
|
val bb = ByteArray(128)
|
||||||
val readlength = ByteBuffer.wrap(length).getInt()
|
val readbytes = din.read(bb)
|
||||||
//println("Read Length : $readlength")
|
if (readbytes == -1) {
|
||||||
val bb = ByteArray(readlength)
|
Logger.info { "Connection closed by Streamer Output with IP $key" }
|
||||||
din.readFully(bb)
|
break
|
||||||
// B4A format, 4 bytes di depan adalah size
|
}
|
||||||
val str = String(bb)
|
if (readbytes == 0) continue
|
||||||
//println("Received from $key : $str")
|
var stringlength = 0
|
||||||
|
try{
|
||||||
|
stringlength = LitteEndianToInt(bb[0], bb[1], bb[2], bb[3])
|
||||||
|
if (stringlength<1 || stringlength>bb.size-4) throw Exception("Invalid string length $stringlength")
|
||||||
|
} catch (ex:Exception){
|
||||||
|
Logger.error { "Error reading length from Streamer Output with IP $key, Message : ${ex.message}" }
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val str = String(bb,4, stringlength).trim()
|
||||||
|
if (str.isBlank()) continue
|
||||||
|
if (!str.startsWith("STATUSBARIX")) continue
|
||||||
if (ValidString(str)) {
|
if (ValidString(str)) {
|
||||||
// Valid command from Barix is in format $"STATUSBARIX;VU;BuffRemain;StatusData"$
|
// Valid command from Barix is in format $"STATUSBARIX;VU;BuffRemain;StatusData"$
|
||||||
pattern.find(str)?.let { matchResult ->
|
pattern.find(str)?.let { matchResult ->
|
||||||
@@ -60,7 +71,8 @@ class TCP_Barix_Command_Server {
|
|||||||
socket.inetAddress.hostAddress,
|
socket.inetAddress.hostAddress,
|
||||||
vu.toInt(),
|
vu.toInt(),
|
||||||
buffremain.toInt(),
|
buffremain.toInt(),
|
||||||
statusdata.toIntOrNull() ?: 0
|
statusdata.toIntOrNull() ?: 0,
|
||||||
|
statusdata.isNullOrEmpty() // barix tidak ada statusdata , Q-AG1 ada
|
||||||
)
|
)
|
||||||
//Logger.info { "Received valid command from $key : $status" }
|
//Logger.info { "Received valid command from $key : $status" }
|
||||||
cb.accept(status)
|
cb.accept(status)
|
||||||
|
|||||||
@@ -522,6 +522,22 @@ class Somecodes {
|
|||||||
return value is String && value.isNotBlank()
|
return value is String && value.isNotBlank()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun LitteEndianToInt(vararg bb: Byte): Int {
|
||||||
|
var result = 0
|
||||||
|
for (i in bb.indices) {
|
||||||
|
result = result or ((bb[i].toInt() and 0xFF) shl (8 * i))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun BigEndianToInt(vararg bb: Byte): Int {
|
||||||
|
var result = 0
|
||||||
|
for (i in bb.indices) {
|
||||||
|
result = result or ((bb[i].toInt() and 0xFF) shl (8 * (bb.size - 1 - i)))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if all strings in a list are valid non-blank strings.
|
* Check if all strings in a list are valid non-blank strings.
|
||||||
* @param values The list of strings to check.
|
* @param values The list of strings to check.
|
||||||
|
|||||||
@@ -8,4 +8,22 @@ data class QueuePaging(var index: UInt, var Date_Time: String, var Source: Strin
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "QueuePaging(index=$index, Date_Time='$Date_Time', Source='$Source', Type='$Type', Message='$Message', BroadcastZones='$BroadcastZones')"
|
return "QueuePaging(index=$index, Date_Time='$Date_Time', Source='$Source', Type='$Type', Message='$Message', BroadcastZones='$BroadcastZones')"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the QueuePaging entry is expired (older than 5 seconds)
|
||||||
|
* @param qt QueuePaging entry to check
|
||||||
|
* @return true if expired, false otherwise
|
||||||
|
*/
|
||||||
|
fun isExpired(qt: QueuePaging) : Boolean{
|
||||||
|
try{
|
||||||
|
val t1 = java.time.LocalDateTime.parse(qt.Date_Time, codes.Somecodes.datetimeformat1)
|
||||||
|
val delta = java.time.Duration.between(t1, java.time.LocalDateTime.now())
|
||||||
|
return delta.seconds > 5
|
||||||
|
} catch (_: Exception){
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
|
import codes.Somecodes.Companion.datetimeformat1
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
data class QueueTable(var index: UInt, var Date_Time: String, var Source: String, var Type: String, var Message: String, var SB_TAGS: String, var BroadcastZones: String, var Repeat: UInt, var Language: String){
|
data class QueueTable(var index: UInt, var Date_Time: String, var Source: String, var Type: String, var Message: String, var SB_TAGS: String, var BroadcastZones: String, var Repeat: UInt, var Language: String){
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,4 +14,23 @@ data class QueueTable(var index: UInt, var Date_Time: String, var Source: String
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "QueueTable(index=$index, Date_Time='$Date_Time', Source='$Source', Type='$Type', Message='$Message', SB_TAGS='$SB_TAGS', BroadcastZones='$BroadcastZones', Repeat=$Repeat, Language='$Language')"
|
return "QueueTable(index=$index, Date_Time='$Date_Time', Source='$Source', Type='$Type', Message='$Message', SB_TAGS='$SB_TAGS', BroadcastZones='$BroadcastZones', Repeat=$Repeat, Language='$Language')"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the QueueTable entry is expired (older than 5 seconds)
|
||||||
|
* @param qt QueueTable entry to check
|
||||||
|
* @return true if expired, false otherwise
|
||||||
|
*/
|
||||||
|
fun isExpired(qt: QueueTable) : Boolean{
|
||||||
|
try{
|
||||||
|
val t1 = LocalDateTime.parse(qt.Date_Time, datetimeformat1)
|
||||||
|
val delta = java.time.Duration.between(t1, LocalDateTime.now())
|
||||||
|
// expired if more than 5 seconds
|
||||||
|
return delta.seconds > 5
|
||||||
|
} catch (_: Exception){
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user