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 +4 -4
- data/lib/base.rb +64 -22
- data/lib/bus.rb +5 -3
- data/lib/button.rb +8 -1
- data/lib/channel.rb +9 -0
- data/lib/command.rb +3 -3
- data/lib/errors.rb +1 -1
- data/lib/inst.rb +1 -5
- data/lib/meta.rb +23 -13
- data/lib/recorder.rb +9 -4
- data/lib/routines.rb +56 -50
- data/lib/runvm.rb +10 -12
- data/lib/strip.rb +15 -15
- data/lib/vban.rb +14 -0
- data/lib/version.rb +1 -1
- data/lib/voicemeeter.rb +42 -12
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: feb89f841882b2ece4f1bc959c8a5a728a738b054798635d2937ff9dceacf37c
|
4
|
+
data.tar.gz: 382ba6af1cde36e8b450d0549e383f9e6c68040d8385923ec8b2c413ddfc3d1b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
-
|
116
|
+
@properties = {
|
96
117
|
:name => kind,
|
97
|
-
:exe => "voicemeeter.exe"
|
118
|
+
:exe => "voicemeeter.exe",
|
98
119
|
}
|
99
|
-
|
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
|
-
|
127
|
+
@properties = {
|
107
128
|
:name => kind,
|
108
|
-
:exe => "voicemeeterpro.exe"
|
129
|
+
:exe => "voicemeeterpro.exe",
|
109
130
|
}
|
110
|
-
|
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
|
-
|
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
|
-
|
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
|
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.
|
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
|
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
|
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
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
|
68
|
-
|
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
|
238
|
-
self.setter("#{
|
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
|
-
|
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 =
|
33
|
-
|
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
|
-
|
14
|
-
|
13
|
+
Define basic behaviours of API functions
|
14
|
+
|
15
|
+
Mixin required modules
|
15
16
|
"""
|
16
|
-
include
|
17
|
+
include Profiles
|
17
18
|
include RunVM
|
18
19
|
|
19
|
-
attr_accessor :
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
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(
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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(
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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, *
|
93
|
-
if m2.to_i.to_s == m2 then m2 = m2.to_i
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
-
|
6
|
-
include Base
|
3
|
+
include Base
|
7
4
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
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
|
-
|
6
|
-
|
7
|
-
|
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
|
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
|
19
|
-
VirtualStrip.new(remote, i
|
15
|
+
PhysicalStrip.new(remote, i) : \
|
16
|
+
VirtualStrip.new(remote, i)
|
20
17
|
end
|
21
18
|
end
|
22
19
|
|
23
|
-
def initialize(remote, i
|
24
|
-
super
|
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.
|
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
|
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
|
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
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
|
-
|
7
|
-
|
8
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
39
|
+
yield if block_given?
|
40
|
+
|
41
|
+
ensure
|
42
|
+
logout
|
18
43
|
end
|
19
44
|
end
|
20
45
|
|
21
|
-
|
22
|
-
|
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.
|
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-
|
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
|