commit 07/10/2025

This commit is contained in:
2025-10-07 14:18:00 +07:00
parent 1c72c7577f
commit d04a8bedd1
5 changed files with 91 additions and 27 deletions

View File

@@ -548,7 +548,6 @@ class MainExtension01 {
val zz = qp.BroadcastZones.split(";")
if (AllBroadcastZonesValid(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

View File

@@ -130,14 +130,89 @@ class AudioPlayer (var samplingrate: Int) {
* Writes the audio data from a byte array to a WAV file.
* @param data The byte array containing the audio data.
* @param target The target file name for the WAV file.
* @param withChime If true, adds a chime sound at the beginning and end of the audio.
* @param callback A BiConsumer that accepts a Boolean indicating success or failure and a String message.
*/
fun WavWriter(data: ByteArray, target: String, callback: BiConsumer<Boolean, String>) {
val source = AudioFileInfo()
source.bytes = data
source.fileName = "In-Memory Data"
val sources = listOf(source)
WavWriter(sources, target, false, callback)
fun WavWriter(data: ByteArray, target: String, withChime: Boolean = true, callback: BiConsumer<Boolean, String>) {
CoroutineScope(Dispatchers.IO).launch {
bass.BASS_SetDevice(0) // Set to No Sound device for writing
val streamhandle = bass.BASS_StreamCreate(samplingrate, 1, BASS_STREAM_DECODE, Pointer(-1), null)
if (streamhandle!=0){
val encodehandle = bassenc.BASS_Encode_Start(streamhandle, target, BASS_ENCODE_PCM, null, null)
if (encodehandle!=0){
fun pushData(data: ByteArray): Boolean {
val mem = Memory(data.size.toLong())
mem.write(0, data, 0, data.size)
val pushresult = bass.BASS_StreamPutData(streamhandle, mem, data.size)
if (pushresult==-1){
val errcode = bass.BASS_ErrorGetCode()
println("BASS_StreamPutData failed: $errcode")
}
return pushresult != -1
}
var all_success = true
if (withChime){
val chup = contentCache.getAudioFile("chimeup")
if (chup!=null && chup.isValid()){
if (pushData(chup.bytes)){
println("Chime up pushed")
} else {
all_success = false
println("Chime up failed")
}
} else println("Chime Up not valid")
}
if (pushData(data)){
println("Data pushed")
} else {
all_success = false
println("Data push failed")
}
if (withChime){
val chdn = contentCache.getAudioFile("chimedown")
if (chdn!=null && chdn.isValid()){
if (pushData(chdn.bytes)){
println("Chime down pushed")
} else {
all_success = false
println("Chime down failed")
}
} else println("Chime Down not valid")
}
val readsize: Long = 1024 * 1024 // read 1 MB at a time
var totalread: Long = 0
do{
val p = Memory(readsize)
val read = bass.BASS_ChannelGetData(streamhandle, p, 4096)
if (read > 0) {
totalread += read
}
} while (read > 0)
println("Finished reading stream data, total $totalread bytes read")
if (all_success){
callback.accept(true, "WAV file written successfully: $target")
} else {
callback.accept(false, "Failed to write some data to WAV file: $target")
}
bassenc.BASS_Encode_Stop(encodehandle)
} else callback.accept(false, "Failed to start encoding: ${bass.BASS_ErrorGetCode()}")
bass.BASS_StreamFree(streamhandle)
} else {
callback.accept(false, "Failed to create stream: ${bass.BASS_ErrorGetCode()}")
}
}
}
/**
@@ -147,7 +222,7 @@ class AudioPlayer (var samplingrate: Int) {
* @param withChime If true, adds a chime sound at the beginning and end of the audio.
* @param callback A BiConsumer that accepts a Boolean indicating success or failure and a String message.
*/
fun WavWriter(sources: List<AudioFileInfo>, target: String, withChime: Boolean, callback: BiConsumer<Boolean, String>) {
fun WavWriter(sources: List<AudioFileInfo>, target: String, withChime: Boolean = true, callback: BiConsumer<Boolean, String>) {
if (sources.isEmpty()) {
callback.accept(false, " Invalid sources")
return

View File

@@ -13,7 +13,7 @@ import java.time.LocalDateTime
* @param broadcastzones The zones to which the paging is broadcasted, is a semicolon-separated string.
*/
class PagingJob(val fromIP: String, val broadcastzones: String) {
val filePath : Path = PagingResult_directory.resolve(LocalDateTime.now().format(filenameformat)+"_RAW.wav")
val filePath : Path = PagingResult_directory.resolve("PAGING_"+fromIP+"_"+LocalDateTime.now().format(filenameformat)+".wav")
private val bos : ByteArrayOutputStream = ByteArrayOutputStream()
var totalBytesReceived = 0; private set
var isRunning = true; private set
@@ -25,7 +25,6 @@ class PagingJob(val fromIP: String, val broadcastzones: String) {
* @param length The number of bytes to write from the data array.
*/
fun addData(data: ByteArray, length: Int) {
Logger.info{"PagingJob from $fromIP, zones: $broadcastzones, received $length bytes"}
bos.write(data, 0, length)
totalBytesReceived += length
}

View File

@@ -66,12 +66,10 @@ class TCP_Android_Command_Server {
din.read(bb)
// B4A format, 4 bytes di depan adalah size
val str = String(bb, 4, bb.size - 4)
println("Received from $key : $str")
str.split("@").map { it.trim() }.filter { ValidString(it) }
.forEach {
process_command(key,it) { reply ->
try {
println("Reply to $key : ${reply.length} bytes")
dout.write(String_to_Byte_Android(reply))
} catch (e: Exception) {
logcb.accept("Failed to send reply to $key, Message : $e")
@@ -155,12 +153,13 @@ class TCP_Android_Command_Server {
}
"PCMFILE_START","STARTPAGINGAND" -> {
val zones = parts.getOrElse(3) { "" }.replace(",",";")
val zones = parts.getOrElse(1) { "" }.replace(",",";")
if (ValidString(zones)){
// create pagingjob
val pj = PagingJob(key, zones)
// masukin ke list
listOnGoingPaging[key] = pj
Logger.info{"PagingJob created for Android $key, zones: $zones, file: ${pj.filePath.absolutePathString()}"}
// start minta data dari udpreceiver
udpreceiver.RequestDataFrom(key){
@@ -184,10 +183,12 @@ class TCP_Android_Command_Server {
// get remaining data
val data = pj.GetData()
pj.Close()
audioPlayer.WavWriter(data, pj.filePath.absolutePathString()){
Logger.info{"Paging job closed from Android $key, total bytes received ${data.size}, writing to file ${pj.filePath.absolutePathString()}"}
audioPlayer.WavWriter(data, pj.filePath.absolutePathString(), true){
success, message ->
if (success){
// insert to paging queue
val qp = QueuePaging(
0u,
LocalDateTime.now().format(datetimeformat1),
@@ -235,14 +236,10 @@ class TCP_Android_Command_Server {
// pengiriman variabel ke Android
val username = parts.getOrElse(1) { "" }
if (ValidString(username)){
println("Initialize request from $key with username $username")
val userlogin = listUserLogin.find { it.username == username }
if (userlogin != null){
println("User $username found in listUserLogin")
val userdb = db.userDB.List.find { it.username == username }
if (userdb != null){
println("User $username found in userDB")
println(userdb)
val result = StringBuilder()
result.append("ZONE")
userdb.broadcastzones.split(";").map { it.trim() }.filter { it.isNotBlank() }.forEach {
@@ -322,8 +319,6 @@ class TCP_Android_Command_Server {
// send to sender
cb.accept(result.toString())
println("Result so far: $result")
println("Result size: ${result.length} bytes")
result.clear()
//Append MSG, for Android only Indonesia and English
@@ -365,11 +360,8 @@ class TCP_Android_Command_Server {
result.append("VARPROCEDURE;").append(index).append(";").append(soundbank.TAG).append(";").append(soundbank.Description).append("@")
}
// send to sender
println("Final Result: $result")
println("Final Result size: ${result.length} bytes")
cb.accept(result.toString())
logcb.accept("All variables sent to $key with username $username")
return
} else logcb.accept("STARTINITIALIZE failed from $key with username $username not found in userDB")
} else logcb.accept("STARTINITIALIZE failed from $key with unregistered username $username")

View File

@@ -1145,7 +1145,7 @@ class MariaDB(
"SB_TAGS VARCHAR(1024)," + // Comma-separated soundbank tags
"BroadcastZones VARCHAR(1024) NOT NULL," + // Comma-separated broadcast zones
"`Repeat` INT NOT NULL," + // Number of repeats
"Language VARCHAR(45) NOT NULL" + // Language of the message
"Language VARCHAR(100) NOT NULL" + // Language of the message
")"
super.Create(tabledefinition)
}
@@ -1311,7 +1311,7 @@ class MariaDB(
"Date_Time VARCHAR(45) NOT NULL," + // Date and time of the entry
"Source VARCHAR(45) NOT NULL," + // Source of the entry
"Type VARCHAR(45) NOT NULL," + // Type of the entry
"Message VARCHAR(512) NOT NULL," + // Message content
"Message VARCHAR(1024) NOT NULL," + // Message content
"BroadcastZones VARCHAR(1024)" + // Comma-separated soundbank tags
")"
super.Create(tabledefinition)
@@ -1330,7 +1330,7 @@ class MariaDB(
resultSet.getString("Source"),
resultSet.getString("Type"),
resultSet.getString("Message"),
resultSet.getString("SB_TAGS"),
resultSet.getString("BroadcastZones"),
)
queueList.add(queuePaging)
List.add(queuePaging)
@@ -1730,7 +1730,6 @@ class MariaDB(
statement?.setString(4, data.description)
val rowsAffected = statement?.executeUpdate()
if (rowsAffected != null && rowsAffected > 0) {
Logger.info{"Log added : $data"}
return true
} else {
Logger.warn{"Failed to add log entry : $data"}