pan lowest non-locked item

This commit is contained in:
2023-10-20 17:40:13 -04:00
parent ad9281b609
commit e4640181c3

View File

@@ -2,6 +2,9 @@ package net.eksb.obsdc
import io.obswebsocket.community.client.OBSRemoteController
import io.obswebsocket.community.client.message.event.ui.StudioModeStateChangedEvent
import io.obswebsocket.community.client.message.request.RequestBatch
import io.obswebsocket.community.client.message.request.sceneitems.GetSceneItemLockedRequest
import io.obswebsocket.community.client.message.response.sceneitems.GetSceneItemLockedResponse
import io.obswebsocket.community.client.model.Scene
import io.obswebsocket.community.client.model.SceneItem.Transform
import io.obswebsocket.community.client.model.SceneItem.Transform.TransformBuilder
@@ -15,6 +18,8 @@ class Obs(private val q:BlockingQueue<Op>): AutoCloseable {
private val panAmount = 50F
private var alive = true
private val controller = OBSRemoteController.builder()
.host("localhost")
.port(4455)
@@ -26,14 +31,16 @@ class Obs(private val q:BlockingQueue<Op>): AutoCloseable {
.onClose { code -> log.error("closed:${code}")}
.onControllerError { e -> log.error("controller error", e ) }
.onCommunicatorError { e -> log.error("comm error", e ) }
.onDisconnect { log.info("disconnected") }
.onDisconnect {
log.info("disconnected")
if (alive) reconnect()
}
.and()
.registerEventListener(StudioModeStateChangedEvent::class.java) {
log.info("studio mode state change: ${it}")
}
.build()
private var alive = true
init {
Runtime.getRuntime().addShutdownHook(thread(start=false) {
@@ -43,6 +50,10 @@ class Obs(private val q:BlockingQueue<Op>): AutoCloseable {
})
}
private fun reconnect() {
controller.connect()
}
fun run() {
controller.connect()
}
@@ -99,24 +110,53 @@ class Obs(private val q:BlockingQueue<Op>): AutoCloseable {
}
}
// Pan the bottom-most non-locked item.
private fun pan(block:TransformBuilder.(Transform)->TransformBuilder) {
controller.getCurrentProgramScene { response ->
val sceneName = response.currentProgramSceneName
log.info("scene name: ${sceneName}")
controller.getSceneItemList(sceneName) { response ->
val item = response.sceneItems.last()
val itemId = item.sceneItemId
log.info("last item id: ${itemId}")
controller.getSceneItemTransform(sceneName, itemId) { response ->
val transform = response.sceneItemTransform
log.info("position: ${transform.positionX} x ${transform.positionY}")
val newTransform = block(Transform.builder(), transform).build()
controller.setSceneItemTransform(sceneName, itemId, newTransform) { response ->
log.info("transform successful: ${response.isSuccessful}")
// Have to set the current scene to take effect if in studio mode.
controller.setCurrentProgramScene(sceneName) { response ->
ready()
val items = response.sceneItems
// Even though locked status is in the response from OBS, the library does not parse it.
// So we have to ask for it explicitly:
controller.sendRequestBatch(
RequestBatch.builder()
.requests(
response.sceneItems.map { item ->
GetSceneItemLockedRequest.builder()
.sceneName(sceneName)
.sceneItemId(item.sceneItemId)
.build()
}
)
.build()
) { response ->
val item = response.data.results
.map { result ->
(result.responseData as GetSceneItemLockedResponse.SpecificData).sceneItemLocked
}
.zip(items)
.asSequence()
.filter { (locked,item) -> ! locked }
.map { (locked,item) -> item }
.sortedBy { item -> item.sceneItemIndex }
.firstOrNull()
log.info("item to pan: ${item?.sceneItemId}")
if (item != null) {
controller.getSceneItemTransform(sceneName, item.sceneItemId) { response ->
val transform = response.sceneItemTransform
log.info("position: ${transform.positionX} x ${transform.positionY}")
val newTransform = block(Transform.builder(), transform).build()
controller.setSceneItemTransform(sceneName, item.sceneItemId, newTransform) { response ->
log.info("transform successful: ${response.isSuccessful}")
// Have to set the current scene to take effect if in studio mode.
controller.setCurrentProgramScene(sceneName) { response ->
ready()
}
}
}
} else {
ready()
}
}
}