mirror of
https://github.com/onyx-and-iris/vban-cmd-python.git
synced 2026-03-03 00:39:10 +00:00
add Recorder
add it to banana+potato
This commit is contained in:
parent
a0ec00652b
commit
dc681f50d0
@ -11,6 +11,7 @@ from .error import VBANCMDError
|
|||||||
from .kinds import KindMapClass
|
from .kinds import KindMapClass
|
||||||
from .kinds import request_kind_map as kindmap
|
from .kinds import request_kind_map as kindmap
|
||||||
from .macrobutton import MacroButton
|
from .macrobutton import MacroButton
|
||||||
|
from .recorder import Recorder
|
||||||
from .strip import request_strip_obj as strip
|
from .strip import request_strip_obj as strip
|
||||||
from .vban import request_vban_obj as vban
|
from .vban import request_vban_obj as vban
|
||||||
from .vbancmd import VbanCmd
|
from .vbancmd import VbanCmd
|
||||||
@ -26,7 +27,7 @@ class FactoryBuilder:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
BuilderProgress = IntEnum(
|
BuilderProgress = IntEnum(
|
||||||
'BuilderProgress', 'strip bus command macrobutton vban', start=0
|
'BuilderProgress', 'strip bus command macrobutton vban recorder', start=0
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, factory, kind: KindMapClass):
|
def __init__(self, factory, kind: KindMapClass):
|
||||||
@ -38,6 +39,7 @@ class FactoryBuilder:
|
|||||||
f'Finished building commands for {self._factory}',
|
f'Finished building commands for {self._factory}',
|
||||||
f'Finished building macrobuttons for {self._factory}',
|
f'Finished building macrobuttons for {self._factory}',
|
||||||
f'Finished building vban in/out streams for {self._factory}',
|
f'Finished building vban in/out streams for {self._factory}',
|
||||||
|
f'Finished building recorder for {self._factory}',
|
||||||
)
|
)
|
||||||
self.logger = logger.getChild(self.__class__.__name__)
|
self.logger = logger.getChild(self.__class__.__name__)
|
||||||
|
|
||||||
@ -72,6 +74,10 @@ class FactoryBuilder:
|
|||||||
self._factory.vban = vban(self._factory)
|
self._factory.vban = vban(self._factory)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def make_recorder(self):
|
||||||
|
self._factory.recorder = Recorder.make(self._factory)
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
class FactoryBase(VbanCmd):
|
class FactoryBase(VbanCmd):
|
||||||
"""Base class for factories, subclasses VbanCmd."""
|
"""Base class for factories, subclasses VbanCmd."""
|
||||||
@ -166,7 +172,7 @@ class BananaFactory(FactoryBase):
|
|||||||
@property
|
@property
|
||||||
def steps(self) -> Iterable:
|
def steps(self) -> Iterable:
|
||||||
"""steps required to build the interface for a kind"""
|
"""steps required to build the interface for a kind"""
|
||||||
return self._steps
|
return self._steps + (self.builder.make_recorder,)
|
||||||
|
|
||||||
|
|
||||||
class PotatoFactory(FactoryBase):
|
class PotatoFactory(FactoryBase):
|
||||||
@ -188,7 +194,7 @@ class PotatoFactory(FactoryBase):
|
|||||||
@property
|
@property
|
||||||
def steps(self) -> Iterable:
|
def steps(self) -> Iterable:
|
||||||
"""steps required to build the interface for a kind"""
|
"""steps required to build the interface for a kind"""
|
||||||
return self._steps
|
return self._steps + (self.builder.make_recorder,)
|
||||||
|
|
||||||
|
|
||||||
def vbancmd_factory(kind_id: str, **kwargs) -> VbanCmd:
|
def vbancmd_factory(kind_id: str, **kwargs) -> VbanCmd:
|
||||||
|
|||||||
136
vban_cmd/recorder.py
Normal file
136
vban_cmd/recorder.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
from .error import VBANCMDError
|
||||||
|
from .iremote import IRemote
|
||||||
|
from .meta import action_fn
|
||||||
|
|
||||||
|
|
||||||
|
class Recorder(IRemote):
|
||||||
|
"""
|
||||||
|
Implements the common interface
|
||||||
|
|
||||||
|
Defines concrete implementation for recorder
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def make(cls, remote):
|
||||||
|
"""
|
||||||
|
Factory function for recorder class.
|
||||||
|
|
||||||
|
Returns a Recorder class of a kind.
|
||||||
|
"""
|
||||||
|
Recorder_cls = type(
|
||||||
|
f'Recorder{remote.kind}',
|
||||||
|
(cls,),
|
||||||
|
{
|
||||||
|
**{
|
||||||
|
param: action_fn(param)
|
||||||
|
for param in [
|
||||||
|
'play',
|
||||||
|
'stop',
|
||||||
|
'pause',
|
||||||
|
'replay',
|
||||||
|
'record',
|
||||||
|
'ff',
|
||||||
|
'rew',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return Recorder_cls(remote)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{type(self).__name__}'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def identifier(self) -> str:
|
||||||
|
return 'recorder'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def samplerate(self) -> int:
|
||||||
|
return
|
||||||
|
|
||||||
|
@samplerate.setter
|
||||||
|
def samplerate(self, val: int):
|
||||||
|
opts = (22050, 24000, 32000, 44100, 48000, 88200, 96000, 176400, 192000)
|
||||||
|
if val not in opts:
|
||||||
|
self.logger.warning(f'samplerate got: {val} but expected a value in {opts}')
|
||||||
|
self.setter('samplerate', val)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def bitresolution(self) -> int:
|
||||||
|
return
|
||||||
|
|
||||||
|
@bitresolution.setter
|
||||||
|
def bitresolution(self, val: int):
|
||||||
|
opts = (8, 16, 24, 32)
|
||||||
|
if val not in opts:
|
||||||
|
self.logger.warning(
|
||||||
|
f'bitresolution got: {val} but expected a value in {opts}'
|
||||||
|
)
|
||||||
|
self.setter('bitresolution', val)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def channel(self) -> int:
|
||||||
|
return
|
||||||
|
|
||||||
|
@channel.setter
|
||||||
|
def channel(self, val: int):
|
||||||
|
if not 1 <= val <= 8:
|
||||||
|
self.logger.warning(f'channel got: {val} but expected a value from 1 to 8')
|
||||||
|
self.setter('channel', val)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def kbps(self):
|
||||||
|
return
|
||||||
|
|
||||||
|
@kbps.setter
|
||||||
|
def kbps(self, val: int):
|
||||||
|
opts = (32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320)
|
||||||
|
if val not in opts:
|
||||||
|
self.logger.warning(f'kbps got: {val} but expected a value in {opts}')
|
||||||
|
self.setter('kbps', val)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def gain(self) -> float:
|
||||||
|
return
|
||||||
|
|
||||||
|
@gain.setter
|
||||||
|
def gain(self, val: float):
|
||||||
|
self.setter('gain', val)
|
||||||
|
|
||||||
|
def load(self, file: os.PathLike):
|
||||||
|
try:
|
||||||
|
self.setter('load', str(file))
|
||||||
|
except UnicodeError:
|
||||||
|
raise VBANCMDError('File full directory must be a raw string')
|
||||||
|
|
||||||
|
def goto(self, time_str):
|
||||||
|
def get_sec():
|
||||||
|
"""Get seconds from time string"""
|
||||||
|
h, m, s = time_str.split(':')
|
||||||
|
return int(h) * 3600 + int(m) * 60 + int(s)
|
||||||
|
|
||||||
|
time_str = str(time_str) # coerce the type
|
||||||
|
if (
|
||||||
|
re.match(
|
||||||
|
r'^(?:[01]\d|2[0123]):(?:[012345]\d):(?:[012345]\d)$',
|
||||||
|
time_str,
|
||||||
|
)
|
||||||
|
is not None
|
||||||
|
):
|
||||||
|
self.setter('goto', get_sec())
|
||||||
|
else:
|
||||||
|
self.logger.warning(
|
||||||
|
"goto expects a string that matches the format 'hh:mm:ss'"
|
||||||
|
)
|
||||||
|
|
||||||
|
def filetype(self, val: str):
|
||||||
|
opts = {'wav': 1, 'aiff': 2, 'bwf': 3, 'mp3': 100}
|
||||||
|
try:
|
||||||
|
self.setter('filetype', opts[val.lower()])
|
||||||
|
except KeyError:
|
||||||
|
self.logger.warning(
|
||||||
|
f'filetype got: {val} but expected a value in {list(opts.keys())}'
|
||||||
|
)
|
||||||
Loading…
x
Reference in New Issue
Block a user