voicemeeter_api_ruby 2.0.0 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28ea13d4f9276d77a39c3edb392132cf026d6cb5fd6425c13a1ede4e2d6f9589
4
- data.tar.gz: fcc60c1caa213fa159031a2b066f233a0c44872769c5827857708ff3d3531083
3
+ metadata.gz: feb89f841882b2ece4f1bc959c8a5a728a738b054798635d2937ff9dceacf37c
4
+ data.tar.gz: 382ba6af1cde36e8b450d0549e383f9e6c68040d8385923ec8b2c413ddfc3d1b
5
5
  SHA512:
6
- metadata.gz: be2142be5a1e2ad1857877f96d435ec912c036ec61a6107bf53ebf5e7f0246391d4e42c17a89aab288981b6c5fac197c44331b3086eaa64dfc7ed86568f4cabd
7
- data.tar.gz: 286a5397a410123a5d2fb9795267aa885955bfcfa3dc81b80382b896b06d2648328df723aa2872918436943c8c0f9f543be90a0de5ab6dd5547dc1432b33292b
6
+ metadata.gz: 719e6d87cf5514dc7d759bdf15bf75ae32a533686894c172e4c1d4151dc2b7c480e8967a0d0d41a4187a0df2ff7f4094a3bc9520f86cf7f75c0604f00b711b7e
7
+ data.tar.gz: 728b8458b2897592282c24b944a0d1a3dca0af14791c0c3c73a1d1eb474a9462f4f24eecd5aa3caad2fec024f111998dedac8e057b5d092f727a763feda6ab5e
data/lib/base.rb CHANGED
@@ -1,11 +1,18 @@
1
+ require 'toml'
1
2
  require 'ffi'
2
3
  require_relative 'inst'
3
4
 
4
5
  include InstallationFunctions
5
6
 
7
+
6
8
  module Base
9
+ """
10
+ Perform low level tasks.
11
+ """
7
12
  extend FFI::Library
8
13
 
14
+ $kinds_all = ["basic", "banana", "potato"]
15
+
9
16
  begin
10
17
  OS_BITS = get_arch
11
18
  VM_PATH = get_vmpath(OS_BITS)
@@ -48,77 +55,91 @@ module Base
48
55
  DELAY = 0.001
49
56
  MAX_POLLS = 8
50
57
 
51
- def pdirty
58
+ def pdirty?
52
59
  return vmr_pdirty&.nonzero?
53
60
  end
54
61
 
55
- def mdirty
62
+ def mdirty?
56
63
  return vmr_mdirty&.nonzero?
57
64
  end
58
65
 
66
+ private
59
67
  def clear_polling
60
- while self.pdirty || self.mdirty
68
+ while self.pdirty? || self.mdirty?
61
69
  end
62
70
  end
63
71
 
64
- def polling(func)
65
- MAX_POLLS.times do
66
- break if func.include?('param') && !self.pdirty
67
- break if func.include?('macro') && !self.mdirty
68
- sleep(DELAY)
72
+ def polling(func, **kwargs)
73
+ params = {
74
+ "get_parameter" => kwargs[:name],
75
+ "macro_getstatus" => "mb_#{kwargs[:id]}_#{kwargs[:mode]}"
76
+ }
77
+ @max_polls.times do |i|
78
+ if @cache.key? params[func]
79
+ if func.include?('param') && self.pdirty? ||
80
+ func.include?('macro') && self.mdirty?
81
+ return @cache.delete(params[func])[0]
82
+ end
83
+ sleep(DELAY)
84
+ break if @cache[params[func]][1] == false && i == 1
85
+ end
69
86
  end
87
+
88
+ val = yield
89
+ @cache.store(params[func], [val, false])
90
+ val
70
91
  end
71
92
 
72
93
  def retval=(values)
73
94
  """ Writer validation for CAPI calls """
74
95
  retval, func = *values
75
96
  raise CAPIErrors.new(retval, func) if retval&.nonzero?
76
-
77
97
  @retval = retval
78
98
  end
79
99
 
80
100
  def run_as(func, *args)
81
101
  val = send('vmr_' + func, *args)
82
- sleep(DELAY * 20) if func.include? 'set_param'
83
- sleep(DELAY * 50) if func.include? 'macro_set'
84
-
85
102
  self.retval = [val, func]
103
+ sleep(DELAY) if func.include?('set') && @wait
86
104
  end
87
105
  end
88
106
 
89
107
  module Define_Version
108
+ """
109
+ Defines the console layout for a specific kind of Voicemeeter.
110
+ """
90
111
  include Base
91
-
112
+ private
92
113
  def define_version(kind)
93
114
  case kind
94
115
  when "basic"
95
- self.properties = {
116
+ @properties = {
96
117
  :name => kind,
97
- :exe => "voicemeeter.exe"
118
+ :exe => "voicemeeter.exe",
98
119
  }
99
- self.layout = {
120
+ @layout = {
100
121
  :strip => {:p_in => 2, :v_in=> 1},
101
122
  :bus => {:p_out => 1, :v_out=> 1},
102
123
  :vban => {:instream => 4, :outstream => 4},
103
124
  :mb => 70,
104
125
  }
105
126
  when "banana"
106
- self.properties = {
127
+ @properties = {
107
128
  :name => kind,
108
- :exe => "voicemeeterpro.exe"
129
+ :exe => "voicemeeterpro.exe",
109
130
  }
110
- self.layout = {
131
+ @layout = {
111
132
  :strip => {:p_in => 3, :v_in=> 2},
112
133
  :bus => {:p_out => 3, :v_out=> 2},
113
134
  :vban => {:instream => 8, :outstream => 8},
114
135
  :mb => 70,
115
136
  }
116
137
  when "potato"
117
- self.properties = {
138
+ @properties = {
118
139
  :name => kind,
119
- :exe => "voicemeeter8#{OS_BITS == 64 ? "x64" : ""}.exe"
140
+ :exe => "voicemeeter8#{OS_BITS == 64 ? "x64" : ""}.exe",
120
141
  }
121
- self.layout = {
142
+ @layout = {
122
143
  :strip => {:p_in => 5, :v_in=> 3},
123
144
  :bus => {:p_out => 5, :v_out=> 3},
124
145
  :vban => {:instream => 8, :outstream => 8},
@@ -127,3 +148,24 @@ module Define_Version
127
148
  end
128
149
  end
129
150
  end
151
+
152
+
153
+ module Profiles
154
+ include Define_Version
155
+ private
156
+ def get_profiles
157
+ filepath = File.join(File.dirname(__dir__), "/profiles/#{@properties[:name]}/*.toml")
158
+
159
+ Dir.glob(filepath).to_h do |toml_file|
160
+ filename = File.basename(toml_file, ".toml")
161
+ puts "loading profile #{@properties[:name]}/#{filename}"
162
+ [filename, TOML::Parser.new(File.read(toml_file)).parsed]
163
+ end
164
+ end
165
+ public
166
+ def set_profile(value)
167
+ raise VMRemoteErrors.new("No profile with name #{value} was loaded") unless @profiles.key? value
168
+ self.send("set_multi", @profiles[value])
169
+ sleep(DELAY)
170
+ end
171
+ end
data/lib/bus.rb CHANGED
@@ -2,13 +2,14 @@ require_relative 'channel'
2
2
 
3
3
 
4
4
  class Bus < IChannel
5
+ """
6
+ Concrete class for Bus objects
7
+ """
5
8
  def self.make(remote, layout_bus)
6
9
  "
7
10
  Factory function for Bus classes.
8
11
  "
9
- p_out = layout_bus[:p_out]
10
- v_out = layout_bus[:v_out]
11
-
12
+ p_out, v_out = layout_bus.map { |k, v| v }
12
13
  (0...(p_out + v_out)).map do |i|
13
14
  i < p_out ? \
14
15
  PhysicalBus.new(remote, i) : \
@@ -20,6 +21,7 @@ class Bus < IChannel
20
21
  super
21
22
  self.make_accessor_bool :mute, :mono, :eq
22
23
  self.make_accessor_float :gain
24
+ self.make_accessor_string :label
23
25
  end
24
26
 
25
27
  def cmd
data/lib/button.rb CHANGED
@@ -18,6 +18,13 @@ class IMacroButton
18
18
  def setter(set, mode)
19
19
  @remote.macro_setstatus(@index, set, mode)
20
20
  end
21
+
22
+ def set_multi(param_hash)
23
+ param_hash.each do |(key,val)|
24
+ self.send("#{key}=", val)
25
+ end
26
+ sleep(remote.delay)
27
+ end
21
28
  end
22
29
 
23
30
 
@@ -32,4 +39,4 @@ class MacroButton < IMacroButton
32
39
  super
33
40
  self.make_accessor_macrobutton :state, :stateonly, :trigger
34
41
  end
35
- end
42
+ end
data/lib/channel.rb CHANGED
@@ -2,6 +2,9 @@ require_relative 'meta'
2
2
  require_relative 'errors'
3
3
 
4
4
  class IChannel
5
+ """
6
+ Base class for audio channels
7
+ """
5
8
  include Channel_Meta_Functions
6
9
 
7
10
  attr_accessor :remote, :index
@@ -22,4 +25,10 @@ class IChannel
22
25
  def cmd
23
26
  raise NotImplementedError
24
27
  end
28
+
29
+ def set_multi(param_hash)
30
+ param_hash.each do |(key,val)|
31
+ self.send("#{key}=", val)
32
+ end
33
+ end
25
34
  end
data/lib/command.rb CHANGED
@@ -23,18 +23,18 @@ end
23
23
  class Command < ICommand
24
24
  def initialize(remote)
25
25
  super
26
- self.make_writer_only :show, :restart, :reset, :shutdown
26
+ self.make_action_prop :show, :restart, :reset, :shutdown
27
27
  self.make_writer_bool :showvbanchat, :lock
28
28
  end
29
29
 
30
30
  def load(value)
31
- raise VMRemoteErrros.new("Expected a string") unless value.is_a? String
31
+ raise VMRemoteErrors.new("Expected a string") unless value.is_a? String
32
32
  self.setter("load", value)
33
33
  sleep(0.2)
34
34
  end
35
35
 
36
36
  def save(value)
37
- raise VMRemoteErrros.new("Expected a string") unless value.is_a? String
37
+ raise VMRemoteErrors.new("Expected a string") unless value.is_a? String
38
38
  self.setter("save", value)
39
39
  sleep(0.2)
40
40
  end
data/lib/errors.rb CHANGED
@@ -34,4 +34,4 @@ module Errors
34
34
  end
35
35
  end
36
36
  end
37
- end
37
+ end
data/lib/inst.rb CHANGED
@@ -4,11 +4,8 @@ require_relative 'errors'
4
4
 
5
5
  include Errors
6
6
 
7
- BASIC = 1
8
- BANANA = 2
9
- POTATO = 3
10
-
11
7
  module InstallationFunctions
8
+ private
12
9
  def get_arch
13
10
  key = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
14
11
  Win32::Registry::HKEY_LOCAL_MACHINE.open(key) do |reg|
@@ -23,7 +20,6 @@ module InstallationFunctions
23
20
  def get_vmpath(os_bits)
24
21
  vm_key = "VB:Voicemeeter {17359A74-1236-5467}"
25
22
  reg_key = "Software#{os_bits == 64 ? "\\WOW6432Node" : ""}\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
26
-
27
23
  Win32::Registry::HKEY_LOCAL_MACHINE.open(reg_key + vm_key) do |reg|
28
24
  value = reg["UninstallString"]
29
25
 
data/lib/meta.rb CHANGED
@@ -1,16 +1,20 @@
1
1
  require_relative 'errors'
2
2
 
3
+ class FalseClass; def to_i; 0 end end
4
+ class TrueClass; def to_i; 1 end end
5
+
3
6
  module Meta_Functions
7
+ private
4
8
  def make_accessor_bool(*params)
5
9
  params.each do |param|
6
10
  define_singleton_method("#{param}") do
7
11
  return !(self.getter("#{param}")).zero?
8
12
  end
9
13
 
10
- opts = [false, true]
14
+ opts = [false, true, 0, 1]
11
15
  define_singleton_method("#{param}=") do |value|
12
16
  raise OutOfBoundsErrors.new(opts) unless opts.include? value
13
- self.setter("#{param}", value ? 1 : 0)
17
+ self.setter("#{param}", value.to_i == 1 ? 1 : 0)
14
18
  end
15
19
  end
16
20
  end
@@ -64,12 +68,10 @@ module Meta_Functions
64
68
  end
65
69
  end
66
70
 
67
- def _make_channel_props(num_A, num_B)
68
- channels = (1..(num_A + num_B)).map.each do |i|
71
+ def make_channel_props(num_A, num_B)
72
+ (1..(num_A + num_B)).map do |i|
69
73
  i <= num_A ? "A#{i}" : "B#{i - num_A}"
70
74
  end
71
-
72
- self.make_accessor_bool *channels
73
75
  end
74
76
  end
75
77
 
@@ -88,10 +90,10 @@ module Channel_Meta_Functions
88
90
  return !(self.getter("#{val}")).zero?
89
91
  end
90
92
 
91
- opts = [false, true]
93
+ opts = [false, true, 0, 1]
92
94
  define_singleton_method("#{param}=") do |value|
93
95
  raise OutOfBoundsErrors.new(opts) unless opts.include? value
94
- self.setter("#{val}", value ? 1 : 0)
96
+ self.setter("#{val}", value.to_i == 1 ? 1 : 0)
95
97
  end
96
98
  end
97
99
  end
@@ -214,10 +216,10 @@ module MacroButton_Meta_Functions
214
216
  return !(self.getter(mode[param])).zero?
215
217
  end
216
218
 
217
- opts = [false, true]
219
+ opts = [false, true, 0, 1]
218
220
  define_singleton_method("#{param}=") do |value|
219
221
  raise OutOfBoundsErrors.new(opts[param]) unless opts.include? value
220
- self.setter(value ? 1 : 0, mode[param])
222
+ self.setter(value.to_i == 1 ? 1 : 0, mode[param])
221
223
  end
222
224
  end
223
225
  end
@@ -225,17 +227,25 @@ end
225
227
 
226
228
  module Commands_Meta_Functions
227
229
  include Meta_Functions
230
+ def make_action_prop(*params)
231
+ params.each do |param|
232
+ define_singleton_method("#{param}") do
233
+ self.setter("#{param}", 1)
234
+ end
235
+ end
236
+ end
237
+
228
238
  def make_writer_bool(*params)
229
239
  params.each do |param|
230
240
  cmds = {
231
241
  :showvbanchat => 'DialogShow.VBANCHAT',
232
242
  }
233
243
  if cmds[param] then val = cmds[param] else val = param end
234
-
244
+
235
245
  opts = [false, true]
236
246
  define_singleton_method("#{param}=") do |value|
237
- raise OutOfBoundsErrors.new(opts[param]) unless opts.include? value
238
- self.setter("#{val}", value ? 1 : 0)
247
+ raise OutOfBoundsErrors.new(opts) unless opts.include? value
248
+ self.setter("#{param}", value.to_i == 1 ? 1 : 0)
239
249
  end
240
250
  end
241
251
  end
data/lib/recorder.rb CHANGED
@@ -2,6 +2,9 @@ require_relative 'meta'
2
2
 
3
3
 
4
4
  class IRecorder
5
+ """
6
+ Base class for Recorder object
7
+ """
5
8
  include Meta_Functions
6
9
 
7
10
  attr_accessor :remote
@@ -25,13 +28,15 @@ end
25
28
 
26
29
 
27
30
  class Recorder < IRecorder
28
- def initialize(remote, layout_bus)
31
+ """
32
+ Concrete class for recorder
33
+ """
34
+ def initialize(remote)
29
35
  super(remote)
30
36
  self.make_writer_only :play, :stop, :record, :ff, :rew
31
37
 
32
- num_A = layout_bus[:p_out]
33
- num_B = layout_bus[:v_out]
34
- self._make_channel_props(num_A, num_B)
38
+ num_A, num_B = remote.layout[:bus].map { |k, v| v }
39
+ self.make_accessor_bool *make_channel_props(num_A, num_B)
35
40
  end
36
41
 
37
42
  def cmd
data/lib/routines.rb CHANGED
@@ -10,29 +10,29 @@ require_relative 'recorder'
10
10
 
11
11
  class Routines
12
12
  """
13
- define basic behaviours of API functions
14
- mixin modules
13
+ Define basic behaviours of API functions
14
+
15
+ Mixin required modules
15
16
  """
16
- include Define_Version
17
+ include Profiles
17
18
  include RunVM
18
19
 
19
- attr_accessor :properties, :layout, :strip, :bus, :button, :vban, :command,
20
- :recorder
20
+ attr_accessor :strip, :bus, :button, :vban, :command, :recorder
21
21
 
22
- attr_reader :retval
22
+ attr_reader :retval, :cache, :wait, :layout, :properties,
23
+ :delay, :max_polls, :profiles
23
24
 
24
25
  SIZE = 1
25
26
  BUFF = 512
26
27
 
27
- def initialize(kind)
28
+ def initialize(kind, **kwargs)
28
29
  define_version(kind)
29
30
 
30
- self.strip = Strip.make(self, @layout[:strip], @layout[:bus])
31
- self.bus = Bus.make(self, @layout[:bus])
32
- self.button = MacroButton.make(self, @layout[:mb])
33
- self.vban = Vban.make(self, @layout[:vban])
34
- self.command = Command.new(self)
35
- self.recorder = Recorder.new(self, @layout[:bus])
31
+ @cache = Hash.new
32
+ @wait = true
33
+ @delay = kwargs[:delay] || DELAY
34
+ @max_polls = kwargs[:max_polls] || MAX_POLLS
35
+ @profiles = get_profiles
36
36
  end
37
37
 
38
38
  def login
@@ -42,7 +42,8 @@ class Routines
42
42
  rescue CAPIErrors => error
43
43
  case
44
44
  when error.value == 1
45
- run_voicemeeter
45
+ self.start(@properties[:name])
46
+ clear_polling
46
47
  when error.value < 0
47
48
  raise
48
49
  end
@@ -54,16 +55,16 @@ class Routines
54
55
  end
55
56
 
56
57
  def get_parameter(name, is_string=false)
57
- self.polling(__method__.to_s)
58
-
59
- if is_string
60
- c_get = FFI::MemoryPointer.new(:string, BUFF, true)
61
- run_as("get_parameter_string", name, c_get)
62
- c_get.read_string
63
- else
64
- c_get = FFI::MemoryPointer.new(:float, SIZE)
65
- run_as("get_parameter_float", name, c_get)
66
- c_get.read_float.round(1)
58
+ self.polling("get_parameter", name: name) do
59
+ if is_string
60
+ c_get = FFI::MemoryPointer.new(:string, BUFF, true)
61
+ run_as("get_parameter_string", name, c_get)
62
+ c_get.read_string
63
+ else
64
+ c_get = FFI::MemoryPointer.new(:float, SIZE)
65
+ run_as("get_parameter_float", name, c_get)
66
+ c_get.read_float.round(1)
67
+ end
67
68
  end
68
69
  end
69
70
 
@@ -73,45 +74,50 @@ class Routines
73
74
  else
74
75
  run_as("set_parameter_float", name, value.to_f)
75
76
  end
77
+ @cache.store(name, [value, true])
76
78
  end
77
79
 
78
80
  def macro_getstatus(id, mode)
79
- self.polling(__method__.to_s)
80
-
81
- c_get = FFI::MemoryPointer.new(:float, SIZE)
82
- run_as("macro_getstatus", id, c_get, mode)
83
- c_get.read_float.to_i
81
+ self.polling("macro_getstatus", id: id, mode: mode) do
82
+ c_get = FFI::MemoryPointer.new(:float, SIZE)
83
+ run_as("macro_getstatus", id, c_get, mode)
84
+ c_get.read_float.to_i
85
+ end
84
86
  end
85
87
 
86
88
  def macro_setstatus(id, state, mode)
87
89
  run_as("macro_setstatus", id, state, mode)
90
+ @cache.store("mb_#{id}_#{mode}", [state, true])
88
91
  end
89
92
 
90
93
  def set_parameter_multi(param_hash)
94
+ @wait = false
91
95
  param_hash.each do |(key,val)|
92
- prop, m2, m3, *remaining = key.to_s.split('_')
93
- if m2.to_i.to_s == m2 then m2 = m2.to_i end
94
- if m3.to_i.to_s == m3 then m3 = m3.to_i end
95
-
96
- param_hash[key].each do |(k,v)|
97
- param = k
98
- value = v
99
-
100
- case prop
101
- when "strip"
102
- self.strip[m2].send("#{param}=", value)
103
- when "bus"
104
- self.bus[m2].send("#{param}=", value)
105
- when "button"
106
- self.button[m2].send("#{param}=", value)
107
- when "vban"
108
- if m2 == "instream"
109
- self.vban.instream[m3].send("#{param}=", value)
110
- else
111
- self.vban.outstream[m3].send("#{param}=", value)
112
- end
96
+ prop, m2, m3, *rem = key.to_s.split('_')
97
+ if m2.to_i.to_s == m2 then m2 = m2.to_i
98
+ elsif m3.to_i.to_s == m3 then m3 = m3.to_i end
99
+
100
+ case prop
101
+ when "strip"
102
+ self.strip[m2].set_multi(val)
103
+ when "bus"
104
+ self.bus[m2].set_multi(val)
105
+ when "button", "mb"
106
+ self.button[m2].set_multi(val)
107
+ when "vban"
108
+ if ["instream", "in"].include? m2
109
+ self.vban.instream[m3].set_multi(val)
110
+ elsif ["outstream", "out"].include? m2
111
+ self.vban.outstream[m3].set_multi(val)
113
112
  end
114
113
  end
115
114
  end
115
+ @wait = true
116
116
  end
117
+
118
+ alias_method "set_multi", :set_parameter_multi
119
+ alias_method "get", :get_parameter
120
+ alias_method "set", :set_parameter
121
+ alias_method "pdirty", :pdirty?
122
+ alias_method "mdirty", :pdirty?
117
123
  end
data/lib/runvm.rb CHANGED
@@ -1,20 +1,18 @@
1
- require 'open3'
2
- require_relative 'errors'
3
1
  require_relative 'base'
4
2
 
5
- module RunVM
6
- include Base
3
+ include Base
7
4
 
8
- def run_voicemeeter
9
- if VM_PATH.join(@properties[:exe]).executable?
10
- exe_path = String(VM_PATH.join(@properties[:exe]))
11
- else
12
- raise InstallErrors.new("Could not find Voicemeeter exe file")
5
+ module RunVM
6
+ """
7
+ Starts Voicemeeter of the Kind requested.
8
+ """
9
+ def start(kind)
10
+ enums = $kinds_all.map.with_index do |val, i|
11
+ get_arch == 64 && val == "potato" ? [val, i+4] : [val, i+1]
13
12
  end
13
+ exes = enums.to_h { |k, v| [k, v.to_i] }
14
14
 
15
- Open3.popen3(exe_path, '')
15
+ run_as('runvm', exes[kind])
16
16
  sleep(1)
17
-
18
- clear_polling
19
17
  end
20
18
  end
data/lib/strip.rb CHANGED
@@ -2,29 +2,29 @@ require_relative 'channel'
2
2
 
3
3
 
4
4
  class Strip < IChannel
5
- attr_reader :num_A, :num_B
6
-
7
- def self.make(remote, layout_strip, out_channels)
5
+ """
6
+ Concrete class for Strip objects
7
+ """
8
+ def self.make(remote, layout_strip)
8
9
  "
9
10
  Factory function for Strip classes.
10
11
  "
11
- p_in = layout_strip[:p_in]
12
- v_in = layout_strip[:v_in]
13
- num_A = out_channels[:p_out]
14
- num_B = out_channels[:v_out]
15
-
12
+ p_in, v_in = layout_strip.map { |k, v| v }
16
13
  (0...(p_in + v_in)).map do |i|
17
14
  i < p_in ? \
18
- PhysicalStrip.new(remote, i, num_A, num_B) : \
19
- VirtualStrip.new(remote, i, num_A, num_B)
15
+ PhysicalStrip.new(remote, i) : \
16
+ VirtualStrip.new(remote, i)
20
17
  end
21
18
  end
22
19
 
23
- def initialize(remote, i, num_A, num_B)
24
- super(remote, i)
20
+ def initialize(remote, i)
21
+ super
25
22
  self.make_accessor_bool :solo, :mute, :mono
26
23
  self.make_accessor_float :gain
27
- self._make_channel_props(num_A, num_B)
24
+ self.make_accessor_string :label
25
+
26
+ num_A, num_B = remote.layout[:bus].map { |k, v| v }
27
+ self.make_accessor_bool *make_channel_props(num_A, num_B)
28
28
  end
29
29
 
30
30
  def cmd
@@ -33,7 +33,7 @@ class Strip < IChannel
33
33
  end
34
34
 
35
35
  class PhysicalStrip < Strip
36
- def initialize(remote, i, num_A, num_B)
36
+ def initialize(remote, i)
37
37
  super
38
38
  self.make_accessor_float :comp, :gate
39
39
  self.make_accessor_int :limit
@@ -42,7 +42,7 @@ class PhysicalStrip < Strip
42
42
  end
43
43
 
44
44
  class VirtualStrip < Strip
45
- def initialize(remote, i, num_A, num_B)
45
+ def initialize(remote, i)
46
46
  super
47
47
  self.make_accessor_bool :mc, :k
48
48
  end
data/lib/vban.rb CHANGED
@@ -3,6 +3,9 @@ require_relative 'errors'
3
3
 
4
4
 
5
5
  class IVban
6
+ """
7
+ Base class for Vban objects
8
+ """
6
9
  include Vban_Meta_Functions
7
10
 
8
11
  attr_accessor :remote, :index
@@ -27,10 +30,19 @@ class IVban
27
30
  def direction
28
31
  raise NotImplementedError
29
32
  end
33
+
34
+ def set_multi(param_hash)
35
+ param_hash.each do |(key,val)|
36
+ self.send("#{key}=", val)
37
+ end
38
+ end
30
39
  end
31
40
 
32
41
 
33
42
  class Vban < IVban
43
+ """
44
+ Concrete class for Vban objects
45
+ """
34
46
  def self.make(remote, vban_streams)
35
47
  "
36
48
  Factory function for Vban class.
@@ -69,6 +81,7 @@ class Vban < IVban
69
81
  end
70
82
  end
71
83
 
84
+
72
85
  class VbanInstream < Vban
73
86
  def initialize(remote, i)
74
87
  super
@@ -80,6 +93,7 @@ class VbanInstream < Vban
80
93
  end
81
94
  end
82
95
 
96
+
83
97
  class VbanOutstream < Vban
84
98
  def initialize(remote, i)
85
99
  super
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Voicemeeter_API_Ruby
2
- VERSION = '2.0.0'
2
+ VERSION = '2.0.4'
3
3
  end
data/lib/voicemeeter.rb CHANGED
@@ -1,30 +1,60 @@
1
1
  require_relative 'routines'
2
2
  require_relative 'errors'
3
3
 
4
+
4
5
  module Voicemeeter
6
+ include RunVM
7
+
8
+ private
5
9
  class Remote < Routines
6
- def self.make
7
- ["basic", "banana", "potato"].to_h do |kind|
8
- [kind, Remote.new(kind)]
10
+ """
11
+ Remote class, subclasses Routines
12
+
13
+ Console layout built according to version definition.
14
+
15
+ Offers a run method for resource closure.
16
+ """
17
+ def self.make(**kwargs)
18
+ """
19
+ Factory function that generates a remote class for each kind.
20
+
21
+ Returns a hash of Remote classes.
22
+ """
23
+ $kinds_all.to_h do |kind|
24
+ [kind, Remote.new(kind, **kwargs)]
9
25
  end
10
26
  end
11
27
 
28
+ def initialize(kind)
29
+ super
30
+ self.strip = Strip.make(self, @layout[:strip])
31
+ self.bus = Bus.make(self, @layout[:bus])
32
+ self.button = MacroButton.make(self, @layout[:mb])
33
+ self.vban = Vban.make(self, @layout[:vban])
34
+ self.command = Command.new(self)
35
+ self.recorder = Recorder.new(self)
36
+ end
37
+
12
38
  def run
13
- if block_given?
14
- yield
15
-
16
- logout
17
- end
39
+ yield if block_given?
40
+
41
+ ensure
42
+ logout
18
43
  end
19
44
  end
20
45
 
21
- def remote(kind)
22
- _remotes = Remote.make
46
+ public
47
+ def remote(kind, **kwargs)
48
+ """
49
+ Request a Remote for a specific kind and login to the API
50
+ """
51
+ _remotes = Remote.make(**kwargs)
52
+
53
+ raise VMRemoteErrors.new("Unknown Voicemeeter Kind.") unless _remotes.key? kind
23
54
 
24
- raise VMRemoteErrors.new("Unknown Voicemeeter Kind") unless _remotes[kind]
25
55
  _remotes[kind].login
26
56
  return _remotes[kind]
27
57
  end
28
58
 
29
- module_function :remote
59
+ module_function :remote, :start
30
60
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: voicemeeter_api_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - onyx_online
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-17 00:00:00.000000000 Z
11
+ date: 2022-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi
@@ -30,6 +30,20 @@ dependencies:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: 1.9.10
33
+ - !ruby/object:Gem::Dependency
34
+ name: toml
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.3.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.3.0
33
47
  - !ruby/object:Gem::Dependency
34
48
  name: rake
35
49
  requirement: !ruby/object:Gem::Requirement