15 Commits
Author SHA1 Message Date
onyx_online 799ae52b02 add prettier settings 2023-05-26 21:17:17 +01:00
onyx_online bc93654297 move identify payload out of auth block
patch bump
2022-11-25 18:05:10 +00:00
onyx_online aafcd185d0 patch bump
add full request payload to logger.

raise OBSWSError if auth enabled but no password provided

add example tasks to rake file

add logging section to README
2022-11-25 17:57:56 +00:00
onyx_online 43ecfb37f5 upd gemfile.lock 2022-11-18 15:00:34 +00:00
onyx_online 2e70c63ae7 fix patch ver 2022-11-18 14:54:29 +00:00
onyx_online c67ce47026 pass payload for call_vendor_request
patch bump
2022-11-18 14:52:28 +00:00
norm 0bac7eaf3a added missing response classes
patch bump
2022-11-03 04:11:59 +00:00
norm 5b0ce79e46 fix bug in get_group_list
patch bump
2022-11-03 03:36:56 +00:00
norm a0f5d8e57b add levels example 2022-10-27 06:45:52 +01:00
norm f1a1c970e0 add low, high, all constants to SUBS 2022-10-27 06:45:21 +01:00
onyx-and-iris 449684c405 upd gemfile.lock files 2022-10-25 00:33:24 +01:00
onyx-and-iris da5ef76c81 minor bump 2022-10-25 00:06:10 +01:00
onyx-and-iris 8752132012 scene rotate example added 2022-10-25 00:05:12 +01:00
onyx-and-iris fb162ca195 logger level set to info in events example 2022-10-25 00:04:28 +01:00
onyx-and-iris b33fe94cee moved logger auth success to req,event classes
override to_s for req,event classes

rename authenticate to identify in base class
2022-10-25 00:03:43 +01:00
15 changed files with 200 additions and 50 deletions
+4
View File
@@ -0,0 +1,4 @@
{
"singleQuote": false,
"tabWidth": 2
}
+1 -1
View File
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
obsws (0.0.3)
obsws (0.1.3)
observer (~> 0.1.1)
waitutil (~> 0.2.1)
websocket-driver (~> 0.7.5)
+13
View File
@@ -115,6 +115,19 @@ If a request fails an `OBSWSError` will be raised with a status code.
For a full list of status codes refer to [Codes](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#requeststatus)
### Logging
To see the raw messages set log level to debug
example:
```ruby
require "obsws"
OBSWS::LOGGER.debug!
...
```
### Tests
To run all tests:
+14
View File
@@ -1,5 +1,7 @@
require "minitest/test_task"
HERE = File.expand_path File.dirname(__FILE__)
Minitest::TestTask.create(:test) do |t|
t.libs << "test"
t.warning = false
@@ -7,3 +9,15 @@ Minitest::TestTask.create(:test) do |t|
end
task default: :test
task :events do
filepath = File.join(HERE, "examples", "events", "main.rb")
ruby filepath
end
task :levels do
filepath = File.join(HERE, "examples", "levels", "main.rb")
ruby filepath
end
task :scene_rotate do
filepath = File.join(HERE, "examples", "scene_rotate", "main.rb")
ruby filepath
end
+2 -2
View File
@@ -4,6 +4,6 @@ source "https://rubygems.org"
# gem "rails"
gem "perfect_toml", "~> 0.9.0"
gem "obsws", path: "../.."
gem "perfect_toml", "~> 0.9.0"
+2 -2
View File
@@ -1,7 +1,7 @@
PATH
remote: ../..
specs:
obsws (0.0.2)
obsws (0.1.0)
observer (~> 0.1.1)
waitutil (~> 0.2.1)
websocket-driver (~> 0.7.5)
@@ -24,4 +24,4 @@ DEPENDENCIES
perfect_toml (~> 0.9.0)
BUNDLED WITH
2.3.24
2.3.22
+1 -1
View File
@@ -1,7 +1,7 @@
require "obsws"
require "perfect_toml"
OBSWS::LOGGER.debug!
OBSWS::LOGGER.info!
class Observer
attr_reader :running
+53
View File
@@ -0,0 +1,53 @@
require "obsws"
require "perfect_toml"
OBSWS::LOGGER.info!
DEVICE = "Desktop Audio"
module LevelTypes
VU = 0
POSTFADER = 1
PREFADER = 2
end
class Observer
attr_reader :running
def initialize(**kwargs)
kwargs[:subs] = OBSWS::Events::SUBS::LOW_VOLUME | OBSWS::Events::SUBS::INPUTVOLUMEMETERS
@e_client = OBSWS::Events::Client.new(**kwargs)
@e_client.add_observer(self)
end
def on_input_mute_state_changed(data)
"""An input's mute state has changed."""
if data.input_name == DEVICE
puts "#{DEVICE} mute toggled"
end
end
def on_input_volume_meters(data)
def fget(x) = x > 0 ? (20 * Math.log(x, 10)).round(1) : -200.0
data.inputs.each do |d|
name = d[:inputName]
if name == DEVICE && !d[:inputLevelsMul].empty?
left, right = d[:inputLevelsMul]
puts "#{name} [L: #{fget(left[LevelTypes::POSTFADER])}, R: #{fget(right[LevelTypes::POSTFADER])}]"
end
end
end
end
def conn_from_toml
PerfectTOML.load_file("obs.toml", symbolize_names: true)[:connection]
end
def main
o = Observer.new(**conn_from_toml)
puts "press <Enter> to quit"
loop { exit if gets.chomp.empty? }
end
main if $0 == __FILE__
+9
View File
@@ -0,0 +1,9 @@
# frozen_string_literal: true
source "https://rubygems.org"
# gem "rails"
gem "obsws", path: "../.."
gem "perfect_toml", "~> 0.9.0"
+27
View File
@@ -0,0 +1,27 @@
PATH
remote: ../..
specs:
obsws (0.1.0)
observer (~> 0.1.1)
waitutil (~> 0.2.1)
websocket-driver (~> 0.7.5)
GEM
remote: https://rubygems.org/
specs:
observer (0.1.1)
perfect_toml (0.9.0)
waitutil (0.2.1)
websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
PLATFORMS
x64-mingw-ucrt
DEPENDENCIES
obsws!
perfect_toml (~> 0.9.0)
BUNDLED WITH
2.3.22
+22
View File
@@ -0,0 +1,22 @@
require "obsws"
require "perfect_toml"
OBSWS::LOGGER.info!
def conn_from_toml
PerfectTOML.load_file("obs.toml", symbolize_names: true)[:connection]
end
def main
r_client = OBSWS::Requests::Client.new(**conn_from_toml)
r_client.run do
resp = r_client.get_scene_list
resp.scenes.reverse.each do |s|
puts "Switching to scene #{s[:sceneName]}"
r_client.set_current_program_scene(s[:sceneName])
sleep(0.5)
end
end
end
main if $0 == __FILE__
+12 -12
View File
@@ -45,12 +45,12 @@ module OBSWS
@closed = true
end
@driver.on :message do |msg|
LOGGER.debug("received [#{msg}] passing to handler")
LOGGER.debug("received: #{msg.data}")
msg_handler(JSON.parse(msg.data, symbolize_names: true))
end
start_driver
WaitUtil.wait_for_condition(
"waiting successful identification",
"successful identification",
delay_sec: 0.01,
timeout_sec: 3
) { @identified }
@@ -74,7 +74,7 @@ module OBSWS
)
end
def authenticate(auth = nil)
def identify(auth)
payload = {
op: Mixin::OPCodes::IDENTIFY,
d: {
@@ -82,21 +82,21 @@ module OBSWS
eventSubscriptions: @subs
}
}
payload[:d][:authentication] = auth_token(**auth) if auth
if auth
if @password.empty?
raise OBSWSError("auth enabled but no password provided")
end
LOGGER.info("initiating authentication")
payload[:d][:authentication] = auth_token(**auth)
end
@driver.text(JSON.generate(payload))
end
def msg_handler(data)
case data[:op]
when Mixin::OPCodes::HELLO
if data[:d].key? :authentication
LOGGER.debug("initiating authentication")
else
LOGGER.debug("authentication disabled... skipping.")
end
authenticate(data[:d][:authentication])
identify(data[:d][:authentication])
when Mixin::OPCodes::IDENTIFIED
LOGGER.debug("client succesfully identified with server")
@identified = true
when Mixin::OPCodes::EVENT, Mixin::OPCodes::REQUESTRESPONSE
changed
@@ -113,8 +113,8 @@ module OBSWS
}
}
payload[:d][:requestData] = data if data
LOGGER.debug("sending request: #{payload}")
queued = @driver.text(JSON.generate(payload))
LOGGER.debug("request with id #{id} queued? #{queued}")
end
end
end
+24 -27
View File
@@ -7,38 +7,30 @@ module OBSWS
module Events
module SUBS
NONE = 0
GENERAL = (1 << 0)
CONFIG = (1 << 1)
SCENES = (1 << 2)
INPUTS = (1 << 3)
TRANSITIONS = (1 << 4)
FILTERS = (1 << 5)
OUTPUTS = (1 << 6)
SCENEITEMS = (1 << 7)
MEDIAINPUTS = (1 << 8)
VENDORS = (1 << 9)
UI = (1 << 10)
GENERAL = 1 << 0
CONFIG = 1 << 1
SCENES = 1 << 2
INPUTS = 1 << 3
TRANSITIONS = 1 << 4
FILTERS = 1 << 5
OUTPUTS = 1 << 6
SCENEITEMS = 1 << 7
MEDIAINPUTS = 1 << 8
VENDORS = 1 << 9
UI = 1 << 10
def low_volume
GENERAL | CONFIG | SCENES | INPUTS | TRANSITIONS | FILTERS | OUTPUTS |
LOW_VOLUME = GENERAL | CONFIG | SCENES | INPUTS | TRANSITIONS | FILTERS | OUTPUTS |
SCENEITEMS | MEDIAINPUTS | VENDORS | UI
end
INPUTVOLUMEMETERS = (1 << 16)
INPUTACTIVESTATECHANGED = (1 << 17)
INPUTSHOWSTATECHANGED = (1 << 18)
SCENEITEMTRANSFORMCHANGED = (1 << 19)
INPUTVOLUMEMETERS = 1 << 16
INPUTACTIVESTATECHANGED = 1 << 17
INPUTSHOWSTATECHANGED = 1 << 18
SCENEITEMTRANSFORMCHANGED = 1 << 19
def high_volume
INPUTVOLUMEMETERS | INPUTACTIVESTATECHANGED | INPUTSHOWSTATECHANGED |
HIGH_VOLUME = INPUTVOLUMEMETERS | INPUTACTIVESTATECHANGED | INPUTSHOWSTATECHANGED |
SCENEITEMTRANSFORMCHANGED
end
def all
low_volume | high_volume
end
module_function :low_volume, :high_volume, :all
ALL = LOW_VOLUME | HIGH_VOLUME
end
module Callbacks
@@ -75,11 +67,16 @@ module OBSWS
include Mixin::OPCodes
def initialize(**kwargs)
kwargs[:subs] = SUBS.low_volume
kwargs[:subs] ||= SUBS::LOW_VOLUME
@base_client = Base.new(**kwargs)
LOGGER.info("#{self} succesfully identified with server")
@base_client.add_observer(self)
end
def to_s
"#{self.class.name.split("::").last(2).join("::")}"
end
def update(op_code, data)
if op_code == Mixin::OPCodes::EVENT
event = data[:eventType]
+15 -4
View File
@@ -14,16 +14,21 @@ module OBSWS
def initialize(**kwargs)
@base_client = Base.new(**kwargs)
LOGGER.info("#{self} succesfully identified with server")
@base_client.add_observer(self)
@response = { requestId: 0 }
end
def to_s
"#{self.class.name.split("::").last(2).join("::")}"
end
def run
yield
ensure
close
WaitUtil.wait_for_condition(
"driver has closed",
"driver to close",
delay_sec: 0.01,
timeout_sec: 1
) { @base_client.closed }
@@ -37,7 +42,7 @@ module OBSWS
id = rand(1..1000)
@base_client.req(id, req, data)
WaitUtil.wait_for_condition(
"reponse id matches request id",
"reponse id to match request id",
delay_sec: 0.001,
timeout_sec: 3
) { @response[:requestId] == id }
@@ -72,7 +77,10 @@ module OBSWS
end
def call_vendor_request(name, type_, data = nil)
call(requestType, requestData)
payload = { vendorName: name, requestType: type_ }
payload[:requestData] = data if data
resp = call("CallVendorRequest", payload)
Mixin::Response.new(resp, resp.keys)
end
def get_hotkey_list
@@ -256,7 +264,7 @@ module OBSWS
end
def get_group_list
resp = call("GetSceneList")
resp = call("GetGroupList")
Mixin::Response.new(resp, resp.keys)
end
@@ -324,6 +332,7 @@ module OBSWS
def get_special_inputs
resp = call("GetSpecialInputs")
Mixin::Response.new(resp, resp.keys)
end
def create_input(
@@ -341,6 +350,7 @@ module OBSWS
sceneItemEnabled: scene_item_enabled
}
resp = call("CreateInput", payload)
Mixin::Response.new(resp, resp.keys)
end
def remove_input(name)
@@ -823,6 +833,7 @@ module OBSWS
def stop_record
resp = call("StopRecord")
Mixin::Response.new(resp, resp.keys)
end
def toggle_record_pause
+1 -1
View File
@@ -7,7 +7,7 @@ module OBSWS
end
def minor
0
1
end
def patch