voicemeeter_api_ruby 3.0.0 → 4.1.1

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.
data/lib/base.rb CHANGED
@@ -1,151 +1,219 @@
1
- require_relative 'runvm'
2
- require_relative 'profiles'
3
- require_relative 'errors'
4
- require_relative 'strip'
5
- require_relative 'bus'
6
- require_relative 'button'
7
- require_relative 'vban'
8
- require_relative 'command'
9
- require_relative 'recorder'
10
-
11
- class Base
12
- '
13
- Base class responsible for wrapping the C Remote API
14
-
15
- Mixin required modules
16
- '
17
- include Profiles
18
- include RunVM
19
-
20
- attr_accessor :strip, :bus, :button, :vban, :command, :recorder
21
-
22
- attr_reader :kind, :retval, :cache, :profiles, :delay
23
-
24
- DELAY = 0.001
25
- SYNC = false
26
- SIZE = 1
27
- BUFF = 512
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
- @delay = DELAY
36
- @profiles = get_profiles(@kind)
37
- @cdll =
38
- lambda do |func, *args|
39
- self.retval = [send("vmr_#{func}", *args), func]
40
- end
41
- end
42
-
43
- def login
44
- @cdll.call('login')
45
- clear_polling
46
- rescue CAPIErrors => error
47
- case
48
- when error.value == 1
49
- self.start(@kind.name)
50
- clear_polling
51
- when error.value < 0
52
- raise
53
- end
54
- end
55
-
56
- def logout
57
- clear_polling
58
- sleep(0.1)
59
- @cdll.call('logout')
60
- end
61
-
62
- def get_parameter(name, is_string = false)
63
- self.polling('get_parameter', name: name) do
64
- if is_string
65
- c_get = FFI::MemoryPointer.new(:string, BUFF, true)
66
- @cdll.call('get_parameter_string', name, c_get)
67
- c_get.read_string
68
- else
69
- c_get = FFI::MemoryPointer.new(:float, SIZE)
70
- @cdll.call('get_parameter_float', name, c_get)
71
- c_get.read_float.round(1)
72
- end
73
- end
74
- end
75
-
76
- def set_parameter(name, value)
77
- if value.is_a? String
78
- @cdll.call('set_parameter_string', name, value)
79
- else
80
- @cdll.call('set_parameter_float', name, value.to_f)
81
- end
82
- @cache.store(name, value)
83
- end
84
-
85
- def get_buttonstatus(id, mode)
86
- self.polling('get_buttonstatus', id: id, mode: mode) do
87
- c_get = FFI::MemoryPointer.new(:float, SIZE)
88
- @cdll.call('get_buttonstatus', id, c_get, mode)
89
- c_get.read_float.to_i
90
- end
91
- end
92
-
93
- def set_buttonstatus(id, state, mode)
94
- @cdll.call('set_buttonstatus', id, state, mode)
95
- @cache.store("mb_#{id}_#{mode}", state)
96
- end
97
-
98
- def set_parameter_multi(param_hash)
99
- param_hash.each do |(key, val)|
100
- prop, m2, m3, *rem = key.to_s.split('_')
101
- if m2.to_i.to_s == m2
102
- m2 = m2.to_i
103
- elsif m3.to_i.to_s == m3
104
- m3 = m3.to_i
105
- end
106
-
107
- case prop
108
- when 'strip'
109
- self.strip[m2].set_multi(val)
110
- when 'bus'
111
- self.bus[m2].set_multi(val)
112
- when 'button', 'mb'
113
- self.button[m2].set_multi(val)
114
- when 'vban'
115
- if %w[instream in].include? m2
116
- self.vban.instream[m3].set_multi(val)
117
- elsif %w[outstream out].include? m2
118
- self.vban.outstream[m3].set_multi(val)
119
- end
120
- end
121
- sleep(DELAY)
122
- end
123
- end
124
-
125
- def get_level(type, index)
126
- c_get = FFI::MemoryPointer.new(:float, SIZE)
127
- @cdll.call('get_level', type, index, c_get)
128
- c_get.read_float
129
- end
130
-
131
- def strip_levels
132
- '
133
- Returns the full level array for strips, PREFADER mode,
134
- before math conversion
135
- '
136
- (0...(2 * @p_in + 8 * @v_in)).map { |i| get_level(0, i) }
137
- end
138
-
139
- def bus_levels
140
- '
141
- Returns the full level array for buses, before math conversion
142
- '
143
- (0...(8 * (@p_out + @v_out))).map { |i| get_level(3, i) }
144
- end
145
-
146
- alias_method 'set_multi', :set_parameter_multi
147
- alias_method 'get', :get_parameter
148
- alias_method 'set', :set_parameter
149
- alias_method 'pdirty', :pdirty?
150
- alias_method 'mdirty', :pdirty?
151
- end
1
+ require 'observer'
2
+
3
+ require_relative 'runvm'
4
+ require_relative 'configs'
5
+ require_relative 'errors'
6
+
7
+ class Base
8
+ '
9
+ Base class responsible for wrapping the C Remote API
10
+
11
+ Mixin required modules
12
+ '
13
+ include Observable
14
+ include Configs
15
+ include RunVM
16
+
17
+ attr_accessor :strip, :bus, :button, :vban, :command, :recorder, :device
18
+ attr_accessor :strip_mode
19
+
20
+ attr_reader :kind, :p_in, :v_in, :p_out, :v_out, :retval, :cache
21
+ attr_reader :running, :_strip_comp, :_bus_comp
22
+
23
+ DELAY = 0.001
24
+ SYNC = false
25
+ RATELIMIT = 0.033
26
+ SIZE = 1
27
+
28
+ def initialize(kind, **kwargs)
29
+ @kind = kind
30
+ @p_in, @v_in = kind.layout[:strip].values
31
+ @p_out, @v_out = kind.layout[:bus].values
32
+ @cache = Hash.new
33
+ @sync = kwargs[:sync] || SYNC
34
+ @ratelimit = kwargs[:ratelimit] || RATELIMIT
35
+ @running = false
36
+ @strip_mode = 0
37
+ @delay = DELAY
38
+ end
39
+
40
+ def init_thread
41
+ @running = true
42
+ @cache['strip_level'], @cache['bus_level'] = _get_levels
43
+ Thread.new do
44
+ loop do
45
+ Thread.stop if !@running
46
+ if pdirty?
47
+ changed
48
+ notify_observers('pdirty')
49
+ elsif mdirty?
50
+ changed
51
+ notify_observers('mdirty')
52
+ elsif ldirty?
53
+ changed
54
+ @_strip_comp =
55
+ @cache['strip_level'].map.with_index do |x, i|
56
+ !(x == @strip_buf[i])
57
+ end
58
+ @_bus_comp =
59
+ @cache['bus_level'].map.with_index do |x, i|
60
+ !(x == @bus_buf[i])
61
+ end
62
+ @cache['strip_level'] = @strip_buf
63
+ @cache['bus_level'] = @bus_buf
64
+ notify_observers('ldirty')
65
+ end
66
+ sleep(@ratelimit)
67
+ end
68
+ end
69
+ end
70
+
71
+ def end_thread
72
+ @running = false
73
+ end
74
+
75
+ def login
76
+ @@cdll.call(:login)
77
+ clear_polling
78
+ rescue CAPIErrors => error
79
+ case
80
+ when error.value == 1
81
+ self.start(@kind.name)
82
+ clear_polling
83
+ when error.value < 0
84
+ raise
85
+ end
86
+ end
87
+
88
+ def logout
89
+ clear_polling
90
+ sleep(0.1)
91
+ @@cdll.call(:logout)
92
+ end
93
+
94
+ def type
95
+ c_type = FFI::MemoryPointer.new(:long, SIZE)
96
+ @@cdll.call(:vmtype, c_type)
97
+ types = { 1 => 'basic', 2 => 'banana', 3 => 'potato' }
98
+ types[c_type.read_long]
99
+ end
100
+
101
+ def version
102
+ c_ver = FFI::MemoryPointer.new(:long, SIZE)
103
+ @@cdll.call(:vmversion, c_ver)
104
+ v1 = (c_ver.read_long & 0xFF000000) >> 24
105
+ v2 = (c_ver.read_long & 0x00FF0000) >> 16
106
+ v3 = (c_ver.read_long & 0x0000FF00) >> 8
107
+ v4 = c_ver.read_long & 0x000000FF
108
+ "#{v1}.#{v2}.#{v3}.#{v4}"
109
+ end
110
+
111
+ def get_parameter(name, is_string = false)
112
+ self.polling('get_parameter', name: name) do
113
+ if is_string
114
+ c_get = FFI::MemoryPointer.new(:string, 512, true)
115
+ @@cdll.call(:get_parameter_string, name, c_get)
116
+ c_get.read_string
117
+ else
118
+ c_get = FFI::MemoryPointer.new(:float, SIZE)
119
+ @@cdll.call(:get_parameter_float, name, c_get)
120
+ c_get.read_float.round(1)
121
+ end
122
+ end
123
+ end
124
+
125
+ def set_parameter(name, value)
126
+ if value.is_a? String
127
+ @@cdll.call(:set_parameter_string, name, value)
128
+ else
129
+ @@cdll.call(:set_parameter_float, name, value.to_f)
130
+ end
131
+ @cache.store(name, value)
132
+ end
133
+
134
+ def get_buttonstatus(id, mode)
135
+ self.polling('get_buttonstatus', id: id, mode: mode) do
136
+ c_get = FFI::MemoryPointer.new(:float, SIZE)
137
+ @@cdll.call(:get_buttonstatus, id, c_get, mode)
138
+ c_get.read_float.to_i
139
+ end
140
+ end
141
+
142
+ def set_buttonstatus(id, state, mode)
143
+ @@cdll.call(:set_buttonstatus, id, state, mode)
144
+ @cache.store("mb_#{id}_#{mode}", state)
145
+ end
146
+
147
+ def set_parameter_multi(param_hash)
148
+ param_hash.each do |(key, val)|
149
+ prop, m2, m3, *rem = key.to_s.split('_')
150
+ if m2.to_i.to_s == m2
151
+ m2 = m2.to_i
152
+ elsif m3.to_i.to_s == m3
153
+ m3 = m3.to_i
154
+ end
155
+
156
+ case prop
157
+ when 'strip'
158
+ self.strip[m2].set_multi(val)
159
+ when 'bus'
160
+ self.bus[m2].set_multi(val)
161
+ when 'button', 'mb'
162
+ self.button[m2].set_multi(val)
163
+ when 'vban'
164
+ if %w[instream in].include? m2
165
+ self.vban.instream[m3].set_multi(val)
166
+ elsif %w[outstream out].include? m2
167
+ self.vban.outstream[m3].set_multi(val)
168
+ end
169
+ end
170
+ sleep(DELAY)
171
+ end
172
+ end
173
+
174
+ def get_level(type, index)
175
+ c_get = FFI::MemoryPointer.new(:float, SIZE)
176
+ @@cdll.call(:get_level, type, index, c_get)
177
+ c_get.read_float
178
+ end
179
+
180
+ def _get_levels
181
+ s = (0...(2 * @p_in + 8 * @v_in)).map { |i| get_level(0, i) }
182
+ b = (0...(8 * (@p_out + @v_out))).map { |i| get_level(3, i) }
183
+ [s, b]
184
+ end
185
+
186
+ def get_num_devices(direction)
187
+ unless %w[in out].include? direction
188
+ raise VMRemoteErrors.new('expected in or out')
189
+ end
190
+ if direction == 'in'
191
+ val = @@cdll.call(:get_num_indevices)
192
+ else
193
+ val = @@cdll.call(:get_num_outdevices)
194
+ end
195
+ val[0]
196
+ end
197
+
198
+ def get_device_description(index, direction)
199
+ unless %w[in out].include? direction
200
+ raise VMRemoteErrors.new('expected in or out')
201
+ end
202
+ c_type = FFI::MemoryPointer.new(:long, SIZE)
203
+ c_name = FFI::MemoryPointer.new(:string, 256, true)
204
+ c_hwid = FFI::MemoryPointer.new(:string, 256, true)
205
+ if direction == 'in'
206
+ @@cdll.call(:get_desc_indevices, index, c_type, c_name, c_hwid)
207
+ else
208
+ @@cdll.call(:get_desc_outdevices, index, c_type, c_name, c_hwid)
209
+ end
210
+ [c_name.read_string, c_type.read_long, c_hwid.read_string]
211
+ end
212
+
213
+ alias_method 'set_multi', :set_parameter_multi
214
+ alias_method 'get', :get_parameter
215
+ alias_method 'set', :set_parameter
216
+ alias_method 'pdirty', :pdirty?
217
+ alias_method 'mdirty', :mdirty?
218
+ alias_method 'ldirty', :ldirty?
219
+ end
data/lib/bus.rb CHANGED
@@ -1,64 +1,97 @@
1
- require_relative 'channel'
2
-
3
- class Bus < IChannel
4
- '
5
- Concrete Bus class
6
- '
7
- include Fades
8
-
9
- attr_accessor :mode
10
-
11
- def self.make(remote, layout_bus)
12
- '
13
- Factory function for Bus classes.
14
- '
15
- p_out, v_out = layout_bus.values
16
- (0...(p_out + v_out)).map do |i|
17
- i < p_out ? PhysicalBus.new(remote, i) : VirtualBus.new(remote, i)
18
- end
19
- end
20
-
21
- def initialize(remote, i)
22
- super
23
- self.make_accessor_bool :mute, :mono, :eq
24
- self.make_accessor_float :gain
25
- self.make_accessor_string :label
26
-
27
- @mode = BusModes.new(remote, i)
28
- end
29
-
30
- def identifier
31
- :bus
32
- end
33
- end
34
-
35
- class PhysicalBus < Bus
36
- end
37
- class VirtualBus < Bus
38
- end
39
-
40
- class BusModes < IChannel
41
- def initialize(remote, i)
42
- super
43
- self.make_bus_modes :normal,
44
- :amix,
45
- :bmix,
46
- :repeat,
47
- :composite,
48
- :tvmix,
49
- :upmix21,
50
- :upmix41,
51
- :upmix61,
52
- :centeronly,
53
- :lfeonly,
54
- :rearonly
55
- end
56
-
57
- def identifier
58
- :bus
59
- end
60
-
61
- def cmd
62
- "#{super}.mode"
63
- end
64
- end
1
+ require_relative 'iremote'
2
+ require_relative 'mixin'
3
+
4
+ class Bus < IRemote
5
+ '
6
+ Concrete Bus class
7
+ '
8
+ include Channel_Meta_Functions
9
+ include Fades
10
+
11
+ attr_accessor :mode, :levels
12
+
13
+ def self.make(remote, layout_bus)
14
+ '
15
+ Factory function for Bus classes.
16
+ '
17
+ p_out, v_out = layout_bus.values
18
+ (0...(p_out + v_out)).map do |i|
19
+ i < p_out ? PhysicalBus.new(remote, i) : VirtualBus.new(remote, i)
20
+ end
21
+ end
22
+
23
+ def initialize(remote, i)
24
+ super
25
+ self.make_accessor_bool :mute, :mono, :eq, :sel
26
+ self.make_accessor_float :gain
27
+ self.make_accessor_string :label
28
+
29
+ @mode = BusModes.new(remote, i)
30
+ @levels = BusLevels.new(remote, i)
31
+ end
32
+
33
+ def identifier
34
+ "bus[#{@index}]"
35
+ end
36
+ end
37
+
38
+ class PhysicalBus < Bus
39
+ def initialize(remote, i)
40
+ super
41
+ self.make_reader_only :device, :sr
42
+ end
43
+ end
44
+
45
+ class VirtualBus < Bus
46
+ end
47
+
48
+ class BusModes < IRemote
49
+ include Channel_Meta_Functions
50
+
51
+ def initialize(remote, i)
52
+ super
53
+ self.make_bus_modes :normal,
54
+ :amix,
55
+ :bmix,
56
+ :repeat,
57
+ :composite,
58
+ :tvmix,
59
+ :upmix21,
60
+ :upmix41,
61
+ :upmix61,
62
+ :centeronly,
63
+ :lfeonly,
64
+ :rearonly
65
+ end
66
+
67
+ def identifier
68
+ "bus[#{@index}].mode"
69
+ end
70
+ end
71
+
72
+ class BusLevels < IRemote
73
+ def initialize(remote, i)
74
+ super
75
+ @init = i * 8
76
+ @offset = 8
77
+ end
78
+
79
+ def identifier
80
+ "bus[#{@index}]"
81
+ end
82
+
83
+ def getter(mode)
84
+ if @remote.running
85
+ vals = @remote.cache['bus_level'][@init, @offset]
86
+ else
87
+ vals = (@init...@offset).map { |i| @remote.get_level(mode, i) }
88
+ end
89
+ vals.map { |x| x > 0 ? (20 * Math.log(x, 10)).round(1) : -200.0 }
90
+ end
91
+
92
+ def all
93
+ getter(3)
94
+ end
95
+
96
+ def isdirty?() = @remote._bus_comp[@init, @offset].any?
97
+ end
data/lib/button.rb CHANGED
@@ -1,36 +1,23 @@
1
- require_relative 'meta'
2
-
3
- class IMacroButton
4
- include MacroButton_Meta_Functions
5
-
6
- attr_accessor :remote, :index
7
-
8
- def initialize(remote, index)
9
- self.remote = remote
10
- self.index = index
11
- end
12
-
13
- def getter(mode)
14
- @remote.get_buttonstatus(@index, mode)
15
- end
16
-
17
- def setter(set, mode)
18
- @remote.set_buttonstatus(@index, set, mode)
19
- end
20
-
21
- def set_multi(param_hash)
22
- param_hash.each { |(key, val)| self.send("#{key}=", val) }
23
- sleep(remote.delay)
24
- end
25
- end
26
-
27
- class MacroButton < IMacroButton
28
- def self.make(remote, num_buttons)
29
- (0...num_buttons).map { |i| MacroButton.new(remote, i) }
30
- end
31
-
32
- def initialize(remote, i)
33
- super
34
- self.make_accessor_macrobutton :state, :stateonly, :trigger
35
- end
36
- end
1
+ require_relative 'iremote'
2
+ require_relative 'meta'
3
+
4
+ class MacroButton < IRemote
5
+ include MacroButton_Meta_Functions
6
+
7
+ def self.make(remote, num_buttons)
8
+ (0...num_buttons).map { |i| MacroButton.new(remote, i) }
9
+ end
10
+
11
+ def initialize(remote, i)
12
+ super
13
+ self.make_accessor_macrobutton :state, :stateonly, :trigger
14
+ end
15
+
16
+ def getter(mode)
17
+ @remote.get_buttonstatus(@index, mode)
18
+ end
19
+
20
+ def setter(set, mode)
21
+ @remote.set_buttonstatus(@index, set, mode)
22
+ end
23
+ end