voicemeeter_api_ruby 4.1.5 → 4.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29df5251a1e4d779dd265a785112c0c8907b89f5f9a30a45a9e50985ed2400e7
4
- data.tar.gz: c4a9acbbbe3330aca966d4470373b9ec9f9fe3bcefa0b1f6e60ed665b853c712
3
+ metadata.gz: dfec081c74f1dbdd1b315bd0c3aeaff0b80da1e520b995c584d087f2753cb56e
4
+ data.tar.gz: 5e40c74ebc5d8aef7f153f278b3737387f43748604d073d35a308fa817a21627
5
5
  SHA512:
6
- metadata.gz: c9e8f17bd773dbbbb9980f5bb91283b0f97be75acff6f2bf0c2315721fdfc9916509ec86a0a28e6db3d548fadbb161c3b40da9cbd8639b4fc98719fe309d1e27
7
- data.tar.gz: 12d256fb220ab60c3492d65855ed6cdf714af851f1a7dfcb2d6b3297e2c844a9776162ff600351c9f4baeb71a3a2e99492e19388a588f459301ed1aff4259d7d
6
+ metadata.gz: 189d225992622d19c21d7eb6a3f81e08db74b5b5556b7f8794bcc3fe4c0efe17393fbd6897bae1c869d1b4ebef9eafae1433827a1ecafecb393e0349260bcfb8
7
+ data.tar.gz: 933d748eb4ca2bcae4081a35c4b3cc9258b08defa79fca143c0caced8ec3c00773c55acc086f71f36c9ede579515dca945dcd26de335ed825dedd8a2529294a3
data/CHANGELOG.md CHANGED
@@ -9,7 +9,24 @@ Before any major/minor/patch is released all unit tests will be run to verify th
9
9
 
10
10
  ## [Unreleased] - These changes have not been added to RubyGems yet
11
11
 
12
- - [ ] add xy parameters to strip/bus
12
+ - [ ]
13
+
14
+ ## [4.3.0] - 2022-07-29
15
+
16
+ ### Added
17
+
18
+ - Mixin module
19
+ - xy, fx parameters to strip/bus
20
+ - unit tests for xy, fx
21
+ - xy, fx to readme
22
+ - config tests added
23
+ - gemfile to obs example
24
+
25
+ ### Changed
26
+
27
+ - moved gem files into voicemeeter/ dir
28
+ - update obs example
29
+ - using require_relative in case using direct download.
13
30
 
14
31
  ## [4.1.0] - 2022-07-19
15
32
 
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
+ [![Gem Version](https://badge.fury.io/rb/voicemeeter_api_ruby.svg)](https://badge.fury.io/rb/voicemeeter_api_ruby)
2
+ ![Gem Downloads](https://ruby-gem-downloads-badge.herokuapp.com/voicemeeter_api_ruby?type=total&color=red)
1
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/onyx-and-iris/voicemeeter-api-ruby/blob/dev/LICENSE)
2
4
  [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/plugin-ruby)
3
5
  ![tests: failed count](https://img.shields.io/badge/dynamic/json?color=blue&label=tests&query=summary.failure_count&suffix=%20failed&url=https%3A%2F%2Fraw.githubusercontent.com%2Fonyx-and-iris%2Fvoicemeeter-api-ruby%2Fdev%2Fspec%2Frspec.json)
4
- [![Gem Version](https://badge.fury.io/rb/voicemeeter_api_ruby.svg)](https://badge.fury.io/rb/voicemeeter_api_ruby)
5
- ![](https://ruby-gem-downloads-badge.herokuapp.com/voicemeeter_api_ruby?type=total&color=red)
6
6
 
7
7
  # Ruby Wrapper for Voicemeeter API
8
8
 
@@ -98,6 +98,20 @@ The following properties are available.
98
98
  - `bass`: float, from -12.0 to 12.0
99
99
  - `mid`: float, from -12.0 to 12.0
100
100
  - `treble`: float, from -12.0 to 12.0
101
+ - `reverb`: float, from 0.0 to 10.0
102
+ - `delay`: float, from 0.0 to 10.0
103
+ - `fx1`: float, from 0.0 to 10.0
104
+ - `fx2`: float, from 0.0 to 10.0
105
+ - `pan_x`: float, from -0.5 to 0.5
106
+ - `pan_y`: float, from 0.0 to 1.0
107
+ - `color_x`: float, from -0.5 to 0.5
108
+ - `color_y`: float, from 0.0 to 1.0
109
+ - `fx_x`: float, from -0.5 to 0.5
110
+ - `fx_y`: float, from 0.0 to 1.0
111
+ - `postreverb`: boolean
112
+ - `postdelay`: boolean
113
+ - `postfx1`: boolean
114
+ - `postfx2`: boolean
101
115
 
102
116
  example:
103
117
 
@@ -164,6 +178,11 @@ The following properties are available.
164
178
  - `label`: string
165
179
  - `device`: string
166
180
  - `sr`: int
181
+ - `returnreverb`: float, from 0.0 to 10.0
182
+ - `returndelay`: float, from 0.0 to 10.0
183
+ - `returnfx1`: float, from 0.0 to 10.0
184
+ - `returnfx2`: float, from 0.0 to 10.0
185
+ - `monitor`: boolean
167
186
 
168
187
  example:
169
188
 
@@ -264,10 +283,10 @@ vm.recorder.play
264
283
  vm.recorder.stop
265
284
 
266
285
  # Enable loop play
267
- vm.recorder.loop = True
286
+ vm.recorder.loop = true
268
287
 
269
288
  # Disable recorder out channel B2
270
- vm.recorder.B2 = False
289
+ vm.recorder.B2 = false
271
290
 
272
291
  # filepath as string
273
292
  vm.recorder.load('C:\music\mytune.mp3')
@@ -300,7 +319,7 @@ example:
300
319
  vm.vban.enable
301
320
 
302
321
  # turn on vban instream 0
303
- vm.vban.instream[0].on = True
322
+ vm.vban.instream[0].on = true
304
323
 
305
324
  # set bit property for outstream 3 to 24
306
325
  vm.vban.outstream[3].bit = 24
@@ -0,0 +1,223 @@
1
+ require "observer"
2
+
3
+ require_relative "runvm"
4
+ require_relative "configs"
5
+ require_relative "errors"
6
+
7
+ module Voicemeeter
8
+ class Base
9
+ "
10
+ Base class responsible for wrapping the C Remote API
11
+
12
+ Mixin required modules
13
+ "
14
+ include Observable
15
+ include Configs
16
+ include RunVM
17
+
18
+ attr_accessor :strip, :bus, :button, :vban, :command, :recorder, :device
19
+ attr_accessor :strip_mode
20
+
21
+ attr_reader :kind, :p_in, :v_in, :p_out, :v_out, :retval, :cache
22
+ attr_reader :running, :_strip_comp, :_bus_comp, :delay
23
+
24
+ DELAY = 0.001
25
+ SYNC = false
26
+ RATELIMIT = 0.033
27
+ SIZE = 1
28
+
29
+ def initialize(kind, **kwargs)
30
+ @kind = kind
31
+ @p_in, @v_in = kind.layout[:strip].values
32
+ @p_out, @v_out = kind.layout[:bus].values
33
+ @cache = Hash.new
34
+ @sync = kwargs[:sync] || SYNC
35
+ @ratelimit = kwargs[:ratelimit] || RATELIMIT
36
+ @running = false
37
+ @strip_mode = 0
38
+ @delay = DELAY
39
+ end
40
+
41
+ def init_thread
42
+ @running = true
43
+ @cache["strip_level"], @cache["bus_level"] = _get_levels
44
+ Thread.new do
45
+ loop do
46
+ Thread.stop if !@running
47
+ if pdirty?
48
+ changed
49
+ notify_observers("pdirty")
50
+ end
51
+ if mdirty?
52
+ changed
53
+ notify_observers("mdirty")
54
+ end
55
+ if ldirty?
56
+ changed
57
+ @_strip_comp =
58
+ @cache["strip_level"].map.with_index do |x, i|
59
+ !(x == @strip_buf[i])
60
+ end
61
+ @_bus_comp =
62
+ @cache["bus_level"].map.with_index { |x, i| !(x == @bus_buf[i]) }
63
+ @cache["strip_level"] = @strip_buf
64
+ @cache["bus_level"] = @bus_buf
65
+ notify_observers("ldirty")
66
+ end
67
+ sleep(@ratelimit)
68
+ end
69
+ end
70
+ end
71
+
72
+ def end_thread
73
+ @running = false
74
+ end
75
+
76
+ def login
77
+ @@cdll.call(:login)
78
+ clear_polling
79
+ rescue CAPIErrors => error
80
+ case
81
+ when error.value == 1
82
+ self.start(@kind.name)
83
+ clear_polling
84
+ when error.value < 0
85
+ raise
86
+ end
87
+ end
88
+
89
+ def logout
90
+ clear_polling
91
+ sleep(0.1)
92
+ @@cdll.call(:logout)
93
+ end
94
+
95
+ def type
96
+ c_type = FFI::MemoryPointer.new(:long, SIZE)
97
+ @@cdll.call(:vmtype, c_type)
98
+ types = { 1 => "basic", 2 => "banana", 3 => "potato" }
99
+ types[c_type.read_long]
100
+ end
101
+
102
+ def version
103
+ c_ver = FFI::MemoryPointer.new(:long, SIZE)
104
+ @@cdll.call(:vmversion, c_ver)
105
+ v1 = (c_ver.read_long & 0xFF000000) >> 24
106
+ v2 = (c_ver.read_long & 0x00FF0000) >> 16
107
+ v3 = (c_ver.read_long & 0x0000FF00) >> 8
108
+ v4 = c_ver.read_long & 0x000000FF
109
+ "#{v1}.#{v2}.#{v3}.#{v4}"
110
+ end
111
+
112
+ def get_parameter(name, is_string = false)
113
+ self.polling("get_parameter", name: name) do
114
+ if is_string
115
+ c_get = FFI::MemoryPointer.new(:string, 512, true)
116
+ @@cdll.call(:get_parameter_string, name, c_get)
117
+ c_get.read_string
118
+ else
119
+ c_get = FFI::MemoryPointer.new(:float, SIZE)
120
+ @@cdll.call(:get_parameter_float, name, c_get)
121
+ c_get.read_float.round(1)
122
+ end
123
+ end
124
+ end
125
+
126
+ def set_parameter(name, value)
127
+ if value.is_a? String
128
+ @@cdll.call(:set_parameter_string, name, value)
129
+ else
130
+ @@cdll.call(:set_parameter_float, name, value.to_f)
131
+ end
132
+ @cache.store(name, value)
133
+ end
134
+
135
+ def get_buttonstatus(id, mode)
136
+ self.polling("get_buttonstatus", id: id, mode: mode) do
137
+ c_get = FFI::MemoryPointer.new(:float, SIZE)
138
+ @@cdll.call(:get_buttonstatus, id, c_get, mode)
139
+ c_get.read_float.to_i
140
+ end
141
+ end
142
+
143
+ def set_buttonstatus(id, state, mode)
144
+ @@cdll.call(:set_buttonstatus, id, state, mode)
145
+ @cache.store("mb_#{id}_#{mode}", state)
146
+ end
147
+
148
+ def set_parameter_multi(param_hash)
149
+ param_hash.each do |(key, val)|
150
+ prop, m2, m3, *rem = key.to_s.split("_")
151
+ if m2.to_i.to_s == m2
152
+ m2 = m2.to_i
153
+ elsif m3.to_i.to_s == m3
154
+ m3 = m3.to_i
155
+ end
156
+
157
+ case prop
158
+ when "strip"
159
+ self.strip[m2].set_multi(val)
160
+ when "bus"
161
+ self.bus[m2].set_multi(val)
162
+ when "button", "mb"
163
+ self.button[m2].set_multi(val)
164
+ when "vban"
165
+ if %w[instream in].include? m2
166
+ self.vban.instream[m3].set_multi(val)
167
+ elsif %w[outstream out].include? m2
168
+ self.vban.outstream[m3].set_multi(val)
169
+ end
170
+ end
171
+ sleep(DELAY)
172
+ end
173
+ end
174
+
175
+ def get_level(type, index)
176
+ c_get = FFI::MemoryPointer.new(:float, SIZE)
177
+ @@cdll.call(:get_level, type, index, c_get)
178
+ c_get.read_float
179
+ end
180
+
181
+ def _get_levels
182
+ [
183
+ (0...(2 * @p_in + 8 * @v_in)).map { |i| get_level(@strip_mode, i) },
184
+ (0...(8 * (@p_out + @v_out))).map { |i| get_level(3, i) }
185
+ ]
186
+ end
187
+
188
+ def get_num_devices(direction)
189
+ unless %w[in out].include? direction
190
+ raise VMRemoteErrors.new("expected in or out")
191
+ end
192
+ if direction == "in"
193
+ val = @@cdll.call(:get_num_indevices)
194
+ else
195
+ val = @@cdll.call(:get_num_outdevices)
196
+ end
197
+ val[0]
198
+ end
199
+
200
+ def get_device_description(index, direction)
201
+ unless %w[in out].include? direction
202
+ raise VMRemoteErrors.new("expected in or out")
203
+ end
204
+ c_type = FFI::MemoryPointer.new(:long, SIZE)
205
+ c_name = FFI::MemoryPointer.new(:string, 256, true)
206
+ c_hwid = FFI::MemoryPointer.new(:string, 256, true)
207
+ if direction == "in"
208
+ @@cdll.call(:get_desc_indevices, index, c_type, c_name, c_hwid)
209
+ else
210
+ @@cdll.call(:get_desc_outdevices, index, c_type, c_name, c_hwid)
211
+ end
212
+ [c_name.read_string, c_type.read_long, c_hwid.read_string]
213
+ end
214
+
215
+ alias_method "set_multi", :set_parameter_multi
216
+ alias_method "apply", :set_parameter_multi
217
+ alias_method "get", :get_parameter
218
+ alias_method "set", :set_parameter
219
+ alias_method "pdirty", :pdirty?
220
+ alias_method "mdirty", :mdirty?
221
+ alias_method "ldirty", :ldirty?
222
+ end
223
+ end
@@ -0,0 +1,99 @@
1
+ require_relative "iremote"
2
+
3
+ module Voicemeeter
4
+ class Bus < IRemote
5
+ "
6
+ Concrete Bus class
7
+ "
8
+ include Channel_Meta_Functions
9
+ include Mixin::Fades
10
+ include Mixin::Return
11
+
12
+ attr_accessor :mode, :levels
13
+
14
+ def self.make(remote, layout_bus)
15
+ "
16
+ Factory function for Bus classes.
17
+ "
18
+ p_out, v_out = layout_bus.values
19
+ (0...(p_out + v_out)).map do |i|
20
+ i < p_out ? PhysicalBus.new(remote, i) : VirtualBus.new(remote, i)
21
+ end
22
+ end
23
+
24
+ def initialize(remote, i)
25
+ super
26
+ self.make_accessor_bool :mute, :mono, :eq, :eq_ab, :sel, :monitor
27
+ self.make_accessor_float :gain
28
+ self.make_accessor_string :label
29
+
30
+ @mode = BusModes.new(remote, i)
31
+ @levels = BusLevels.new(remote, i)
32
+ end
33
+
34
+ def identifier
35
+ "bus[#{@index}]"
36
+ end
37
+ end
38
+
39
+ class PhysicalBus < Bus
40
+ def initialize(remote, i)
41
+ super
42
+ self.make_reader_only :device, :sr
43
+ end
44
+ end
45
+
46
+ class VirtualBus < Bus
47
+ end
48
+
49
+ class BusModes < IRemote
50
+ include Channel_Meta_Functions
51
+
52
+ def initialize(remote, i)
53
+ super
54
+ self.make_bus_modes :normal,
55
+ :amix,
56
+ :bmix,
57
+ :repeat,
58
+ :composite,
59
+ :tvmix,
60
+ :upmix21,
61
+ :upmix41,
62
+ :upmix61,
63
+ :centeronly,
64
+ :lfeonly,
65
+ :rearonly
66
+ end
67
+
68
+ def identifier
69
+ "bus[#{@index}].mode"
70
+ end
71
+ end
72
+
73
+ class BusLevels < IRemote
74
+ def initialize(remote, i)
75
+ super
76
+ @init = i * 8
77
+ @offset = 8
78
+ end
79
+
80
+ def identifier
81
+ "bus[#{@index}]"
82
+ end
83
+
84
+ def getter(mode)
85
+ if @remote.running
86
+ vals = @remote.cache["bus_level"][@init, @offset]
87
+ else
88
+ vals = (@init...@offset).map { |i| @remote.get_level(mode, i) }
89
+ end
90
+ vals.map { |x| x > 0 ? (20 * Math.log(x, 10)).round(1) : -200.0 }
91
+ end
92
+
93
+ def all
94
+ getter(3)
95
+ end
96
+
97
+ def isdirty? = @remote._bus_comp[@init, @offset].any?
98
+ end
99
+ end
@@ -0,0 +1,25 @@
1
+ require_relative "iremote"
2
+ require_relative "meta"
3
+
4
+ module Voicemeeter
5
+ class MacroButton < IRemote
6
+ include MacroButton_Meta_Functions
7
+
8
+ def self.make(remote, num_buttons)
9
+ (0...num_buttons).map { |i| MacroButton.new(remote, i) }
10
+ end
11
+
12
+ def initialize(remote, i)
13
+ super
14
+ self.make_accessor_macrobutton :state, :stateonly, :trigger
15
+ end
16
+
17
+ def getter(mode)
18
+ @remote.get_buttonstatus(@index, mode)
19
+ end
20
+
21
+ def setter(set, mode)
22
+ @remote.set_buttonstatus(@index, set, mode)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,126 @@
1
+ require "ffi"
2
+ require_relative "inst"
3
+
4
+ module Voicemeeter
5
+ module CBindings
6
+ "
7
+ Creates Ruby bindings to the C DLL
8
+
9
+ Performs other low level tasks
10
+ "
11
+ extend Voicemeeter::InstallationFunctions
12
+ extend FFI::Library
13
+
14
+ private
15
+
16
+ begin
17
+ OS_BITS = FFI::Platform::CPU.downcase == "x64" ? 64 : 32
18
+ VM_PATH = get_vmpath(OS_BITS)
19
+ DLL_NAME = "VoicemeeterRemote#{OS_BITS == 64 ? "64" : ""}.dll"
20
+
21
+ self.vm_dll = VM_PATH.join(DLL_NAME)
22
+ rescue InstallErrors => error
23
+ puts "ERROR: #{error.message}"
24
+ raise
25
+ end
26
+
27
+ ffi_lib @vm_dll
28
+ ffi_convention :stdcall
29
+
30
+ attach_function :vm_login, :VBVMR_Login, [], :long
31
+ attach_function :vm_logout, :VBVMR_Logout, [], :long
32
+ attach_function :vm_runvm, :VBVMR_RunVoicemeeter, [:long], :long
33
+ attach_function :vm_vmtype, :VBVMR_GetVoicemeeterType, [:pointer], :long
34
+ attach_function :vm_vmversion, :VBVMR_GetVoicemeeterVersion, [:pointer], :long
35
+
36
+ attach_function :vm_mdirty, :VBVMR_MacroButton_IsDirty, [], :long
37
+ attach_function :vm_get_buttonstatus,
38
+ :VBVMR_MacroButton_GetStatus,
39
+ %i[long pointer long],
40
+ :long
41
+ attach_function :vm_set_buttonstatus,
42
+ :VBVMR_MacroButton_SetStatus,
43
+ %i[long float long],
44
+ :long
45
+
46
+ attach_function :vm_pdirty, :VBVMR_IsParametersDirty, [], :long
47
+ attach_function :vm_get_parameter_float,
48
+ :VBVMR_GetParameterFloat,
49
+ %i[string pointer],
50
+ :long
51
+ attach_function :vm_set_parameter_float,
52
+ :VBVMR_SetParameterFloat,
53
+ %i[string float],
54
+ :long
55
+
56
+ attach_function :vm_get_parameter_string,
57
+ :VBVMR_GetParameterStringA,
58
+ %i[string pointer],
59
+ :long
60
+ attach_function :vm_set_parameter_string,
61
+ :VBVMR_SetParameterStringA,
62
+ %i[string string],
63
+ :long
64
+
65
+ attach_function :vm_set_parameter_multi,
66
+ :VBVMR_SetParameters,
67
+ [:string],
68
+ :long
69
+
70
+ attach_function :vm_get_level, :VBVMR_GetLevel, %i[long long pointer], :long
71
+
72
+ attach_function :vm_get_num_indevices, :VBVMR_Input_GetDeviceNumber, [], :long
73
+ attach_function :vm_get_desc_indevices,
74
+ :VBVMR_Input_GetDeviceDescA,
75
+ %i[long pointer pointer pointer],
76
+ :long
77
+
78
+ attach_function :vm_get_num_outdevices,
79
+ :VBVMR_Output_GetDeviceNumber,
80
+ [],
81
+ :long
82
+ attach_function :vm_get_desc_outdevices,
83
+ :VBVMR_Output_GetDeviceDescA,
84
+ %i[long pointer pointer pointer],
85
+ :long
86
+
87
+ @@cdll =
88
+ lambda { |func, *args| retval = [send("vm_#{func}", *args), func] }
89
+
90
+ def clear_polling = while pdirty? || mdirty?; end
91
+
92
+ def polling(func, **kwargs)
93
+ params = {
94
+ "get_parameter" => kwargs[:name],
95
+ "get_buttonstatus" => "mb_#{kwargs[:id]}_#{kwargs[:mode]}"
96
+ }
97
+ return @cache.delete(params[func]) if @cache.key? params[func]
98
+
99
+ clear_polling if @sync
100
+
101
+ yield
102
+ end
103
+
104
+ def retval=(values)
105
+ " Writer validation for CAPI calls "
106
+ retval, func = *values
107
+ unless %i[get_num_indevices get_num_outdevices].include? func
108
+ raise CAPIErrors.new(retval, func) if retval&.nonzero?
109
+ end
110
+ @retval = retval
111
+ end
112
+
113
+ public
114
+
115
+ def pdirty? = vm_pdirty&.nonzero?
116
+
117
+ def mdirty? = vm_mdirty&.nonzero?
118
+
119
+ def ldirty?
120
+ @strip_buf, @bus_buf = _get_levels
121
+ return(
122
+ !(@cache["strip_level"] == @strip_buf && @cache["bus_level"] == @bus_buf)
123
+ )
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,38 @@
1
+ require_relative "iremote"
2
+ require_relative "meta"
3
+
4
+ module Voicemeeter
5
+ class Command < IRemote
6
+ include Commands_Meta_Functions
7
+
8
+ def initialize(remote)
9
+ super
10
+ self.make_action_prop :show, :restart, :shutdown
11
+ self.make_writer_bool :showvbanchat, :lock
12
+ end
13
+
14
+ def identifier
15
+ :command
16
+ end
17
+
18
+ def hide
19
+ self.setter("show", 0)
20
+ end
21
+
22
+ def load(value)
23
+ raise VMRemoteErrors.new("Expected a string") unless value.is_a? String
24
+ self.setter("load", value)
25
+ sleep(0.2)
26
+ end
27
+
28
+ def save(value)
29
+ raise VMRemoteErrors.new("Expected a string") unless value.is_a? String
30
+ self.setter("save", value)
31
+ sleep(0.2)
32
+ end
33
+
34
+ def reset
35
+ @remote.set_config("reset")
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,83 @@
1
+ require "toml"
2
+ require_relative "kinds"
3
+
4
+ module Voicemeeter
5
+ module Configs
6
+ private
7
+
8
+ @@configs = Hash.new
9
+
10
+ class TOMLStrBuilder
11
+ def initialize(kind)
12
+ @p_in, @v_in = kind[:layout][:strip].values
13
+ @p_out, @v_out = kind[:layout][:bus].values
14
+ @vs_params =
15
+ ["mute = false", "mono = false", "solo = false", "gain = 0.0"] +
16
+ (1..@p_out).map { |i| "A#{i} = false" } +
17
+ (1..@v_out).map { |i| "B#{i} = false" }
18
+
19
+ @ps_params = @vs_params + ["comp = 0.0", "gate = 0.0"]
20
+ @bus_params = ["mono = false", "eq = false", "mute = false"]
21
+ end
22
+
23
+ def build
24
+ "
25
+ Builds a TOML script for the parser
26
+ "
27
+ @ps = (0...@p_in).map { |i| ["[strip_#{i}]"] + @ps_params }
28
+ @ps.map! { |a| a.map { |s| s.gsub("B1 = false", "B1 = true") } }
29
+ @vs =
30
+ (@p_in...(@p_in + @v_in)).map { |i| ["[strip_#{i}]"] + @vs_params }
31
+ @vs.map! { |a| a.map { |s| s.gsub("A1 = false", "A1 = true") } }
32
+
33
+ @b = (0...(@p_out + @v_out)).map { |i| ["[bus_#{i}]"] + @bus_params }
34
+
35
+ [@ps + @vs + @b].join("\n")
36
+ end
37
+ end
38
+
39
+ def parser(data)
40
+ TOML::Parser.new(data).parsed
41
+ end
42
+
43
+ def get_configs(kind_id)
44
+ file_path = File.join(Dir.pwd, "configs", "#{kind_id}")
45
+
46
+ if Dir.exist?(file_path)
47
+ Dir
48
+ .glob(File.join(file_path, "*.toml"))
49
+ .to_h do |toml_file|
50
+ filename = File.basename(toml_file, ".toml")
51
+ puts "loading config #{kind_id}/#{filename} into memory"
52
+ [filename, parser(File.read(toml_file))]
53
+ end
54
+ end
55
+ end
56
+
57
+ def loader
58
+ if @@configs.empty?
59
+ builder = TOMLStrBuilder.new(@kind)
60
+ puts "loading config reset into memory"
61
+ @@configs["reset"] = parser(builder.build)
62
+ configs = get_configs(@kind.name.to_s)
63
+
64
+ @@configs.merge!(configs) unless configs.nil?
65
+ end
66
+ end
67
+
68
+ public
69
+
70
+ def set_config(value)
71
+ loader
72
+ unless @@configs.key? value
73
+ raise VMRemoteErrors.new("No profile with name #{value} was loaded")
74
+ end
75
+
76
+ self.send("set_multi", @@configs[value])
77
+ puts "config #{@kind.name}/#{value} applied!"
78
+ sleep(@delay)
79
+ end
80
+
81
+ alias_method "apply_config", :set_config
82
+ end
83
+ end