mirror of
https://github.com/onyx-and-iris/voicemeeter-api-python.git
synced 2026-04-18 12:33:34 +00:00
Compare commits
4 Commits
71f77b7830
...
bounds-che
| Author | SHA1 | Date | |
|---|---|---|---|
| c2daba1a62 | |||
| 3036cdff2f | |||
| b02f3af665 | |||
| 145f85b7cd |
@@ -11,7 +11,7 @@ Before any major/minor/patch bump all unit tests will be run to verify they pass
|
||||
|
||||
- [x]
|
||||
|
||||
## [2.1.0] - 2023-06-30
|
||||
## [2.1.1] - 2023-07-01
|
||||
|
||||
### Added
|
||||
|
||||
@@ -24,6 +24,10 @@ Before any major/minor/patch bump all unit tests will be run to verify they pass
|
||||
|
||||
- Recorder.loop removed from documentation
|
||||
|
||||
### Changed
|
||||
|
||||
- When out of bounds values are passed, log warnings instead of raising Errors. See [Issue #6][Issue 6].
|
||||
|
||||
## [2.0.0] - 2023-06-25
|
||||
|
||||
Where possible I've attempted to make the changes backwards compatible. The breaking changes affect two higher classes, Strip and Bus, as well as the behaviour of events. All other changes are additive or QOL aimed at giving more options to the developer. For example, every low-level CAPI call is now logged and error raised on Exception, you can now register callback functions as well as observer classes, extra examples to demonstrate different use cases etc.
|
||||
@@ -376,3 +380,4 @@ I will move this commit to a separate branch in preparation for version 2.0.
|
||||
- project packaged with poetry and added to pypi.
|
||||
|
||||
[issue 4]: https://github.com/onyx-and-iris/voicemeeter-api-python/issues/4
|
||||
[Issue 6]: https://github.com/onyx-and-iris/voicemeeter-api-python/issues/6
|
||||
|
||||
@@ -629,7 +629,9 @@ vm.option.sr = 48000
|
||||
|
||||
The following methods are available:
|
||||
|
||||
- `buffer(driver, buffer)` : Set buffer size for particular audio driver.
|
||||
- `buffer(driver, buf)` : Set buffer size for particular audio driver.
|
||||
- buf: int, from 128 to 2048
|
||||
- driver:str, ("mme", "wdm", "ks", "asio")
|
||||
|
||||
example:
|
||||
|
||||
@@ -637,10 +639,6 @@ example:
|
||||
vm.option.buffer("wdm", 512)
|
||||
```
|
||||
|
||||
driver defined as one of ("mme", "wdm", "ks", "asio")
|
||||
|
||||
buffer, from 128 to 2048
|
||||
|
||||
##### delay[i]
|
||||
|
||||
- `get()`: int
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "voicemeeter-api"
|
||||
version = "2.0.2"
|
||||
version = "2.1.1"
|
||||
description = "A Python wrapper for the Voiceemeter API"
|
||||
authors = ["onyx-and-iris <code@onyxandiris.online>"]
|
||||
license = "MIT"
|
||||
|
||||
@@ -6,36 +6,50 @@ import voicemeeterlib
|
||||
from voicemeeterlib.kinds import KindId
|
||||
from voicemeeterlib.kinds import request_kind_map as kindmap
|
||||
|
||||
# let's keep things random
|
||||
KIND_ID = random.choice(tuple(kind_id.name.lower() for kind_id in KindId))
|
||||
vm = voicemeeterlib.api(KIND_ID)
|
||||
kind = kindmap(KIND_ID)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Data:
|
||||
"""bounds data to map tests to a kind"""
|
||||
|
||||
name: str = kind.name
|
||||
phys_in: int = kind.ins[0] - 1
|
||||
virt_in: int = kind.ins[0] + kind.ins[-1] - 1
|
||||
phys_out: int = kind.outs[0] - 1
|
||||
virt_out: int = kind.outs[0] + kind.outs[-1] - 1
|
||||
vban_in: int = kind.vban[0] - 1
|
||||
vban_out: int = kind.vban[-1] - 1
|
||||
button_lower: int = 0
|
||||
button_upper: int = 79
|
||||
asio_in: int = kind.asio[0] - 1
|
||||
asio_out: int = kind.asio[-1] - 1
|
||||
insert_lower: int = 0
|
||||
insert_higher: int = kind.insert - 1
|
||||
name: str
|
||||
phys_in: int
|
||||
virt_in: int
|
||||
phys_out: int
|
||||
virt_out: int
|
||||
vban_in: int
|
||||
vban_out: int
|
||||
button_lower: int
|
||||
button_upper: int
|
||||
asio_in: int
|
||||
asio_out: int
|
||||
insert_lower: int
|
||||
insert_higher: int
|
||||
|
||||
@property
|
||||
def channels(self):
|
||||
return (2 * self.phys_in) + (8 * self.virt_in)
|
||||
|
||||
|
||||
data = Data()
|
||||
# let's keep things random
|
||||
KIND_ID = random.choice(tuple(kind_id.name.lower() for kind_id in KindId))
|
||||
vm = voicemeeterlib.api(KIND_ID)
|
||||
kind = kindmap(KIND_ID)
|
||||
|
||||
data = Data(
|
||||
name=kind.name,
|
||||
phys_in=kind.ins[0] - 1,
|
||||
virt_in=kind.ins[0] + kind.ins[-1] - 1,
|
||||
phys_out=kind.outs[0] - 1,
|
||||
virt_out=kind.outs[0] + kind.outs[-1] - 1,
|
||||
vban_in=kind.vban[0] - 1,
|
||||
vban_out=kind.vban[-1] - 1,
|
||||
button_lower=0,
|
||||
button_upper=79,
|
||||
asio_in=kind.asio[0] - 1,
|
||||
asio_out=kind.asio[-1] - 1,
|
||||
insert_lower=0,
|
||||
insert_higher=kind.insert - 1,
|
||||
)
|
||||
|
||||
|
||||
def setup_module():
|
||||
|
||||
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="20" role="img" aria-label="tests: 139"><title>tests: 139</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="68" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="37" height="20" fill="#555"/><rect x="37" width="31" height="20" fill="#4c1"/><rect width="68" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="195" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="270">tests</text><text x="195" y="140" transform="scale(.1)" fill="#fff" textLength="270">tests</text><text aria-hidden="true" x="515" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="210">139</text><text x="515" y="140" transform="scale(.1)" fill="#fff" textLength="210">139</text></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="20" role="img" aria-label="tests: 155"><title>tests: 155</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="68" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="37" height="20" fill="#555"/><rect x="37" width="31" height="20" fill="#4c1"/><rect width="68" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="195" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="270">tests</text><text x="195" y="140" transform="scale(.1)" fill="#fff" textLength="270">tests</text><text aria-hidden="true" x="515" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="210">155</text><text x="515" y="140" transform="scale(.1)" fill="#fff" textLength="210">155</text></g></svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -156,6 +156,7 @@ class TestSetAndGetBoolHigher:
|
||||
[("A1"), ("B2")],
|
||||
)
|
||||
def test_it_sets_and_gets_recorder_bool_params(self, param, value):
|
||||
assert hasattr(vm.recorder, param)
|
||||
setattr(vm.recorder, param, value)
|
||||
assert getattr(vm.recorder, param) == value
|
||||
|
||||
@@ -168,7 +169,56 @@ class TestSetAndGetBoolHigher:
|
||||
[("loop")],
|
||||
)
|
||||
def test_it_sets_recorder_bool_params(self, param, value):
|
||||
assert hasattr(vm.recorder, param)
|
||||
setattr(vm.recorder, param, value)
|
||||
assert getattr(vm.recorder, param) == value
|
||||
|
||||
""" recoder.mode tests """
|
||||
|
||||
@pytest.mark.skipif(
|
||||
data.name == "basic",
|
||||
reason="Skip test if kind is basic",
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"param",
|
||||
[("loop"), ("recbus")],
|
||||
)
|
||||
def test_it_sets_recorder_mode_bool_params(self, param, value):
|
||||
assert hasattr(vm.recorder.mode, param)
|
||||
setattr(vm.recorder.mode, param, value)
|
||||
assert getattr(vm.recorder.mode, param) == value
|
||||
|
||||
""" recorder.armstrip """
|
||||
|
||||
@pytest.mark.skipif(
|
||||
data.name == "basic",
|
||||
reason="Skip test if kind is basic",
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"index",
|
||||
[
|
||||
(data.phys_out),
|
||||
(data.virt_out),
|
||||
],
|
||||
)
|
||||
def test_it_sets_recorder_armstrip_bool_params(self, index, value):
|
||||
vm.recorder.armstrip[index].set(value)
|
||||
|
||||
""" recorder.armbus """
|
||||
|
||||
@pytest.mark.skipif(
|
||||
data.name == "basic",
|
||||
reason="Skip test if kind is basic",
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"index",
|
||||
[
|
||||
(data.phys_out),
|
||||
(data.virt_out),
|
||||
],
|
||||
)
|
||||
def test_it_sets_recorder_armbus_bool_params(self, index, value):
|
||||
vm.recorder.armbus[index].set(True)
|
||||
|
||||
""" fx tests """
|
||||
|
||||
@@ -323,6 +373,26 @@ class TestSetAndGetIntHigher:
|
||||
vm.option.delay[index].set(value)
|
||||
assert vm.option.delay[index].get() == value
|
||||
|
||||
""" recorder tests """
|
||||
|
||||
@pytest.mark.skipif(
|
||||
data.name == "basic",
|
||||
reason="Skip test if kind is basic",
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"param,value",
|
||||
[
|
||||
("samplerate", 32000),
|
||||
("samplerate", 96000),
|
||||
("bitresolution", 16),
|
||||
("bitresolution", 32),
|
||||
],
|
||||
)
|
||||
def test_it_sets_and_gets_recorder_int_params(self, param, value):
|
||||
assert hasattr(vm.recorder, param)
|
||||
setattr(vm.recorder, param, value)
|
||||
assert getattr(vm.recorder, param) == value
|
||||
|
||||
|
||||
class TestSetAndGetFloatHigher:
|
||||
__test__ = True
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from .error import VMError
|
||||
from .iremote import IRemote
|
||||
from .kinds import kinds_all
|
||||
|
||||
@@ -196,7 +195,7 @@ class Option(IRemote):
|
||||
def sr(self, val: int):
|
||||
opts = (44100, 48000, 88200, 96000, 176400, 192000)
|
||||
if val not in opts:
|
||||
raise VMError(f"Expected one of: {opts}")
|
||||
self.logger.warning(f"sr got: {val} but expected a value in {opts}")
|
||||
self.setter("sr", val)
|
||||
|
||||
@property
|
||||
|
||||
@@ -21,10 +21,10 @@ class Recorder(IRemote):
|
||||
Returns a Recorder class of a kind.
|
||||
"""
|
||||
CHANNELOUTMIXIN_cls = _make_channelout_mixins[remote.kind.name]
|
||||
ARMSTRIPMIXIN_cls = _make_armchannel_mixins(remote)[remote.kind.name]
|
||||
ARMCHANNELMIXIN_cls = _make_armchannel_mixins(remote)[remote.kind.name]
|
||||
REC_cls = type(
|
||||
f"Recorder{remote.kind}",
|
||||
(cls, CHANNELOUTMIXIN_cls, ARMSTRIPMIXIN_cls),
|
||||
(cls, CHANNELOUTMIXIN_cls, ARMCHANNELMIXIN_cls),
|
||||
{
|
||||
**{
|
||||
param: action_fn(param)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from abc import abstractmethod
|
||||
|
||||
from .error import VMError
|
||||
from .iremote import IRemote
|
||||
|
||||
|
||||
@@ -50,7 +49,9 @@ class VbanStream(IRemote):
|
||||
@port.setter
|
||||
def port(self, val: int):
|
||||
if not 1024 <= val <= 65535:
|
||||
raise VMError("Expected value from 1024 to 65535")
|
||||
self.logger.warning(
|
||||
f"port got: {val} but expected a value from 1024 to 65535"
|
||||
)
|
||||
self.setter("port", val)
|
||||
|
||||
@property
|
||||
@@ -61,7 +62,7 @@ class VbanStream(IRemote):
|
||||
def sr(self, val: int):
|
||||
opts = (11025, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000)
|
||||
if val not in opts:
|
||||
raise VMError(f"Expected one of: {opts}")
|
||||
self.logger.warning(f"sr got: {val} but expected a value in {opts}")
|
||||
self.setter("sr", val)
|
||||
|
||||
@property
|
||||
@@ -71,7 +72,7 @@ class VbanStream(IRemote):
|
||||
@channel.setter
|
||||
def channel(self, val: int):
|
||||
if not 1 <= val <= 8:
|
||||
raise VMError("Expected value from 1 to 8")
|
||||
self.logger.warning(f"channel got: {val} but expected a value from 1 to 8")
|
||||
self.setter("channel", val)
|
||||
|
||||
@property
|
||||
@@ -81,7 +82,7 @@ class VbanStream(IRemote):
|
||||
@bit.setter
|
||||
def bit(self, val: int):
|
||||
if val not in (16, 24):
|
||||
raise VMError("Expected value 16 or 24")
|
||||
self.logger.warning(f"bit got: {val} but expected value 16 or 24")
|
||||
self.setter("bit", 1 if (val == 16) else 2)
|
||||
|
||||
@property
|
||||
@@ -91,7 +92,7 @@ class VbanStream(IRemote):
|
||||
@quality.setter
|
||||
def quality(self, val: int):
|
||||
if not 0 <= val <= 4:
|
||||
raise VMError("Expected value from 0 to 4")
|
||||
self.logger.warning(f"quality got: {val} but expected a value from 0 to 4")
|
||||
self.setter("quality", val)
|
||||
|
||||
@property
|
||||
@@ -101,7 +102,7 @@ class VbanStream(IRemote):
|
||||
@route.setter
|
||||
def route(self, val: int):
|
||||
if not 0 <= val <= 8:
|
||||
raise VMError("Expected value from 0 to 8")
|
||||
self.logger.warning(f"route got: {val} but expected a value from 0 to 8")
|
||||
self.setter("route", val)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user