vmr-http 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vmr_http-0.2.0/PKG-INFO +93 -0
- vmr_http-0.2.0/README.md +73 -0
- vmr_http-0.2.0/pyproject.toml +39 -0
- vmr_http-0.2.0/src/vmr_http/__init__.py +0 -0
- vmr_http-0.2.0/src/vmr_http/app.py +42 -0
- vmr_http-0.2.0/src/vmr_http/dependencies.py +8 -0
- vmr_http-0.2.0/src/vmr_http/models/bus.py +14 -0
- vmr_http-0.2.0/src/vmr_http/models/strip.py +54 -0
- vmr_http-0.2.0/src/vmr_http/web/__init__.py +0 -0
- vmr_http-0.2.0/src/vmr_http/web/bus.py +55 -0
- vmr_http-0.2.0/src/vmr_http/web/busmode.py +45 -0
- vmr_http-0.2.0/src/vmr_http/web/strip.py +227 -0
- vmr_http-0.2.0/src/vmr_http/web/stripcomp.py +37 -0
- vmr_http-0.2.0/src/vmr_http/web/stripdenoiser.py +44 -0
- vmr_http-0.2.0/src/vmr_http/web/stripgate.py +37 -0
vmr_http-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: vmr-http
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: HTTP API for controlling Voicemeeter
|
|
5
|
+
Author: onyx-and-iris
|
|
6
|
+
Author-email: onyx-and-iris <code@onyxandiris.online>
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Programming Language :: Python
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
14
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
15
|
+
Requires-Dist: fastapi>=0.135.3
|
|
16
|
+
Requires-Dist: uvicorn>=0.43.0
|
|
17
|
+
Requires-Dist: voicemeeter-api>=2.7.2
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Voicemeeter HTTP
|
|
22
|
+
|
|
23
|
+
[](https://github.com/astral-sh/uv)
|
|
24
|
+
[](https://github.com/astral-sh/ruff)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```console
|
|
31
|
+
pip install vmr-http
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Run
|
|
35
|
+
|
|
36
|
+
```console
|
|
37
|
+
uvicorn vmr_http.app:app
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Use
|
|
41
|
+
|
|
42
|
+
*Set multiple Strip parameters at once*
|
|
43
|
+
|
|
44
|
+
```console
|
|
45
|
+
curl -X 'PUT' \
|
|
46
|
+
'http://127.0.0.1:8000/strip/0' \
|
|
47
|
+
-H 'accept: application/json' \
|
|
48
|
+
-H 'Content-Type: application/json' \
|
|
49
|
+
-d '{
|
|
50
|
+
"gain": -38.7,
|
|
51
|
+
"mute": true,
|
|
52
|
+
"mono": true,
|
|
53
|
+
"A1": true,
|
|
54
|
+
"A2": false,
|
|
55
|
+
"A5": true,
|
|
56
|
+
"B1": true,
|
|
57
|
+
"B3": true
|
|
58
|
+
}'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
*Set Strip mute*
|
|
62
|
+
|
|
63
|
+
```console
|
|
64
|
+
curl -X 'PUT' \
|
|
65
|
+
'http://127.0.0.1:8000/strip/1/mute' \
|
|
66
|
+
-H 'accept: application/json' \
|
|
67
|
+
-H 'Content-Type: application/json' \
|
|
68
|
+
-d '{
|
|
69
|
+
"mute": true
|
|
70
|
+
}'
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
*Get Bus gain*
|
|
74
|
+
|
|
75
|
+
```console
|
|
76
|
+
curl -X 'GET' \
|
|
77
|
+
'http://127.0.0.1:8000/bus/3/gain' \
|
|
78
|
+
-H 'accept: application/json'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
*Get Bus Mode*
|
|
82
|
+
|
|
83
|
+
```console
|
|
84
|
+
curl -X 'GET' \
|
|
85
|
+
'http://127.0.0.1:8000/bus/mode/4/mode' \
|
|
86
|
+
-H 'accept: application/json'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Documentation
|
|
90
|
+
|
|
91
|
+
FastAPI [generates automatic docs][auto-docs], visit the link in the startup message when you launch the server.
|
|
92
|
+
|
|
93
|
+
[auto-docs]: https://fastapi.tiangolo.com/features/#automatic-docs
|
vmr_http-0.2.0/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Voicemeeter HTTP
|
|
2
|
+
|
|
3
|
+
[](https://github.com/astral-sh/uv)
|
|
4
|
+
[](https://github.com/astral-sh/ruff)
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```console
|
|
11
|
+
pip install vmr-http
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Run
|
|
15
|
+
|
|
16
|
+
```console
|
|
17
|
+
uvicorn vmr_http.app:app
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Use
|
|
21
|
+
|
|
22
|
+
*Set multiple Strip parameters at once*
|
|
23
|
+
|
|
24
|
+
```console
|
|
25
|
+
curl -X 'PUT' \
|
|
26
|
+
'http://127.0.0.1:8000/strip/0' \
|
|
27
|
+
-H 'accept: application/json' \
|
|
28
|
+
-H 'Content-Type: application/json' \
|
|
29
|
+
-d '{
|
|
30
|
+
"gain": -38.7,
|
|
31
|
+
"mute": true,
|
|
32
|
+
"mono": true,
|
|
33
|
+
"A1": true,
|
|
34
|
+
"A2": false,
|
|
35
|
+
"A5": true,
|
|
36
|
+
"B1": true,
|
|
37
|
+
"B3": true
|
|
38
|
+
}'
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
*Set Strip mute*
|
|
42
|
+
|
|
43
|
+
```console
|
|
44
|
+
curl -X 'PUT' \
|
|
45
|
+
'http://127.0.0.1:8000/strip/1/mute' \
|
|
46
|
+
-H 'accept: application/json' \
|
|
47
|
+
-H 'Content-Type: application/json' \
|
|
48
|
+
-d '{
|
|
49
|
+
"mute": true
|
|
50
|
+
}'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
*Get Bus gain*
|
|
54
|
+
|
|
55
|
+
```console
|
|
56
|
+
curl -X 'GET' \
|
|
57
|
+
'http://127.0.0.1:8000/bus/3/gain' \
|
|
58
|
+
-H 'accept: application/json'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
*Get Bus Mode*
|
|
62
|
+
|
|
63
|
+
```console
|
|
64
|
+
curl -X 'GET' \
|
|
65
|
+
'http://127.0.0.1:8000/bus/mode/4/mode' \
|
|
66
|
+
-H 'accept: application/json'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Documentation
|
|
70
|
+
|
|
71
|
+
FastAPI [generates automatic docs][auto-docs], visit the link in the startup message when you launch the server.
|
|
72
|
+
|
|
73
|
+
[auto-docs]: https://fastapi.tiangolo.com/features/#automatic-docs
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "vmr-http"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "HTTP API for controlling Voicemeeter"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "onyx-and-iris", email = "code@onyxandiris.online" }]
|
|
7
|
+
requires-python = ">=3.10"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"fastapi>=0.135.3",
|
|
10
|
+
"uvicorn>=0.43.0",
|
|
11
|
+
"voicemeeter-api>=2.7.2",
|
|
12
|
+
]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Programming Language :: Python",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
21
|
+
"Programming Language :: Python :: Implementation :: PyPy",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[build-system]
|
|
25
|
+
requires = ["uv_build>=0.11.3,<0.12.0"]
|
|
26
|
+
build-backend = "uv_build"
|
|
27
|
+
|
|
28
|
+
[dependency-groups]
|
|
29
|
+
dev = [
|
|
30
|
+
"fastapi[standard]>=0.135.3",
|
|
31
|
+
"poethepoet>=0.43.0",
|
|
32
|
+
"ruff>=0.15.9",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[tool.fastapi]
|
|
36
|
+
entrypoint = "vmr_http.app:app"
|
|
37
|
+
|
|
38
|
+
[tool.uv.sources]
|
|
39
|
+
voicemeeter-api = { path = "../voicemeeter-api-python", editable = true }
|
|
File without changes
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""entry point for the FastAPI application."""
|
|
2
|
+
|
|
3
|
+
from contextlib import asynccontextmanager
|
|
4
|
+
|
|
5
|
+
import voicemeeterlib
|
|
6
|
+
from fastapi import Depends, FastAPI, HTTPException
|
|
7
|
+
from voicemeeterlib.error import CAPIError
|
|
8
|
+
|
|
9
|
+
from .dependencies import get_voicemeeter_client
|
|
10
|
+
from .web import bus, strip
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@asynccontextmanager
|
|
14
|
+
async def lifespan(app):
|
|
15
|
+
"""Lifespan function to initialize and clean up the Voicemeeter client."""
|
|
16
|
+
app.state.voicemeeter = voicemeeterlib.api('potato', sync=True)
|
|
17
|
+
app.state.voicemeeter.login()
|
|
18
|
+
yield
|
|
19
|
+
app.state.voicemeeter.logout()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
app = FastAPI(
|
|
23
|
+
lifespan=lifespan,
|
|
24
|
+
description='A REST API for controlling Voicemeeter.',
|
|
25
|
+
openapi_tags=[
|
|
26
|
+
{'name': 'strip', 'description': 'Endpoints for controlling strip parameters.'},
|
|
27
|
+
{'name': 'bus', 'description': 'Endpoints for controlling bus parameters.'},
|
|
28
|
+
],
|
|
29
|
+
)
|
|
30
|
+
app.include_router(strip.router, prefix='/strip')
|
|
31
|
+
app.include_router(bus.router, prefix='/bus')
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@app.get('/health')
|
|
35
|
+
def health_check(voicemeeter=Depends(get_voicemeeter_client)):
|
|
36
|
+
"""Health check endpoint to verify the service is running."""
|
|
37
|
+
try:
|
|
38
|
+
version = voicemeeter.version # Check if we can communicate with Voicemeeter
|
|
39
|
+
type_ = voicemeeter.type
|
|
40
|
+
except CAPIError as e:
|
|
41
|
+
raise HTTPException(status_code=503, detail=f'Voicemeeter API error: {str(e)}')
|
|
42
|
+
return {'status': 'ok', 'service': 'vmr-http', 'version': version, 'type': type_}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Models for the parameters of a bus."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BusParams(BaseModel):
|
|
9
|
+
"""Parameters for a single bus."""
|
|
10
|
+
|
|
11
|
+
gain: Optional[float] = None
|
|
12
|
+
mute: Optional[bool] = None
|
|
13
|
+
mono: Optional[int] = None
|
|
14
|
+
eq: Optional[bool] = None
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Models for the parameters of a strip."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class StripParams(BaseModel):
|
|
9
|
+
"""Parameters for a single strip."""
|
|
10
|
+
|
|
11
|
+
gain: Optional[float] = None
|
|
12
|
+
mute: Optional[bool] = None
|
|
13
|
+
mono: Optional[bool] = None
|
|
14
|
+
solo: Optional[bool] = None
|
|
15
|
+
A1: Optional[bool] = None
|
|
16
|
+
A2: Optional[bool] = None
|
|
17
|
+
A3: Optional[bool] = None
|
|
18
|
+
A4: Optional[bool] = None
|
|
19
|
+
A5: Optional[bool] = None
|
|
20
|
+
B1: Optional[bool] = None
|
|
21
|
+
B2: Optional[bool] = None
|
|
22
|
+
B3: Optional[bool] = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class StripCompParams(BaseModel):
|
|
26
|
+
"""Parameters for the compressor of a strip."""
|
|
27
|
+
|
|
28
|
+
knob: Optional[float] = None
|
|
29
|
+
gainin: Optional[float] = None
|
|
30
|
+
ratio: Optional[float] = None
|
|
31
|
+
threshold: Optional[float] = None
|
|
32
|
+
attack: Optional[float] = None
|
|
33
|
+
release: Optional[float] = None
|
|
34
|
+
knee: Optional[float] = None
|
|
35
|
+
gainout: Optional[float] = None
|
|
36
|
+
makeup: Optional[bool] = None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class StripGateParams(BaseModel):
|
|
40
|
+
"""Parameters for the gate of a strip."""
|
|
41
|
+
|
|
42
|
+
knob: Optional[float] = None
|
|
43
|
+
threshold: Optional[float] = None
|
|
44
|
+
damping: Optional[float] = None
|
|
45
|
+
bpsidechain: Optional[float] = None
|
|
46
|
+
attack: Optional[float] = None
|
|
47
|
+
hold: Optional[float] = None
|
|
48
|
+
release: Optional[float] = None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class StripDenoiserParams(BaseModel):
|
|
52
|
+
"""Parameters for the denoiser of a strip."""
|
|
53
|
+
|
|
54
|
+
knob: Optional[float] = None
|
|
File without changes
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""module for bus-related endpoints."""
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, Body, Depends
|
|
4
|
+
|
|
5
|
+
from vmr_http.dependencies import get_voicemeeter_client
|
|
6
|
+
from vmr_http.models.bus import BusParams
|
|
7
|
+
|
|
8
|
+
from . import busmode
|
|
9
|
+
|
|
10
|
+
router = APIRouter()
|
|
11
|
+
router.include_router(busmode.router, prefix='/mode', tags=['bus mode'])
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@router.put('/{index}', tags=['bus'])
|
|
15
|
+
async def set_bus_params(index: int, request: BusParams, voicemeeter=Depends(get_voicemeeter_client)):
|
|
16
|
+
"""Set multiple parameters of a bus at once."""
|
|
17
|
+
bus = voicemeeter.bus[index]
|
|
18
|
+
for key, value in request.model_dump(exclude_unset=True).items():
|
|
19
|
+
setattr(bus, key, value)
|
|
20
|
+
|
|
21
|
+
return {key: getattr(bus, key) for key in request.model_dump(exclude_unset=True)}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@router.get('/{index}/gain', tags=['bus'])
|
|
25
|
+
async def get_gain(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
26
|
+
"""Get the current gain value for the specified bus index."""
|
|
27
|
+
return {'gain': voicemeeter.bus[index].gain}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@router.put('/{index}/gain', tags=['bus'])
|
|
31
|
+
async def set_gain(
|
|
32
|
+
index: int,
|
|
33
|
+
gain: float = Body(..., embed=True),
|
|
34
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
35
|
+
):
|
|
36
|
+
"""Set the gain value for the specified bus index."""
|
|
37
|
+
voicemeeter.bus[index].gain = gain
|
|
38
|
+
return {'gain': voicemeeter.bus[index].gain}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@router.get('/{index}/mute', tags=['bus'])
|
|
42
|
+
async def get_mute(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
43
|
+
"""Get the current mute status for the specified bus index."""
|
|
44
|
+
return {'mute': voicemeeter.bus[index].mute}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@router.put('/{index}/mute', tags=['bus'])
|
|
48
|
+
async def set_mute(
|
|
49
|
+
index: int,
|
|
50
|
+
mute: bool = Body(..., embed=True),
|
|
51
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
52
|
+
):
|
|
53
|
+
"""Set the mute status for the specified bus index."""
|
|
54
|
+
voicemeeter.bus[index].mute = mute
|
|
55
|
+
return {'mute': voicemeeter.bus[index].mute}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""module for bus mode related endpoints."""
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, Body, Depends, HTTPException
|
|
4
|
+
|
|
5
|
+
from vmr_http.dependencies import get_voicemeeter_client
|
|
6
|
+
|
|
7
|
+
router = APIRouter()
|
|
8
|
+
|
|
9
|
+
_readable_busmodes = {
|
|
10
|
+
'normal': 'Normal',
|
|
11
|
+
'amix': 'Mix Down A',
|
|
12
|
+
'bmix': 'Mix Down B',
|
|
13
|
+
'repeat': 'Stereo Repeat',
|
|
14
|
+
'composite': 'Composite',
|
|
15
|
+
'tvmix': 'Up Mix TV',
|
|
16
|
+
'upmix21': 'Up Mix 2.1',
|
|
17
|
+
'upmix41': 'Up Mix 4.1',
|
|
18
|
+
'upmix61': 'Up Mix 6.1',
|
|
19
|
+
'centeronly': 'Center Only',
|
|
20
|
+
'lfeonly': 'Low Frequency Effect Only',
|
|
21
|
+
'rearonly': 'Rear Only',
|
|
22
|
+
}
|
|
23
|
+
_reversed_busmodes = {v: k for k, v in _readable_busmodes.items()}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@router.get('/{index}')
|
|
27
|
+
async def get_bus_mode(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
28
|
+
"""Get the current bus mode for the specified bus index."""
|
|
29
|
+
return {'mode': _readable_busmodes.get(voicemeeter.bus[index].mode.get(), 'Unknown')}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@router.put('/{index}')
|
|
33
|
+
async def set_bus_mode(
|
|
34
|
+
index: int,
|
|
35
|
+
mode: str = Body(..., embed=True),
|
|
36
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
37
|
+
):
|
|
38
|
+
"""Set the bus mode for the specified bus index."""
|
|
39
|
+
if mode not in _reversed_busmodes:
|
|
40
|
+
raise HTTPException(
|
|
41
|
+
status_code=400, detail=f'Invalid mode. Valid modes are: {", ".join(_reversed_busmodes.keys())}'
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
setattr(voicemeeter.bus[index].mode, _reversed_busmodes[mode], True)
|
|
45
|
+
return {'mode': _readable_busmodes[_reversed_busmodes[mode]]}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"""module for strip-related endpoints."""
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, Body, Depends
|
|
4
|
+
|
|
5
|
+
from vmr_http.dependencies import get_voicemeeter_client
|
|
6
|
+
from vmr_http.models.strip import StripParams
|
|
7
|
+
|
|
8
|
+
from . import stripcomp, stripdenoiser, stripgate
|
|
9
|
+
|
|
10
|
+
router = APIRouter()
|
|
11
|
+
router.include_router(stripcomp.router, prefix='/comp', tags=['strip comp'])
|
|
12
|
+
router.include_router(stripgate.router, prefix='/gate', tags=['strip gate'])
|
|
13
|
+
router.include_router(stripdenoiser.router, prefix='/denoiser', tags=['strip denoiser'])
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@router.put('/{index}', tags=['strip'])
|
|
17
|
+
async def set_strip_params(index: int, request: StripParams, voicemeeter=Depends(get_voicemeeter_client)):
|
|
18
|
+
"""Set the parameters for the specified strip index."""
|
|
19
|
+
strip = voicemeeter.strip[index]
|
|
20
|
+
for key, value in request.model_dump(exclude_unset=True).items():
|
|
21
|
+
setattr(strip, key, value)
|
|
22
|
+
|
|
23
|
+
return {key: getattr(strip, key) for key in request.model_dump(exclude_unset=True)}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@router.get('/{index}/gain', tags=['strip'])
|
|
27
|
+
async def get_gain(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
28
|
+
"""Get the current gain value for the specified strip index."""
|
|
29
|
+
return {'gain': voicemeeter.strip[index].gain}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@router.put('/{index}/gain', tags=['strip'])
|
|
33
|
+
async def set_gain(
|
|
34
|
+
index: int,
|
|
35
|
+
gain: float = Body(..., embed=True),
|
|
36
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
37
|
+
):
|
|
38
|
+
"""Set the gain value for the specified strip index."""
|
|
39
|
+
voicemeeter.strip[index].gain = gain
|
|
40
|
+
return {'gain': voicemeeter.strip[index].gain}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@router.get('/{index}/mute', tags=['strip'])
|
|
44
|
+
async def get_mute(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
45
|
+
"""Get the current mute status for the specified strip index."""
|
|
46
|
+
return {'mute': voicemeeter.strip[index].mute}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@router.put('/{index}/mute', tags=['strip'])
|
|
50
|
+
async def set_mute(
|
|
51
|
+
index: int,
|
|
52
|
+
mute: bool = Body(..., embed=True),
|
|
53
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
54
|
+
):
|
|
55
|
+
"""Set the mute status for the specified strip index."""
|
|
56
|
+
voicemeeter.strip[index].mute = mute
|
|
57
|
+
return {'mute': voicemeeter.strip[index].mute}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@router.get('/{index}/mono', tags=['strip'])
|
|
61
|
+
async def get_mono(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
62
|
+
"""Get the current mono status for the specified strip index."""
|
|
63
|
+
return {'mono': voicemeeter.strip[index].mono}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@router.put('/{index}/mono', tags=['strip'])
|
|
67
|
+
async def set_mono(
|
|
68
|
+
index: int,
|
|
69
|
+
mono: bool = Body(..., embed=True),
|
|
70
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
71
|
+
):
|
|
72
|
+
"""Set the mono status for the specified strip index."""
|
|
73
|
+
voicemeeter.strip[index].mono = mono
|
|
74
|
+
return {'mono': voicemeeter.strip[index].mono}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@router.get('/{index}/solo', tags=['strip'])
|
|
78
|
+
async def get_solo(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
79
|
+
"""Get the current solo status for the specified strip index."""
|
|
80
|
+
return {'solo': voicemeeter.strip[index].solo}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@router.put('/{index}/solo', tags=['strip'])
|
|
84
|
+
async def set_solo(
|
|
85
|
+
index: int,
|
|
86
|
+
solo: bool = Body(..., embed=True),
|
|
87
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
88
|
+
):
|
|
89
|
+
"""Set the solo status for the specified strip index."""
|
|
90
|
+
voicemeeter.strip[index].solo = solo
|
|
91
|
+
return {'solo': voicemeeter.strip[index].solo}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@router.get('/{index}/A1', tags=['strip'])
|
|
95
|
+
async def get_A1(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
96
|
+
"""Get the current A1 output status for the specified strip index."""
|
|
97
|
+
return {'A1': voicemeeter.strip[index].A1}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@router.put('/{index}/A1', tags=['strip'])
|
|
101
|
+
async def set_A1(
|
|
102
|
+
index: int,
|
|
103
|
+
A1: bool = Body(..., embed=True),
|
|
104
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
105
|
+
):
|
|
106
|
+
"""Set the A1 output status for the specified strip index."""
|
|
107
|
+
voicemeeter.strip[index].A1 = A1
|
|
108
|
+
return {'A1': voicemeeter.strip[index].A1}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@router.get('/{index}/A2', tags=['strip'])
|
|
112
|
+
async def get_A2(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
113
|
+
"""Get the current A2 output status for the specified strip index."""
|
|
114
|
+
return {'A2': voicemeeter.strip[index].A2}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@router.put('/{index}/A2', tags=['strip'])
|
|
118
|
+
async def set_A2(
|
|
119
|
+
index: int,
|
|
120
|
+
A2: bool = Body(..., embed=True),
|
|
121
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
122
|
+
):
|
|
123
|
+
"""Set the A2 output status for the specified strip index."""
|
|
124
|
+
voicemeeter.strip[index].A2 = A2
|
|
125
|
+
return {'A2': voicemeeter.strip[index].A2}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@router.get('/{index}/A3', tags=['strip'])
|
|
129
|
+
async def get_A3(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
130
|
+
"""Get the current A3 output status for the specified strip index."""
|
|
131
|
+
return {'A3': voicemeeter.strip[index].A3}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@router.put('/{index}/A3', tags=['strip'])
|
|
135
|
+
async def set_A3(
|
|
136
|
+
index: int,
|
|
137
|
+
A3: bool = Body(..., embed=True),
|
|
138
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
139
|
+
):
|
|
140
|
+
"""Set the A3 output status for the specified strip index."""
|
|
141
|
+
voicemeeter.strip[index].A3 = A3
|
|
142
|
+
return {'A3': voicemeeter.strip[index].A3}
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@router.get('/{index}/A4', tags=['strip'])
|
|
146
|
+
async def get_A4(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
147
|
+
"""Get the current A4 output status for the specified strip index."""
|
|
148
|
+
return {'A4': voicemeeter.strip[index].A4}
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@router.put('/{index}/A4', tags=['strip'])
|
|
152
|
+
async def set_A4(
|
|
153
|
+
index: int,
|
|
154
|
+
A4: bool = Body(..., embed=True),
|
|
155
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
156
|
+
):
|
|
157
|
+
"""Set the A4 output status for the specified strip index."""
|
|
158
|
+
voicemeeter.strip[index].A4 = A4
|
|
159
|
+
return {'A4': voicemeeter.strip[index].A4}
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@router.get('/{index}/A5', tags=['strip'])
|
|
163
|
+
async def get_A5(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
164
|
+
"""Get the current A5 output status for the specified strip index."""
|
|
165
|
+
return {'A5': voicemeeter.strip[index].A5}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@router.put('/{index}/A5', tags=['strip'])
|
|
169
|
+
async def set_A5(
|
|
170
|
+
index: int,
|
|
171
|
+
A5: bool = Body(..., embed=True),
|
|
172
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
173
|
+
):
|
|
174
|
+
"""Set the A5 output status for the specified strip index."""
|
|
175
|
+
voicemeeter.strip[index].A5 = A5
|
|
176
|
+
return {'A5': voicemeeter.strip[index].A5}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@router.get('/{index}/B1', tags=['strip'])
|
|
180
|
+
async def get_B1(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
181
|
+
"""Get the current B1 output status for the specified strip index."""
|
|
182
|
+
return {'B1': voicemeeter.strip[index].B1}
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@router.put('/{index}/B1', tags=['strip'])
|
|
186
|
+
async def set_B1(
|
|
187
|
+
index: int,
|
|
188
|
+
B1: bool = Body(..., embed=True),
|
|
189
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
190
|
+
):
|
|
191
|
+
"""Set the B1 output status for the specified strip index."""
|
|
192
|
+
voicemeeter.strip[index].B1 = B1
|
|
193
|
+
return {'B1': voicemeeter.strip[index].B1}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@router.get('/{index}/B2', tags=['strip'])
|
|
197
|
+
async def get_B2(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
198
|
+
"""Get the current B2 output status for the specified strip index."""
|
|
199
|
+
return {'B2': voicemeeter.strip[index].B2}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@router.put('/{index}/B2', tags=['strip'])
|
|
203
|
+
async def set_B2(
|
|
204
|
+
index: int,
|
|
205
|
+
B2: bool = Body(..., embed=True),
|
|
206
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
207
|
+
):
|
|
208
|
+
"""Set the B2 output status for the specified strip index."""
|
|
209
|
+
voicemeeter.strip[index].B2 = B2
|
|
210
|
+
return {'B2': voicemeeter.strip[index].B2}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@router.get('/{index}/B3', tags=['strip'])
|
|
214
|
+
async def get_B3(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
215
|
+
"""Get the current B3 output status for the specified strip index."""
|
|
216
|
+
return {'B3': voicemeeter.strip[index].B3}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@router.put('/{index}/B3', tags=['strip'])
|
|
220
|
+
async def set_B3(
|
|
221
|
+
index: int,
|
|
222
|
+
B3: bool = Body(..., embed=True),
|
|
223
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
224
|
+
):
|
|
225
|
+
"""Set the B3 output status for the specified strip index."""
|
|
226
|
+
voicemeeter.strip[index].B3 = B3
|
|
227
|
+
return {'B3': voicemeeter.strip[index].B3}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""module for strip compressor related endpoints."""
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, Body, Depends
|
|
4
|
+
|
|
5
|
+
from vmr_http.dependencies import get_voicemeeter_client
|
|
6
|
+
from vmr_http.models.strip import StripCompParams
|
|
7
|
+
|
|
8
|
+
router = APIRouter()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@router.put('/{index}/comp')
|
|
12
|
+
async def set_strip_comp_params(index: int, request: StripCompParams, voicemeeter=Depends(get_voicemeeter_client)):
|
|
13
|
+
"""Set the compressor parameters for the specified strip index."""
|
|
14
|
+
strip_comp = voicemeeter.strip[index].comp
|
|
15
|
+
for key, value in request.model_dump(exclude_unset=True).items():
|
|
16
|
+
setattr(strip_comp, key, value)
|
|
17
|
+
|
|
18
|
+
return {key: getattr(strip_comp, key) for key in request.model_dump(exclude_unset=True)}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@router.get('/{index}/comp/knob')
|
|
22
|
+
async def get_strip_comp_knob(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
23
|
+
"""Get the current compressor knob value for the specified strip index."""
|
|
24
|
+
strip_comp = voicemeeter.strip[index].comp
|
|
25
|
+
return {'knob': strip_comp.knob}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@router.put('/{index}/comp/knob')
|
|
29
|
+
async def set_strip_comp_knob(
|
|
30
|
+
index: int,
|
|
31
|
+
knob: float = Body(..., embed=True),
|
|
32
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
33
|
+
):
|
|
34
|
+
"""Set the compressor knob value for the specified strip index."""
|
|
35
|
+
strip_comp = voicemeeter.strip[index].comp
|
|
36
|
+
strip_comp.knob = knob
|
|
37
|
+
return {'knob': strip_comp.knob}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""module for strip denoiser related endpoints."""
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, Body, Depends
|
|
4
|
+
|
|
5
|
+
from vmr_http.dependencies import get_voicemeeter_client
|
|
6
|
+
from vmr_http.models.strip import StripDenoiserParams
|
|
7
|
+
|
|
8
|
+
router = APIRouter()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@router.put('/{index}/denoiser')
|
|
12
|
+
async def set_strip_denoiser_params(
|
|
13
|
+
index: int,
|
|
14
|
+
request: StripDenoiserParams,
|
|
15
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
16
|
+
):
|
|
17
|
+
"""Set the denoiser parameters for the specified strip index."""
|
|
18
|
+
strip_denoiser = voicemeeter.strip[index].denoiser
|
|
19
|
+
for key, value in request.model_dump(exclude_unset=True).items():
|
|
20
|
+
setattr(strip_denoiser, key, value)
|
|
21
|
+
|
|
22
|
+
return {key: getattr(strip_denoiser, key) for key in request.model_dump(exclude_unset=True)}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@router.get('/{index}/denoiser/knob')
|
|
26
|
+
async def get_strip_denoiser_knob(
|
|
27
|
+
index: int,
|
|
28
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
29
|
+
):
|
|
30
|
+
"""Get the denoiser knob value for the specified strip index."""
|
|
31
|
+
strip_denoiser = voicemeeter.strip[index].denoiser
|
|
32
|
+
return {'knob': strip_denoiser.knob}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@router.put('/{index}/denoiser/knob')
|
|
36
|
+
async def set_strip_denoiser_knob(
|
|
37
|
+
index: int,
|
|
38
|
+
knob: float = Body(..., embed=True),
|
|
39
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
40
|
+
):
|
|
41
|
+
"""Set the denoiser knob value for the specified strip index."""
|
|
42
|
+
strip_denoiser = voicemeeter.strip[index].denoiser
|
|
43
|
+
strip_denoiser.knob = knob
|
|
44
|
+
return {'knob': strip_denoiser.knob}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""module for strip gate related endpoints."""
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, Body, Depends
|
|
4
|
+
|
|
5
|
+
from vmr_http.dependencies import get_voicemeeter_client
|
|
6
|
+
from vmr_http.models.strip import StripGateParams
|
|
7
|
+
|
|
8
|
+
router = APIRouter()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@router.put('/{index}/gate')
|
|
12
|
+
async def set_strip_gate_params(index: int, request: StripGateParams, voicemeeter=Depends(get_voicemeeter_client)):
|
|
13
|
+
"""Set the gate parameters for the specified strip index."""
|
|
14
|
+
strip_gate = voicemeeter.strip[index].gate
|
|
15
|
+
for key, value in request.model_dump(exclude_unset=True).items():
|
|
16
|
+
setattr(strip_gate, key, value)
|
|
17
|
+
|
|
18
|
+
return {key: getattr(strip_gate, key) for key in request.model_dump(exclude_unset=True)}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@router.get('/{index}/gate/knob')
|
|
22
|
+
async def get_strip_gate_knob(index: int, voicemeeter=Depends(get_voicemeeter_client)):
|
|
23
|
+
"""Get the current gate knob value for the specified strip index."""
|
|
24
|
+
strip_gate = voicemeeter.strip[index].gate
|
|
25
|
+
return {'knob': strip_gate.knob}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@router.put('/{index}/gate/knob')
|
|
29
|
+
async def set_strip_gate_knob(
|
|
30
|
+
index: int,
|
|
31
|
+
knob: float = Body(..., embed=True),
|
|
32
|
+
voicemeeter=Depends(get_voicemeeter_client),
|
|
33
|
+
):
|
|
34
|
+
"""Set the gate knob value for the specified strip index."""
|
|
35
|
+
strip_gate = voicemeeter.strip[index].gate
|
|
36
|
+
strip_gate.knob = knob
|
|
37
|
+
return {'knob': strip_gate.knob}
|