commit 07/10/2025
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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"}
|
||||
|
||||
Reference in New Issue
Block a user