add profiles

added profiles module.
added example profile configs
added toml dependency to setup.py
add apply_profile and reset functions to base class
This commit is contained in:
onyx-and-iris 2022-03-23 11:28:42 +00:00
parent 5d593200d3
commit 1c57528cd8
7 changed files with 221 additions and 15 deletions

View File

@ -0,0 +1,36 @@
extends = 'blank'
[strip-0]
limit = 12
label = ""
[strip-1]
A1 = true
A2 = true
A3 = true
B1 = true
B2 = true
mono = true
solo = true
mute = true
limit = 12
label = ""
[strip-2]
limit = 12
label = ""
[strip-3]
limit = 12
label = ""
[strip-4]
A1 = false
A2 = false
A3 = false
B1 = false
B2 = false
k = false
solo = false
mute = false
limit = 12
label = ""

View File

@ -0,0 +1,18 @@
extends = 'blank'
[strip-0]
A1 = true
B1 = true
mono = true
solo = true
mute = true
limit = 12
label = ""
[strip-1]
A1 = false
B1 = false
mono = false
solo = false
mute = false
limit = 12
label = ""

View File

@ -0,0 +1,43 @@
extends = 'blank'
[strip-0]
limit = 12
label = ""
[strip-1]
limit = 12
label = ""
[strip-2]
A1 = true
A2 = true
A3 = true
A4 = true
A5 = true
B1 = true
B2 = true
B3 = true
mono = true
solo = true
mute = true
limit = 12
label = ""
[strip-3]
limit = 12
label = ""
[strip-4]
limit = 12
label = ""
[strip-5]
limit = 12
label = ""
[strip-6]
limit = 12
label = ""
[strip-7]
limit = 12
label = ""

View File

@ -6,6 +6,7 @@ setup(
description='VBAN CMD Python API',
packages=['vbancmd'],
install_requires=[
'toml'
],
extras_require={
'development': [

77
vbancmd/profiles.py Normal file
View File

@ -0,0 +1,77 @@
import toml
from . import kinds
from .util import project_path
from pathlib import Path
profiles = {}
def _make_blank_profile(kind):
phys_in, virt_in = kind.ins
phys_out, virt_out = kind.outs
all_input_strip_config = {
'gain': 0.0,
'solo': False,
'mute': False,
'mono': False,
**{f'A{i}': False for i in range(1, phys_out+1)},
**{f'B{i}': False for i in range(1, virt_out+1)},
}
phys_input_strip_config={
'comp': 0.0,
'gate': 0.0,
}
output_bus_config = {
'gain': 0.0,
'eq': False,
'mute': False,
'mono': False,
}
all_ = {f'strip-{i}': all_input_strip_config for i in range(phys_in+virt_in)}
phys = {f'strip-{i}': phys_input_strip_config for i in range(phys_in)}
abc = all_
for i in phys.keys():
abc[i] = all_[i] | phys[i]
return {
**abc,
**{f'bus-{i}': output_bus_config for i in range(phys_out+virt_out)}
}
def _make_base_profile(kind):
phys_in, virt_in = kind.ins
blank = _make_blank_profile(kind)
overrides = {
**{f'strip-{i}': dict(B1=True) for i in range(phys_in)},
**{f'strip-{i}': dict(A1=True) for i in range(phys_in, phys_in+virt_in)}
}
base = blank
for i in overrides.keys():
base[i] = blank[i] | overrides[i]
return base
for kind in kinds.all:
profiles[kind.id] = {
'blank': _make_blank_profile(kind),
'base': _make_base_profile(kind)
}
# Load profiles from config files in profiles/<kind_id>/<profile>.toml
for kind in kinds.all:
profiles_paths = [
Path(project_path()) / 'profiles' / kind.id,
Path.cwd() / 'profiles' / kind.id,
Path.home() / 'Documents/Voicemeeter' / 'profiles' / kind.id,
]
for path in profiles_paths:
if path.is_dir():
filenames = list(path.glob('*.toml'))
configs = {}
for filename in filenames:
name = filename.with_suffix('').stem
try:
configs[name] = toml.load(filename)
except toml.TomlDecodeError:
print(f'Invalid TOML profile: {kind.id}/{filename.stem}')
for name, cfg in configs.items():
print(f'Loaded profile {kind.id}/{name}')
profiles[kind.id][name] = cfg

View File

@ -1,3 +1,10 @@
from pathlib import Path
PROJECT_DIR = str(Path(__file__).parents[1])
def project_path():
return PROJECT_DIR
def cache(func):
""" check if recently cached was an updated value """
def wrapper(*args, **kwargs):

View File

@ -7,6 +7,7 @@ from typing import NamedTuple, NoReturn, Optional, Union
from .errors import VMCMDErrors
from . import kinds
from . import profiles
from .dataclass import (
HEADER_SIZE,
VBAN_VMRT_Packet_Data,
@ -59,6 +60,22 @@ class VbanCmd(abc.ABC):
self.login()
return self
def login(self):
"""
Start listening for RT Packets
Start background threads:
Register to RT service
Keep public packet updated.
"""
self._rt_packet_socket.bind((socket.gethostbyname(socket.gethostname()), self._port))
worker = Thread(target=self._send_register_rt, daemon=True)
worker.start()
self._public_packet = self._get_rt()
worker2 = Thread(target=self._keepupdated, daemon=True)
worker2.start()
def _send_register_rt(self):
"""
Continuously register to the RT Packet Service
@ -154,7 +171,7 @@ class VbanCmd(abc.ABC):
count = int.from_bytes(self._text_header.framecounter, 'little') + 1
self._text_header.framecounter = count.to_bytes(4, 'little')
self.cache[f'{id_}.{param}'] = [val, True]
sleep(0.018)
sleep(self._ratelimiter)
def sendtext(self, cmd):
""" Sends a multiple parameter string over a network. """
@ -197,21 +214,24 @@ class VbanCmd(abc.ABC):
raise ValueError(obj)
target.apply(submapping)
def login(self):
"""
Start listening for RT Packets
def apply_profile(self, name: str):
try:
profile = self.profiles[name]
if 'extends' in profile:
base = self.profiles[profile['extends']]
del profile['extends']
for key in profile.keys():
if key in base:
base[key] |= profile[key]
else:
base[key] = profile[key]
profile = base
self.apply(profile)
except KeyError:
raise VMCMDErrors(f'Unknown profile: {self.kind.id}/{name}')
Start background threads:
Register to RT service
Keep public packet updated.
"""
self._rt_packet_socket.bind((socket.gethostbyname(socket.gethostname()), self._port))
worker = Thread(target=self._send_register_rt, daemon=True)
worker.start()
self._public_packet = self._get_rt()
worker2 = Thread(target=self._keepupdated, daemon=True)
worker2.start()
def reset(self) -> NoReturn:
self.apply_profile('base')
def logout(self):
""" sets thread flag, closes sockets """
@ -250,8 +270,12 @@ def _make_remote(kind: NamedTuple) -> VbanCmd:
for i in range(self.phys_out + self.virt_out))
self.command = Command.make(self)
def get_profiles(self):
return profiles.profiles[kind.id]
return type(f'VbanCmd{kind.name}', (VbanCmd,), {
'__init__': init,
'profiles': property(get_profiles)
})
_remotes = {kind.id: _make_remote(kind) for kind in kinds.all}