diff options
author | Joe Rayhawk <jrayhawk@fairlystable.org> | 2022-10-29 16:46:42 -0700 |
---|---|---|
committer | Joe Rayhawk <jrayhawk@fairlystable.org> | 2022-10-29 16:46:42 -0700 |
commit | 2549b4c49fb2751aceea258c9a098f14fa8e2aed (patch) | |
tree | cb42bcb872885cd4cdf0a380b9012d950b53fd9f /src | |
parent | 2685cb0a5ff2736e7392a60436f762e67cdd104f (diff) | |
download | crystal-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/obswebsocket.cr | 94 |
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 |