commit 28/07/2025
This commit is contained in:
22
.idea/libraries/kotlinx_coroutines_core.xml
generated
Normal file
22
.idea/libraries/kotlinx_coroutines_core.xml
generated
Normal file
@@ -0,0 +1,22 @@
|
||||
<component name="libraryTable">
|
||||
<library name="kotlinx-coroutines-core" type="repository">
|
||||
<properties maven-id="org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.9.0/kotlinx-coroutines-core-1.9.0.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.9.0/kotlinx-coroutines-core-jvm-1.9.0.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/23.0.0/annotations-23.0.0.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.0.0/kotlin-stdlib-2.0.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.9.0/kotlinx-coroutines-core-jvm-1.9.0-javadoc.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/23.0.0/annotations-23.0.0-javadoc.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.0.0/kotlin-stdlib-2.0.0-javadoc.jar!/" />
|
||||
</JAVADOC>
|
||||
<SOURCES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.9.0/kotlinx-coroutines-core-1.9.0-sources.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.9.0/kotlinx-coroutines-core-jvm-1.9.0-sources.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/23.0.0/annotations-23.0.0-sources.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.0.0/kotlin-stdlib-2.0.0-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -16,5 +16,6 @@
|
||||
<orderEntry type="library" name="net.java.dev.jna" level="project" />
|
||||
<orderEntry type="library" name="io.javalin" level="project" />
|
||||
<orderEntry type="library" name="mariadb.jdbc.java.client" level="project" />
|
||||
<orderEntry type="library" name="kotlinx-coroutines-core" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
99
src/audio/UDPSenderFromFile.kt
Normal file
99
src/audio/UDPSenderFromFile.kt
Normal file
@@ -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<String>, targetPort: Int ) {
|
||||
val bass: Bass = Bass.Instance
|
||||
var filehandle: Int = 0
|
||||
var listSocketAddress = ArrayList<SocketAddress>()
|
||||
|
||||
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<Boolean, String>){
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user