voicemeeter-api-python/voicemeeterlib/misc.py

268 lines
6.1 KiB
Python
Raw Normal View History

from typing import Optional
from . import kinds
from .iremote import IRemote
class FX(IRemote):
def __str__(self):
2025-01-15 12:40:31 +00:00
return f'{type(self).__name__}'
@property
def identifier(self) -> str:
2025-01-15 12:40:31 +00:00
return 'FX'
@property
def reverb(self) -> bool:
2025-01-15 12:40:31 +00:00
return self.getter('reverb.On') == 1
@reverb.setter
def reverb(self, val: bool):
2025-01-15 12:40:31 +00:00
self.setter('reverb.On', 1 if val else 0)
@property
def reverb_ab(self) -> bool:
2025-01-15 12:40:31 +00:00
return self.getter('reverb.ab') == 1
@reverb_ab.setter
def reverb_ab(self, val: bool):
2025-01-15 12:40:31 +00:00
self.setter('reverb.ab', 1 if val else 0)
@property
def delay(self) -> bool:
2025-01-15 12:40:31 +00:00
return self.getter('delay.On') == 1
@delay.setter
def delay(self, val: bool):
2025-01-15 12:40:31 +00:00
self.setter('delay.On', 1 if val else 0)
@property
def delay_ab(self) -> bool:
2025-01-15 12:40:31 +00:00
return self.getter('delay.ab') == 1
@delay_ab.setter
def delay_ab(self, val: bool):
2025-01-15 12:40:31 +00:00
self.setter('delay.ab', 1 if val else 0)
class Patch(IRemote):
@classmethod
def make(cls, remote):
"""
Factory method for Patch.
Mixes in required classes.
Returns a Patch class of a kind.
"""
ASIO_cls = _make_asio_mixins(remote)[remote.kind.name]
return type(
2025-01-15 12:40:31 +00:00
f'Patch{remote.kind}',
(cls, ASIO_cls),
{
2025-01-15 12:40:31 +00:00
'composite': tuple(Composite(remote, i) for i in range(8)),
'insert': tuple(Insert(remote, i) for i in range(remote.kind.insert)),
},
)(remote)
def __str__(self):
2025-01-15 12:40:31 +00:00
return f'{type(self).__name__}'
@property
def identifier(self) -> str:
2025-01-15 12:40:31 +00:00
return 'patch'
@property
def postfadercomp(self) -> bool:
2025-01-15 12:40:31 +00:00
return self.getter('postfadercomposite') == 1
@postfadercomp.setter
def postfadercomp(self, val: bool):
2025-01-15 12:40:31 +00:00
self.setter('postfadercomposite', 1 if val else 0)
@property
def postfxinsert(self) -> bool:
2025-01-15 12:40:31 +00:00
return self.getter('postfxinsert') == 1
@postfxinsert.setter
def postfxinsert(self, val: bool):
2025-01-15 12:40:31 +00:00
self.setter('postfxinsert', 1 if val else 0)
class Asio(IRemote):
@property
def identifier(self) -> str:
2025-01-15 12:40:31 +00:00
return 'patch'
class AsioIn(Asio):
def get(self) -> int:
2025-01-15 12:40:31 +00:00
return int(self.getter(f'asio[{self.index}]'))
def set(self, val: int):
2025-01-15 12:40:31 +00:00
self.setter(f'asio[{self.index}]', val)
class AsioOut(Asio):
def __init__(self, remote, i, param):
IRemote.__init__(self, remote, i)
self._param = param
def get(self) -> int:
2025-01-15 12:40:31 +00:00
return int(self.getter(f'out{self._param}[{self.index}]'))
def set(self, val: int):
2025-01-15 12:40:31 +00:00
self.setter(f'out{self._param}[{self.index}]', val)
def _make_asio_mixin(remote, kind):
"""Creates an ASIO mixin for a kind"""
asio_in, asio_out = kind.asio
return type(
2025-01-15 12:40:31 +00:00
f'ASIO{kind}',
(IRemote,),
{
2025-01-15 12:40:31 +00:00
'asio': tuple(AsioIn(remote, i) for i in range(asio_in)),
**{
param: tuple(AsioOut(remote, i, param) for i in range(asio_out))
2025-01-15 12:40:31 +00:00
for param in ['A2', 'A3', 'A4', 'A5']
},
},
)
def _make_asio_mixins(remote):
return {kind.name: _make_asio_mixin(remote, kind) for kind in kinds.all}
class Composite(IRemote):
@property
def identifier(self) -> str:
2025-01-15 12:40:31 +00:00
return 'patch'
def get(self) -> int:
2025-01-15 12:40:31 +00:00
return int(self.getter(f'composite[{self.index}]'))
def set(self, val: int):
2025-01-15 12:40:31 +00:00
self.setter(f'composite[{self.index}]', val)
class Insert(IRemote):
@property
def identifier(self) -> str:
2025-01-15 12:40:31 +00:00
return 'patch'
@property
def on(self) -> bool:
2025-01-15 12:40:31 +00:00
return self.getter(f'insert[{self.index}]') == 1
@on.setter
def on(self, val: bool):
2025-01-15 12:40:31 +00:00
self.setter(f'insert[{self.index}]', 1 if val else 0)
class Option(IRemote):
@classmethod
def make(cls, remote):
"""
Factory method for Option.
Mixes in required classes.
Returns a Option class of a kind.
"""
return type(
2025-01-15 12:40:31 +00:00
f'Option{remote.kind}',
(cls,),
{
2025-01-15 12:40:31 +00:00
'delay': tuple(Delay(remote, i) for i in range(remote.kind.phys_out)),
},
)(remote)
def __str__(self):
2025-01-15 12:40:31 +00:00
return f'{type(self).__name__}'
@property
def identifier(self) -> str:
2025-01-15 12:40:31 +00:00
return 'option'
@property
def sr(self) -> int:
2025-01-15 12:40:31 +00:00
return int(self.getter('sr'))
@sr.setter
def sr(self, val: int):
opts = (44100, 48000, 88200, 96000, 176400, 192000)
if val not in opts:
2025-01-15 12:40:31 +00:00
self.logger.warning(f'sr got: {val} but expected a value in {opts}')
self.setter('sr', val)
@property
def asiosr(self) -> bool:
2025-01-15 12:40:31 +00:00
return self.getter('asiosr') == 1
@asiosr.setter
def asiosr(self, val: bool):
2025-01-15 12:40:31 +00:00
self.setter('asiosr', 1 if val else 0)
@property
def monitoronsel(self) -> bool:
2025-01-15 12:40:31 +00:00
return self.getter('monitoronsel') == 1
@monitoronsel.setter
def monitoronsel(self, val: bool):
2025-01-15 12:40:31 +00:00
self.setter('monitoronsel', 1 if val else 0)
def buffer(self, driver, buffer):
2025-01-15 12:40:31 +00:00
self.setter(f'buffer.{driver}', buffer)
class Delay(IRemote):
@property
def identifier(self) -> str:
2025-01-15 12:40:31 +00:00
return 'option'
def get(self) -> int:
2025-01-15 12:40:31 +00:00
return int(self.getter(f'delay[{self.index}]'))
def set(self, val: int):
2025-01-15 12:40:31 +00:00
self.setter(f'delay[{self.index}]', val)
class Midi:
def __init__(self):
self._channel = None
self.cache = {}
self._most_recent = None
@property
def channel(self) -> int:
return self._channel
@property
def current(self) -> int:
return self._most_recent
def get(self, key: int) -> Optional[int]:
return self.cache.get(key)
def _set(self, key: int, velocity: int):
self.cache[key] = velocity
class VmGui:
_launched = None
@property
def launched(self) -> bool:
return self._launched
@launched.setter
def launched(self, val: bool):
self._launched = val
@property
def launched_by_api(self):
return not self.launched