mirror of
https://github.com/onyx-and-iris/voicemeeter-api-python.git
synced 2024-11-15 16:40:46 +00:00
implement a strategy pattern into dsl example
logging mode switched to DEBUG.
This commit is contained in:
parent
ce7cda100f
commit
eb66f9e2bc
@ -1,6 +1,8 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from enum import IntEnum
|
||||||
|
|
||||||
from pyparsing import (
|
from pyparsing import (
|
||||||
Combine,
|
Combine,
|
||||||
@ -10,24 +12,88 @@ from pyparsing import (
|
|||||||
Suppress,
|
Suppress,
|
||||||
Word,
|
Word,
|
||||||
alphanums,
|
alphanums,
|
||||||
alphas,
|
|
||||||
nums,
|
nums,
|
||||||
)
|
)
|
||||||
|
|
||||||
import voicemeeterlib
|
import voicemeeterlib
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
argparser = argparse.ArgumentParser(description="creates a basic dsl")
|
argparser = argparse.ArgumentParser(description="creates a basic dsl")
|
||||||
argparser.add_argument("-i", action="store_true")
|
argparser.add_argument("-i", action="store_true")
|
||||||
args = argparser.parse_args()
|
args = argparser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
ParamKinds = IntEnum(
|
||||||
|
"ParamKinds",
|
||||||
|
"bool float string",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Strategy(ABC):
|
||||||
|
def __init__(self, target, param, val):
|
||||||
|
self.target = target
|
||||||
|
self.param = param
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def run(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BoolStrategy(Strategy):
|
||||||
|
def run(self):
|
||||||
|
setattr(self.target, self.param, self.strtobool(self.val))
|
||||||
|
|
||||||
|
def strtobool(self, val):
|
||||||
|
"""Convert a string representation of truth to it's numeric form."""
|
||||||
|
|
||||||
|
val = val.lower()
|
||||||
|
if val in ("y", "yes", "t", "true", "on", "1"):
|
||||||
|
return 1
|
||||||
|
elif val in ("n", "no", "f", "false", "off", "0"):
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
raise ValueError("invalid truth value %r" % (val,))
|
||||||
|
|
||||||
|
|
||||||
|
class FloatStrategy(Strategy):
|
||||||
|
def run(self):
|
||||||
|
setattr(self.target, self.param, float(self.val))
|
||||||
|
|
||||||
|
|
||||||
|
class StringStrategy(Strategy):
|
||||||
|
def run(self):
|
||||||
|
setattr(self.target, self.param, " ".join(self.val))
|
||||||
|
|
||||||
|
|
||||||
|
class Context:
|
||||||
|
def __init__(self, strategy: Strategy) -> None:
|
||||||
|
self._strategy = strategy
|
||||||
|
|
||||||
|
@property
|
||||||
|
def strategy(self) -> Strategy:
|
||||||
|
return self._strategy
|
||||||
|
|
||||||
|
@strategy.setter
|
||||||
|
def strategy(self, strategy: Strategy) -> None:
|
||||||
|
self._strategy = strategy
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.strategy.run()
|
||||||
|
|
||||||
|
|
||||||
class Parser:
|
class Parser:
|
||||||
|
IS_STRING = ("label",)
|
||||||
|
|
||||||
def __init__(self, vm):
|
def __init__(self, vm):
|
||||||
|
self.logger = logger.getChild(self.__class__.__name__)
|
||||||
self.vm = vm
|
self.vm = vm
|
||||||
self.kls = Group(OneOrMore(Word(alphanums)))
|
self.kls = Group(OneOrMore(Word(alphanums)))
|
||||||
self.token = Suppress("->")
|
self.token = Suppress("->")
|
||||||
self.param = Word(alphanums)
|
self.param = Group(OneOrMore(Word(alphanums)))
|
||||||
self.value = Combine(
|
self.value = Combine(
|
||||||
Optional("-") + Word(nums) + Optional(".") + Optional(Word(nums))
|
Optional("-") + Word(nums) + Optional(".") + Optional(Word(nums))
|
||||||
) | Group(OneOrMore(Word(alphanums)))
|
) | Group(OneOrMore(Word(alphanums)))
|
||||||
@ -39,27 +105,64 @@ class Parser:
|
|||||||
+ Optional(self.value)
|
+ Optional(self.value)
|
||||||
)
|
)
|
||||||
|
|
||||||
def parse(self, cmds):
|
def converter(self, cmds):
|
||||||
|
"""determines the kind of parameter from the parsed string"""
|
||||||
|
|
||||||
res = list()
|
res = list()
|
||||||
|
|
||||||
for cmd in cmds:
|
for cmd in cmds:
|
||||||
if len(self.event.parseString(cmd)) == 2:
|
self.logger.debug(f"running command: {cmd}")
|
||||||
kls, param = self.event.parseString(cmd)
|
match cmd_parsed := self.event.parseString(cmd):
|
||||||
target = getattr(self.vm, kls[0])[int(kls[-1])]
|
case [[kls, index], [param]]:
|
||||||
|
target = getattr(self.vm, kls)[int(index)]
|
||||||
res.append(getattr(target, param))
|
res.append(getattr(target, param))
|
||||||
elif len(self.event.parseString(cmd)) == 3:
|
case [[kls, index], [param], val] if param in self.IS_STRING:
|
||||||
kls, param, val = self.event.parseString(cmd)
|
target = getattr(self.vm, kls)[int(index)]
|
||||||
target = getattr(self.vm, kls[0])[int(kls[-1])]
|
context = self._get_context(ParamKinds.string, target, param, val)
|
||||||
if "".join(val) in ["off", "on"]:
|
context.run()
|
||||||
setattr(target, param, bool(["off", "on"].index("".join(val))))
|
case [[kls, index], [param], [val] | val]:
|
||||||
elif param in ["gain", "comp", "gate", "limit", "audibility"]:
|
target = getattr(self.vm, kls)[int(index)]
|
||||||
setattr(target, param, float("".join(val)))
|
try:
|
||||||
elif param in ["label"]:
|
context = self._get_context(ParamKinds.bool, target, param, val)
|
||||||
setattr(target, param, " ".join(val))
|
context.run()
|
||||||
|
except ValueError as e:
|
||||||
|
self.logger.error(f"{e}... switching to float strategy")
|
||||||
|
context.strategy = FloatStrategy(target, param, val)
|
||||||
|
context.run()
|
||||||
|
case [
|
||||||
|
[kls, index],
|
||||||
|
[secondary, param],
|
||||||
|
[val] | val,
|
||||||
|
]:
|
||||||
|
primary = getattr(self.vm, kls)[int(index)]
|
||||||
|
target = getattr(primary, secondary)
|
||||||
|
try:
|
||||||
|
context = self._get_context(ParamKinds.bool, target, param, val)
|
||||||
|
context.run()
|
||||||
|
except ValueError as e:
|
||||||
|
self.logger.error(f"{e}... switching to float strategy")
|
||||||
|
context.strategy = FloatStrategy(target, param, val)
|
||||||
|
context.run()
|
||||||
|
case _:
|
||||||
|
self.logger.error(
|
||||||
|
f"unable to determine the kind of parameter from {cmd_parsed}"
|
||||||
|
)
|
||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def _get_context(self, kind, *args):
|
||||||
|
"""
|
||||||
|
determines a strategy for a kind of parameter and passes it to the context.
|
||||||
|
"""
|
||||||
|
|
||||||
|
match kind:
|
||||||
|
case ParamKinds.bool:
|
||||||
|
context = Context(BoolStrategy(*args))
|
||||||
|
case ParamKinds.float:
|
||||||
|
context = Context(FloatStrategy(*args))
|
||||||
|
case ParamKinds.string:
|
||||||
|
context = Context(StringStrategy(*args))
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
def interactive_mode(parser):
|
def interactive_mode(parser):
|
||||||
while cmd := input("Please enter command (Press <Enter> to exit)\n"):
|
while cmd := input("Please enter command (Press <Enter> to exit)\n"):
|
||||||
@ -70,25 +173,23 @@ def interactive_mode(parser):
|
|||||||
def main():
|
def main():
|
||||||
# fmt: off
|
# fmt: off
|
||||||
cmds = (
|
cmds = (
|
||||||
"strip 0 -> mute -> on", "strip 0 -> mute", "bus 0 -> mute -> on",
|
"strip 0 -> mute -> true", "strip 0 -> mute", "bus 0 -> mute -> true",
|
||||||
"strip 0 -> mute -> off", "bus 0 -> mute -> on", "strip 3 -> solo -> on",
|
"strip 0 -> mute -> false", "bus 0 -> mute -> true", "strip 3 -> solo -> true",
|
||||||
"strip 3 -> solo -> off", "strip 1 -> A1 -> on", "strip 1 -> A1",
|
"strip 3 -> solo -> false", "strip 1 -> A1 -> true", "strip 1 -> A1",
|
||||||
"strip 1 -> A1 -> off", "strip 1 -> A1", "bus 3 -> eq -> on",
|
"strip 1 -> A1 -> false", "strip 1 -> A1", "strip 3 -> eq on -> true",
|
||||||
"bus 3 -> eq -> off", "strip 4 -> gain -> 1.2", "strip 0 -> gain -> -8.2",
|
"bus 3 -> eq on -> false", "strip 4 -> gain -> 1.2", "strip 0 -> gain -> -8.2",
|
||||||
"strip 0 -> gain", "strip 1 -> label -> rode podmic", "strip 2 -> limit -> -28",
|
"strip 0 -> gain", "strip 1 -> label -> rode podmic", "strip 2 -> limit -> -28",
|
||||||
"strip 2 -> limit",
|
"strip 2 -> limit", "strip 3 -> comp knob -> 3.8"
|
||||||
)
|
)
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
KIND_ID = "banana"
|
with voicemeeterlib.api("potato") as vm:
|
||||||
|
|
||||||
with voicemeeterlib.api(KIND_ID) as vm:
|
|
||||||
parser = Parser(vm)
|
parser = Parser(vm)
|
||||||
if args.i:
|
if args.i:
|
||||||
interactive_mode(parser)
|
interactive_mode(parser)
|
||||||
return
|
return
|
||||||
|
|
||||||
if res := parser.parse(cmds):
|
if res := parser.converter(cmds):
|
||||||
print(res)
|
print(res)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user