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.
@@ -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
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
24
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](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
@@ -0,0 +1,73 @@
1
+ # Voicemeeter HTTP
2
+
3
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
4
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](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,8 @@
1
+ """module containing dependencies for the API endpoints."""
2
+
3
+ from fastapi import Request
4
+
5
+
6
+ def get_voicemeeter_client(request: Request):
7
+ """Dependency to get the Voicemeeter client from the application state."""
8
+ return request.app.state.voicemeeter
@@ -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}