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/cbindings.rb CHANGED
@@ -1,103 +1,128 @@
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
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 = 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,
71
+ :VBVMR_GetLevel,
72
+ %i[long long pointer],
73
+ :long
74
+
75
+ attach_function :vm_get_num_indevices,
76
+ :VBVMR_Input_GetDeviceNumber, [], :long
77
+ attach_function :vm_get_desc_indevices,
78
+ :VBVMR_Input_GetDeviceDescA, %i[long pointer pointer pointer],
79
+ :long
80
+
81
+ attach_function :vm_get_num_outdevices,
82
+ :VBVMR_Output_GetDeviceNumber, [], :long
83
+ attach_function :vm_get_desc_outdevices,
84
+ :VBVMR_Output_GetDeviceDescA, %i[long pointer pointer pointer],
85
+ :long
86
+
87
+
88
+ @@cdll =
89
+ lambda do |func, *args|
90
+ self.retval = [send("vm_#{func}", *args), func]
91
+ end
92
+
93
+ def clear_polling() = while pdirty? || mdirty?; end
94
+
95
+ def polling(func, **kwargs)
96
+ params = {
97
+ 'get_parameter' => kwargs[:name],
98
+ 'get_buttonstatus' => "mb_#{kwargs[:id]}_#{kwargs[:mode]}",
99
+ }
100
+ return @cache.delete(params[func]) if @cache.key? params[func]
101
+
102
+ clear_polling if @sync
103
+
104
+ yield
105
+ end
106
+
107
+ def retval=(values)
108
+ ' Writer validation for CAPI calls '
109
+ retval, func = *values
110
+ unless [:get_num_indevices, :get_num_outdevices].include? func
111
+ raise CAPIErrors.new(retval, func) if retval&.nonzero?
112
+ end
113
+ @retval = retval
114
+ end
115
+
116
+ public
117
+
118
+ def pdirty?() = vm_pdirty&.nonzero?
119
+
120
+ def mdirty?() = vm_mdirty&.nonzero?
121
+
122
+ def ldirty?
123
+ @strip_buf, @bus_buf = _get_levels
124
+ return !(
125
+ @cache['strip_level'] == @strip_buf && @cache['bus_level'] == @bus_buf
126
+ )
127
+ end
128
+ end
data/lib/command.rb CHANGED
@@ -1,41 +1,36 @@
1
- require_relative 'meta'
2
-
3
- class ICommand
4
- include Commands_Meta_Functions
5
-
6
- def initialize(remote)
7
- @remote = remote
8
- end
9
-
10
- def setter(param, value)
11
- @remote.set_parameter("#{self.identifier}.#{param}", value)
12
- end
13
-
14
- def identifier
15
- :command
16
- end
17
- end
18
-
19
- class Command < ICommand
20
- def initialize(remote)
21
- super
22
- self.make_action_prop :show, :restart, :reset, :shutdown
23
- self.make_writer_bool :showvbanchat, :lock
24
- end
25
-
26
- def hide
27
- self.setter('show', 0)
28
- end
29
-
30
- def load(value)
31
- raise VMRemoteErrors.new('Expected a string') unless value.is_a? String
32
- self.setter('load', value)
33
- sleep(0.2)
34
- end
35
-
36
- def save(value)
37
- raise VMRemoteErrors.new('Expected a string') unless value.is_a? String
38
- self.setter('save', value)
39
- sleep(0.2)
40
- end
41
- end
1
+ require_relative 'iremote'
2
+ require_relative 'meta'
3
+
4
+ class Command < IRemote
5
+ include Commands_Meta_Functions
6
+
7
+ def initialize(remote)
8
+ super
9
+ self.make_action_prop :show, :restart, :shutdown
10
+ self.make_writer_bool :showvbanchat, :lock
11
+ end
12
+
13
+ def identifier
14
+ :command
15
+ end
16
+
17
+ def hide
18
+ self.setter('show', 0)
19
+ end
20
+
21
+ def load(value)
22
+ raise VMRemoteErrors.new('Expected a string') unless value.is_a? String
23
+ self.setter('load', value)
24
+ sleep(0.2)
25
+ end
26
+
27
+ def save(value)
28
+ raise VMRemoteErrors.new('Expected a string') unless value.is_a? String
29
+ self.setter('save', value)
30
+ sleep(0.2)
31
+ end
32
+
33
+ def reset
34
+ @remote.set_config('reset')
35
+ end
36
+ end
data/lib/configs.rb ADDED
@@ -0,0 +1,81 @@
1
+ require 'kinds'
2
+ require 'toml'
3
+
4
+ module Configs
5
+ private
6
+
7
+ @@configs = Hash.new
8
+
9
+ class TOMLStrBuilder
10
+ def initialize(kind)
11
+ @p_in, @v_in = kind[:layout][:strip].values
12
+ @p_out, @v_out = kind[:layout][:bus].values
13
+ @vs_params =
14
+ ['mute = false', 'mono = false', 'solo = false', 'gain = 0.0'] +
15
+ (1..@p_out).map { |i| "A#{i} = false" } +
16
+ (1..@v_out).map { |i| "B#{i} = false" }
17
+
18
+ @ps_params = @vs_params + ['comp = 0.0', 'gate = 0.0']
19
+ @bus_params = ['mono = false', 'eq = false', 'mute = false']
20
+ end
21
+
22
+ def build
23
+ '
24
+ Builds a TOML script for the parser
25
+ '
26
+ @ps = (0...@p_in).map { |i| ["[strip_#{i}]"] + @ps_params }
27
+ @ps.map! { |a| a.map { |s| s.gsub('B1 = false', 'B1 = true') } }
28
+ @vs =
29
+ (@p_in...(@p_in + @v_in)).map do |i|
30
+ ["[strip_#{i}]"] + @vs_params
31
+ end
32
+ @vs.map! { |a| a.map { |s| s.gsub('A1 = false', 'A1 = true') } }
33
+
34
+ @b =
35
+ (0...(@p_out + @v_out)).map { |i| ["[bus_#{i}]"] + @bus_params }
36
+
37
+ [@ps + @vs + @b].join("\n")
38
+ end
39
+ end
40
+
41
+ def parser(data)
42
+ TOML::Parser.new(data).parsed
43
+ end
44
+
45
+ def get_configs(kind_id)
46
+ file_pattern =
47
+ File.join(File.dirname(__dir__), 'configs', "#{kind_id}", '*.toml')
48
+
49
+ Dir
50
+ .glob(file_pattern)
51
+ .to_h do |toml_file|
52
+ filename = File.basename(toml_file, '.toml')
53
+ puts "loading config #{kind_id}/#{filename} into memory"
54
+ [filename, parser(File.read(toml_file))]
55
+ end
56
+ end
57
+
58
+ def loader
59
+ if @@configs.empty?
60
+ builder = TOMLStrBuilder.new(@kind)
61
+ puts 'loading config reset into memory'
62
+ @@configs['reset'] = parser(builder.build)
63
+ @@configs.merge!(get_configs(@kind.name.to_s))
64
+ end
65
+ end
66
+
67
+ public
68
+
69
+ def set_config(value)
70
+ loader
71
+ unless @@configs.key? value
72
+ raise VMRemoteErrors.new("No profile with name #{value} was loaded")
73
+ end
74
+
75
+ self.send('set_multi', @@configs[value])
76
+ puts "config #{@kind.name}/#{value} applied!"
77
+ sleep(@delay)
78
+ end
79
+
80
+ alias_method 'apply_config', :set_config
81
+ end
data/lib/device.rb ADDED
@@ -0,0 +1,24 @@
1
+ require_relative 'iremote'
2
+ require_relative 'meta'
3
+
4
+ class Device
5
+ def initialize(remote)
6
+ @remote = remote
7
+ end
8
+
9
+ def getter(**kwargs)
10
+ return @remote.get_num_devices(kwargs[:direction]) if kwargs[:index].nil?
11
+
12
+ vals = @remote.get_device_description(kwargs[:index], kwargs[:direction])
13
+ types = { 1 => 'mme', 3 => 'wdm', 4 => 'ks', 5 => 'asio' }
14
+ { 'name': vals[0], 'type': types[vals[1]], 'id': vals[2] }
15
+ end
16
+
17
+ def ins() = getter(direction: 'in')
18
+
19
+ def outs() = getter(direction: 'out')
20
+
21
+ def input(i) = getter(index: i, direction: 'in')
22
+
23
+ def output(i) = getter(index: i, direction: 'out')
24
+ end
data/lib/inst.rb CHANGED
@@ -1,38 +1,29 @@
1
- require 'win32/registry'
2
- require 'pathname'
3
- require_relative 'errors'
4
-
5
- include Errors
6
-
7
- module InstallationFunctions
8
- private
9
-
10
- def get_arch
11
- key = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
12
- Win32::Registry::HKEY_LOCAL_MACHINE.open(key) do |reg|
13
- os_bits = reg['PROCESSOR_ARCHITECTURE']
14
- return 64 if os_bits.include? '64'
15
- return 32
16
- end
17
- end
18
-
19
- def get_vmpath(os_bits)
20
- vm_key = 'VB:Voicemeeter {17359A74-1236-5467}'
21
- reg_key =
22
- "Software#{os_bits == 64 ? "\\WOW6432Node" : ''}\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
23
- Win32::Registry::HKEY_LOCAL_MACHINE.open(reg_key + vm_key) do |reg|
24
- value = reg['UninstallString']
25
-
26
- pn = Pathname.new(value)
27
- return pn.dirname
28
- end
29
- raise InstallErrors.new('Could not get the Voicemeeter path')
30
- end
31
-
32
- def vmr_dll=(value)
33
- unless value.file?
34
- raise InstallErrors.new('Could not fetch the dll file')
35
- end
36
- @vmr_dll = value
37
- end
38
- end
1
+ require 'win32/registry'
2
+ require 'pathname'
3
+ require_relative 'errors'
4
+
5
+ include Errors
6
+
7
+ module InstallationFunctions
8
+ private
9
+
10
+ def get_vmpath(os_bits)
11
+ vm_key = 'VB:Voicemeeter {17359A74-1236-5467}'
12
+ reg_key =
13
+ "Software#{os_bits == 64 ? "\\WOW6432Node" : ''}\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
14
+ Win32::Registry::HKEY_LOCAL_MACHINE.open(reg_key + vm_key) do |reg|
15
+ value = reg['UninstallString']
16
+
17
+ pn = Pathname.new(value)
18
+ return pn.dirname
19
+ end
20
+ raise InstallErrors.new('Could not get the Voicemeeter path')
21
+ end
22
+
23
+ def vm_dll=(value)
24
+ unless value.file?
25
+ raise InstallErrors.new('Could not fetch the dll file')
26
+ end
27
+ @vm_dll = value
28
+ end
29
+ end
data/lib/iremote.rb ADDED
@@ -0,0 +1,30 @@
1
+ require_relative 'meta'
2
+ require_relative 'errors'
3
+
4
+ class IRemote
5
+ '
6
+ Common interface between base class and higher classes.
7
+ '
8
+ include Meta_Functions
9
+
10
+ def initialize(remote, i = nil)
11
+ @remote = remote
12
+ @index = i
13
+ end
14
+
15
+ def getter(param, is_string = false)
16
+ @remote.get_parameter("#{self.identifier}.#{param}", is_string)
17
+ end
18
+
19
+ def setter(param, value)
20
+ @remote.set_parameter("#{self.identifier}.#{param}", value)
21
+ end
22
+
23
+ def identifier
24
+ raise 'Called abstract method: identifier'
25
+ end
26
+
27
+ def set_multi(param_hash)
28
+ param_hash.each { |(key, val)| self.send("#{key}=", val) }
29
+ end
30
+ end