voicemeeter_api_ruby 4.4.3 → 4.6.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.
- 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/event.rb +39 -10
- data/lib/voicemeeter/meta.rb +3 -10
- 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/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
|
@@ -13,23 +13,52 @@ module Voicemeeter
|
|
13
13
|
"#{self.class.name.split("::").last}#{@index}"
|
14
14
|
end
|
15
15
|
|
16
|
-
def info(msg)
|
17
|
-
info_msg = ["#{msg} events
|
18
|
-
|
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"}")
|
19
44
|
end
|
20
45
|
|
21
46
|
def get
|
22
47
|
%w[pdirty mdirty midi ldirty].reject { |ev| !send("#{ev}") }
|
23
48
|
end
|
24
49
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
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) }
|
28
57
|
end
|
29
58
|
|
30
|
-
def remove(
|
31
|
-
|
32
|
-
|
59
|
+
def remove(events)
|
60
|
+
events = [events] if !events.respond_to? :each
|
61
|
+
events.each { |ev| send("#{ev}=", false) }
|
33
62
|
end
|
34
63
|
end
|
35
64
|
end
|
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/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-10-
|
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
|