Class: Voicemeeter::Base
- Inherits:
-
Object
- Object
- Voicemeeter::Base
- Includes:
- Events::Director, Logging, Util::Cache, Util::Timeout, Worker
- Defined in:
- lib/voicemeeter/base.rb
Overview
Base class for Remote
Direct Known Subclasses
Constant Summary collapse
- RATELIMIT =
0.033
- DELAY =
0.001
- LOGIN_TIMEOUT =
2
Instance Attribute Summary collapse
-
#cache ⇒ Object
readonly
Returns the value of attribute cache.
-
#delay ⇒ Object
readonly
Returns the value of attribute delay.
-
#event ⇒ Object
readonly
Returns the value of attribute event.
-
#kind ⇒ Object
readonly
Returns the value of attribute kind.
-
#midi ⇒ Object
readonly
Returns the value of attribute midi.
Instance Method Summary collapse
- #apply(data) ⇒ Object
- #apply_config(name) ⇒ Object
- #clear_dirty ⇒ Object
- #get(name, is_string = false) ⇒ Object
- #get_buttonstatus(id, mode) ⇒ Object
- #get_device_description(index, dir) ⇒ Object
- #get_level(mode, index) ⇒ Object
- #get_midi_message ⇒ Object
- #get_num_devices(dir) ⇒ Object
-
#initialize(kind, **kwargs) ⇒ Base
constructor
A new instance of Base.
- #ldirty? ⇒ Boolean
- #login ⇒ Object
- #logout ⇒ Object
- #mdirty? ⇒ Boolean
- #pdirty? ⇒ Boolean
- #run_voicemeeter(kind_id) ⇒ Object
- #sendtext(script) ⇒ Object
- #set(name, value) ⇒ Object
- #set_buttonstatus(id, mode, state) ⇒ Object
- #to_s ⇒ Object
- #type ⇒ Object
- #version ⇒ Object
Methods included from Events::Director
#deregister, #fire, #observers, #on, #register
Methods included from Worker
#end_event_threads, #init_event_threads, #running?
Methods included from Logging
Constructor Details
#initialize(kind, **kwargs) ⇒ Base
Returns a new instance of Base.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/voicemeeter/base.rb', line 16 def initialize(kind, **kwargs) @kind = kind @sync = kwargs[:sync] || false @ratelimit = kwargs[:ratelimit] || RATELIMIT @delay = kwargs[:delay] || DELAY @login_timeout = kwargs[:login_timeout] || LOGIN_TIMEOUT @bits = kwargs[:bits] || 64 if ![32, 64].include? @bits logger.warn "kwarg bits got #{@bits}, expected either 32 or 64, defaulting to 64" @bits = 64 end @event = Events::Tracker.new( **(kwargs.select { |k, _| %i[pdirty mdirty ldirty midi].include? k }) ) @midi = Midi.new @cache = {strip_mode: 0} end |
Instance Attribute Details
#cache ⇒ Object (readonly)
Returns the value of attribute cache.
10 11 12 |
# File 'lib/voicemeeter/base.rb', line 10 def cache @cache end |
#delay ⇒ Object (readonly)
Returns the value of attribute delay.
10 11 12 |
# File 'lib/voicemeeter/base.rb', line 10 def delay @delay end |
#event ⇒ Object (readonly)
Returns the value of attribute event.
10 11 12 |
# File 'lib/voicemeeter/base.rb', line 10 def event @event end |
#kind ⇒ Object (readonly)
Returns the value of attribute kind.
10 11 12 |
# File 'lib/voicemeeter/base.rb', line 10 def kind @kind end |
#midi ⇒ Object (readonly)
Returns the value of attribute midi.
10 11 12 |
# File 'lib/voicemeeter/base.rb', line 10 def midi @midi end |
Instance Method Details
#apply(data) ⇒ Object
214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/voicemeeter/base.rb', line 214 def apply(data) data.each do |key, hash| case key.to_s.split("-") in [/strip|bus|button/ => kls, /^[0-9]+$/ => index] target = public_send(kls) in ["vban", /in|instream|out|oustream/ => dir, /^[0-9]+$/ => index] target = vban.public_send("#{dir.chomp("stream")}stream") else raise KeyError, "invalid config key '#{key}'" end target[index.to_i].apply(hash) end end |
#apply_config(name) ⇒ Object
228 229 230 231 |
# File 'lib/voicemeeter/base.rb', line 228 def apply_config(name) apply(configs[name]) logger.info "profile #{name} applied!" end |
#clear_dirty ⇒ Object
65 66 67 68 69 |
# File 'lib/voicemeeter/base.rb', line 65 def clear_dirty catch(:clear) do loop { throw(:clear) unless pdirty? || mdirty? } end end |
#get(name, is_string = false) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/voicemeeter/base.rb', line 104 def get(name, is_string = false) if is_string cget = FFI::MemoryPointer.new(:string, 512, true) CBindings.call(:bind_get_parameter_string_a, name, cget) cget.read_string else cget = FFI::MemoryPointer.new(:float, 1) CBindings.call(:bind_get_parameter_float, name, cget) cget.read_float.round(1) end end |
#get_buttonstatus(id, mode) ⇒ Object
125 126 127 128 129 |
# File 'lib/voicemeeter/base.rb', line 125 def (id, mode) cget = FFI::MemoryPointer.new(:float, 1) CBindings.call(:bind_macro_button_get_status, id, cget, mode) cget.read_float.to_i end |
#get_device_description(index, dir) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/voicemeeter/base.rb', line 161 def get_device_description(index, dir) unless %i[in out].include? dir raise Errors::VMError.new "dir got: #{dir}, expected :in or :out" end ctype = FFI::MemoryPointer.new(:long, 1) cname = FFI::MemoryPointer.new(:string, 256, true) chwid = FFI::MemoryPointer.new(:string, 256, true) if dir == :in CBindings.call( :bind_input_get_device_desc_a, index, ctype, cname, chwid ) else CBindings.call( :bind_output_get_device_desc_a, index, ctype, cname, chwid ) end [cname.read_string, ctype.read_long, chwid.read_string] end |
#get_level(mode, index) ⇒ Object
136 137 138 139 140 |
# File 'lib/voicemeeter/base.rb', line 136 def get_level(mode, index) cget = FFI::MemoryPointer.new(:float, 1) CBindings.call(:bind_get_level, mode, index, cget) cget.read_float end |
#get_midi_message ⇒ Object
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/voicemeeter/base.rb', line 188 def cmsg = FFI::MemoryPointer.new(:string, 1024, true) res = CBindings.call( :bind_get_midi_message, cmsg, 1024, ok: [-5, -6], exp: ->(x) { x >= 0 } ) if (got_midi = res > 0) data = cmsg.read_bytes(res).bytes data.each_slice(3) do |ch, key, velocity| midi.channel = ch midi.current = key midi.cache[key] = velocity end end got_midi end |
#get_num_devices(dir) ⇒ Object
150 151 152 153 154 155 156 157 158 159 |
# File 'lib/voicemeeter/base.rb', line 150 def get_num_devices(dir) unless %i[in out].include? dir raise Errors::VMError.new "dir got: #{dir}, expected :in or :out" end if dir == :in CBindings.call(:bind_input_get_device_number, exp: ->(x) { x >= 0 }) else CBindings.call(:bind_output_get_device_number, exp: ->(x) { x >= 0 }) end end |
#ldirty? ⇒ Boolean
57 58 59 60 61 62 63 |
# File 'lib/voicemeeter/base.rb', line 57 def ldirty? cache[:strip_buf], cache[:bus_buf] = _get_levels !( cache[:strip_level] == cache[:strip_buf] && cache[:bus_level] == cache[:bus_buf] ) end |
#login ⇒ Object
39 40 41 |
# File 'lib/voicemeeter/base.rb', line 39 def login CBindings.call(:bind_login, ok: [0, 1]) == 1 and run_voicemeeter(kind.name) end |
#logout ⇒ Object
43 44 45 46 47 |
# File 'lib/voicemeeter/base.rb', line 43 def logout sleep(0.1) CBindings.call(:bind_logout) logger.info "Successfully logged out of #{self}" end |
#mdirty? ⇒ Boolean
53 54 55 |
# File 'lib/voicemeeter/base.rb', line 53 def mdirty? CBindings.call(:bind_macro_button_is_dirty, ok: [0, 1]) == 1 end |
#pdirty? ⇒ Boolean
49 50 51 |
# File 'lib/voicemeeter/base.rb', line 49 def pdirty? CBindings.call(:bind_is_parameters_dirty, ok: [0, 1]) == 1 end |
#run_voicemeeter(kind_id) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/voicemeeter/base.rb', line 71 def run_voicemeeter(kind_id) kinds = { basic: ([Install::OS_BITS, @bits].all? { |v| v == 64 }) ? Kinds::KindEnum::BASICX64 : Kinds::KindEnum::BASIC, banana: ([Install::OS_BITS, @bits].all? { |v| v == 64 }) ? Kinds::KindEnum::BANANAX64 : Kinds::KindEnum::BANANA, potato: ([Install::OS_BITS, @bits].all? { |v| v == 64 }) ? Kinds::KindEnum::POTATOX64 : Kinds::KindEnum::POTATO } if caller(1..1).first[/`(.*)'/, 1] == "login" logger.debug "Voicemeeter engine running but the GUI appears to be down... launching." end CBindings.call(:bind_run_voicemeeter, kinds[kind_id]) end |
#sendtext(script) ⇒ Object
209 210 211 212 |
# File 'lib/voicemeeter/base.rb', line 209 def sendtext(script) raise ArgumentError, "script must not exceed 48kB" if script.length > 48000 CBindings.call(:bind_set_parameters, script) end |
#set(name, value) ⇒ Object
116 117 118 119 120 121 122 123 |
# File 'lib/voicemeeter/base.rb', line 116 def set(name, value) if value.is_a? String CBindings.call(:bind_set_parameter_string_a, name, value) else CBindings.call(:bind_set_parameter_float, name, value.to_f) end cache.store(name, value) end |
#set_buttonstatus(id, mode, state) ⇒ Object
131 132 133 134 |
# File 'lib/voicemeeter/base.rb', line 131 def (id, mode, state) CBindings.call(:bind_macro_button_set_status, id, state, mode) cache.store("mb_#{id}_#{mode}", state) end |
#to_s ⇒ Object
35 36 37 |
# File 'lib/voicemeeter/base.rb', line 35 def to_s "Voicemeeter #{kind}" end |
#type ⇒ Object
86 87 88 89 90 91 |
# File 'lib/voicemeeter/base.rb', line 86 def type ckind = FFI::MemoryPointer.new(:long, 1) CBindings.call(:bind_get_voicemeeter_type, ckind) kinds = [nil, :basic, :banana, :potato] kinds[ckind.read_long] end |
#version ⇒ Object
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/voicemeeter/base.rb', line 93 def version cver = FFI::MemoryPointer.new(:long, 1) CBindings.call(:bind_get_voicemeeter_version, cver) [ (cver.read_long & 0xFF000000) >> 24, (cver.read_long & 0x00FF0000) >> 16, (cver.read_long & 0x0000FF00) >> 8, cver.read_long & 0x000000FF ].join(".") end |