4 Commits

Author SHA1 Message Date
c2daba1a62 when out of bounds values are passed, log warnings
bump to version 2.1.1

closes #6
2023-07-01 19:50:54 +01:00
3036cdff2f upd banana badge 2023-07-01 19:26:56 +01:00
b02f3af665 add recorder, recorder.mode tests 2023-07-01 19:26:32 +01:00
145f85b7cd rename ARMSTRIPMIXIN_cls to ARMCHANNELMIXIN_cls 2023-07-01 18:09:31 +01:00
9 changed files with 125 additions and 38 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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():

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)