From 10f02081101a1375b6cad64419e8fa320f64fab1 Mon Sep 17 00:00:00 2001 From: Joe Rayhawk Date: Thu, 24 Nov 2022 19:34:39 -0800 Subject: Support for non-studio-mode --- src/obswebsocket.cr | 84 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/obswebsocket.cr b/src/obswebsocket.cr index dd00ec5..e4a1509 100644 --- a/src/obswebsocket.cr +++ b/src/obswebsocket.cr @@ -65,6 +65,9 @@ module OBS class SourceMissingException < Exception end + class StudioModeException < Exception + end + class ResponseDataMissingException < Exception end @@ -78,6 +81,7 @@ module OBS @outputs : OBS::Outputs = OBS::Outputs.allocate @video : OBS::VideoSettings = OBS::VideoSettings.allocate @stats : OBS::Stats = OBS::Stats.allocate + @studiomode : Bool | Nil = nil @eventsubs = Array( Tuple( Channel(JSON::Any), UInt32 ) ).new # convert this to Hash if anyone ever wants eventsub_remove() @openrequests = Hash( String, Channel( JSON::Any ) ).new @negotiated = false @@ -90,6 +94,23 @@ module OBS def closed? return @closed end + def studiomode : Bool + if @studiomode == nil + d = self.send_sync( OBS.req( "GetStudioModeEnabled" ) ) + @studiomode = d["responseData"]["studioModeEnabled"].as_bool + end + @studiomode.not_nil! + end + def studiomode=( state : Bool ) : Bool + unless self.studiomode == state + d = self.send_sync( OBS.req( "SetStudioModeEnabled", JSON.parse( { "studioModeEnabled" => state }.to_json ) ) ) + d["requestStatus"]["result"].as_bool && ( @studiomode = state ) + end + return state + end + def studiomodecache=( state : Bool ) + @studiomode = state + end def eventsub_add( channel : Channel( JSON::Any ), mask : UInt32 = @eventmask ) unless @eventmask.bits_set?( mask ) @eventmask = @eventmask|( mask ) # bitwise OR @@ -126,7 +147,11 @@ module OBS return @stats end def transition! - self.send_sync( OBS.req( "TriggerStudioModeTransition" ) ) + if self.studiomode + self.send_sync( OBS.req( "TriggerStudioModeTransition" ) ) + else + raise StudioModeException.new("Not currently in Studio Mode.") + end end def block_until_negotiated unless @negotiated @@ -246,18 +271,22 @@ module OBS @scenecollection.currentcache( edata["sceneCollectionName"].as_s ) when "SceneCollectionListChanged" @scenecollection.deletecache() - # FIXME: Save requests by using the edata here + # We could probably save requests by using the edata here. when "CurrentProfileChanging" when "CurrentProfileChanged" when "ProfileListChanged" when "SceneListChanged" - # FIXME + @scenes.deletecache + # We could probably save requests by using the edata here. when "SceneCreated" - # FIXME + @scenes.deletecache + # We could probably save requests by using the edata here. when "SceneRemoved" - # FIXME + @scenes.deletecache + # We could probably save requests by using the edata here. when "SceneNameChanged" - # FIXME + @scenes.deletecache + # We could probably save requests by using the edata here. when "InputCreated" edata = d["eventData"] @inputs[edata["inputName"].to_s] = OBS::Input.new( self, edata ) @@ -282,12 +311,16 @@ module OBS when "CurrentSceneTransitionChanged" when "CurrentSceneTransitionDurationChanged" when "StudioModeStateChanged" + edata = d["eventData"] + @studiomode = edata["studioModeEnabled"].as_bool when "SceneTransitionStarted" when "SceneTransitionEnded" when "SceneTransitionVideoEnded" when "SceneItemSelected" when "SceneItemCreated" - # FIXME + edata = d["eventData"] + @scenes[edata["sceneName"].to_s].deletecache() + # This could probably be made more efficient using the eventData when "SceneItemRemoved" edata = d["eventData"] @scenes[edata["sceneName"].to_s].deletecache( edata["sceneItemId"].as_i64, edata["sourceName"].as_s ) @@ -295,7 +328,9 @@ module OBS edata = d["eventData"] @scenes[edata["sceneName"].as_s][edata["sceneItemId"].as_i64].enabledcache( edata["sceneItemEnabled"].as_bool ) when "SceneItemListReindexed" - # FIXME + edata = d["eventData"] + @scenes[edata["sceneName"].to_s].deletecache() + # This could probably be made more efficient using the eventData when "SceneItemLockStateChanged" when "SceneItemTransformChanged" edata = d["eventData"] @@ -557,14 +592,18 @@ module OBS @scenes_by_index = Array(String).new @scenes = Hash(String, OBS::Scene).new @program = String.new - @preview = String.new + @preview : Nil | String = nil def initialize( @obs : OBS::WebSocket ) end def populate d = @obs.send_sync( OBS.req( "GetSceneList" ) ) if ( rdata = d["responseData"]? ) @program = rdata["currentProgramSceneName"].as_s - @preview = rdata["currentPreviewSceneName"].as_s + if @preview = rdata["currentPreviewSceneName"].as_s? + @obs.studiomodecache=true + else + @obs.studiomodecache=false + end rdata["scenes"].as_a.each_with_index{ | scene, i | name = scene["sceneName"].as_s @scenes_by_index.push(name) @@ -575,13 +614,6 @@ module OBS end return true end - def invalidate - STDERR.puts( "SCENELIST THREAD: scenes invalidated" ) - @scenes_by_index = Array(String).new - @scenes = Hash(String, OBS::Scene).new - @program = String.new - @preview = String.new - end def programcache( v : String ) @program = v end @@ -593,8 +625,12 @@ module OBS @preview = v end def preview - @preview.empty? && populate() - @scenes[@preview] + @preview || populate() + if @preview + return @scenes[@preview] + else + return @preview + end end def current @program.empty? && populate @@ -735,6 +771,7 @@ module OBS end def preview! # we get weird behavior on transitions unless we block here + @obs.studiomode || @obs.send_sync( OBS.req( "SetStudioModeEnabled", JSON.parse( { "studioModeEnabled" => true }.to_json ) ) ) @obs.send_sync( OBS.req( "SetCurrentPreviewScene", JSON.parse( { "sceneName" => @name }.to_json ) ) ) end def createinput( iname : String, kind : String, settings : OBS::InputSettings | Hash( String, String | Bool | Int64 | Float64 ) | Nil = nil, enabled : Bool = true ) @@ -854,6 +891,15 @@ module OBS @last_known_real_transform = Hash( String, OBS::SceneItemTransform ).new def initialize( @obs : OBS::WebSocket ) end + def []( index : String ) : OBS::Scene | OBS::Input + if @obs.inputs[index]? + return @obs.inputs[index] + elsif @obs.scenes[index]? + return @obs.scenes[index] + else + raise IndexError.new("Source unknown.") + end + end def []?( index : String ) : OBS::Scene | OBS::Input | Nil if @obs.inputs[index]? return @obs.inputs[index] -- cgit v1.2.3