voicemeeter_api_ruby 4.4.2 → 4.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -1
- data/README.md +73 -31
- data/lib/voicemeeter/base.rb +6 -0
- data/lib/voicemeeter/bus.rb +16 -2
- data/lib/voicemeeter/cbindings.rb +22 -9
- data/lib/voicemeeter/device.rb +4 -0
- data/lib/voicemeeter/event.rb +43 -10
- data/lib/voicemeeter/iremote.rb +4 -0
- data/lib/voicemeeter/meta.rb +3 -10
- data/lib/voicemeeter/midi.rb +4 -0
- data/lib/voicemeeter/strip.rb +17 -2
- data/lib/voicemeeter/version.rb +2 -2
- data/lib/voicemeeter/worker.rb +1 -1
- data/lib/voicemeeter.rb +9 -0
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 853191cf2f0496441c9db529fb2863f29f769088107e704f779cd3fa602baf4a
|
4
|
+
data.tar.gz: ac9610c2aa4bf7a3319dbd7677774b5b52d579970d58412447357e9d67443830
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4dddc3aaa0fb7e600c489b0c0773a542447e9ff6fe1e839783b45f8766742a21d1354846daf5a2a3ee08f43ee85fc2272326ed6a696201eaa741f6b5002a1299
|
7
|
+
data.tar.gz: ab40474cf35aede927799ce48465a482269345803ec79692ccbe0da6bb082368545000a8622286530c08d9a8764b3e983c91383c89caf603d3432799a6d4fda0
|
data/CHANGELOG.md
CHANGED
@@ -9,7 +9,22 @@ 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
|
-
- [ ]
|
12
|
+
- [ ]
|
13
|
+
|
14
|
+
## [4.6.0] - 2022-10-17
|
15
|
+
|
16
|
+
### Added
|
17
|
+
|
18
|
+
- StripDevice, BusDevice classes.
|
19
|
+
- midi example
|
20
|
+
- logger module to dependencies.
|
21
|
+
- README updated to reflect changes.
|
22
|
+
|
23
|
+
### Changed
|
24
|
+
|
25
|
+
- log level info to examples.
|
26
|
+
- bus levels now printed in observer example.
|
27
|
+
- Event add/remove methods now accept multiple events.
|
13
28
|
|
14
29
|
## [4.4.0] - 2022-08-06
|
15
30
|
|
data/README.md
CHANGED
@@ -91,8 +91,6 @@ The following properties are available.
|
|
91
91
|
- `limit`: int, from -40 to 12
|
92
92
|
- `A1 - A5`, `B1 - B3`: boolean
|
93
93
|
- `label`: string
|
94
|
-
- `device`: string
|
95
|
-
- `sr`: int
|
96
94
|
- `mc`: boolean
|
97
95
|
- `k`: int, from 0 to 4
|
98
96
|
- `bass`: float, from -12.0 to 12.0
|
@@ -176,8 +174,6 @@ The following properties are available.
|
|
176
174
|
- `sel`: boolean
|
177
175
|
- `gain`: float, from -60.0 to 12.0
|
178
176
|
- `label`: string
|
179
|
-
- `device`: string
|
180
|
-
- `sr`: int
|
181
177
|
- `returnreverb`: float, from 0.0 to 10.0
|
182
178
|
- `returndelay`: float, from 0.0 to 10.0
|
183
179
|
- `returnfx1`: float, from 0.0 to 10.0
|
@@ -243,6 +239,24 @@ vm.strip[0].fadeto(-10.3, 1000)
|
|
243
239
|
vm.bus[3].fadeby(-5.6, 500)
|
244
240
|
```
|
245
241
|
|
242
|
+
#### Strip.Device | Bus.Device
|
243
|
+
|
244
|
+
The following properties are available
|
245
|
+
|
246
|
+
- `name`: str
|
247
|
+
- `sr`: int
|
248
|
+
- `wdm`: str
|
249
|
+
- `ks`: str
|
250
|
+
- `mme`: str
|
251
|
+
- `asio`: str
|
252
|
+
|
253
|
+
example:
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
puts vm.strip[0].device.name
|
257
|
+
vm.bus[0].device.asio = "Audient USB Audio ASIO Driver"
|
258
|
+
```
|
259
|
+
|
246
260
|
### Macrobuttons
|
247
261
|
|
248
262
|
Three modes defined: state, stateonly and trigger.
|
@@ -428,62 +442,90 @@ vm.run { vm.apply_config('example') }
|
|
428
442
|
|
429
443
|
will load a config file at mydir/configs/banana/example.toml for Voicemeeter Banana.
|
430
444
|
|
431
|
-
##
|
445
|
+
## Events
|
432
446
|
|
433
|
-
|
447
|
+
Level updates are considered high volume, by default they are NOT listened for.
|
434
448
|
|
435
|
-
|
449
|
+
Use keyword args `pdirty`, `mdirty`, `midi`, `ldirty` to initialize event updates.
|
436
450
|
|
437
|
-
|
451
|
+
example:
|
438
452
|
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
453
|
+
```ruby
|
454
|
+
require 'voicemeeter'
|
455
|
+
# Set updates to occur every 50ms
|
456
|
+
# Listen for level updates but disable midi updates
|
457
|
+
vm = Voicemeeter.remote('banana', ratelimit: 0.05, ldirty: true, midi: false)
|
458
|
+
vm.run { ... }
|
459
|
+
```
|
445
460
|
|
461
|
+
#### `vm.add_observer`|`vm.delete_observer`
|
446
462
|
|
447
|
-
|
463
|
+
Use the add_observer/delete_observer methods to register/deregister an app as an observer.
|
448
464
|
|
449
|
-
|
465
|
+
example:
|
450
466
|
|
451
|
-
|
452
|
-
|
467
|
+
```ruby
|
468
|
+
# register an app to receive updates
|
469
|
+
class App():
|
470
|
+
def initialize(vm)
|
471
|
+
@vm = vm
|
472
|
+
@vm.add_observer(self)
|
473
|
+
...
|
474
|
+
```
|
453
475
|
|
454
|
-
|
476
|
+
#### `vm.event`
|
455
477
|
|
456
|
-
|
478
|
+
Use the event class to toggle updates as necessary.
|
457
479
|
|
458
|
-
|
480
|
+
The following properties are available:
|
459
481
|
|
460
|
-
|
482
|
+
- `pdirty`: boolean
|
483
|
+
- `mdirty`: boolean
|
484
|
+
- `midi`: boolean
|
485
|
+
- `ldirty`: boolean
|
461
486
|
|
462
487
|
example:
|
463
488
|
|
464
489
|
```ruby
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
vm = Voicemeeter.remote('banana', ratelimit: 0.05, ldirty: true, midi: false)
|
469
|
-
vm.run { ... }
|
490
|
+
vm.event.ldirty = true
|
491
|
+
|
492
|
+
vm.event.pdirty = false
|
470
493
|
```
|
471
494
|
|
472
|
-
|
495
|
+
Or add, remove an array of events.
|
473
496
|
|
474
|
-
|
497
|
+
The following methods are available:
|
498
|
+
|
499
|
+
- `add()`
|
500
|
+
- `remove()`
|
501
|
+
- `get()`
|
475
502
|
|
476
503
|
example:
|
477
504
|
|
478
505
|
```ruby
|
479
|
-
vm.event.add(
|
506
|
+
vm.event.add(%w[pdirty mdirty midi ldirty])
|
480
507
|
|
481
|
-
vm.event.remove(
|
508
|
+
vm.event.remove(%w[pdirty mdirty midi ldirty])
|
482
509
|
|
483
510
|
# get a list of currently subscribed
|
484
511
|
p vm.event.get
|
485
512
|
```
|
486
513
|
|
514
|
+
## `Voicemeeter Module`
|
515
|
+
|
516
|
+
### Remote class
|
517
|
+
|
518
|
+
#### Voicemeeter.remote
|
519
|
+
|
520
|
+
You may pass the following optional keyword arguments:
|
521
|
+
|
522
|
+
- `sync`: boolean=false, force the getters to wait for dirty parameters to clear. For most cases leave this as false.
|
523
|
+
- `ratelimit`: float=0.033, how often to check for updates in ms.
|
524
|
+
- `pdirty`: boolean=true, parameter updates
|
525
|
+
- `mdirty`: boolean=true, macrobutton updates
|
526
|
+
- `midi`: boolean=true, midi updates
|
527
|
+
- `ldirty`: boolean=false, level updates
|
528
|
+
|
487
529
|
Access to lower level Getters and Setters are provided with these functions:
|
488
530
|
|
489
531
|
- `vm.get(param, string=false)`: For getting the value of any parameter. Set string to true if getting a property value expected to return a string.
|
data/lib/voicemeeter/base.rb
CHANGED
@@ -45,9 +45,14 @@ module Voicemeeter
|
|
45
45
|
@event = Event.new(**kwargs)
|
46
46
|
end
|
47
47
|
|
48
|
+
def to_s
|
49
|
+
"Voicemeeter #{@kind.name.capitalize}"
|
50
|
+
end
|
51
|
+
|
48
52
|
def login
|
49
53
|
@@cdll.call(:login)
|
50
54
|
clear_polling
|
55
|
+
LOGGER.info("Logged into Voiceemeter #{self}")
|
51
56
|
rescue CAPIErrors => error
|
52
57
|
case
|
53
58
|
when error.value == 1
|
@@ -62,6 +67,7 @@ module Voicemeeter
|
|
62
67
|
clear_polling
|
63
68
|
sleep(0.1)
|
64
69
|
@@cdll.call(:logout)
|
70
|
+
LOGGER.info("Logged out of Voiceemeter #{self}")
|
65
71
|
end
|
66
72
|
|
67
73
|
def type
|
data/lib/voicemeeter/bus.rb
CHANGED
@@ -9,7 +9,7 @@ module Voicemeeter
|
|
9
9
|
include Mixin::Fades
|
10
10
|
include Mixin::Return
|
11
11
|
|
12
|
-
attr_accessor :mode, :levels
|
12
|
+
attr_accessor :mode, :levels, :device
|
13
13
|
|
14
14
|
def self.make(remote, layout_bus)
|
15
15
|
"
|
@@ -39,7 +39,7 @@ module Voicemeeter
|
|
39
39
|
class PhysicalBus < Bus
|
40
40
|
def initialize(remote, i)
|
41
41
|
super
|
42
|
-
|
42
|
+
@device = BusDevice.new(remote, i)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -96,4 +96,18 @@ module Voicemeeter
|
|
96
96
|
|
97
97
|
def isdirty? = @remote._bus_comp[@init, @offset].any?
|
98
98
|
end
|
99
|
+
|
100
|
+
class BusDevice < IRemote
|
101
|
+
include Channel_Meta_Functions
|
102
|
+
|
103
|
+
def initialize(remote, i)
|
104
|
+
super
|
105
|
+
self.make_reader_only :name, :sr
|
106
|
+
self.make_writer_only :wdm, :ks, :mme, :asio
|
107
|
+
end
|
108
|
+
|
109
|
+
def identifier
|
110
|
+
"bus[#{@index}].device"
|
111
|
+
end
|
112
|
+
end
|
99
113
|
end
|
@@ -31,7 +31,10 @@ module Voicemeeter
|
|
31
31
|
attach_function :vm_logout, :VBVMR_Logout, [], :long
|
32
32
|
attach_function :vm_runvm, :VBVMR_RunVoicemeeter, [:long], :long
|
33
33
|
attach_function :vm_vmtype, :VBVMR_GetVoicemeeterType, [:pointer], :long
|
34
|
-
attach_function :vm_vmversion,
|
34
|
+
attach_function :vm_vmversion,
|
35
|
+
:VBVMR_GetVoicemeeterVersion,
|
36
|
+
[:pointer],
|
37
|
+
:long
|
35
38
|
|
36
39
|
attach_function :vm_mdirty, :VBVMR_MacroButton_IsDirty, [], :long
|
37
40
|
attach_function :vm_get_buttonstatus,
|
@@ -69,7 +72,10 @@ module Voicemeeter
|
|
69
72
|
|
70
73
|
attach_function :vm_get_level, :VBVMR_GetLevel, %i[long long pointer], :long
|
71
74
|
|
72
|
-
attach_function :vm_get_num_indevices,
|
75
|
+
attach_function :vm_get_num_indevices,
|
76
|
+
:VBVMR_Input_GetDeviceNumber,
|
77
|
+
[],
|
78
|
+
:long
|
73
79
|
attach_function :vm_get_desc_indevices,
|
74
80
|
:VBVMR_Input_GetDeviceDescA,
|
75
81
|
%i[long pointer pointer pointer],
|
@@ -89,10 +95,7 @@ module Voicemeeter
|
|
89
95
|
%i[pointer long],
|
90
96
|
:long
|
91
97
|
|
92
|
-
@@cdll =
|
93
|
-
lambda { |func, *args| retval = [send("vm_#{func}", *args), func] }
|
94
|
-
|
95
|
-
def clear_polling = while pdirty? || mdirty?; end
|
98
|
+
@@cdll = lambda { |func, *args| retval = [send("vm_#{func}", *args), func] }
|
96
99
|
|
97
100
|
def polling(func, **kwargs)
|
98
101
|
params = {
|
@@ -109,7 +112,11 @@ module Voicemeeter
|
|
109
112
|
def retval=(values)
|
110
113
|
" Writer validation for CAPI calls "
|
111
114
|
retval, func = *values
|
112
|
-
unless %i[
|
115
|
+
unless %i[
|
116
|
+
get_num_indevices
|
117
|
+
get_num_outdevices
|
118
|
+
get_midi_message
|
119
|
+
].include? func
|
113
120
|
raise CAPIErrors.new(retval, func) if retval&.nonzero?
|
114
121
|
end
|
115
122
|
@retval = retval
|
@@ -117,6 +124,10 @@ module Voicemeeter
|
|
117
124
|
|
118
125
|
public
|
119
126
|
|
127
|
+
def clear_polling =
|
128
|
+
while pdirty? || mdirty?
|
129
|
+
end
|
130
|
+
|
120
131
|
def pdirty? = vm_pdirty&.nonzero?
|
121
132
|
|
122
133
|
def mdirty? = vm_mdirty&.nonzero?
|
@@ -124,8 +135,10 @@ module Voicemeeter
|
|
124
135
|
def ldirty?
|
125
136
|
@strip_buf, @bus_buf = _get_levels
|
126
137
|
return(
|
127
|
-
!(
|
138
|
+
!(
|
139
|
+
@cache["strip_level"] == @strip_buf && @cache["bus_level"] == @bus_buf
|
140
|
+
)
|
128
141
|
)
|
129
142
|
end
|
130
143
|
end
|
131
|
-
end
|
144
|
+
end
|
data/lib/voicemeeter/device.rb
CHANGED
data/lib/voicemeeter/event.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Voicemeeter
|
2
2
|
class Event
|
3
|
-
|
3
|
+
attr_reader :pdirty, :mdirty, :midi, :ldirty
|
4
4
|
|
5
5
|
def initialize(pdirty: true, mdirty: true, midi: true, ldirty: false)
|
6
6
|
@pdirty = pdirty
|
@@ -9,23 +9,56 @@ module Voicemeeter
|
|
9
9
|
@ldirty = ldirty
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
12
|
+
def to_s
|
13
|
+
"#{self.class.name.split("::").last}#{@index}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def info(msg = nil)
|
17
|
+
info_msg = msg ? ["#{msg} events."] : []
|
18
|
+
if any?
|
19
|
+
info_msg += ["Now listening for #{get.join(", ")} events"]
|
20
|
+
else
|
21
|
+
info_msg += ["Not listening for any events"]
|
22
|
+
end
|
23
|
+
LOGGER.info(info_msg.join(" "))
|
24
|
+
end
|
25
|
+
|
26
|
+
def pdirty=(val)
|
27
|
+
@pdirty = val
|
28
|
+
info("pdirty #{val ? "added to" : "removed from"}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def mdirty=(val)
|
32
|
+
@mdirty = val
|
33
|
+
info("mdirty #{val ? "added to" : "removed from"}")
|
34
|
+
end
|
35
|
+
|
36
|
+
def ldirty=(val)
|
37
|
+
@ldirty = val
|
38
|
+
info("ldirty #{val ? "added to" : "removed from"}")
|
39
|
+
end
|
40
|
+
|
41
|
+
def midi=(val)
|
42
|
+
@midi = val
|
43
|
+
info("midi #{val ? "added to" : "removed from"}")
|
15
44
|
end
|
16
45
|
|
17
46
|
def get
|
18
47
|
%w[pdirty mdirty midi ldirty].reject { |ev| !send("#{ev}") }
|
19
48
|
end
|
20
49
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
50
|
+
def any?
|
51
|
+
[pdirty, mdirty, midi, ldirty].any?
|
52
|
+
end
|
53
|
+
|
54
|
+
def add(events)
|
55
|
+
events = [events] if !events.respond_to? :each
|
56
|
+
events.each { |ev| send("#{ev}=", true) }
|
24
57
|
end
|
25
58
|
|
26
|
-
def remove(
|
27
|
-
|
28
|
-
|
59
|
+
def remove(events)
|
60
|
+
events = [events] if !events.respond_to? :each
|
61
|
+
events.each { |ev| send("#{ev}=", false) }
|
29
62
|
end
|
30
63
|
end
|
31
64
|
end
|
data/lib/voicemeeter/iremote.rb
CHANGED
data/lib/voicemeeter/meta.rb
CHANGED
@@ -114,19 +114,12 @@ module Voicemeeter
|
|
114
114
|
|
115
115
|
def make_reader_only(*params)
|
116
116
|
params.each do |param|
|
117
|
-
cmds = { device: "device.name", sr: "device.sr" }
|
118
|
-
if cmds.key? param
|
119
|
-
cmd = cmds[param]
|
120
|
-
else
|
121
|
-
cmd = param
|
122
|
-
end
|
123
|
-
|
124
117
|
define_singleton_method("#{param}") do
|
125
118
|
case param
|
126
|
-
when :
|
127
|
-
return self.getter("#{
|
119
|
+
when :name
|
120
|
+
return self.getter("#{param}", true)
|
128
121
|
when :sr
|
129
|
-
return self.getter("#{
|
122
|
+
return self.getter("#{param}").to_i
|
130
123
|
end
|
131
124
|
end
|
132
125
|
end
|
data/lib/voicemeeter/midi.rb
CHANGED
data/lib/voicemeeter/strip.rb
CHANGED
@@ -10,7 +10,7 @@ module Voicemeeter
|
|
10
10
|
include Mixin::Outputs
|
11
11
|
include Mixin::Fades
|
12
12
|
|
13
|
-
attr_accessor :gainlayer, :levels
|
13
|
+
attr_accessor :gainlayer, :levels, :device
|
14
14
|
|
15
15
|
def self.make(remote, layout_strip)
|
16
16
|
"
|
@@ -45,7 +45,8 @@ module Voicemeeter
|
|
45
45
|
def initialize(remote, i)
|
46
46
|
super
|
47
47
|
self.make_accessor_float :comp, :gate, :audibility
|
48
|
-
|
48
|
+
|
49
|
+
@device = StripDevice.new(remote, i)
|
49
50
|
end
|
50
51
|
end
|
51
52
|
|
@@ -121,4 +122,18 @@ module Voicemeeter
|
|
121
122
|
|
122
123
|
def isdirty? = @remote._strip_comp[@init, @offset].any?
|
123
124
|
end
|
125
|
+
|
126
|
+
class StripDevice < IRemote
|
127
|
+
include Channel_Meta_Functions
|
128
|
+
|
129
|
+
def initialize(remote, i)
|
130
|
+
super
|
131
|
+
self.make_reader_only :name, :sr
|
132
|
+
self.make_writer_only :wdm, :ks, :mme, :asio
|
133
|
+
end
|
134
|
+
|
135
|
+
def identifier
|
136
|
+
"strip[#{@index}].device"
|
137
|
+
end
|
138
|
+
end
|
124
139
|
end
|
data/lib/voicemeeter/version.rb
CHANGED
data/lib/voicemeeter/worker.rb
CHANGED
data/lib/voicemeeter.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "logger"
|
2
|
+
|
1
3
|
require_relative "voicemeeter/base"
|
2
4
|
require_relative "voicemeeter/strip"
|
3
5
|
require_relative "voicemeeter/bus"
|
@@ -7,3 +9,10 @@ require_relative "voicemeeter/command"
|
|
7
9
|
require_relative "voicemeeter/recorder"
|
8
10
|
require_relative "voicemeeter/device"
|
9
11
|
require_relative "voicemeeter/remote"
|
12
|
+
|
13
|
+
module Voicemeeter
|
14
|
+
include Logger::Severity
|
15
|
+
|
16
|
+
LOGGER = Logger.new(STDOUT)
|
17
|
+
LOGGER.level = WARN
|
18
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: voicemeeter_api_ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- onyx_online
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -58,6 +58,26 @@ dependencies:
|
|
58
58
|
- - "~>"
|
59
59
|
- !ruby/object:Gem::Version
|
60
60
|
version: 0.1.1
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: logger
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '1.5'
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 1.5.1
|
71
|
+
type: :runtime
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - "~>"
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '1.5'
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 1.5.1
|
61
81
|
- !ruby/object:Gem::Dependency
|
62
82
|
name: rspec
|
63
83
|
requirement: !ruby/object:Gem::Requirement
|