From 748301a5cbd70a9b7b5e330706c700c207eca1e7 Mon Sep 17 00:00:00 2001 From: rdkartono Date: Tue, 7 Oct 2025 09:28:48 +0700 Subject: [PATCH] commit 07/10/2025 --- src/Main.kt | 9 ++--- src/MainExtension01.kt | 68 ++++++++++++++++++++++++++-------- src/audio/AudioPlayer.kt | 12 ++---- src/audio/ContentCache.kt | 55 ++++++++++++++++++++++++++++ src/content/ContentCache.kt | 73 ------------------------------------- 5 files changed, 114 insertions(+), 103 deletions(-) create mode 100644 src/audio/ContentCache.kt delete mode 100644 src/content/ContentCache.kt diff --git a/src/Main.kt b/src/Main.kt index 203b51f..c2e4293 100644 --- a/src/Main.kt +++ b/src/Main.kt @@ -1,5 +1,5 @@ -import audio.AudioFileInfo import audio.AudioPlayer +import audio.ContentCache import audio.UDPReceiver import barix.BarixConnection import barix.TCP_Barix_Command_Server @@ -43,11 +43,8 @@ val urutan_bahasa = listOf( Language.ARABIC.name ) -/** - * Common audio files, seperti chimeup, chimedown, silence1s, silencehalf - */ -val commonAudio : MutableMap = HashMap() +val contentCache = ContentCache() /** * Create necessary folders if not exist */ @@ -75,7 +72,7 @@ fun files_preparation(){ if (afi.isValid()){ Logger.info { "Common audio $it loaded from ${pp.toAbsolutePath()}" } val key = it.substring(0, it.length - 4) // buang .wav - commonAudio[key] = afi + contentCache.addAudioFile(key, afi) } else { Logger.error { "Failed to load common audio $it from ${pp.toAbsolutePath()}" } } diff --git a/src/MainExtension01.kt b/src/MainExtension01.kt index 59a3317..fbe8bef 100644 --- a/src/MainExtension01.kt +++ b/src/MainExtension01.kt @@ -553,18 +553,32 @@ class MainExtension01 { if (qp.Source == "PAGING") { // nama file ada di Message if (ValidFile(qp.Message)) { + // file ketemu di path val afi = audioPlayer.LoadAudioFile(qp.Message) - zz.forEach { z1 -> - StreamerOutputs.values.find { it.channel == z1 } - ?.SendData(afi.bytes, { db.Add_Log("AAS", it) }, { db.Add_Log("AAS", it) }) - } - val logmessage = - "Broadcast started PAGING with Filename '${qp.Message}' to zones: ${qp.BroadcastZones}" - Logger.info { logmessage } - db.Add_Log("AAS", logmessage) - db.queuepagingDB.DeleteByIndex(qp.index.toInt()) + if (afi.isValid()){ + // file bisa di load, kirim ke masing masing Streamer Output by IP address + ips.forEach { + ip -> + val br = StreamerOutputs[ip] + br?.SendData(afi.bytes, { db.Add_Log("AAS", it) }, { db.Add_Log("AAS", it) }) + } + + val logmessage = + "Broadcast started PAGING with Filename '${qp.Message}' to zones: ${qp.BroadcastZones}" + Logger.info { logmessage } + db.Add_Log("AAS", logmessage) + db.queuepagingDB.DeleteByIndex(qp.index.toInt()) + + return + } else { + // file tidak valid, delete from queue paging + db.queuepagingDB.DeleteByIndex(qp.index.toInt()) + db.Add_Log( + "AAS", + "Cancelled paging message with index ${qp.index} due to invalid audio file" + ) + } - return } else { // file tidak valid, delete from queue paging db.queuepagingDB.DeleteByIndex(qp.index.toInt()) @@ -587,10 +601,18 @@ class MainExtension01 { listfile -> val listafi = mutableListOf() listfile.forEach { filenya -> - val afi = audioPlayer.LoadAudioFile(filenya) - if (afi.isValid()) { + 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( @@ -728,10 +750,17 @@ class MainExtension01 { Get_Soundbank_Files(mb, variables ?: emptyMap(), { listfile -> listfile.forEach { filenya -> - val afi = audioPlayer.LoadAudioFile(filenya) - if (afi.isValid()) { + 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) + } } + } }, { @@ -794,10 +823,17 @@ class MainExtension01 { listfile -> val listafi = mutableListOf() listfile.forEach { filenya -> - val afi = audioPlayer.LoadAudioFile(filenya) - if (afi.isValid()) { + 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() audioPlayer.WavWriter(listafi, targetfile, true, diff --git a/src/audio/AudioPlayer.kt b/src/audio/AudioPlayer.kt index aeee691..a777f6f 100644 --- a/src/audio/AudioPlayer.kt +++ b/src/audio/AudioPlayer.kt @@ -1,23 +1,19 @@ package audio -import audio.Bass.BASS_ACTIVE_PLAYING import audio.Bass.BASS_DEVICE_ENABLED import audio.Bass.BASS_DEVICE_INIT import audio.Bass.BASS_POS_BYTE import audio.Bass.BASS_STREAM_DECODE import audio.Bass.BASS_SAMPLE_MONO -import audio.Bass.STREAMPROC_PUSH import audio.BassEnc.BASS_ENCODE_PCM import codes.Somecodes.Companion.ValidFile import codes.Somecodes.Companion.ValidString import com.sun.jna.Memory import com.sun.jna.Pointer -import commonAudio +import contentCache import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import org.tinylog.Logger import java.util.function.BiConsumer @@ -162,7 +158,7 @@ class AudioPlayer (var samplingrate: Int) { } - val job = CoroutineScope(Dispatchers.IO).launch(CoroutineName("WavWriter $target")) { + CoroutineScope(Dispatchers.IO).launch(CoroutineName("WavWriter $target")) { 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){ @@ -191,7 +187,7 @@ class AudioPlayer (var samplingrate: Int) { var allsuccess = true if (withChime){ - val chup = commonAudio["chimeup"] + val chup = contentCache.getAudioFile("chimeup") if (chup!=null && chup.isValid()){ if (pushData(chup.bytes)){ println("Chime up pushed") @@ -217,7 +213,7 @@ class AudioPlayer (var samplingrate: Int) { } if (withChime){ - val chdn = commonAudio["chimedown"] + val chdn = contentCache.getAudioFile("chimedown") if (chdn!=null && chdn.isValid()){ if (pushData(chdn.bytes)){ println("Chime down pushed") diff --git a/src/audio/ContentCache.kt b/src/audio/ContentCache.kt new file mode 100644 index 0000000..da4ac1e --- /dev/null +++ b/src/audio/ContentCache.kt @@ -0,0 +1,55 @@ +package audio + +/** + * Cache for audio content to avoid reloading from disk + */ +@Suppress("unused") +class ContentCache { + + private val map: MutableMap = HashMap() + + /** + * Clear the cache, but keep essential sounds : chimeup, chimedown, silence1s, silencehalf + */ + fun clear(){ + // dont clear chimeup, chimedown, silence1s, silencehalf + val keysToKeep = setOf("chimeup", "chimedown", "silence1s", "silencehalf") + map.keys.retainAll(keysToKeep) + + } + + /** + * Add an audio file to the cache + * @param key The key to identify the audio file + * @param audioFile The AudioFileInfo object + */ + fun addAudioFile(key: String, audioFile: AudioFileInfo) { + map[key] = audioFile + } + + /** + * Retrieve an audio file from the cache + * @param key The key to identify the audio file + * @return The AudioFileInfo object, or null if not found + */ + fun getAudioFile(key: String): AudioFileInfo? { + return map[key] + } + + /** + * Remove an audio file from the cache + * @param key The key to identify the audio file + */ + fun removeAudioFile(key: String) { + map.remove(key) + } + + /** + * Check if the cache contains the specified key + * @param key The key to check in the cache + * @return True if the key exists, false otherwise + */ + fun haveKey(key: String): Boolean { + return map.containsKey(key) + } +} \ No newline at end of file diff --git a/src/content/ContentCache.kt b/src/content/ContentCache.kt deleted file mode 100644 index ecffe21..0000000 --- a/src/content/ContentCache.kt +++ /dev/null @@ -1,73 +0,0 @@ -package content - -import audio.AudioFileInfo - -/** - * Class to manage loaded content in the application. - * This class provides methods to retrieve and add soundbank data based on specific criteria. - */ -@Suppress("unused") -class ContentCache { - private val contentList = ArrayList() - - - - /** - * Clears all loaded content from the cache. - */ - fun Clear(){ - contentList.clear() - } - - /** - * Removes the specified SoundbankData from the content list. - * @param SoundbankData The SoundbankData to be removed. - */ - fun Remove(SoundbankData: SoundbankData){ - contentList.remove(SoundbankData) - } - - /** - * Removes the specified SoundbankData from the content list based on tag, category, language, and voiceType. - * @param tag The tag of the SoundbankData to be removed. - * @param category The category of the SoundbankData to be removed. - * @param language The language of the SoundbankData to be removed. - * @param voiceType The voice type of the SoundbankData to be removed. - */ - fun Remove(tag: String, category: Category, language: Language, voiceType: VoiceType){ - val existing = Get(tag, category, language, voiceType) - if (existing!=null) contentList.remove(existing) - } - - /** - * Get the specified SoundbankData from tag, category, language, and voiceType. - * @return SoundbankData if found, null otherwise. - */ - fun Get(tag: String, category: Category, language: Language, voiceType: VoiceType): SoundbankData? { - - return contentList.find { - it.TAG == tag && - it.Category == category && - it.Language == language && - it.VoiceType == voiceType && - it.audio.isValid() - } - } - - /** - * Adds a new soundbank to the content list if it does not already exist. - * - * @param tag The unique identifier for the soundbank. - * @param category The category of the soundbank. - * @param language The language of the soundbank. - * @param voiceType The voice type of the soundbank. - * @param audio The audio file information for the soundbank. - * @return True if the soundbank was added, false if it already exists. - */ - fun Add(tag: String, category: Category, language: Language, voiceType: VoiceType, audio: AudioFileInfo): Boolean { - val existing = Get(tag, category, language, voiceType) - if (existing!=null) return false - contentList.add(SoundbankData(tag, category, language, voiceType, audio)) - return true - } -} \ No newline at end of file