Compare commits
2 Commits
9c598a42bb
...
d5d52ad2bd
| Author | SHA1 | Date | |
|---|---|---|---|
| d5d52ad2bd | |||
| 6b0f5b99f9 |
@@ -6,8 +6,12 @@ plugins {
|
|||||||
dependencies {
|
dependencies {
|
||||||
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
|
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.3")
|
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.3")
|
||||||
|
|
||||||
implementation("com.github.hypfvieh:dbus-java-core:4.3.1")
|
implementation("com.github.hypfvieh:dbus-java-core:4.3.1")
|
||||||
runtimeOnly("com.github.hypfvieh:dbus-java-transport-native-unixsocket:4.3.1")
|
runtimeOnly("com.github.hypfvieh:dbus-java-transport-native-unixsocket:4.3.1")
|
||||||
|
|
||||||
|
implementation("io.obs-websocket.community:client:2.0.0")
|
||||||
|
|
||||||
implementation("org.slf4j:slf4j-api:2.0.9")
|
implementation("org.slf4j:slf4j-api:2.0.9")
|
||||||
runtimeOnly("org.slf4j:slf4j-simple:2.0.9")
|
runtimeOnly("org.slf4j:slf4j-simple:2.0.9")
|
||||||
}
|
}
|
||||||
|
|||||||
79
src/main/kotlin/net/eksb/obsdc/DBus.kt
Normal file
79
src/main/kotlin/net/eksb/obsdc/DBus.kt
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package net.eksb.obsdc
|
||||||
|
|
||||||
|
import org.freedesktop.dbus.annotations.DBusInterfaceName
|
||||||
|
import org.freedesktop.dbus.connections.impl.DBusConnection
|
||||||
|
import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder
|
||||||
|
import org.freedesktop.dbus.interfaces.DBusInterface
|
||||||
|
import org.freedesktop.dbus.interfaces.DBusSigHandler
|
||||||
|
import org.freedesktop.dbus.messages.DBusSignal
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
class DBus(handler: Handler) {
|
||||||
|
|
||||||
|
private val thread = thread(
|
||||||
|
start = true,
|
||||||
|
isDaemon = false,
|
||||||
|
name = "dbus",
|
||||||
|
) {
|
||||||
|
DBusConnectionBuilder.forSessionBus().build().use { dbus ->
|
||||||
|
|
||||||
|
// These lines are not necessary to handle signals, but are necessary to register methods.
|
||||||
|
dbus.requestBusName("net.eksb.obsdc")
|
||||||
|
dbus.exportObject("/", ObsdcDBusInterfaceImpl())
|
||||||
|
|
||||||
|
dbus.addSigHandler<ObsdcDBusInterface.Signal> { signal ->
|
||||||
|
log.info("signal: ${signal.op}")
|
||||||
|
val op = Op.valueOf(signal.op)
|
||||||
|
log.info("op: ${op}")
|
||||||
|
handler.handle(op)
|
||||||
|
}
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(60_000)
|
||||||
|
} catch (e:InterruptedException) {
|
||||||
|
log.info("interrupted")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("done")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stop() {
|
||||||
|
thread.interrupt()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val log = LoggerFactory.getLogger(DBus::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T: DBusSignal> DBusConnection.addSigHandler(handler: DBusSigHandler<T>) {
|
||||||
|
addSigHandler(T::class.java, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
@DBusInterfaceName("net.eksb.Obsdc")
|
||||||
|
interface ObsdcDBusInterface: DBusInterface {
|
||||||
|
fun echo(message:String): String
|
||||||
|
class Signal(path:String, val op:String): DBusSignal(path, op)
|
||||||
|
}
|
||||||
|
class ObsdcDBusInterfaceImpl: ObsdcDBusInterface {
|
||||||
|
override fun echo(message: String):String {
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
override fun getObjectPath(): String = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Monitor:
|
||||||
|
`dbus-monitor`
|
||||||
|
|
||||||
|
See what is registered:
|
||||||
|
`qdbus net.eksb.obsdc /`
|
||||||
|
|
||||||
|
Send signal:
|
||||||
|
`dbus-send --session --type=signal --dest=net.eksb.obsdc / net.eksb.Obsdc.Signal string:a`
|
||||||
|
|
||||||
|
Call method:
|
||||||
|
`dbus-send --session --type=method_call --print-reply --dest=net.eksb.obsdc / net.eksb.Obsdc.echo string:b`
|
||||||
|
`qdbus net.eksb.obsdc / net.eksb.Obsdc.echo hello`
|
||||||
|
*/
|
||||||
5
src/main/kotlin/net/eksb/obsdc/Handler.kt
Normal file
5
src/main/kotlin/net/eksb/obsdc/Handler.kt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package net.eksb.obsdc
|
||||||
|
|
||||||
|
fun interface Handler {
|
||||||
|
fun handle(op:Op)
|
||||||
|
}
|
||||||
@@ -1,68 +1,9 @@
|
|||||||
package net.eksb.obsdc
|
package net.eksb.obsdc
|
||||||
|
|
||||||
import org.freedesktop.dbus.annotations.DBusInterfaceName
|
|
||||||
import org.freedesktop.dbus.connections.impl.DBusConnection
|
|
||||||
import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder
|
|
||||||
import org.freedesktop.dbus.interfaces.DBusInterface
|
|
||||||
import org.freedesktop.dbus.interfaces.DBusSigHandler
|
|
||||||
import org.freedesktop.dbus.messages.DBusSignal
|
|
||||||
import org.slf4j.LoggerFactory
|
|
||||||
|
|
||||||
object Main {
|
object Main {
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun main(args:Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
|
val obs = ObsCommunity()
|
||||||
DBusConnectionBuilder.forSessionBus().build().use { dbus ->
|
DBus(obs.handler) // forks non-daemon thread
|
||||||
|
|
||||||
// These lines are not necessary to handle signals, but are necessary to register methods.
|
|
||||||
dbus.requestBusName("net.eksb.obsdc")
|
|
||||||
dbus.exportObject("/", ObsdcDBusInterfaceImpl())
|
|
||||||
|
|
||||||
dbus.addSigHandler<ObsdcDBusInterface.Signal> { signal -> log.info("signal: ${signal.message}") }
|
|
||||||
while (true) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(60_000)
|
|
||||||
} catch (e:InterruptedException) {
|
|
||||||
log.info("interrupted")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.info("done")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T:DBusSignal> DBusConnection.addSigHandler(handler:DBusSigHandler<T>) {
|
|
||||||
addSigHandler(T::class.java, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(Main::class.java)
|
|
||||||
|
|
||||||
@DBusInterfaceName("net.eksb.Obsdc")
|
|
||||||
interface ObsdcDBusInterface: DBusInterface {
|
|
||||||
fun echo(message:String): String
|
|
||||||
class Signal(path:String, val message:String): DBusSignal(path, message)
|
|
||||||
}
|
|
||||||
class ObsdcDBusInterfaceImpl: ObsdcDBusInterface {
|
|
||||||
override fun echo(message: String):String {
|
|
||||||
log.info("echo: ${message}")
|
|
||||||
return message
|
|
||||||
}
|
|
||||||
override fun getObjectPath(): String = "/"
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Monitor:
|
|
||||||
`dbus-monitor`
|
|
||||||
|
|
||||||
See what is registered:
|
|
||||||
`qdbus net.eksb.obsdc /`
|
|
||||||
|
|
||||||
Send signal:
|
|
||||||
`dbus-send --session --type=signal --dest=net.eksb.obsdc / net.eksb.Obsdc.Signal string:a`
|
|
||||||
|
|
||||||
Call method:
|
|
||||||
`dbus-send --session --type=method_call --print-reply --dest=net.eksb.obsdc / net.eksb.Obsdc.echo string:b`
|
|
||||||
`qdbus net.eksb.obsdc / net.eksb.Obsdc.echo hello`
|
|
||||||
*/
|
|
||||||
5
src/main/kotlin/net/eksb/obsdc/Obs.kt
Normal file
5
src/main/kotlin/net/eksb/obsdc/Obs.kt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package net.eksb.obsdc
|
||||||
|
|
||||||
|
interface Obs {
|
||||||
|
val handler:Handler
|
||||||
|
}
|
||||||
46
src/main/kotlin/net/eksb/obsdc/ObsCommunity.kt
Normal file
46
src/main/kotlin/net/eksb/obsdc/ObsCommunity.kt
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package net.eksb.obsdc
|
||||||
|
|
||||||
|
import io.obswebsocket.community.client.OBSRemoteController
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
class ObsCommunity: Obs, AutoCloseable {
|
||||||
|
|
||||||
|
// TODO: make a single controller, and read ops from a queue.
|
||||||
|
|
||||||
|
override fun close() {}
|
||||||
|
|
||||||
|
override val handler: Handler = Handler { op ->
|
||||||
|
var controller:OBSRemoteController? = null
|
||||||
|
|
||||||
|
fun ready() {
|
||||||
|
controller?.let { controller ->
|
||||||
|
log.info("ready to send ${op}")
|
||||||
|
|
||||||
|
when(op) {
|
||||||
|
Op.STUDIO_TRANSITION -> {
|
||||||
|
controller.triggerStudioModeTransition { response ->
|
||||||
|
log.info("Response successful: ${response.isSuccessful}")
|
||||||
|
controller.disconnect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
controller = OBSRemoteController.builder()
|
||||||
|
.host("localhost")
|
||||||
|
.port(4455)
|
||||||
|
.password("R3tRkVXhFofJ2wRF") // TODO put this in a file
|
||||||
|
.autoConnect(true)
|
||||||
|
.lifecycle()
|
||||||
|
.onReady {
|
||||||
|
ready()
|
||||||
|
}
|
||||||
|
.and()
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val log = LoggerFactory.getLogger(ObsCommunity::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/main/kotlin/net/eksb/obsdc/Op.kt
Normal file
6
src/main/kotlin/net/eksb/obsdc/Op.kt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package net.eksb.obsdc
|
||||||
|
|
||||||
|
enum class Op {
|
||||||
|
STUDIO_TRANSITION,
|
||||||
|
;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user