216 lines
6.8 KiB
Kotlin
216 lines
6.8 KiB
Kotlin
import audio.AudioPlayer
|
|
import audio.ContentCache
|
|
import audio.TCPReceiver
|
|
import audio.UDPReceiver
|
|
import barix.BarixConnection
|
|
import barix.TCP_Barix_Command_Server
|
|
import codes.Somecodes
|
|
import com.sun.jna.Platform
|
|
import commandServer.TCP_Android_Command_Server
|
|
import content.Language
|
|
import content.VoiceType
|
|
import database.Log
|
|
import database.MariaDB
|
|
import kotlinx.coroutines.CoroutineScope
|
|
import kotlinx.coroutines.Dispatchers
|
|
import kotlinx.coroutines.delay
|
|
import kotlinx.coroutines.isActive
|
|
import kotlinx.coroutines.launch
|
|
import org.tinylog.Logger
|
|
import org.tinylog.provider.ProviderRegistry
|
|
import oshi.util.GlobalConfig
|
|
import web.WebApp
|
|
import java.nio.file.Files
|
|
import kotlin.concurrent.fixedRateTimer
|
|
import kotlin.io.path.absolutePathString
|
|
|
|
lateinit var db: MariaDB
|
|
lateinit var audioPlayer: AudioPlayer
|
|
val StreamerOutputs: MutableMap<String, BarixConnection> = HashMap()
|
|
lateinit var udpreceiver: UDPReceiver
|
|
lateinit var tcpreceiver: TCPReceiver
|
|
const val version = "0.0.2 (23/09/2025)"
|
|
// AAS 64 channels
|
|
const val max_channel = 64
|
|
|
|
// dipakai untuk pilih voice type, bisa diganti via web nanti
|
|
var selected_voice = VoiceType.VOICE_1.name
|
|
|
|
// dipakai untuk ambil messagebank berdasarkan id
|
|
val urutan_bahasa = listOf(
|
|
Language.INDONESIA.name,
|
|
Language.LOCAL.name,
|
|
Language.ENGLISH.name,
|
|
Language.CHINESE.name,
|
|
Language.JAPANESE.name,
|
|
Language.ARABIC.name
|
|
)
|
|
|
|
|
|
val contentCache = ContentCache()
|
|
/**
|
|
* Create necessary folders if not exist
|
|
*/
|
|
fun folder_preparation(){
|
|
Files.createDirectories(Somecodes.SoundbankResult_directory)
|
|
Files.createDirectories(Somecodes.PagingResult_directory)
|
|
Files.createDirectories(Somecodes.Soundbank_directory)
|
|
Somecodes.Soundbank_Languages_directory.forEach {
|
|
Files.createDirectories(it)
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Extract necessary wav files from classpath to soundbank directory
|
|
* and Load them
|
|
*/
|
|
fun files_preparation(){
|
|
val list = listOf("chimeup.wav", "chimedown.wav", "silence1s.wav", "silencehalf.wav")
|
|
list.forEach {
|
|
Somecodes.ExtractFilesFromClassPath("/$it", Somecodes.Soundbank_directory)
|
|
val pp = Somecodes.Soundbank_directory.resolve(it)
|
|
if (Files.isRegularFile(pp)){
|
|
val afi = audioPlayer.LoadAudioFile(pp.absolutePathString())
|
|
if (afi.isValid()){
|
|
Logger.info { "Common audio $it loaded from ${pp.toAbsolutePath()}" }
|
|
val key = it.substring(0, it.length - 4) // buang .wav
|
|
contentCache.addAudioFile(key, afi)
|
|
} else {
|
|
Logger.error { "Failed to load common audio $it from ${pp.toAbsolutePath()}" }
|
|
}
|
|
} else {
|
|
Logger.error { "Common audio $it not found at ${pp.toAbsolutePath()}" }
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// Application start here
|
|
fun main() {
|
|
if (Platform.isWindows()) {
|
|
// supaya OSHI bisa mendapatkan CPU usage di Windows seperti di Task Manager
|
|
GlobalConfig.set(GlobalConfig.OSHI_OS_WINDOWS_CPU_UTILITY, true)
|
|
}
|
|
Logger.info { "Starting AAS New Generation version $version" }
|
|
|
|
folder_preparation()
|
|
|
|
audioPlayer = AudioPlayer(44100) // 44100 Hz sampling rate
|
|
audioPlayer.InitAudio(1)
|
|
|
|
files_preparation()
|
|
|
|
db = MariaDB()
|
|
|
|
val subcode01 = MainExtension01()
|
|
|
|
// Coroutine untuk cek Paging Queue dan AAS Queue setiap detik
|
|
CoroutineScope(Dispatchers.Default).launch {
|
|
while (isActive) {
|
|
delay(1000)
|
|
// prioritas 1 , habisin queue paging
|
|
subcode01.Read_Queue_Paging()
|
|
// prioritas 2, habisin queue shalat
|
|
subcode01.Read_Queue_Shalat()
|
|
// prioritas 3, habisin queue timer
|
|
subcode01.Read_Queue_Timer()
|
|
// prioritas 4, habisin queue soundbank
|
|
subcode01.Read_Queue_Soundbank()
|
|
}
|
|
}
|
|
// Coroutine untuk cek Schedulebank tiap menit saat detik 00
|
|
CoroutineScope(Dispatchers.Default).launch {
|
|
while (isActive) {
|
|
delay(1000)
|
|
subcode01.Read_Schedule_Table()
|
|
}
|
|
}
|
|
|
|
val web = WebApp(
|
|
3030,
|
|
listOf(
|
|
Pair("admin", "password"),
|
|
Pair("user", "password")
|
|
))
|
|
web.Start()
|
|
|
|
udpreceiver = UDPReceiver()
|
|
if (udpreceiver.Start()) {
|
|
Logger.info { "UDP Receiver started on port 5002" }
|
|
} else {
|
|
Logger.error { "Failed to start UDP Receiver on port 5002" }
|
|
}
|
|
|
|
tcpreceiver = TCPReceiver()
|
|
if (tcpreceiver.Start()) {
|
|
Logger.info { "TCP Receiver started on port 5002" }
|
|
} else {
|
|
Logger.error { "Failed to start TCP Receiver on port 5002" }
|
|
}
|
|
|
|
|
|
|
|
val androidserver = TCP_Android_Command_Server()
|
|
androidserver.StartTcpServer(5003){
|
|
Logger.info { it }
|
|
db.logDB.Add(Log.NewLog("ANDROID", it))
|
|
}
|
|
|
|
val barixserver = TCP_Barix_Command_Server()
|
|
barixserver.StartTcpServer { cmd ->
|
|
//Logger.info { cmd }
|
|
val _streamer = StreamerOutputs[cmd.ipaddress]
|
|
val _sc = db.soundchannelDB.List.find { it.ip == cmd.ipaddress }
|
|
if (_streamer == null) {
|
|
// belum create BarixConnection untuk ipaddress ini
|
|
//Logger.info { "New Streamer Output connection from ${cmd.ipaddress}" }
|
|
if (_sc != null) {
|
|
val _bc = BarixConnection(_sc.index, _sc.channel, cmd.ipaddress)
|
|
_bc.vu = cmd.vu
|
|
_bc.bufferRemain = cmd.buffremain
|
|
_bc.statusData = cmd.statusdata
|
|
StreamerOutputs[cmd.ipaddress] = _bc
|
|
Logger.info { "Created new Streamer Output for channel ${_sc.channel} with IP ${cmd.ipaddress}" }
|
|
} else Logger.warn { "soundChannelDB doesn't have soundchannel with IP ${cmd.ipaddress}" }
|
|
|
|
} else {
|
|
// sudah ada, update data
|
|
if (_sc != null && _sc.channel != _streamer.channel) {
|
|
_streamer.channel = _sc.channel
|
|
}
|
|
_streamer.vu = cmd.vu
|
|
_streamer.bufferRemain = cmd.buffremain
|
|
_streamer.statusData = cmd.statusdata
|
|
}
|
|
|
|
}
|
|
|
|
val onlinechecker = fixedRateTimer(name = "onlinecheck", initialDelay = 1000, period = 1000) {
|
|
// cek setiap 1 detik, decrement online counter semua BarixConnection
|
|
StreamerOutputs.values.forEach {
|
|
it.decrementOnlineCounter()
|
|
}
|
|
}
|
|
|
|
db.Add_Log("AAS"," Application started")
|
|
|
|
// shutdown hook
|
|
Runtime.getRuntime().addShutdownHook(Thread {
|
|
db.Add_Log("AAS"," Application stopping")
|
|
Logger.info { "Shutdown hook called, stopping services..." }
|
|
barixserver.StopTcpCommand()
|
|
androidserver.StopTcpCommand()
|
|
onlinechecker.cancel()
|
|
web.Stop()
|
|
udpreceiver.Stop()
|
|
tcpreceiver.Stop()
|
|
audioPlayer.Close()
|
|
db.close()
|
|
Logger.info { "All services stopped, exiting application." }
|
|
ProviderRegistry.getLoggingProvider().shutdown()
|
|
})
|
|
|
|
|
|
}
|