From bc26a5153c8026443b91202f667bcbd967457191 Mon Sep 17 00:00:00 2001 From: Joe Rayhawk Date: Tue, 22 Nov 2022 16:36:27 -0800 Subject: Descope most of the cached OBS state and simplify reference graph --- src/obswebsocket.cr | 228 ++++++++++++++++++++++++++-------------------------- 1 file changed, 112 insertions(+), 116 deletions(-) (limited to 'src/obswebsocket.cr') diff --git a/src/obswebsocket.cr b/src/obswebsocket.cr index 0daea20..1ac4997 100644 --- a/src/obswebsocket.cr +++ b/src/obswebsocket.cr @@ -41,18 +41,18 @@ module OBS class WebSocket # A bunch of these get initialized in OBS::WebSocket.initialize, # but we still want a class-wide typedef here to avoid managing Nils - @@inputs : OBS::Inputs = OBS::Inputs.allocate - @@scenes : OBS::SceneList = OBS::SceneList.allocate + @inputs : OBS::Inputs = OBS::Inputs.allocate + @scenes : OBS::SceneList = OBS::SceneList.allocate @sources : OBS::Sources = OBS::Sources.allocate @scenecollection : OBS::SceneCollection = OBS::SceneCollection.allocate @outputs : OBS::Outputs = OBS::Outputs.allocate @video : OBS::VideoSettings = OBS::VideoSettings.allocate @stats : OBS::Stats = OBS::Stats.allocate - @@eventsubs = Array( Channel(JSON::Any) ).new - @@openrequests = Hash( String, Channel( JSON::Any ) ).new + @eventsubs = Array( Channel(JSON::Any) ).new + @openrequests = Hash( String, Channel( JSON::Any ) ).new @negotiated = false - @@negotiationdelayqueue = 0 - @@negotiationdelay = Channel( Exception | Nil ).new + @negotiationdelayqueue = 0 + @negotiationdelay = Channel( Exception | Nil ).new @connecterror = 0 @shutdown = false @closed = true @@ -62,7 +62,7 @@ module OBS def eventsub_add( channel : Channel( JSON::Any ) ) # FIXME: this currently subscribes to everything # maybe make it more specific at some point - @@eventsubs.push( channel ) + @eventsubs.push( channel ) end def negotiated? return @negotiated @@ -71,10 +71,10 @@ module OBS return @scenecollection end def scenes - return @@scenes + return @scenes end def inputs - return @@inputs + return @inputs end def outputs return @outputs @@ -97,29 +97,29 @@ module OBS def send( json : String ) unless @negotiated STDERR.puts( "DELAYING" ) - @@negotiationdelayqueue += 1 - negotiationresult = @@negotiationdelay.receive + @negotiationdelayqueue += 1 + negotiationresult = @negotiationdelay.receive if negotiationresult.is_a?( Exception ) raise negotiationresult end @negotiated || return false # not sure why this condition would occur without an exception end STDERR.puts( "SENT: #{JSON.parse(json).pretty_inspect}" ) - @@obs_pubsub && @@obs_pubsub.not_nil!.send( json ) + @websocket && @websocket.not_nil!.send( json ) end def send( reschan : ( Channel( JSON::Any ) | Nil ), json : String ) unless @negotiated STDERR.puts( "DELAYING" ) - @@negotiationdelayqueue += 1 - negotiationresult = @@negotiationdelay.receive + @negotiationdelayqueue += 1 + negotiationresult = @negotiationdelay.receive if negotiationresult.is_a?( Exception ) raise negotiationresult end @negotiated || return false # not sure why this condition would occur without an exception end STDERR.puts( "SENT: #{JSON.parse(json).pretty_inspect}" ) - @@obs_pubsub && @@obs_pubsub.not_nil!.send( json ) - @@openrequests[ JSON.parse( json )["d"]["requestId"].as_s ] = reschan + @websocket && @websocket.not_nil!.send( json ) + @openrequests[ JSON.parse( json )["d"]["requestId"].as_s ] = reschan # maybe process reschan.receive here? end def request( type : String, id : String, data : ( String | Nil | JSON::Any ) = nil ) @@ -157,11 +157,10 @@ module OBS self.send( reschan, request.to_s ) end def initialize( uri : String, password : String | Nil = nil, retry : Bool = true ) - @scenecollection.initialize( self ) - @@inputs.initialize( self ) - @@scenes.initialize( self, @@inputs ) - @sources.initialize( self, @@inputs, @@scenes ) + @inputs.initialize( self ) + @scenes.initialize( self ) + @sources.initialize( self ) @outputs.initialize( self ) @video.initialize( self ) @stats.initialize( self ) @@ -173,14 +172,13 @@ module OBS end # FFS why is HTTP::WebSocket.initialize protected? # Now we have to .not_nil! this shit everywhere - # @@obs_pubsub.initialize( HTTP::WebSocket::Protocol.new( URI.parse( uri ), HTTP::Headers{"Cookie" => "SESSIONID=1235", "Sec-WebSocket-Protocol" => "OBS.json"} ) ) - @@obs_pubsub = HTTP::WebSocket.new( URI.parse( uri ), HTTP::Headers{"Cookie" => "SESSIONID=1235", "Sec-WebSocket-Protocol" => "OBS.json"} ) - @@obs_pubsub.not_nil!.on_close do | message | # for some reason HTTP::WebSocket.closed? SIGSEGVs on a dangling pointer on the 1.6 runtime, so we hack around it with our own state variable for now. + # @websocket.initialize( HTTP::WebSocket::Protocol.new( URI.parse( uri ), HTTP::Headers{"Cookie" => "SESSIONID=1235", "Sec-WebSocket-Protocol" => "OBS.json"} ) ) + @websocket = HTTP::WebSocket.new( URI.parse( uri ), HTTP::Headers{"Cookie" => "SESSIONID=1235", "Sec-WebSocket-Protocol" => "OBS.json"} ) + @websocket.not_nil!.on_close do | message | # for some reason HTTP::WebSocket.closed? SIGSEGVs on a dangling pointer on the 1.6 runtime, so we hack around it with our own state variable for now. @closed = true end @closed = false - #metachan = Channel( Tuple( String, Channel( JSON::Any ) ) ).new - @@obs_pubsub.not_nil!.on_message do | message | + @websocket.not_nil!.on_message do | message | json = JSON.parse( message ) STDERR.print( "RECEIVED: ") STDERR.print( json.to_pretty_json ) @@ -212,17 +210,17 @@ module OBS end end - @@obs_pubsub.not_nil!.send( hello.to_s ) + @websocket.not_nil!.send( hello.to_s ) when 2 # identified @negotiated = true - @@negotiationdelayqueue.times do - @@negotiationdelay.send( nil ) - @@negotiationdelayqueue -= 1 + @negotiationdelayqueue.times do + @negotiationdelay.send( nil ) + @negotiationdelayqueue -= 1 end @connecterror = 0 when 5 # event # FIXME: These should be switched over to Enum flags - @@eventsubs.each do | eventchan | + @eventsubs.each do | eventchan | eventchan.send( json["d"] ) end # A Fiber.yield occurs immediately after this to make sure "json" doesn't get overwritten before we can use it. @@ -231,16 +229,16 @@ module OBS case d["eventType"].as_s when "CurrentPreviewSceneChanged" edata = d["eventData"] - @@scenes.previewcache( edata["sceneName"].as_s ) + @scenes.previewcache( edata["sceneName"].as_s ) when "CurrentProgramSceneChanged" edata = d["eventData"] - @@scenes.programcache( edata["sceneName"].as_s ) + @scenes.programcache( edata["sceneName"].as_s ) when "CurrentSceneCollectionChanging" @scenecollection.deletecache() - @@scenes.deletecache() + @scenes.deletecache() when "CurrentSceneCollectionChanged" @scenecollection.deletecache() - @@scenes.deletecache() + @scenes.deletecache() edata = d["eventData"] @scenecollection.currentcache( edata["sceneCollectionName"].as_s ) when "SceneCollectionListChanged" @@ -259,13 +257,13 @@ module OBS # FIXME when "InputCreated" edata = d["eventData"] - @@inputs[edata["inputName"].to_s] = OBS::Input.new( self, edata ) + @inputs[edata["inputName"].to_s] = OBS::Input.new( self, edata ) when "InputNameChanged" edata = d["eventData"] - @@inputs.renamecache( edata["oldInputName"].as_s, edata["inputName"].as_s ) + @inputs.renamecache( edata["oldInputName"].as_s, edata["inputName"].as_s ) when "InputRemoved" edata = d["eventData"] - @@inputs.deletecache( edata["inputName"].as_s ) + @inputs.deletecache( edata["inputName"].as_s ) when "InputActiveStateChanged" when "InputShowStateChanged" when "InputMuteStateChanged" @@ -289,17 +287,17 @@ module OBS # FIXME when "SceneItemRemoved" edata = d["eventData"] - @@scenes[edata["sceneName"].to_s].deletecache( edata["sceneItemId"].as_i64, edata["sourceName"].as_s ) + @scenes[edata["sceneName"].to_s].deletecache( edata["sceneItemId"].as_i64, edata["sourceName"].as_s ) when "SceneItemEnableStateChanged" edata = d["eventData"] - @@scenes[edata["sceneName"].as_s][edata["sceneItemId"].as_i64].enabledcache( edata["sceneItemEnabled"].as_bool ) + @scenes[edata["sceneName"].as_s][edata["sceneItemId"].as_i64].enabledcache( edata["sceneItemEnabled"].as_bool ) when "SceneItemListReindexed" # FIXME when "SceneItemLockStateChanged" when "SceneItemTransformChanged" edata = d["eventData"] transform = edata["sceneItemTransform"] - sceneitem = @@scenes[edata["sceneName"].as_s][edata["sceneItemId"].as_i64] + 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 ) @@ -337,11 +335,11 @@ module OBS if d["requestStatus"]["result"].as_bool == false STDERR.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 ] + if @openrequests[ d["requestId"].as_s ]? + channel = @openrequests[ d["requestId"].as_s ] channel.send( d ) channel.close - @@openrequests.delete( d["requestId"].as_s ) + @openrequests.delete( d["requestId"].as_s ) else STDERR.puts( "PUBSUBREAD THREAD: no response channel known for requestId: #{ d["requestId"].as_s }" ) end @@ -349,7 +347,7 @@ module OBS Fiber.yield end end - @@obs_pubsub.not_nil!.run + @websocket.not_nil!.run rescue ex : Socket::ConnectError | IO::Error if @connecterror < 3 STDERR.print( ex.message ) @@ -358,29 +356,29 @@ module OBS STDERR.print( "\n" ) end unless retry - @@negotiationdelayqueue.times do - @@negotiationdelay.send( ex ) - @@negotiationdelayqueue -= 1 + @negotiationdelayqueue.times do + @negotiationdelay.send( ex ) + @negotiationdelayqueue -= 1 end end rescue ex STDERR.print( ex.pretty_inspect ) STDERR.print( ex.backtrace?.pretty_inspect ) ensure - @closed || @@obs_pubsub && @@obs_pubsub.not_nil!.close + @closed || @websocket && @websocket.not_nil!.close @negotiated = false unless retry - @@negotiationdelayqueue.times do - @@negotiationdelay.send( nil ) - @@negotiationdelayqueue -= 1 + @negotiationdelayqueue.times do + @negotiationdelay.send( nil ) + @negotiationdelayqueue -= 1 end end sleep 10 # invalidate state on everything @scenecollection = OBS::SceneCollection.new( self ) - @@inputs = OBS::Inputs.new( self ) - @@scenes = OBS::SceneList.new( self, @@inputs ) - @sources = OBS::Sources.new( self, @@inputs, @@scenes ) + @inputs = OBS::Inputs.new( self ) + @scenes = OBS::SceneList.new( self ) + @sources = OBS::Sources.new( self ) @outputs = OBS::Outputs.new( self ) @video = OBS::VideoSettings.new( self ) @stats = OBS::Stats.new( self ) @@ -390,23 +388,23 @@ module OBS end def close @shutdown = true - @@obs_pubsub && @@obs_pubsub.close + @websocket && @websocket.close end end class Outputs @outputs = Hash( String, OBS::Output ).new - def initialize( @websocket : OBS::WebSocket ) + def initialize( @obs : OBS::WebSocket ) end def populate reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "GetOutputList", UUID.random.to_s ) ) + @obs.send( reschan, OBS.req( "GetOutputList", UUID.random.to_s ) ) d = reschan.receive if ( rdata = d["responseData"]? ) STDERR.print( "OUTPUTS THREAD: " ) STDERR.print( rdata.pretty_inspect ) rdata["outputs"].as_a.each do | output | - @outputs[output["outputName"].as_s] = OBS::Output.new( @websocket, output ) + @outputs[output["outputName"].as_s] = OBS::Output.new( @obs, output ) end else raise ResponseDataMissingException.new( "#{d["requestType"].as_s} #{d["requestStatus"]["code"].as_i64}: #{d["requestStatus"]["comment"].as_s}" ) @@ -426,9 +424,9 @@ module OBS getter status : OBS::OutputStatus getter flags : Hash( String, Bool ) getter state : Hash( String, String | Bool | Int64 | Float64 | Hash( String, Bool ) ) - def initialize( @websocket : OBS::WebSocket, json : JSON::Any ) + def initialize( @obs : OBS::WebSocket, json : JSON::Any ) @flags = Hash( String, Bool ).from_json(json["outputFlags"].to_json) - @status = OBS::OutputStatus.new( @websocket, json["outputName"].as_s ) + @status = OBS::OutputStatus.new( @obs, json["outputName"].as_s ) @state = Hash(String, String | Bool | Int64 | Float64 | Hash( String, Bool ) ).from_json(json.to_json) end end @@ -437,11 +435,11 @@ module OBS @age = Int64.new( 0 ) @status = Hash(String, String | Bool | Int64 | Float64 ).new getter name : String - def initialize( @websocket : OBS::WebSocket, @name : String ) + def initialize( @obs : OBS::WebSocket, @name : String ) end def populate reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "GetOutputStatus", UUID.random.to_s, JSON.parse( { "outputName" => @name }.to_json ) ) ) + @obs.send( reschan, OBS.req( "GetOutputStatus", UUID.random.to_s, JSON.parse( { "outputName" => @name }.to_json ) ) ) d = reschan.receive if ( rdata = d["responseData"]? ) @age = Time.utc.to_unix @@ -464,11 +462,11 @@ module OBS class VideoSettings @settings = Hash(String, String | Bool | Int64 | Float64 ).new - def initialize( @websocket : OBS::WebSocket ) + def initialize( @obs : OBS::WebSocket ) end def populate reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "GetVideoSettings", UUID.random.to_s ) ) + @obs.send( reschan, OBS.req( "GetVideoSettings", UUID.random.to_s ) ) d = reschan.receive if ( rdata = d["responseData"]? ) @settings = Hash(String, String | Bool | Int64 | Float64 ).from_json(rdata.to_json) @@ -493,11 +491,11 @@ module OBS class Stats @stats = Hash(String, String | Bool | Int64 | Float64 ).new @age = Int64.new( 0 ) - def initialize( @websocket : OBS::WebSocket ) + def initialize( @obs : OBS::WebSocket ) end def populate reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "GetStats", UUID.random.to_s ) ) + @obs.send( reschan, OBS.req( "GetStats", UUID.random.to_s ) ) d = reschan.receive if ( rdata = d["responseData"]? ) @stats = Hash(String, String | Bool | Int64 | Float64 ).from_json(rdata.to_json) @@ -521,17 +519,17 @@ module OBS @inputs : OBS::Inputs @current = String.new @list = Hash( String, OBS::SceneList ).new - def initialize( @websocket : OBS::WebSocket ) - @inputs = @websocket.inputs + def initialize( @obs : OBS::WebSocket ) + @inputs = @obs.inputs end def populate reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "GetSceneCollectionList", UUID.random.to_s ) ) + @obs.send( reschan, OBS.req( "GetSceneCollectionList", UUID.random.to_s ) ) d = reschan.receive if ( rdata = d["responseData"]? ) @current = rdata["currentSceneCollectionName"].as_s rdata["sceneCollections"].as_a.each{ | scenecollection | - @list[scenecollection.as_s] = OBS::SceneList.new( @websocket, @inputs ) + @list[scenecollection.as_s] = OBS::SceneList.new( @obs ) } else raise ResponseDataMissingException.new( "#{d["requestType"].as_s} #{d["requestStatus"]["code"].as_i64}: #{d["requestStatus"]["comment"].as_s}" ) @@ -562,11 +560,11 @@ module OBS @scenes = Hash(String, OBS::Scene).new @program = String.new @preview = String.new - def initialize( @websocket : OBS::WebSocket, @inputs : OBS::Inputs ) + def initialize( @obs : OBS::WebSocket ) end def populate reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "GetSceneList", UUID.random.to_s ) ) + @obs.send( reschan, OBS.req( "GetSceneList", UUID.random.to_s ) ) d = reschan.receive if ( rdata = d["responseData"]? ) @program = rdata["currentProgramSceneName"].as_s @@ -574,7 +572,7 @@ module OBS rdata["scenes"].as_a.each_with_index{ | scene, i | name = scene["sceneName"].as_s @scenes_by_index.push(name) - @scenes[name] = OBS::Scene.new( @websocket, name, self ) + @scenes[name] = OBS::Scene.new( @obs, name, self ) } else raise ResponseDataMissingException.new( "#{d["requestType"].as_s} #{d["requestStatus"]["code"].as_i64}: #{d["requestStatus"]["comment"].as_s}" ) @@ -640,19 +638,19 @@ module OBS getter name : String getter parent : OBS::SceneList # needed for reverse metasceneitem lookup @age = Int64.new( 0 ) - def initialize( @websocket : OBS::WebSocket, @name : String, @parent : OBS::SceneList ) - @filters = OBS::SourceFilters.new( @websocket, @name ) + def initialize( @obs : OBS::WebSocket, @name : String, @parent : OBS::SceneList ) + @filters = OBS::SourceFilters.new( @obs, @name ) end def populate reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "GetSceneItemList", UUID.random.to_s, JSON.parse( { "sceneName" => @name }.to_json ) ) ) + @obs.send( reschan, OBS.req( "GetSceneItemList", UUID.random.to_s, JSON.parse( { "sceneName" => @name }.to_json ) ) ) d = reschan.receive if ( rdata = d["responseData"]? ) # handle "sourceType": "OBS_SOURCE_TYPE_SCENE" rdata["sceneItems"].as_a.each_with_index{ | item, i | sname = item["sourceName"].as_s siid = item["sceneItemId"].as_i64 - @items_by_id[siid] = OBS::SceneItem.new( @websocket, @name, item ) + @items_by_id[siid] = OBS::SceneItem.new( @obs, @name, item ) @items_by_index.push( siid ) @items_by_name[sname] = siid if item["sourceType"].as_s == "OBS_SOURCE_TYPE_SCENE" @@ -739,12 +737,12 @@ module OBS end def program! reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "SetCurrentProgramScene", UUID.random.to_s, JSON.parse( { "sceneName" => @name }.to_json ) ) ) + @obs.send( reschan, OBS.req( "SetCurrentProgramScene", UUID.random.to_s, JSON.parse( { "sceneName" => @name }.to_json ) ) ) reschan.receive # we get weird behavior on transitions unless we block here end def preview! reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "SetCurrentPreviewScene", UUID.random.to_s, JSON.parse( { "sceneName" => @name }.to_json ) ) ) + @obs.send( reschan, OBS.req( "SetCurrentPreviewScene", UUID.random.to_s, JSON.parse( { "sceneName" => @name }.to_json ) ) ) reschan.receive # we get weird behavior on transitions unless we block here end def createinput( iname : String, kind : String, settings : OBS::InputSettings | Hash( String, String | Bool | Int64 | Float64 ) | Nil = nil, enabled : Bool = true ) @@ -760,15 +758,15 @@ module OBS end reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "CreateInput", UUID.random.to_s, JSON.parse(reqdata.to_json) ) ) + @obs.send( reschan, OBS.req( "CreateInput", UUID.random.to_s, JSON.parse(reqdata.to_json) ) ) d = reschan.receive # maybe block until the event comes in? - # will have to depend on the @@eventsubscription state + # will have to depend on the @eventsubscription state if d["requestStatus"]["result"].as_bool # success? # "responseData": { "sceneItemId": 219 } # Is this ever useful? It's a lot more requests than to just redo the entire GetSceneItemList #siid = d["responseData"]["sceneItemId"].as_i64 - parent.@inputs.deletecache + @obs.inputs.deletecache self.deletecache end return d @@ -798,7 +796,7 @@ module OBS getter blendmode : ( String | Nil ) getter locked : Bool getter transform : OBS::SceneItemTransform - def initialize( @websocket : OBS::WebSocket, @scenename : String, json : JSON::Any ) + def initialize( @obs : OBS::WebSocket, @scenename : String, json : JSON::Any ) @id = json["sceneItemId"].as_i64 @name = json["sourceName"].as_s @kind = json["inputKind"]?.as_s? @@ -806,7 +804,7 @@ module OBS @locked = json["sceneItemLocked"].as_bool @enabled = json["sceneItemEnabled"].as_bool @blendmode = json["sceneItemBlendmode"]?.as_s? - @transform = OBS::SceneItemTransform.new( @websocket, json["sceneItemTransform"], @name, @id ) + @transform = OBS::SceneItemTransform.new( @obs, json["sceneItemTransform"], @name, @id ) end def enabledcache( v : Bool ) @enabled = v @@ -823,12 +821,12 @@ module OBS end def enable! reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "SetSceneItemEnabled", UUID.random.to_s, JSON.parse( { "sceneName" => @scenename, "sceneItemId" => @id, "sceneItemEnabled" => true }.to_json ) ) ) + @obs.send( reschan, OBS.req( "SetSceneItemEnabled", UUID.random.to_s, JSON.parse( { "sceneName" => @scenename, "sceneItemId" => @id, "sceneItemEnabled" => true }.to_json ) ) ) d = reschan.receive # block until response end def disable! reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "SetSceneItemEnabled", UUID.random.to_s, JSON.parse( { "sceneName" => @scenename, "sceneItemId" => @id, "sceneItemEnabled" => false }.to_json ) ) ) + @obs.send( reschan, OBS.req( "SetSceneItemEnabled", UUID.random.to_s, JSON.parse( { "sceneName" => @scenename, "sceneItemId" => @id, "sceneItemEnabled" => false }.to_json ) ) ) d = reschan.receive # block until response end def transform( newtransform : OBS::SceneItemTransform | Hash( String, String | Bool | Int64 | Float64 ) ) @@ -837,19 +835,19 @@ module OBS reqdata["sceneName"] = @scenename reqdata["sceneItemTransform"] = Hash( String, String | Bool | Int64 | Float64).new.merge( newtransform.to_h ) reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "SetSceneItemTransform", UUID.random.to_s, JSON.parse(reqdata.to_json) ) ) + @obs.send( reschan, OBS.req( "SetSceneItemTransform", UUID.random.to_s, JSON.parse(reqdata.to_json) ) ) d = reschan.receive end end class SceneItemTransform @sceneitemtransform = Hash(String, String | Bool | Int64 | Float64 ).new - def initialize( @websocket : OBS::WebSocket, json : JSON::Any, @sceneitemname : String, @sceneitemid : Int64 ) + def initialize( @obs : OBS::WebSocket, json : JSON::Any, @sceneitemname : String, @sceneitemid : Int64 ) @sceneitemtransform = Hash(String, String | Bool | Int64 | Float64 ).from_json(json.to_json) end def populate reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "GetSceneItemTransform", UUID.random.to_s, JSON.parse( { "sceneName" => @sceneitemname, "sceneItemId" => @sceneitemid }.to_json ) ) ) + @obs.send( reschan, OBS.req( "GetSceneItemTransform", UUID.random.to_s, JSON.parse( { "sceneName" => @sceneitemname, "sceneItemId" => @sceneitemid }.to_json ) ) ) d = reschan.receive if ( rdata = d["responseData"]? ) @sceneitemtransform = Hash(String, String | Bool | Int64 | Float64 ).from_json(rdata["sceneItemTransform"].to_json) @@ -871,25 +869,23 @@ module OBS end class Sources - getter scenes : OBS::SceneList - getter inputs : OBS::Inputs @last_known_real_transform = Hash( String, OBS::SceneItemTransform ).new - def initialize( @websocket : OBS::WebSocket, @inputs : OBS::Inputs, @scenes : OBS::SceneList ) + def initialize( @obs : OBS::WebSocket ) end def []?( index : String ) : OBS::Scene | OBS::Input | Nil - if @inputs[index]? - return @inputs[index] - elsif @scenes[index]? - return @scenes[index] + if @obs.inputs[index]? + return @obs.inputs[index] + elsif @obs.scenes[index]? + return @obs.scenes[index] else return nil end end def to_h() : Hash( String, OBS::Scene | OBS::Input ) - return @inputs.to_h.merge( @scenes.to_h ) + return @obs.@inputs.to_h.merge( @obs.@scenes.to_h ) end def last_known_real_transform_add( sourcename : String, transform : JSON::Any ) - @last_known_real_transform[ sourcename ] = OBS::SceneItemTransform.new( @websocket, transform, sourcename, 0.to_i64 ) + @last_known_real_transform[ sourcename ] = OBS::SceneItemTransform.new( @obs, transform, sourcename, 0.to_i64 ) end def last_known_real_transform( sourcename : String ) : OBS::SceneItemTransform @last_known_real_transform[ sourcename ] @@ -901,15 +897,15 @@ module OBS class Inputs @inputs = Hash( String, OBS::Input ).new - def initialize( @websocket : OBS::WebSocket ) + def initialize( @obs : OBS::WebSocket ) end def populate reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "GetInputList", UUID.random.to_s) ) + @obs.send( reschan, OBS.req( "GetInputList", UUID.random.to_s) ) d = reschan.receive if ( rdata = d["responseData"]? ) rdata["inputs"].as_a.each{ | input | - @inputs[input["inputName"].as_s] = OBS::Input.new( @websocket, input ) + @inputs[input["inputName"].as_s] = OBS::Input.new( @obs, input ) } else raise ResponseDataMissingException.new( "#{d["requestType"].as_s} #{d["requestStatus"]["code"].as_i64}: #{d["requestStatus"]["comment"].as_s}" ) @@ -948,15 +944,15 @@ module OBS getter name : String getter settings : OBS::InputSettings getter filters : OBS::SourceFilters - def initialize( @websocket : OBS::WebSocket, json : JSON::Any ) + def initialize( @obs : OBS::WebSocket, json : JSON::Any ) @kind = json["inputKind"].as_s @name = json["inputName"].as_s - @settings = OBS::InputSettings.new( @websocket, @name ) - @filters = OBS::SourceFilters.new( @websocket, @name ) + @settings = OBS::InputSettings.new( @obs, @name ) + @filters = OBS::SourceFilters.new( @obs, @name ) end def delete!( ) reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "RemoveInput", UUID.random.to_s, JSON.parse({ "inputName" => @name }.to_json) ) ) + @obs.send( reschan, OBS.req( "RemoveInput", UUID.random.to_s, JSON.parse({ "inputName" => @name }.to_json) ) ) d = reschan.receive end def namecache( name : String ) @@ -973,13 +969,13 @@ module OBS @inputsettings = Hash(String, String | Bool | Int64 | Float64 ).new @inputkind = String.new getter name : String - def initialize( @websocket : OBS::WebSocket, @name : String ) + def initialize( @obs : OBS::WebSocket, @name : String ) end - def initialize( @websocket : OBS::WebSocket, @name : String, @inputkind : String, @inputsettings : Hash( String, String | Bool | Int64 | Float64 ) ) + def initialize( @obs : OBS::WebSocket, @name : String, @inputkind : String, @inputsettings : Hash( String, String | Bool | Int64 | Float64 ) ) end def populate reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "GetInputSettings", UUID.random.to_s, JSON.parse( { "inputName" => @name }.to_json ) ) ) + @obs.send( reschan, OBS.req( "GetInputSettings", UUID.random.to_s, JSON.parse( { "inputName" => @name }.to_json ) ) ) d = reschan.receive if ( rdata = d["responseData"]? ) @inputsettings = Hash(String, String | Bool | Int64 | Float64 ).from_json(rdata["inputSettings"].to_json) @@ -1009,17 +1005,17 @@ module OBS @filters_by_name = Hash( String, OBS::SourceFilter ).new @filters_by_index = Array( String ).new getter sourcename : String - def initialize( @websocket : OBS::WebSocket, @sourcename : String ) + def initialize( @obs : OBS::WebSocket, @sourcename : String ) end def populate reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "GetSourceFilterList", UUID.random.to_s, JSON.parse( { "sourceName" => @sourcename }.to_json ) ) ) + @obs.send( reschan, OBS.req( "GetSourceFilterList", UUID.random.to_s, JSON.parse( { "sourceName" => @sourcename }.to_json ) ) ) d = reschan.receive if ( rdata = d["responseData"]? ) rdata["filters"].as_a.each do | filter | name = filter["filterName"].as_s @filters_by_index.push( name ) - @filters_by_name[name] = OBS::SourceFilter.new( @websocket, @sourcename, filter ) + @filters_by_name[name] = OBS::SourceFilter.new( @obs, @sourcename, filter ) end else raise ResponseDataMissingException.new( "#{d["requestType"].as_s} #{d["requestStatus"]["code"].as_i64}: #{d["requestStatus"]["comment"].as_s}" ) @@ -1050,11 +1046,11 @@ module OBS getter enabled : Bool getter settings : OBS::SourceFilterSettings getter sourcename : String - def initialize( @websocket : OBS::WebSocket, @sourcename, json : JSON::Any ) + def initialize( @obs : OBS::WebSocket, @sourcename, json : JSON::Any ) @kind = json["filterKind"].as_s @name = json["filterName"].as_s @enabled = json["filterEnabled"].as_bool - @settings = OBS::SourceFilterSettings.new( @websocket, @name, json["filterSettings"] ) + @settings = OBS::SourceFilterSettings.new( @obs, @name, json["filterSettings"] ) end def toggle! if @enabled @@ -1065,13 +1061,13 @@ module OBS end def enable! reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "SetSourceFilterEnabled", UUID.random.to_s, JSON.parse( { "sourceName" => @sourcename, "filterName" => @name, "filterEnabled" => true }.to_json ) ) ) + @obs.send( reschan, OBS.req( "SetSourceFilterEnabled", UUID.random.to_s, JSON.parse( { "sourceName" => @sourcename, "filterName" => @name, "filterEnabled" => true }.to_json ) ) ) d = reschan.receive return d["requestStatus"]["result"].as_bool end def disable! reschan = Channel( JSON::Any ).new - @websocket.send( reschan, OBS.req( "SetSourceFilterEnabled", UUID.random.to_s, JSON.parse( { "sourceName" => @sourcename, "filterName" => @name, "filterEnabled" => false }.to_json ) ) ) + @obs.send( reschan, OBS.req( "SetSourceFilterEnabled", UUID.random.to_s, JSON.parse( { "sourceName" => @sourcename, "filterName" => @name, "filterEnabled" => false }.to_json ) ) ) d = reschan.receive return d["requestStatus"]["result"].as_bool end @@ -1086,7 +1082,7 @@ module OBS class SourceFilterSettings getter settings : Hash(String, String | Bool | Int64 | Float64 ) getter sourcename : String - def initialize( @websocket : OBS::WebSocket, @sourcename, json : JSON::Any ) + def initialize( @obs : OBS::WebSocket, @sourcename, json : JSON::Any ) @settings = Hash(String, String | Bool | Int64 | Float64 ).from_json(json.to_json) end # do we need to populate() this somehow? -- cgit v1.2.3