voicemeeter_api_ruby 2.0.2 → 3.0.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.
data/lib/base.rb CHANGED
@@ -1,132 +1,151 @@
1
- require 'ffi'
2
- require_relative 'inst'
3
-
4
- include InstallationFunctions
5
-
6
- module Base
7
- extend FFI::Library
8
-
9
- begin
10
- OS_BITS = get_arch
11
- VM_PATH = get_vmpath(OS_BITS)
12
- DLL_NAME = "VoicemeeterRemote#{OS_BITS == 64 ? "64" : ""}.dll"
13
-
14
- self.vmr_dll = VM_PATH.join(DLL_NAME)
15
- rescue InstallErrors => error
16
- puts "ERROR: #{error.message}"
17
- raise
18
- end
19
-
20
- ffi_lib @vmr_dll
21
- ffi_convention :stdcall
22
-
23
- attach_function :vmr_login, :VBVMR_Login, [], :long
24
- attach_function :vmr_logout, :VBVMR_Logout, [], :long
25
- attach_function :vmr_runvm, :VBVMR_RunVoicemeeter, [:long], :long
26
- attach_function :vmr_vmtype, :VBVMR_GetVoicemeeterType, [:pointer], :long
27
-
28
- attach_function :vmr_mdirty, :VBVMR_MacroButton_IsDirty, [], :long
29
- attach_function :vmr_macro_setstatus, :VBVMR_MacroButton_SetStatus, \
30
- [:long, :float, :long], :long
31
- attach_function :vmr_macro_getstatus, :VBVMR_MacroButton_GetStatus, \
32
- [:long, :pointer, :long], :long
33
-
34
- attach_function :vmr_pdirty, :VBVMR_IsParametersDirty, [], :long
35
- attach_function :vmr_set_parameter_float, :VBVMR_SetParameterFloat, \
36
- [:string, :float], :long
37
- attach_function :vmr_get_parameter_float, :VBVMR_GetParameterFloat, \
38
- [:string, :pointer], :long
39
-
40
- attach_function :vmr_set_parameter_string, :VBVMR_SetParameterStringA, \
41
- [:string, :string], :long
42
- attach_function :vmr_get_parameter_string, :VBVMR_GetParameterStringA, \
43
- [:string, :pointer], :long
44
-
45
- attach_function :vmr_set_parameter_multi, :VBVMR_SetParameters, \
46
- [:string], :long
47
-
48
- DELAY = 0.001
49
- MAX_POLLS = 8
50
-
51
- def cache=(value)
52
- @cache = value
53
- end
54
-
55
- def pdirty
56
- return vmr_pdirty&.nonzero?
57
- end
58
-
59
- def mdirty
60
- return vmr_mdirty&.nonzero?
61
- end
62
-
63
- def clear_polling
64
- while self.pdirty || self.mdirty
65
- end
66
- end
67
-
68
- def polling(func)
69
- MAX_POLLS.times do
70
- return true if func.include?('param') && self.pdirty
71
- return true if func.include?('macro') && self.mdirty
72
- sleep(DELAY)
73
- end
74
- false
75
- end
76
-
77
- def retval=(values)
78
- """ Writer validation for CAPI calls """
79
- retval, func = *values
80
- raise CAPIErrors.new(retval, func) if retval&.nonzero?
81
-
82
- @retval = retval
83
- end
84
-
85
- def run_as(func, *args)
86
- val = send('vmr_' + func, *args)
87
- self.retval = [val, func]
88
- sleep(DELAY)
89
- end
90
- end
91
-
92
- module Define_Version
93
- include Base
94
-
95
- def define_version(kind)
96
- case kind
97
- when "basic"
98
- self.properties = {
99
- :name => kind,
100
- :exe => "voicemeeter.exe"
101
- }
102
- self.layout = {
103
- :strip => {:p_in => 2, :v_in=> 1},
104
- :bus => {:p_out => 1, :v_out=> 1},
105
- :vban => {:instream => 4, :outstream => 4},
106
- :mb => 70,
107
- }
108
- when "banana"
109
- self.properties = {
110
- :name => kind,
111
- :exe => "voicemeeterpro.exe"
112
- }
113
- self.layout = {
114
- :strip => {:p_in => 3, :v_in=> 2},
115
- :bus => {:p_out => 3, :v_out=> 2},
116
- :vban => {:instream => 8, :outstream => 8},
117
- :mb => 70,
118
- }
119
- when "potato"
120
- self.properties = {
121
- :name => kind,
122
- :exe => "voicemeeter8#{OS_BITS == 64 ? "x64" : ""}.exe"
123
- }
124
- self.layout = {
125
- :strip => {:p_in => 5, :v_in=> 3},
126
- :bus => {:p_out => 5, :v_out=> 3},
127
- :vban => {:instream => 8, :outstream => 8},
128
- :mb => 70,
129
- }
130
- end
131
- end
132
- end
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
data/lib/bus.rb CHANGED
@@ -1,31 +1,64 @@
1
- require_relative 'channel'
2
-
3
-
4
- class Bus < IChannel
5
- def self.make(remote, layout_bus)
6
- "
7
- Factory function for Bus classes.
8
- "
9
- p_out = layout_bus[:p_out]
10
- v_out = layout_bus[:v_out]
11
-
12
- (0...(p_out + v_out)).map do |i|
13
- i < p_out ? \
14
- PhysicalBus.new(remote, i) : \
15
- VirtualBus.new(remote, i)
16
- end
17
- end
18
-
19
- def initialize(remote, i)
20
- super
21
- self.make_accessor_bool :mute, :mono, :eq
22
- self.make_accessor_float :gain
23
- end
24
-
25
- def cmd
26
- return "Bus[#{@index}]"
27
- end
28
- end
29
-
30
- class PhysicalBus < Bus; end
31
- class VirtualBus < Bus; end
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
data/lib/button.rb CHANGED
@@ -1,35 +1,36 @@
1
- require_relative 'meta'
2
-
3
-
4
- class IMacroButton
5
- include MacroButton_Meta_Functions
6
-
7
- attr_accessor :remote, :index
8
-
9
- def initialize(remote, index)
10
- self.remote = remote
11
- self.index = index
12
- end
13
-
14
- def getter(mode)
15
- return @remote.macro_getstatus(@index, mode)
16
- end
17
-
18
- def setter(set, mode)
19
- @remote.macro_setstatus(@index, set, mode)
20
- end
21
- end
22
-
23
-
24
- class MacroButton < IMacroButton
25
- def self.make(remote, num_buttons)
26
- (0...num_buttons).map do |i|
27
- MacroButton.new(remote, i)
28
- end
29
- end
30
-
31
- def initialize(remote, i)
32
- super
33
- self.make_accessor_macrobutton :state, :stateonly, :trigger
34
- end
35
- end
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
data/lib/cbindings.rb ADDED
@@ -0,0 +1,103 @@
1
+ require 'ffi'
2
+ require_relative 'inst'
3
+
4
+ include InstallationFunctions
5
+
6
+ module CBindings
7
+ '
8
+ Creates Ruby bindings to the C DLL
9
+
10
+ Performs other low level tasks
11
+ '
12
+ extend FFI::Library
13
+
14
+ private
15
+
16
+ begin
17
+ OS_BITS = get_arch
18
+ VM_PATH = get_vmpath(OS_BITS)
19
+ DLL_NAME = "VoicemeeterRemote#{OS_BITS == 64 ? '64' : ''}.dll"
20
+
21
+ self.vmr_dll = VM_PATH.join(DLL_NAME)
22
+ rescue InstallErrors => error
23
+ puts "ERROR: #{error.message}"
24
+ raise
25
+ end
26
+
27
+ ffi_lib @vmr_dll
28
+ ffi_convention :stdcall
29
+
30
+ attach_function :vmr_login, :VBVMR_Login, [], :long
31
+ attach_function :vmr_logout, :VBVMR_Logout, [], :long
32
+ attach_function :vmr_runvm, :VBVMR_RunVoicemeeter, [:long], :long
33
+ attach_function :vmr_vmtype, :VBVMR_GetVoicemeeterType, [:pointer], :long
34
+
35
+ attach_function :vmr_mdirty, :VBVMR_MacroButton_IsDirty, [], :long
36
+ attach_function :vmr_get_buttonstatus,
37
+ :VBVMR_MacroButton_GetStatus,
38
+ %i[long pointer long],
39
+ :long
40
+ attach_function :vmr_set_buttonstatus,
41
+ :VBVMR_MacroButton_SetStatus,
42
+ %i[long float long],
43
+ :long
44
+
45
+ attach_function :vmr_pdirty, :VBVMR_IsParametersDirty, [], :long
46
+ attach_function :vmr_get_parameter_float,
47
+ :VBVMR_GetParameterFloat,
48
+ %i[string pointer],
49
+ :long
50
+ attach_function :vmr_set_parameter_float,
51
+ :VBVMR_SetParameterFloat,
52
+ %i[string float],
53
+ :long
54
+
55
+ attach_function :vmr_get_parameter_string,
56
+ :VBVMR_GetParameterStringA,
57
+ %i[string pointer],
58
+ :long
59
+ attach_function :vmr_set_parameter_string,
60
+ :VBVMR_SetParameterStringA,
61
+ %i[string string],
62
+ :long
63
+
64
+ attach_function :vmr_set_parameter_multi,
65
+ :VBVMR_SetParameters,
66
+ [:string],
67
+ :long
68
+
69
+ attach_function :vmr_get_level,
70
+ :VBVMR_GetLevel,
71
+ %i[long long pointer],
72
+ :long
73
+
74
+ def polling(func, **kwargs)
75
+ params = {
76
+ 'get_parameter' => kwargs[:name],
77
+ 'get_buttonstatus' => "mb_#{kwargs[:id]}_#{kwargs[:mode]}",
78
+ }
79
+ return @cache.delete(params[func]) if @cache.key? params[func]
80
+
81
+ self.clear_polling if @sync
82
+
83
+ yield
84
+ end
85
+
86
+ def retval=(values)
87
+ ' Writer validation for CAPI calls '
88
+ retval, func = *values
89
+ raise CAPIErrors.new(retval, func) if retval&.nonzero?
90
+ @retval = retval
91
+ end
92
+
93
+ public
94
+
95
+ def clear_polling
96
+ while self.pdirty? || self.mdirty?
97
+ end
98
+ end
99
+
100
+ def pdirty?() = vmr_pdirty&.nonzero?
101
+
102
+ def mdirty?() = vmr_mdirty&.nonzero?
103
+ end
data/lib/channel.rb CHANGED
@@ -1,25 +1,46 @@
1
- require_relative 'meta'
2
- require_relative 'errors'
3
-
4
- class IChannel
5
- include Channel_Meta_Functions
6
-
7
- attr_accessor :remote, :index
8
-
9
- def initialize(remote, i)
10
- self.remote = remote
11
- self.index = i
12
- end
13
-
14
- def getter(param, is_string=false)
15
- @remote.get_parameter("#{self.cmd}.#{param}", is_string)
16
- end
17
-
18
- def setter(param, value)
19
- @remote.set_parameter("#{self.cmd}.#{param}", value)
20
- end
21
-
22
- def cmd
23
- raise NotImplementedError
24
- end
25
- end
1
+ require_relative 'meta'
2
+ require_relative 'errors'
3
+
4
+ class IChannel
5
+ '
6
+ Base Channel class
7
+ '
8
+ include Channel_Meta_Functions
9
+
10
+ def initialize(remote, i)
11
+ @remote = remote
12
+ @index = i
13
+ end
14
+
15
+ def getter(param, is_string = false)
16
+ @remote.get_parameter("#{self.cmd}.#{param}", is_string)
17
+ end
18
+
19
+ def setter(param, value)
20
+ @remote.set_parameter("#{self.cmd}.#{param}", value)
21
+ end
22
+
23
+ def cmd
24
+ "#{self.identifier}[#{@index}]"
25
+ end
26
+
27
+ def identifier
28
+ raise 'Called abstract mehod: identifier'
29
+ end
30
+
31
+ def set_multi(param_hash)
32
+ param_hash.each { |(key, val)| self.send("#{key}=", val) }
33
+ end
34
+ end
35
+
36
+ module Fades
37
+ def fadeto(target, time)
38
+ self.setter('FadeTo', "(#{target}, #{time})")
39
+ sleep(@remote.delay)
40
+ end
41
+
42
+ def fadeby(change, time)
43
+ self.setter('FadeBy', "(#{change}, #{time})")
44
+ sleep(@remote.delay)
45
+ end
46
+ end