summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Rayhawk <jrayhawk@fairlystable.org>2022-10-29 16:46:42 -0700
committerJoe Rayhawk <jrayhawk@fairlystable.org>2022-10-29 16:46:42 -0700
commit2549b4c49fb2751aceea258c9a098f14fa8e2aed (patch)
treecb42bcb872885cd4cdf0a380b9012d950b53fd9f
parent2685cb0a5ff2736e7392a60436f762e67cdd104f (diff)
downloadcrystal-obs-websocket-2549b4c49fb2751aceea258c9a098f14fa8e2aed.tar.gz
crystal-obs-websocket-2549b4c49fb2751aceea258c9a098f14fa8e2aed.zip
Fiberize all event and response handling.
This patch may also get rid of some race conditions and deadlocks.
-rw-r--r--src/obswebsocket.cr94
1 files changed, 50 insertions, 44 deletions
diff --git a/src/obswebsocket.cr b/src/obswebsocket.cr
index f758632..3ab7836 100644
--- a/src/obswebsocket.cr
+++ b/src/obswebsocket.cr
@@ -187,43 +187,43 @@ module OBSWebSocket
eventsubs.each do | eventchan |
eventchan.send( json["d"] )
end
- case json["d"]["eventType"].as_s
- # Note: "spawn do" when more request callouts might happen
- when "CurrentPreviewSceneChanged"
- edata = json["d"]["eventData"]
- @@scenes.previewcache( edata["sceneName"].as_s )
- when "CurrentProgramSceneChanged"
- edata = json["d"]["eventData"]
- @@scenes.programcache( edata["sceneName"].as_s )
- when "InputCreated"
- edata = json["d"]["eventData"]
- @@inputs[edata["inputName"].to_s] = OBSWebSocket::Input.new( @@reqchan, edata )
- when "InputNameChanged"
- edata = json["d"]["eventData"]
- @@inputs.renamecache( edata["oldInputName"].as_s, edata["inputName"].as_s )
- when "InputRemoved"
- edata = json["d"]["eventData"]
- @@inputs.deletecache( edata["inputName"].as_s )
- when "SceneItemRemoved"
- spawn do
- edata = json["d"]["eventData"]
+ # A Fiber.yield occurs immediately after this to make sure "json" doesn't get overwritten before we can use it.
+ spawn do
+ d = json["d"]
+ case d["eventType"].as_s
+ when "CurrentPreviewSceneChanged"
+ edata = d["eventData"]
+ @@scenes.previewcache( edata["sceneName"].as_s )
+ when "CurrentProgramSceneChanged"
+ edata = d["eventData"]
+ @@scenes.programcache( edata["sceneName"].as_s )
+ when "InputCreated"
+ edata = d["eventData"]
+ @@inputs[edata["inputName"].to_s] = OBSWebSocket::Input.new( @@reqchan, edata )
+ when "InputNameChanged"
+ edata = d["eventData"]
+ @@inputs.renamecache( edata["oldInputName"].as_s, edata["inputName"].as_s )
+ when "InputRemoved"
+ edata = d["eventData"]
+ @@inputs.deletecache( edata["inputName"].as_s )
+ when "SceneItemRemoved"
+ edata = d["eventData"]
@@scenes[edata["sceneName"].to_s].deletecache( edata["sceneItemId"].as_i64, edata["sourceName"].as_s )
- end
- when "SceneItemEnableStateChanged"
- spawn do
- edata = json["d"]["eventData"]
+ when "SceneItemEnableStateChanged"
+ edata = d["eventData"]
@@scenes[edata["sceneName"].as_s][edata["sceneItemId"].as_i64].enabledcache( edata["sceneItemEnabled"].as_bool )
- end
- when "SceneItemTransformChanged"
- spawn do
+ when "SceneItemTransformChanged"
+ edata = d["eventData"]
+ transform = edata["sceneItemTransform"]
+ sceneitem = @@scenes[edata["sceneName"].as_s][edata["sceneItemId"].as_i64]
+ sceneitem.transform.cache( transform )
+ if ( transform["sourceHeight"].as_f.to_i64 > 0 ) && ( transform["sourceWidth"].as_f.to_i64 > 0 )
+ sources.last_known_real_transform_add( sceneitem.name, transform )
+ end
+ when "SourceDestroyed"
+ # We always dynamically assemble sources from inputs and scenes, so this event is ignored.
+ when "SourceFilterEnableStateChanged"
edata = json["d"]["eventData"]
- scenes[edata["sceneName"].as_s][edata["sceneItemId"].as_i64].transform.cache( edata["sceneItemTransform"] )
- end
- when "SourceDestroyed"
- # We always dynamically assemble sources from inputs and scenes, so this event is ignored.
- when "SourceFilterEnableStateChanged"
- edata = json["d"]["eventData"]
- spawn do
if ( source = @sources[edata["sourceName"].as_s]? )
puts "SourceFilterEnableStateChanged: #{source.class}"
source.filters[edata["filterName"].as_s].enabledcache( edata["filterEnabled"].as_bool )
@@ -232,18 +232,24 @@ module OBSWebSocket
end
end
end
+ Fiber.yield
when 7 # response
- if json["d"]["requestStatus"]["result"].as_bool == false
- puts "ERROR: #{json["d"]["requestType"].as_s} #{json["d"]["requestStatus"]["code"].as_i64}: #{json["d"]["requestStatus"]["comment"].as_s}"
- end
- if openrequests[ json["d"]["requestId"].as_s ]?
- channel = openrequests[ json["d"]["requestId"].as_s ]
- channel.send( json["d"] )
- channel.close
- openrequests.delete( json["d"]["requestId"].as_s )
- else
- puts "PUBSUBREAD THREAD: no response channel known for requestId: #{ json["d"]["requestId"].as_s }"
+ # A Fiber.yield occurs immediately after this to make sure "json" doesn't get overwritten before we can use it.
+ spawn do
+ d = json["d"]
+ if d["requestStatus"]["result"].as_bool == false
+ puts "ERROR: #{d["requestType"].as_s} #{d["requestStatus"]["code"].as_i64}: #{d["requestStatus"]["comment"].as_s}"
+ end
+ if openrequests[ d["requestId"].as_s ]?
+ channel = openrequests[ d["requestId"].as_s ]
+ channel.send( d )
+ channel.close
+ openrequests.delete( d["requestId"].as_s )
+ else
+ puts "PUBSUBREAD THREAD: no response channel known for requestId: #{ d["requestId"].as_s }"
+ end
end
+ Fiber.yield
end
end
obs_pubsub.run