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="net.java.dev.jna" level="project" />
|
||||||
<orderEntry type="library" name="io.javalin" level="project" />
|
<orderEntry type="library" name="io.javalin" level="project" />
|
||||||
<orderEntry type="library" name="mariadb.jdbc.java.client" level="project" />
|
<orderEntry type="library" name="mariadb.jdbc.java.client" level="project" />
|
||||||
|
<orderEntry type="library" name="kotlinx-coroutines-core" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
@@ -2,6 +2,11 @@ package audio
|
|||||||
|
|
||||||
import audio.Bass.BASS_STREAMPROC_END
|
import audio.Bass.BASS_STREAMPROC_END
|
||||||
import audio.BassEnc.BASS_ENCODE_PCM
|
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 org.tinylog.Logger
|
||||||
import java.io.PipedInputStream
|
import java.io.PipedInputStream
|
||||||
import java.io.PipedOutputStream
|
import java.io.PipedOutputStream
|
||||||
@@ -76,7 +81,8 @@ class UDPReceiverToFile(listeningAddress: String, listeningPort: Int, val sampli
|
|||||||
var isReceiving = false
|
var isReceiving = false
|
||||||
if (isReady){
|
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" }
|
Logger.info { "UDPReceiverToFile started, listening on ${socket?.localSocketAddress} , saving to $outputFilePath" }
|
||||||
|
|
||||||
PipedOutputStream(pipeIn).use { pipeOut ->
|
PipedOutputStream(pipeIn).use { pipeOut ->
|
||||||
@@ -100,11 +106,9 @@ class UDPReceiverToFile(listeningAddress: String, listeningPort: Int, val sampli
|
|||||||
}
|
}
|
||||||
Logger.info { "UDPReceiverToFile ended" }
|
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
|
bass.BASS_SetDevice(0) // Set to No Sound device, we are not playing audio
|
||||||
val streamhandle = bass.BASS_StreamCreate(samplingrate, channel, 0, streamProc, null)
|
val streamhandle = bass.BASS_StreamCreate(samplingrate, channel, 0, streamProc, null)
|
||||||
if (streamhandle!=0){
|
if (streamhandle!=0){
|
||||||
@@ -115,7 +119,7 @@ class UDPReceiverToFile(listeningAddress: String, listeningPort: Int, val sampli
|
|||||||
callback.accept(true, "UDPReceiverToFile started successfully, writing to $outputFilePath")
|
callback.accept(true, "UDPReceiverToFile started successfully, writing to $outputFilePath")
|
||||||
while (isReceiving) {
|
while (isReceiving) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000) // Sleep to avoid busy waiting
|
delay(1000)
|
||||||
} catch (e: InterruptedException) {
|
} catch (e: InterruptedException) {
|
||||||
Logger.error { "UDPReceiverToFile thread interrupted: ${e.message}" }
|
Logger.error { "UDPReceiverToFile thread interrupted: ${e.message}" }
|
||||||
break
|
break
|
||||||
@@ -125,19 +129,18 @@ class UDPReceiverToFile(listeningAddress: String, listeningPort: Int, val sampli
|
|||||||
bass.BASS_StreamFree(streamhandle)
|
bass.BASS_StreamFree(streamhandle)
|
||||||
Logger.info { "UDPReceiverToFile stopped writing to $outputFilePath" }
|
Logger.info { "UDPReceiverToFile stopped writing to $outputFilePath" }
|
||||||
callback.accept(false, "UDPReceiverToFile stopped successfully, written bytes: $bytesWritten")
|
callback.accept(false, "UDPReceiverToFile stopped successfully, written bytes: $bytesWritten")
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
callback.accept(false, "Failed to start encoding: ${bass.BASS_ErrorGetCode()}")
|
callback.accept(false, "Failed to start encoding: ${bass.BASS_ErrorGetCode()}")
|
||||||
return@Thread
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
callback.accept(false, "Failed to create stream: ${bass.BASS_ErrorGetCode()}")
|
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