diff --git a/orx-osc/build.gradle b/orx-osc/build.gradle new file mode 100644 index 00000000..9f2daaa2 --- /dev/null +++ b/orx-osc/build.gradle @@ -0,0 +1,5 @@ +dependencies { + def withoutSlf4j = { exclude group: 'org.slf4j' } + + compile "com.illposed.osc:javaosc-core:0.6", withoutSlf4j +} \ No newline at end of file diff --git a/orx-osc/src/main/kotlin/OSC.kt b/orx-osc/src/main/kotlin/OSC.kt new file mode 100644 index 00000000..9efd0548 --- /dev/null +++ b/orx-osc/src/main/kotlin/OSC.kt @@ -0,0 +1,69 @@ +package org.openrndr.extra.osc + +import com.illposed.osc.OSCMessage +import com.illposed.osc.OSCMessageListener +import com.illposed.osc.messageselector.OSCPatternAddressMessageSelector +import com.illposed.osc.transport.udp.OSCPort +import com.illposed.osc.transport.udp.OSCPortIn +import com.illposed.osc.transport.udp.OSCPortOut +import java.net.InetAddress +import java.net.PortUnreachableException + +private typealias OSCListener = Pair + +class OSC ( + address: InetAddress = InetAddress.getLocalHost(), + portIn: Int = OSCPort.DEFAULT_SC_OSC_PORT, + portOut: Int = portIn +) { + private val receiver: OSCPortIn = OSCPortIn(portIn) + private val sender: OSCPortOut = OSCPortOut(address, portOut) + private val listeners: MutableMap = mutableMapOf() + + fun send(channel: String, vararg message: T) { + if (!sender.isConnected) sender.connect() + + val msg = OSCMessage(channel, message.toList()) + + try { + sender.send(msg) + } catch (ex: Exception) { + when(ex) { + is PortUnreachableException -> System.err.println("Error: Could not connect to OUT port") + is IllegalStateException -> System.err.println("Error: Couldn't send message to channel: $channel") + } + // ex.printStackTrace() - Would rather keep this behind a debug flag + } + } + + fun listen(channel: String, callback: (List) -> Unit) { + val selector = OSCPatternAddressMessageSelector(channel); + + val cb = OSCMessageListener { + callback(it.message.arguments) + } + + receiver.dispatcher.addListener(selector, cb) + + listeners[channel] = Pair(selector, cb) + + if (!receiver.isListening) this.startListening() + } + + // Cannot be called inside a listener's callback + fun removeListener(channel: String?) { + val listener = listeners[channel] + + if (listener != null) { + receiver.dispatcher.removeListener(listener.first, listener.second) + } + } + + private fun startListening() { + receiver.dispatcher.isAlwaysDispatchingImmediately = true; + + receiver.startListening() + + if (receiver.isListening) println("OSC is listening..") + } +} diff --git a/settings.gradle b/settings.gradle index bf88a7f5..96fe2a44 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,6 +16,7 @@ include 'orx-camera', 'orx-noise', 'orx-obj-loader', 'orx-olive', + 'orx-osc', 'orx-poisson-fill', 'orx-shader-phrases', 'orx-kinect-common',