diff --git a/.idea/libraries/kotlinx_coroutines_core.xml b/.idea/libraries/kotlinx_coroutines_core.xml
new file mode 100644
index 0000000..ecaecc9
--- /dev/null
+++ b/.idea/libraries/kotlinx_coroutines_core.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AAS_NewGen.iml b/AAS_NewGen.iml
index c1b8382..8bf29d4 100644
--- a/AAS_NewGen.iml
+++ b/AAS_NewGen.iml
@@ -16,5 +16,6 @@
+
\ No newline at end of file
diff --git a/src/audio/UDPReceiverToFile.kt b/src/audio/UDPReceiverToFile.kt
index 4360e27..9ee3b56 100644
--- a/src/audio/UDPReceiverToFile.kt
+++ b/src/audio/UDPReceiverToFile.kt
@@ -2,6 +2,11 @@ package audio
import audio.Bass.BASS_STREAMPROC_END
import audio.BassEnc.BASS_ENCODE_PCM
+import kotlinx.coroutines.CoroutineName
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.delay
import org.tinylog.Logger
import java.io.PipedInputStream
import java.io.PipedOutputStream
@@ -76,7 +81,8 @@ class UDPReceiverToFile(listeningAddress: String, listeningPort: Int, val sampli
var isReceiving = false
if (isReady){
- val thread1 = Thread{
+ val scope = CoroutineScope(Dispatchers.Default)
+ scope.launch(CoroutineName("UDPReceiverToFile UDP $senderIP $outputFilePath")) {
Logger.info { "UDPReceiverToFile started, listening on ${socket?.localSocketAddress} , saving to $outputFilePath" }
PipedOutputStream(pipeIn).use { pipeOut ->
@@ -100,11 +106,9 @@ class UDPReceiverToFile(listeningAddress: String, listeningPort: Int, val sampli
}
Logger.info { "UDPReceiverToFile ended" }
}
- thread1.name = "UDPReceiverToFile Thread1 $senderIP $outputFilePath"
- thread1.isDaemon = true
- thread1.start()
- val thread2 = Thread{
+
+ scope.launch(CoroutineName("UDPReceiverToFile BASS $senderIP $outputFilePath")) {
bass.BASS_SetDevice(0) // Set to No Sound device, we are not playing audio
val streamhandle = bass.BASS_StreamCreate(samplingrate, channel, 0, streamProc, null)
if (streamhandle!=0){
@@ -115,7 +119,7 @@ class UDPReceiverToFile(listeningAddress: String, listeningPort: Int, val sampli
callback.accept(true, "UDPReceiverToFile started successfully, writing to $outputFilePath")
while (isReceiving) {
try {
- Thread.sleep(1000) // Sleep to avoid busy waiting
+ delay(1000)
} catch (e: InterruptedException) {
Logger.error { "UDPReceiverToFile thread interrupted: ${e.message}" }
break
@@ -125,19 +129,18 @@ class UDPReceiverToFile(listeningAddress: String, listeningPort: Int, val sampli
bass.BASS_StreamFree(streamhandle)
Logger.info { "UDPReceiverToFile stopped writing to $outputFilePath" }
callback.accept(false, "UDPReceiverToFile stopped successfully, written bytes: $bytesWritten")
+
} else {
callback.accept(false, "Failed to start encoding: ${bass.BASS_ErrorGetCode()}")
- return@Thread
}
} else {
callback.accept(false, "Failed to create stream: ${bass.BASS_ErrorGetCode()}")
- return@Thread
}
}
- thread2.name = "UDPReceiverToFile Thread2 $senderIP $outputFilePath"
- thread2.isDaemon = true
- thread2.start()
+
+
+
diff --git a/src/audio/UDPSenderFromFile.kt b/src/audio/UDPSenderFromFile.kt
new file mode 100644
index 0000000..97e10d6
--- /dev/null
+++ b/src/audio/UDPSenderFromFile.kt
@@ -0,0 +1,99 @@
+package audio
+
+import audio.Bass.BASS_STREAM_DECODE
+import codes.Somecodes.Companion.ValidFile
+import com.sun.jna.Memory
+import java.net.DatagramPacket
+import java.net.DatagramSocket
+import java.net.InetSocketAddress
+import java.net.SocketAddress
+import java.util.function.BiConsumer
+import kotlinx.coroutines.CoroutineName
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+@Suppress("unused")
+class UDPSenderFromFile(val fileName: String, val bytesPerPackage: Int=1024, targetIP: Array, targetPort: Int ) {
+ val bass: Bass = Bass.Instance
+ var filehandle: Int = 0
+ var listSocketAddress = ArrayList()
+
+ var initialized: Boolean = false; private set
+ var isRunning: Boolean = false; private set
+ var bytesSent: Int = 0; private set
+
+ init {
+ if (ValidFile(fileName)){
+ bass.BASS_SetDevice(0)
+ val handle = bass.BASS_StreamCreateFile(false, fileName, 0,0, BASS_STREAM_DECODE)
+ if (handle!=0){
+ // test buka file berhasil, tutup lagi
+ bass.BASS_StreamFree(handle)
+ if (targetPort>0 && targetPort<65535){
+ if (targetIP.isNotEmpty()){
+ var validIPs = true
+ for(ip in targetIP){
+ try{
+ var so = InetSocketAddress(ip, targetPort)
+ listSocketAddress.add(so)
+ } catch (e : Exception){
+ validIPs = false
+ }
+ }
+
+ if (validIPs){
+ initialized = true
+ }
+
+ }
+ }
+ }
+
+ }
+ }
+
+ fun Start(callback: BiConsumer){
+ if (initialized){
+
+ val scope = CoroutineScope(Dispatchers.Default)
+ scope.launch(CoroutineName("UDPSenderFromFile $fileName")) {
+ try {
+ val socket = DatagramSocket()
+ bass.BASS_SetDevice(0) // Set to No Sound Device
+ val handle = bass.BASS_StreamCreateFile(false, fileName, 0, 0, BASS_STREAM_DECODE)
+ if (handle!=0){
+ isRunning = true
+ bytesSent = 0
+ callback.accept(true,"UDPSenderFromFile started, sending $fileName to ${listSocketAddress.size} targets")
+ while(isRunning){
+ val buffer = Memory(bytesPerPackage.toLong())
+ val bytesRead = bass.BASS_ChannelGetData(handle, buffer, bytesPerPackage)
+ if (bytesRead > 0) {
+ for(so in listSocketAddress){
+ val bytes = buffer.getByteArray(0, bytesRead)
+ socket.send(DatagramPacket(bytes, bytes.size, so))
+ bytesSent += bytes.size
+ }
+
+ } else isRunning = false
+ }
+ callback.accept(false,"UDPSenderFromFile finished sending $fileName")
+ bass.BASS_StreamFree(handle)
+ socket.close()
+ } else callback.accept(false, "Failed to open file $fileName for reading")
+ } catch (e : Exception){
+ callback.accept(false, "Error in UDPSenderFromFile: ${e.message}")
+ isRunning = false
+ }
+ }
+
+
+ } else callback.accept(false, "UDP Sender not initialized, check file and target IP/Port")
+
+ }
+
+ fun Stop(){
+ isRunning = false
+ }
+}
\ No newline at end of file