mirror of
https://github.com/onyx-and-iris/vban-cli.git
synced 2026-03-02 21:19:11 +00:00
enable rich tracebacks
console, error_console are now app attributes.
This commit is contained in:
parent
4fff581c95
commit
d9810ce270
@ -3,16 +3,21 @@ from typing import Annotated
|
||||
|
||||
import vban_cmd
|
||||
from cyclopts import App, Argument, Parameter, config
|
||||
from rich.traceback import install as install_rich_traceback
|
||||
|
||||
from . import __version__ as version
|
||||
from . import bus, command, console, recorder, strip
|
||||
from .context import Context
|
||||
from .error import VbanCLIConnectionError
|
||||
|
||||
app = App(
|
||||
config=config.Env(
|
||||
'VBAN_CLI_',
|
||||
), # Environment variable prefix for configuration parameters
|
||||
version=version,
|
||||
console=console.out,
|
||||
error_console=console.err,
|
||||
exit_on_error=True,
|
||||
)
|
||||
app.command(strip.app.meta, name='strip')
|
||||
app.command(bus.app.meta, name='bus')
|
||||
@ -20,6 +25,8 @@ app.command(command.app, name='command')
|
||||
app.command(recorder.app, name='recorder')
|
||||
app.register_install_completion_command()
|
||||
|
||||
install_rich_traceback(console=console.err)
|
||||
|
||||
|
||||
@Parameter(name='*')
|
||||
@dataclass
|
||||
@ -43,14 +50,17 @@ def launcher(
|
||||
if command.__name__ == 'sendtext':
|
||||
disable_rt_listeners = True
|
||||
|
||||
with vban_cmd.api(
|
||||
vban_config.kind,
|
||||
ip=vban_config.host,
|
||||
port=vban_config.port,
|
||||
streamname=vban_config.streamname,
|
||||
disable_rt_listeners=disable_rt_listeners,
|
||||
) as client:
|
||||
return command(*bound.args, **bound.kwargs, ctx=Context(client=client))
|
||||
try:
|
||||
with vban_cmd.api(
|
||||
vban_config.kind,
|
||||
ip=vban_config.host,
|
||||
port=vban_config.port,
|
||||
streamname=vban_config.streamname,
|
||||
disable_rt_listeners=disable_rt_listeners,
|
||||
) as client:
|
||||
return command(*bound.args, **bound.kwargs, ctx=Context(client=client))
|
||||
except vban_cmd.error.VBANCMDConnectionError as e:
|
||||
raise VbanCLIConnectionError(str(e)) from e
|
||||
|
||||
|
||||
@app.command(name='sendtext')
|
||||
@ -62,12 +72,8 @@ def sendtext(
|
||||
):
|
||||
"""Send a text command to the current Voicemeeter/Matrix instance."""
|
||||
if resp := ctx.client.sendtext(text):
|
||||
console.out.print(resp)
|
||||
app.console.print(resp)
|
||||
|
||||
|
||||
def run():
|
||||
try:
|
||||
app.meta()
|
||||
except Exception as e:
|
||||
console.err.print(f'Error: {e}')
|
||||
return e.code
|
||||
app.meta()
|
||||
|
||||
@ -2,7 +2,6 @@ from typing import Annotated, Literal, Optional
|
||||
|
||||
from cyclopts import App, Argument, Parameter
|
||||
|
||||
from . import console
|
||||
from .context import Context
|
||||
from .help import BusHelpFormatter
|
||||
|
||||
@ -46,7 +45,7 @@ def mono(
|
||||
If provided, sets the mono state to this value. If not provided, the current mono state is printed.
|
||||
"""
|
||||
if new_value is None:
|
||||
console.out.print(['off', 'mono', 'stereoreverse'][ctx.client.bus[index].mono])
|
||||
app.console.print(['off', 'mono', 'stereoreverse'][ctx.client.bus[index].mono])
|
||||
return
|
||||
ctx.client.bus[index].mono = ['off', 'mono', 'stereoreverse'].index(new_value)
|
||||
|
||||
@ -66,7 +65,7 @@ def mute(
|
||||
If provided, sets the mute state to this value. If not provided, the current mute state is printed.
|
||||
"""
|
||||
if new_value is None:
|
||||
console.out.print(ctx.client.bus[index].mute)
|
||||
app.console.print(ctx.client.bus[index].mute)
|
||||
return
|
||||
ctx.client.bus[index].mute = new_value
|
||||
|
||||
@ -104,6 +103,6 @@ def mode(
|
||||
If provided, sets the bus mode to this value. If not provided, the current bus mode is printed.
|
||||
"""
|
||||
if type_ is None:
|
||||
console.out.print(ctx.client.bus[index].mode.get())
|
||||
app.console.print(ctx.client.bus[index].mode.get())
|
||||
return
|
||||
setattr(ctx.client.bus[index].mode, type_, True)
|
||||
|
||||
@ -2,7 +2,6 @@ from typing import Annotated
|
||||
|
||||
from cyclopts import App, Parameter
|
||||
|
||||
from . import console
|
||||
from .context import Context
|
||||
from .help import BaseHelpFormatter
|
||||
|
||||
@ -16,7 +15,7 @@ def show(
|
||||
):
|
||||
"""Bring the Voicemeeter GUI to the foreground."""
|
||||
ctx.client.command.show()
|
||||
console.out.print('Voicemeeter GUI should now be in the foreground.')
|
||||
app.console.print('Voicemeeter GUI should now be in the foreground.')
|
||||
|
||||
|
||||
@app.command(name='hide')
|
||||
@ -26,7 +25,7 @@ def hide(
|
||||
):
|
||||
"""Send the Voicemeeter GUI to the background."""
|
||||
ctx.client.command.hide()
|
||||
console.out.print('Voicemeeter GUI should now be in the background.')
|
||||
app.console.print('Voicemeeter GUI should now be in the background.')
|
||||
|
||||
|
||||
@app.command(name='shutdown')
|
||||
@ -36,7 +35,7 @@ def shutdown(
|
||||
):
|
||||
"""Shut down Voicemeeter."""
|
||||
ctx.client.command.shutdown()
|
||||
console.out.print('Voicemeeter should now be shut down.')
|
||||
app.console.print('Voicemeeter should now be shut down.')
|
||||
|
||||
|
||||
@app.command(name='restart')
|
||||
@ -46,4 +45,4 @@ def restart(
|
||||
):
|
||||
"""Restart the Voicemeeter engine."""
|
||||
ctx.client.command.restart()
|
||||
console.out.print('Voicemeeter engine should now be restarting.')
|
||||
app.console.print('Voicemeeter engine should now be restarting.')
|
||||
|
||||
@ -39,7 +39,7 @@ def knob(
|
||||
"""
|
||||
if new_knob is None:
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 2.
|
||||
# console.out.print(ctx.client.strip[index].comp.knob)
|
||||
# app.console.print(ctx.client.strip[index].comp.knob)
|
||||
return
|
||||
ctx.client.strip[index].comp.knob = new_knob
|
||||
|
||||
@ -60,6 +60,6 @@ def input_gain(
|
||||
"""
|
||||
if new_gain is None:
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 2.
|
||||
# console.out.print(ctx.client.strip[index].comp.gainin)
|
||||
# app.console.print(ctx.client.strip[index].comp.gainin)
|
||||
return
|
||||
ctx.client.strip[index].comp.gainin = new_gain
|
||||
|
||||
@ -39,6 +39,6 @@ def knob(
|
||||
"""
|
||||
if new_knob is None:
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 2.
|
||||
# console.out.print(ctx.client.strip[index].denoiser.knob)
|
||||
# app.console.print(ctx.client.strip[index].denoiser.knob)
|
||||
return
|
||||
ctx.client.strip[index].denoiser.knob = new_knob
|
||||
|
||||
@ -48,7 +48,7 @@ def on(
|
||||
"""
|
||||
if new_state is None:
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 2.
|
||||
# console.out.print(target.on)
|
||||
# app.console.print(target.on)
|
||||
return
|
||||
target.on = new_state
|
||||
|
||||
@ -86,7 +86,7 @@ def cell_on(
|
||||
"""
|
||||
if new_state is None:
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 2.
|
||||
# console.out.print(target.on)
|
||||
# app.console.print(target.on)
|
||||
return
|
||||
target.on = new_state
|
||||
|
||||
@ -106,7 +106,7 @@ def cell_freq(
|
||||
"""
|
||||
if new_freq is None:
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 2.
|
||||
# console.out.print(target.f)
|
||||
# app.console.print(target.f)
|
||||
return
|
||||
target.f = new_freq
|
||||
|
||||
@ -126,7 +126,7 @@ def cell_gain(
|
||||
"""
|
||||
if new_gain is None:
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 2.
|
||||
# console.out.print(target.gain)
|
||||
# app.console.print(target.gain)
|
||||
return
|
||||
target.gain = new_gain
|
||||
|
||||
@ -146,7 +146,7 @@ def cell_q(
|
||||
"""
|
||||
if new_q is None:
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 2.
|
||||
# console.out.print(target.q)
|
||||
# app.console.print(target.q)
|
||||
return
|
||||
target.q = new_q
|
||||
|
||||
@ -166,6 +166,6 @@ def cell_type(
|
||||
"""
|
||||
if new_type is None:
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 2.
|
||||
# console.out.print(target.type)
|
||||
# app.console.print(target.type)
|
||||
return
|
||||
target.type = new_type
|
||||
|
||||
14
src/vban_cli/error.py
Normal file
14
src/vban_cli/error.py
Normal file
@ -0,0 +1,14 @@
|
||||
class VbanCLIError(Exception):
|
||||
"""Base class for exceptions in this module."""
|
||||
|
||||
def __init__(self, message: str, code: int = 1):
|
||||
super().__init__(message)
|
||||
self.code = code
|
||||
|
||||
|
||||
class VbanCLIConnectionError(VbanCLIError):
|
||||
"""Exception raised for connection errors."""
|
||||
|
||||
|
||||
class VbanCLIValidationError(VbanCLIError):
|
||||
"""Exception raised for validation errors."""
|
||||
@ -2,7 +2,6 @@ from typing import Annotated
|
||||
|
||||
from cyclopts import App, Argument, Parameter
|
||||
|
||||
from . import console
|
||||
from .context import Context
|
||||
from .help import GainlayerHelpFormatter
|
||||
|
||||
@ -43,6 +42,6 @@ def level(
|
||||
If provided, sets the level to this value. If not provided, the current level is printed.
|
||||
"""
|
||||
if new_level is None:
|
||||
console.out.print(ctx.client.strip[strip_index].gainlayer[gainlayer_index].gain)
|
||||
app.console.print(ctx.client.strip[strip_index].gainlayer[gainlayer_index].gain)
|
||||
return
|
||||
ctx.client.strip[strip_index].gainlayer[gainlayer_index].gain = new_level
|
||||
|
||||
@ -39,7 +39,7 @@ def knob(
|
||||
"""
|
||||
if new_knob is None:
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 2.
|
||||
# console.out.print(ctx.client.strip[index].gate.knob)
|
||||
# app.console.print(ctx.client.strip[index].gate.knob)
|
||||
return
|
||||
ctx.client.strip[index].gate.knob = new_knob
|
||||
|
||||
@ -60,6 +60,6 @@ def threshold(
|
||||
"""
|
||||
if new_threshold is None:
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 2.
|
||||
# console.out.print(ctx.client.strip[index].gate.threshold)
|
||||
# app.console.print(ctx.client.strip[index].gate.threshold)
|
||||
return
|
||||
ctx.client.strip[index].gate.threshold = new_threshold
|
||||
|
||||
@ -3,7 +3,7 @@ from typing import Annotated
|
||||
|
||||
from cyclopts import App, Parameter, validators
|
||||
|
||||
from . import console, validation
|
||||
from . import validation
|
||||
from .context import Context
|
||||
from .help import BaseHelpFormatter
|
||||
|
||||
@ -17,7 +17,7 @@ def play(
|
||||
):
|
||||
"""Start the recorder playback."""
|
||||
ctx.client.recorder.play()
|
||||
console.out.print('Recorder playback started.')
|
||||
app.console.print('Recorder playback started.')
|
||||
|
||||
|
||||
@app.command(name='pause')
|
||||
@ -27,7 +27,7 @@ def pause(
|
||||
):
|
||||
"""Pause the recorder playback."""
|
||||
ctx.client.recorder.stop()
|
||||
console.out.print('Recorder playback paused.')
|
||||
app.console.print('Recorder playback paused.')
|
||||
|
||||
|
||||
@app.command(name='stop')
|
||||
@ -40,7 +40,7 @@ def stop(
|
||||
ctx.client.recorder.goto('00:00:00')
|
||||
# We have no way of knowing if the recorder was playing or recording, so we print a generic message.
|
||||
# See https://github.com/onyx-and-iris/vban-cli?tab=readme-ov-file#implementation-notes - 4.
|
||||
console.out.print('Recorder stopped.')
|
||||
app.console.print('Recorder stopped.')
|
||||
|
||||
|
||||
@app.command(name='replay')
|
||||
@ -50,7 +50,7 @@ def replay(
|
||||
):
|
||||
"""Replay the recorder playback."""
|
||||
ctx.client.recorder.replay()
|
||||
console.out.print('Recorder playback replay started.')
|
||||
app.console.print('Recorder playback replay started.')
|
||||
|
||||
|
||||
@app.command(name='record')
|
||||
@ -60,7 +60,7 @@ def record(
|
||||
):
|
||||
"""Start recording."""
|
||||
ctx.client.recorder.record()
|
||||
console.out.print('Recorder recording started.')
|
||||
app.console.print('Recorder recording started.')
|
||||
|
||||
|
||||
@app.command(name='pause-recording')
|
||||
@ -70,7 +70,7 @@ def pause_recording(
|
||||
):
|
||||
"""Pause the recorder recording."""
|
||||
ctx.client.recorder.pause()
|
||||
console.out.print('Recorder recording paused.')
|
||||
app.console.print('Recorder recording paused.')
|
||||
|
||||
|
||||
@app.command(name='ff')
|
||||
@ -80,7 +80,7 @@ def ff(
|
||||
):
|
||||
"""Fast forward the recorder playback."""
|
||||
ctx.client.recorder.ff()
|
||||
console.out.print('Recorder playback fast forwarded.')
|
||||
app.console.print('Recorder playback fast forwarded.')
|
||||
|
||||
|
||||
@app.command(name='rew')
|
||||
@ -90,7 +90,7 @@ def rew(
|
||||
):
|
||||
"""Rewind the recorder playback."""
|
||||
ctx.client.recorder.rew()
|
||||
console.out.print('Recorder playback rewound.')
|
||||
app.console.print('Recorder playback rewound.')
|
||||
|
||||
|
||||
@app.command(name='load')
|
||||
@ -110,7 +110,7 @@ def load(
|
||||
|
||||
note: This command may only work if vban-cli is running on localhost and may not work if vban-cli is running on a remote server."""
|
||||
ctx.client.recorder.load(file_path)
|
||||
console.out.print(f'Loaded file: {file_path}')
|
||||
app.console.print(f'Loaded file: {file_path}')
|
||||
|
||||
|
||||
@app.command(name='goto')
|
||||
@ -128,4 +128,4 @@ def goto(
|
||||
):
|
||||
"""Go to a specific timestamp in the recorder playback."""
|
||||
ctx.client.recorder.goto(time_string)
|
||||
console.out.print(f'Went to timestamp {time_string} in recorder playback.')
|
||||
app.console.print(f'Went to timestamp {time_string} in recorder playback.')
|
||||
|
||||
@ -2,7 +2,7 @@ from typing import Annotated, Optional
|
||||
|
||||
from cyclopts import App, Argument, Parameter
|
||||
|
||||
from . import comp, console, denoiser, eq, gainlayer, gate
|
||||
from . import comp, denoiser, eq, gainlayer, gate
|
||||
from .context import Context
|
||||
from .help import StripHelpFormatter
|
||||
|
||||
@ -47,7 +47,7 @@ def mono(
|
||||
If provided, sets the mono state to this value. If not provided, the current mono state is printed.
|
||||
"""
|
||||
if new_state is None:
|
||||
console.out.print(ctx.client.strip[index].mono)
|
||||
app.console.print(ctx.client.strip[index].mono)
|
||||
return
|
||||
ctx.client.strip[index].mono = new_state
|
||||
|
||||
@ -67,7 +67,7 @@ def solo(
|
||||
If provided, sets the solo state to this value. If not provided, the current solo state is printed.
|
||||
"""
|
||||
if new_state is None:
|
||||
console.out.print(ctx.client.strip[index].solo)
|
||||
app.console.print(ctx.client.strip[index].solo)
|
||||
return
|
||||
ctx.client.strip[index].solo = new_state
|
||||
|
||||
@ -87,7 +87,7 @@ def mute(
|
||||
If provided, sets the mute state to this value. If not provided, the current mute state is printed.
|
||||
"""
|
||||
if new_state is None:
|
||||
console.out.print(ctx.client.strip[index].mute)
|
||||
app.console.print(ctx.client.strip[index].mute)
|
||||
return
|
||||
ctx.client.strip[index].mute = new_state
|
||||
|
||||
@ -107,7 +107,7 @@ def gain(
|
||||
If provided, sets the gain to this value. If not provided, the current gain is printed.
|
||||
"""
|
||||
if new_value is None:
|
||||
console.out.print(ctx.client.strip[index].gain)
|
||||
app.console.print(ctx.client.strip[index].gain)
|
||||
return
|
||||
ctx.client.strip[index].gain = new_value
|
||||
|
||||
@ -127,7 +127,7 @@ def a1(
|
||||
If provided, sets the A1 state to this value. If not provided, the current A1 state is printed.
|
||||
"""
|
||||
if new_value is None:
|
||||
console.out.print(ctx.client.strip[index].A1)
|
||||
app.console.print(ctx.client.strip[index].A1)
|
||||
return
|
||||
ctx.client.strip[index].A1 = new_value
|
||||
|
||||
@ -147,7 +147,7 @@ def a2(
|
||||
If provided, sets the A2 state to this value. If not provided, the current A2 state is printed.
|
||||
"""
|
||||
if new_value is None:
|
||||
console.out.print(ctx.client.strip[index].A2)
|
||||
app.console.print(ctx.client.strip[index].A2)
|
||||
return
|
||||
ctx.client.strip[index].A2 = new_value
|
||||
|
||||
@ -167,7 +167,7 @@ def a3(
|
||||
If provided, sets the A3 state to this value. If not provided, the current A3 state is printed.
|
||||
"""
|
||||
if new_value is None:
|
||||
console.out.print(ctx.client.strip[index].A3)
|
||||
app.console.print(ctx.client.strip[index].A3)
|
||||
return
|
||||
ctx.client.strip[index].A3 = new_value
|
||||
|
||||
@ -187,7 +187,7 @@ def a4(
|
||||
If provided, sets the A4 state to this value. If not provided, the current A4 state is printed.
|
||||
"""
|
||||
if new_value is None:
|
||||
console.out.print(ctx.client.strip[index].A4)
|
||||
app.console.print(ctx.client.strip[index].A4)
|
||||
return
|
||||
ctx.client.strip[index].A4 = new_value
|
||||
|
||||
@ -207,7 +207,7 @@ def a5(
|
||||
If provided, sets the A5 state to this value. If not provided, the current A5 state is printed.
|
||||
"""
|
||||
if new_value is None:
|
||||
console.out.print(ctx.client.strip[index].A5)
|
||||
app.console.print(ctx.client.strip[index].A5)
|
||||
return
|
||||
ctx.client.strip[index].A5 = new_value
|
||||
|
||||
@ -227,7 +227,7 @@ def b1(
|
||||
If provided, sets the B1 state to this value. If not provided, the current B1 state is printed.
|
||||
"""
|
||||
if new_value is None:
|
||||
console.out.print(ctx.client.strip[index].B1)
|
||||
app.console.print(ctx.client.strip[index].B1)
|
||||
return
|
||||
ctx.client.strip[index].B1 = new_value
|
||||
|
||||
@ -247,7 +247,7 @@ def b2(
|
||||
If provided, sets the B2 state to this value. If not provided, the current B2 state is printed.
|
||||
"""
|
||||
if new_value is None:
|
||||
console.out.print(ctx.client.strip[index].B2)
|
||||
app.console.print(ctx.client.strip[index].B2)
|
||||
return
|
||||
ctx.client.strip[index].B2 = new_value
|
||||
|
||||
@ -267,6 +267,6 @@ def b3(
|
||||
If provided, sets the B3 state to this value. If not provided, the current B3 state is printed.
|
||||
"""
|
||||
if new_value is None:
|
||||
console.out.print(ctx.client.strip[index].B3)
|
||||
app.console.print(ctx.client.strip[index].B3)
|
||||
return
|
||||
ctx.client.strip[index].B3 = new_value
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import re
|
||||
|
||||
from .error import VbanCLIValidationError
|
||||
|
||||
|
||||
def is_valid_time_string(type_, value: str) -> str:
|
||||
"""Validate if the given string is a valid time format (HH:MM:SS)."""
|
||||
pattern = r'^(?:[01]\d|2[0123]):(?:[012345]\d):(?:[012345]\d)$'
|
||||
if not re.match(pattern, value):
|
||||
raise ValueError('Invalid time format. Expected HH:MM:SS.')
|
||||
raise VbanCLIValidationError('Invalid time format. Expected HH:MM:SS.')
|
||||
return value
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user