voicemeeter_api_ruby 4.1.4 → 4.3.0
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/CHANGELOG.md +18 -1
- data/README.md +23 -4
- data/lib/voicemeeter/base.rb +223 -0
- data/lib/voicemeeter/bus.rb +99 -0
- data/lib/voicemeeter/button.rb +25 -0
- data/lib/voicemeeter/cbindings.rb +126 -0
- data/lib/voicemeeter/command.rb +38 -0
- data/lib/voicemeeter/configs.rb +83 -0
- data/lib/voicemeeter/device.rb +26 -0
- data/lib/voicemeeter/errors.rb +43 -0
- data/lib/voicemeeter/inst.rb +27 -0
- data/lib/voicemeeter/iremote.rb +34 -0
- data/lib/voicemeeter/kinds.rb +79 -0
- data/lib/voicemeeter/meta.rb +255 -0
- data/lib/voicemeeter/mixin.rb +61 -0
- data/lib/voicemeeter/recorder.rb +22 -0
- data/lib/voicemeeter/runvm.rb +31 -0
- data/lib/voicemeeter/strip.rb +126 -0
- data/lib/voicemeeter/vban.rb +80 -0
- data/lib/voicemeeter/version.rb +25 -0
- data/lib/voicemeeter.rb +8 -8
- metadata +20 -19
- data/lib/base.rb +0 -219
- data/lib/bus.rb +0 -105
- data/lib/button.rb +0 -23
- data/lib/cbindings.rb +0 -125
- data/lib/command.rb +0 -36
- data/lib/configs.rb +0 -80
- data/lib/device.rb +0 -24
- data/lib/errors.rb +0 -41
- data/lib/inst.rb +0 -27
- data/lib/iremote.rb +0 -30
- data/lib/kinds.rb +0 -77
- data/lib/meta.rb +0 -275
- data/lib/recorder.rb +0 -20
- data/lib/runvm.rb +0 -29
- data/lib/strip.rb +0 -135
- data/lib/vban.rb +0 -78
- data/lib/version.rb +0 -3
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative "iremote"
|
2
|
+
require_relative "meta"
|
3
|
+
|
4
|
+
module Voicemeeter
|
5
|
+
class Device
|
6
|
+
def initialize(remote)
|
7
|
+
@remote = remote
|
8
|
+
end
|
9
|
+
|
10
|
+
def getter(**kwargs)
|
11
|
+
return @remote.get_num_devices(kwargs[:direction]) if kwargs[:index].nil?
|
12
|
+
|
13
|
+
vals = @remote.get_device_description(kwargs[:index], kwargs[:direction])
|
14
|
+
types = { 1 => "mme", 3 => "wdm", 4 => "ks", 5 => "asio" }
|
15
|
+
{ name: vals[0], type: types[vals[1]], id: vals[2] }
|
16
|
+
end
|
17
|
+
|
18
|
+
def ins = getter(direction: "in")
|
19
|
+
|
20
|
+
def outs = getter(direction: "out")
|
21
|
+
|
22
|
+
def input(i) = getter(index: i, direction: "in")
|
23
|
+
|
24
|
+
def output(i) = getter(index: i, direction: "out")
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Voicemeeter
|
2
|
+
module Errors
|
3
|
+
class VMRemoteErrors < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class InstallErrors < VMRemoteErrors
|
7
|
+
end
|
8
|
+
|
9
|
+
class CAPIErrors < VMRemoteErrors
|
10
|
+
attr_accessor :value, :func
|
11
|
+
|
12
|
+
def initialize(value, func)
|
13
|
+
self.value = value
|
14
|
+
self.func = func
|
15
|
+
end
|
16
|
+
|
17
|
+
def message
|
18
|
+
"
|
19
|
+
When attempting to run function #{@func} the
|
20
|
+
C API returned value #{@value}. See documentation for further info
|
21
|
+
"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class OutOfBoundsErrors < VMRemoteErrors
|
26
|
+
attr_accessor :range
|
27
|
+
|
28
|
+
def initialize(range)
|
29
|
+
self.range = range
|
30
|
+
end
|
31
|
+
|
32
|
+
def message
|
33
|
+
if @range.kind_of?(Range)
|
34
|
+
"Value error, expected value in range (#{range.first}..#{range.last})"
|
35
|
+
elsif @range.kind_of?(Array)
|
36
|
+
"Value error, expected one of: #{@range}"
|
37
|
+
else
|
38
|
+
"Value error, expected #{@range}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "win32/registry"
|
2
|
+
require "pathname"
|
3
|
+
require_relative "errors"
|
4
|
+
|
5
|
+
module Voicemeeter
|
6
|
+
module InstallationFunctions
|
7
|
+
private
|
8
|
+
|
9
|
+
def get_vmpath(os_bits)
|
10
|
+
vm_key = "VB:Voicemeeter {17359A74-1236-5467}"
|
11
|
+
reg_key =
|
12
|
+
"Software#{os_bits == 64 ? "\\WOW6432Node" : ""}\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
|
13
|
+
Win32::Registry::HKEY_LOCAL_MACHINE.open(reg_key + vm_key) do |reg|
|
14
|
+
value = reg["UninstallString"]
|
15
|
+
|
16
|
+
pn = Pathname.new(value)
|
17
|
+
return pn.dirname
|
18
|
+
end
|
19
|
+
raise InstallErrors.new("Could not get the Voicemeeter path")
|
20
|
+
end
|
21
|
+
|
22
|
+
def vm_dll=(value)
|
23
|
+
raise InstallErrors.new("Could not fetch the dll file") unless value.file?
|
24
|
+
@vm_dll = value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative "meta"
|
2
|
+
require_relative "errors"
|
3
|
+
|
4
|
+
module Voicemeeter
|
5
|
+
class IRemote
|
6
|
+
"
|
7
|
+
Common interface between base class and higher classes.
|
8
|
+
"
|
9
|
+
include Meta_Functions
|
10
|
+
|
11
|
+
def initialize(remote, i = nil)
|
12
|
+
@remote = remote
|
13
|
+
@index = i
|
14
|
+
end
|
15
|
+
|
16
|
+
def getter(param, is_string = false)
|
17
|
+
@remote.get_parameter("#{self.identifier}.#{param}", is_string)
|
18
|
+
end
|
19
|
+
|
20
|
+
def setter(param, value)
|
21
|
+
@remote.set_parameter("#{self.identifier}.#{param}", value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def identifier
|
25
|
+
raise "Called abstract method: identifier"
|
26
|
+
end
|
27
|
+
|
28
|
+
def set_multi(param_hash)
|
29
|
+
param_hash.each { |(key, val)| self.send("#{key}=", val) }
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method "apply", :set_multi
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Voicemeeter
|
2
|
+
module Kinds
|
3
|
+
"
|
4
|
+
A Kind struct for each version of Voicemeeter
|
5
|
+
"
|
6
|
+
attr_reader :kind_map, :kinds_all
|
7
|
+
|
8
|
+
Kind = Struct.new(:name, :layout)
|
9
|
+
basic =
|
10
|
+
Kind.new(
|
11
|
+
"basic",
|
12
|
+
{
|
13
|
+
strip: {
|
14
|
+
p_in: 2,
|
15
|
+
v_in: 1
|
16
|
+
},
|
17
|
+
bus: {
|
18
|
+
p_out: 1,
|
19
|
+
v_out: 1
|
20
|
+
},
|
21
|
+
vban: {
|
22
|
+
instream: 4,
|
23
|
+
outstream: 4
|
24
|
+
},
|
25
|
+
mb: 80
|
26
|
+
}
|
27
|
+
)
|
28
|
+
|
29
|
+
banana =
|
30
|
+
Kind.new(
|
31
|
+
"banana",
|
32
|
+
{
|
33
|
+
strip: {
|
34
|
+
p_in: 3,
|
35
|
+
v_in: 2
|
36
|
+
},
|
37
|
+
bus: {
|
38
|
+
p_out: 3,
|
39
|
+
v_out: 2
|
40
|
+
},
|
41
|
+
vban: {
|
42
|
+
instream: 8,
|
43
|
+
outstream: 8
|
44
|
+
},
|
45
|
+
mb: 80
|
46
|
+
}
|
47
|
+
)
|
48
|
+
|
49
|
+
potato =
|
50
|
+
Kind.new(
|
51
|
+
"potato",
|
52
|
+
{
|
53
|
+
strip: {
|
54
|
+
p_in: 5,
|
55
|
+
v_in: 3
|
56
|
+
},
|
57
|
+
bus: {
|
58
|
+
p_out: 5,
|
59
|
+
v_out: 3
|
60
|
+
},
|
61
|
+
vban: {
|
62
|
+
instream: 8,
|
63
|
+
outstream: 8
|
64
|
+
},
|
65
|
+
mb: 80
|
66
|
+
}
|
67
|
+
)
|
68
|
+
|
69
|
+
@kind_map = [basic, banana, potato].to_h { |kind| [kind.name, kind] }
|
70
|
+
|
71
|
+
def get_kind(kind_id)
|
72
|
+
@kind_map[kind_id]
|
73
|
+
end
|
74
|
+
|
75
|
+
@kinds_all = @kind_map.values
|
76
|
+
|
77
|
+
module_function :get_kind, :kind_map, :kinds_all
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,255 @@
|
|
1
|
+
require_relative "errors"
|
2
|
+
|
3
|
+
module Voicemeeter
|
4
|
+
module Conversions
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def Boolean(value)
|
8
|
+
case value
|
9
|
+
when true, 1
|
10
|
+
true
|
11
|
+
when false, nil, 0
|
12
|
+
false
|
13
|
+
else
|
14
|
+
raise ArgumentError, "invalid value for Boolean(): \"#{value.inspect}\""
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Meta_Functions
|
20
|
+
private
|
21
|
+
|
22
|
+
include Conversions
|
23
|
+
|
24
|
+
def make_accessor_bool(*params)
|
25
|
+
params.each do |param|
|
26
|
+
define_singleton_method("#{param}") do
|
27
|
+
return !(self.getter("#{param}")).zero?
|
28
|
+
end
|
29
|
+
|
30
|
+
define_singleton_method("#{param}=") do |value|
|
31
|
+
self.setter("#{param}", Boolean(value) ? 1 : 0)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def make_accessor_int(*params)
|
37
|
+
params.each do |param|
|
38
|
+
define_singleton_method("#{param}") do
|
39
|
+
return self.getter("#{param}").to_i
|
40
|
+
end
|
41
|
+
|
42
|
+
define_singleton_method("#{param}=") do |value|
|
43
|
+
self.setter("#{param}", value)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def make_accessor_float(*params)
|
49
|
+
params.each do |param|
|
50
|
+
define_singleton_method("#{param}") { return self.getter("#{param}") }
|
51
|
+
|
52
|
+
define_singleton_method("#{param}=") do |value|
|
53
|
+
self.setter("#{param}", value)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def make_accessor_string(*params)
|
59
|
+
params.each do |param|
|
60
|
+
define_singleton_method("#{param}") do
|
61
|
+
return self.getter("#{param}", true)
|
62
|
+
end
|
63
|
+
|
64
|
+
define_singleton_method("#{param}=") do |value|
|
65
|
+
self.setter("#{param}", value)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def make_reader_only(*params)
|
71
|
+
params.each do |param|
|
72
|
+
define_singleton_method("#{param}") { return self.getter("#{param}") }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def make_writer_only(*params)
|
77
|
+
params.each do |param|
|
78
|
+
define_singleton_method("#{param}=") do |value = 1|
|
79
|
+
self.setter("#{param}", value)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def make_channel_props(num_A, num_B)
|
85
|
+
(1..(num_A + num_B)).map { |i| i <= num_A ? "A#{i}" : "B#{i - num_A}" }
|
86
|
+
end
|
87
|
+
|
88
|
+
def make_action_prop(*params)
|
89
|
+
params.each do |param|
|
90
|
+
define_singleton_method("#{param}") { self.setter("#{param}", 1) }
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
module Channel_Meta_Functions
|
96
|
+
private
|
97
|
+
|
98
|
+
include Meta_Functions
|
99
|
+
|
100
|
+
def make_accessor_bool(*params)
|
101
|
+
params.each do |param|
|
102
|
+
cmds = { eq: "EQ.on", eq_ab: "EQ.ab" }
|
103
|
+
if cmds.key? param
|
104
|
+
cmd = cmds[param]
|
105
|
+
else
|
106
|
+
cmd = param
|
107
|
+
end
|
108
|
+
|
109
|
+
define_singleton_method("#{param}") do
|
110
|
+
return !(self.getter("#{cmd}")).zero?
|
111
|
+
end
|
112
|
+
|
113
|
+
define_singleton_method("#{param}=") do |value|
|
114
|
+
self.setter("#{cmd}", Boolean(value) ? 1 : 0)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def make_reader_only(*params)
|
120
|
+
params.each do |param|
|
121
|
+
cmds = { device: "device.name", sr: "device.sr" }
|
122
|
+
if cmds.key? param
|
123
|
+
cmd = cmds[param]
|
124
|
+
else
|
125
|
+
cmd = param
|
126
|
+
end
|
127
|
+
|
128
|
+
define_singleton_method("#{param}") do
|
129
|
+
case param
|
130
|
+
when :device
|
131
|
+
return self.getter("#{cmd}", true)
|
132
|
+
when :sr
|
133
|
+
return self.getter("#{cmd}").to_i
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def make_bus_modes(*params)
|
140
|
+
params.each do |param|
|
141
|
+
define_singleton_method("#{param}") do
|
142
|
+
@remote.clear_polling
|
143
|
+
return !(self.getter("#{param}")).zero?
|
144
|
+
end
|
145
|
+
|
146
|
+
define_singleton_method("#{param}=") do |value|
|
147
|
+
self.setter("#{param}", Boolean(value) ? 1 : 0)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
module Vban_Meta_Functions
|
154
|
+
private
|
155
|
+
|
156
|
+
include Meta_Functions
|
157
|
+
|
158
|
+
def make_reader_int(*params)
|
159
|
+
params.each do |param|
|
160
|
+
define_singleton_method("#{param}") do
|
161
|
+
case param
|
162
|
+
when :bit
|
163
|
+
return self.getter("#{param}").to_i == 1 ? 16 : 24
|
164
|
+
else
|
165
|
+
return self.getter("#{param}").to_i
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def make_accessor_int(*params)
|
172
|
+
params.each do |param|
|
173
|
+
define_singleton_method("#{param}") do
|
174
|
+
case param
|
175
|
+
when :bit
|
176
|
+
return self.getter("#{param}").to_i == 1 ? 16 : 24
|
177
|
+
else
|
178
|
+
return self.getter("#{param}").to_i
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
opts = {
|
183
|
+
sr: [
|
184
|
+
11_025,
|
185
|
+
16_000,
|
186
|
+
22_050,
|
187
|
+
24_000,
|
188
|
+
32_000,
|
189
|
+
44_100,
|
190
|
+
48_000,
|
191
|
+
64_000,
|
192
|
+
88_200,
|
193
|
+
96_000
|
194
|
+
],
|
195
|
+
channel: (1..8),
|
196
|
+
bit: [16, 24],
|
197
|
+
quality: (0..4),
|
198
|
+
route: (0..8)
|
199
|
+
}
|
200
|
+
|
201
|
+
define_singleton_method("#{param}=") do |value|
|
202
|
+
unless opts[param].member? value
|
203
|
+
raise OutOfBoundsErrors.new(opts[param])
|
204
|
+
end
|
205
|
+
case param
|
206
|
+
when :bit
|
207
|
+
self.setter("#{param}", value == 16 ? 1 : 2)
|
208
|
+
else
|
209
|
+
self.setter("#{param}", value)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
module MacroButton_Meta_Functions
|
217
|
+
private
|
218
|
+
|
219
|
+
include Conversions
|
220
|
+
|
221
|
+
def make_accessor_macrobutton(*params)
|
222
|
+
params.each do |param|
|
223
|
+
mode = { state: 1, stateonly: 2, trigger: 3 }
|
224
|
+
|
225
|
+
define_singleton_method("#{param}") do
|
226
|
+
return !(self.getter(mode[param])).zero?
|
227
|
+
end
|
228
|
+
|
229
|
+
define_singleton_method("#{param}=") do |value|
|
230
|
+
self.setter(Boolean(value) ? 1 : 0, mode[param])
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
module Commands_Meta_Functions
|
237
|
+
private
|
238
|
+
|
239
|
+
include Meta_Functions
|
240
|
+
def make_writer_bool(*params)
|
241
|
+
params.each do |param|
|
242
|
+
cmds = { showvbanchat: "DialogShow.VBANCHAT" }
|
243
|
+
if cmds.key? param
|
244
|
+
cmd = cmds[param]
|
245
|
+
else
|
246
|
+
cmd = param
|
247
|
+
end
|
248
|
+
|
249
|
+
define_singleton_method("#{param}=") do |value|
|
250
|
+
self.setter("#{cmd}", Boolean(value) ? 1 : 0)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Voicemeeter
|
2
|
+
module Mixin
|
3
|
+
module Fades
|
4
|
+
def fadeto(target, time)
|
5
|
+
self.setter("FadeTo", "(#{target}, #{time})")
|
6
|
+
sleep(@remote.delay)
|
7
|
+
end
|
8
|
+
|
9
|
+
def fadeby(change, time)
|
10
|
+
self.setter("FadeBy", "(#{change}, #{time})")
|
11
|
+
sleep(@remote.delay)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Apps
|
16
|
+
def appgain(name, gain)
|
17
|
+
self.setter("AppGain", "(\"#{name}\", #{gain})")
|
18
|
+
end
|
19
|
+
|
20
|
+
def appmute(name, mute)
|
21
|
+
self.setter("AppMute", "(\"#{name}\", #{mute ? 1 : 0})")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module Xy
|
26
|
+
include Channel_Meta_Functions
|
27
|
+
|
28
|
+
def initialize(remote, i)
|
29
|
+
super
|
30
|
+
self.make_accessor_float :pan_x,
|
31
|
+
:pan_y,
|
32
|
+
:color_x,
|
33
|
+
:color_y,
|
34
|
+
:fx_x,
|
35
|
+
:fx_y
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module Fx
|
40
|
+
include Channel_Meta_Functions
|
41
|
+
|
42
|
+
def initialize(remote, i)
|
43
|
+
super
|
44
|
+
self.make_accessor_float :reverb, :delay, :fx1, :fx2
|
45
|
+
self.make_accessor_bool :postreverb, :postdelay, :postfx1, :postfx2
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module Return
|
50
|
+
include Channel_Meta_Functions
|
51
|
+
|
52
|
+
def initialize(remote, i)
|
53
|
+
super
|
54
|
+
self.make_accessor_float :returnreverb,
|
55
|
+
:returndelay,
|
56
|
+
:returnfx1,
|
57
|
+
:returnfx2
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative "iremote"
|
2
|
+
require_relative "meta"
|
3
|
+
|
4
|
+
module Voicemeeter
|
5
|
+
class Recorder < IRemote
|
6
|
+
"
|
7
|
+
Concrete Recorder class
|
8
|
+
"
|
9
|
+
|
10
|
+
def initialize(remote)
|
11
|
+
super
|
12
|
+
self.make_action_prop :play, :stop, :record, :ff, :rew
|
13
|
+
|
14
|
+
num_A, num_B = remote.kind.layout[:bus].values
|
15
|
+
self.make_accessor_bool *make_channel_props(num_A, num_B)
|
16
|
+
end
|
17
|
+
|
18
|
+
def identifier
|
19
|
+
:recorder
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative "cbindings"
|
2
|
+
require_relative "kinds"
|
3
|
+
|
4
|
+
module Voicemeeter
|
5
|
+
module RunVM
|
6
|
+
"
|
7
|
+
Starts Voicemeeter of the Kind requested.
|
8
|
+
"
|
9
|
+
include CBindings
|
10
|
+
include Kinds
|
11
|
+
|
12
|
+
def start(kind_id)
|
13
|
+
unless Kinds.kind_map.key? kind_id
|
14
|
+
raise VMRemoteErrors.new("Unknown Voicemeeter Kind.")
|
15
|
+
end
|
16
|
+
|
17
|
+
enums =
|
18
|
+
Kinds.kinds_all.map.with_index do |kind, i|
|
19
|
+
if CBindings::OS_BITS == 64 && kind.name.to_s == "potato"
|
20
|
+
[kind.name.to_s, i + 4]
|
21
|
+
else
|
22
|
+
[kind.name.to_s, i + 1]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
exes = enums.to_h { |k, v| [k, v.to_i] }
|
26
|
+
|
27
|
+
CBindings.vm_runvm(exes[kind_id])
|
28
|
+
sleep(1)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require_relative "iremote"
|
2
|
+
require_relative "mixin"
|
3
|
+
|
4
|
+
module Voicemeeter
|
5
|
+
class Strip < IRemote
|
6
|
+
"
|
7
|
+
Concrete Strip class
|
8
|
+
"
|
9
|
+
include Channel_Meta_Functions
|
10
|
+
include Mixin::Fades
|
11
|
+
|
12
|
+
attr_accessor :gainlayer, :levels
|
13
|
+
|
14
|
+
def self.make(remote, layout_strip)
|
15
|
+
"
|
16
|
+
Factory function for Strip classes.
|
17
|
+
"
|
18
|
+
p_in, v_in = layout_strip.values
|
19
|
+
(0...(p_in + v_in)).map do |i|
|
20
|
+
i < p_in ? PhysicalStrip.new(remote, i) : VirtualStrip.new(remote, i)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(remote, i)
|
25
|
+
super
|
26
|
+
self.make_accessor_bool :solo, :mute, :mono
|
27
|
+
self.make_accessor_float :gain
|
28
|
+
self.make_accessor_int :limit
|
29
|
+
self.make_accessor_string :label
|
30
|
+
|
31
|
+
num_A, num_B = remote.kind.layout[:bus].values
|
32
|
+
self.make_accessor_bool *make_channel_props(num_A, num_B)
|
33
|
+
|
34
|
+
@gainlayer = (0...8).map { |j| GainLayer.new(remote, i, j) }
|
35
|
+
@levels = StripLevels.new(remote, i)
|
36
|
+
end
|
37
|
+
|
38
|
+
def identifier
|
39
|
+
"strip[#{@index}]"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class PhysicalStrip < Strip
|
44
|
+
include Mixin::Xy
|
45
|
+
include Mixin::Fx
|
46
|
+
|
47
|
+
def initialize(remote, i)
|
48
|
+
super
|
49
|
+
self.make_accessor_float :comp, :gate, :audibility
|
50
|
+
self.make_reader_only :device, :sr
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class VirtualStrip < Strip
|
55
|
+
include Mixin::Apps
|
56
|
+
|
57
|
+
def initialize(remote, i)
|
58
|
+
super
|
59
|
+
self.make_accessor_bool :mc
|
60
|
+
self.make_accessor_int :k
|
61
|
+
self.make_accessor_float :bass, :mid, :treble
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class GainLayer < IRemote
|
66
|
+
def initialize(remote, i, j)
|
67
|
+
super(remote, i)
|
68
|
+
@j = j
|
69
|
+
end
|
70
|
+
|
71
|
+
def identifier
|
72
|
+
"strip[#{@index}]"
|
73
|
+
end
|
74
|
+
|
75
|
+
def gain
|
76
|
+
self.getter("gainlayer[#{@j}]")
|
77
|
+
end
|
78
|
+
|
79
|
+
def gain=(value)
|
80
|
+
self.setter("gainlayer[#{@j}]", value)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class StripLevels < IRemote
|
85
|
+
def initialize(remote, i)
|
86
|
+
super
|
87
|
+
if i < @remote.p_in
|
88
|
+
@init = i * 2
|
89
|
+
@offset = 2
|
90
|
+
else
|
91
|
+
@init = (@remote.p_in * 2) + ((i - @remote.p_in) * 8)
|
92
|
+
@offset = 8
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def identifier
|
97
|
+
"strip[#{@index}]"
|
98
|
+
end
|
99
|
+
|
100
|
+
def get_level(mode)
|
101
|
+
if @remote.running
|
102
|
+
vals = @remote.cache["strip_level"][@init, @offset]
|
103
|
+
else
|
104
|
+
vals = (@init...@offset).map { |i| get_level(mode, i) }
|
105
|
+
end
|
106
|
+
vals.map { |x| x > 0 ? (20 * Math.log(x, 10)).round(1) : -200.0 }
|
107
|
+
end
|
108
|
+
|
109
|
+
def prefader
|
110
|
+
@remote.strip_mode = 0
|
111
|
+
get_level(0)
|
112
|
+
end
|
113
|
+
|
114
|
+
def postfader
|
115
|
+
@remote.strip_mode = 1
|
116
|
+
get_level(1)
|
117
|
+
end
|
118
|
+
|
119
|
+
def postmute
|
120
|
+
@remote.strip_mode = 2
|
121
|
+
get_level(2)
|
122
|
+
end
|
123
|
+
|
124
|
+
def isdirty? = @remote._strip_comp[@init, @offset].any?
|
125
|
+
end
|
126
|
+
end
|