diff options
author | Eddy Pedroni <epedroni@pm.me> | 2025-02-23 09:06:33 +0100 |
---|---|---|
committer | Eddy Pedroni <epedroni@pm.me> | 2025-02-23 09:06:33 +0100 |
commit | 7c0c69431a1ba4939e739a5429c03c067bf6e1dd (patch) | |
tree | 19f5fd0830d3e18928bfac3ef16be17eddc76b1f /solo-tool-project | |
parent | bef8eee0f63cc5ccb963be9467381e4e605e7f53 (diff) |
Pass launchpad mini tests
Diffstat (limited to 'solo-tool-project')
6 files changed, 131 insertions, 129 deletions
diff --git a/solo-tool-project/src/solo_tool/handlers.py b/solo-tool-project/src/solo_tool/handlers.py new file mode 100644 index 0000000..13e982b --- /dev/null +++ b/solo-tool-project/src/solo_tool/handlers.py @@ -0,0 +1,21 @@ +from collections.abc import Callable + +from solo_tool.solo_tool import SoloTool + +def changeSong(st: SoloTool, delta: int) -> Callable[[], None]: + def f(): + if st.song is None: + st.song = 0 + else: + st.song += delta + return f + +def seekRelative(st: SoloTool, delta: float) -> Callable[[], None]: + def f(): + st.position += delta + return f + +def positionToKeyPoint(st: SoloTool) -> Callable[[], None]: + def f(): + st.keyPoint = st.position + return f diff --git a/solo-tool-project/src/solo_tool/midi_controller_launchpad_mini.py b/solo-tool-project/src/solo_tool/midi_controller_launchpad_mini.py index 4fde8fc..3dc8ec6 100644 --- a/solo-tool-project/src/solo_tool/midi_controller_launchpad_mini.py +++ b/solo-tool-project/src/solo_tool/midi_controller_launchpad_mini.py @@ -1,5 +1,5 @@ from .midi_wrapper_mido import MidiWrapper -from .solo_tool_controller import SoloToolController +from . import handlers class MidiController: DEVICE_NAME = "Launchpad Mini MIDI 1" @@ -20,7 +20,6 @@ class MidiController: def __init__(self, soloTool, midiWrapperOverride=None): self._soloTool = soloTool - self._soloToolController = SoloToolController(soloTool) if midiWrapperOverride is not None: self._midiWrapper = midiWrapperOverride else: @@ -28,31 +27,25 @@ class MidiController: self._registerHandlers() self._soloTool.registerPlayingStateCallback(self._updatePlayPauseButton) - self._soloTool.registerPlaybackVolumeCallback(self._updateVolumeRow) - self._soloTool.registerPlaybackRateCallback(self._updateRateRow) - self._soloTool.registerAbLimitEnabledCallback(self._updateToggleAbLimitEnableButton) - - self._aLimit = 0.0 - self._bLimit = 0.0 + self._soloTool.registerVolumeCallback(self._updateVolumeRow) + self._soloTool.registerRateCallback(self._updateRateRow) def _registerHandlers(self): self._handlers = { 96 : self._soloTool.stop, - 114 : self._soloTool.jumpToA, + 114 : self._soloTool.jump, 112 : self._playPause, - 98 : self._toggleAbLimitEnable, - 118 : self._soloTool.previousStoredAbLimits, - 119 : self._soloTool.nextStoredAbLimits, - 116 : self._setALimit, - 117 : self._setBLimit, - 48 : self._soloToolController.previousSong, - 49 : self._createSeekHandler(-0.25), - 50 : self._createSeekHandler(-0.05), - 51 : self._createSeekHandler(-0.01), - 52 : self._createSeekHandler(0.01), - 53 : self._createSeekHandler(0.05), - 54 : self._createSeekHandler(0.25), - 55 : self._soloToolController.nextSong, + #118 : self._soloTool.previousStoredAbLimits, + #119 : self._soloTool.nextStoredAbLimits, + 117 : handlers.positionToKeyPoint(self._soloTool), + 48 : handlers.changeSong(self._soloTool, -1), + 49 : handlers.seekRelative(self._soloTool, -0.25), + 50 : handlers.seekRelative(self._soloTool, -0.05), + 51 : handlers.seekRelative(self._soloTool, -0.01), + 52 : handlers.seekRelative(self._soloTool, 0.01), + 53 : handlers.seekRelative(self._soloTool, 0.05), + 54 : handlers.seekRelative(self._soloTool, 0.25), + 55 : handlers.changeSong(self._soloTool, 1), } for i in range(0, 8): @@ -84,24 +77,6 @@ class MidiController: else: self._soloTool.play() - def _createSeekHandler(self, delta): - def f(): - newPosition = self._soloTool.getPlaybackPosition() + delta - newPosition = min(1.0, max(0.0, newPosition)) - self._soloTool.setPlaybackPosition(newPosition) - return f - - def _setALimit(self): - self._aLimit = self._soloTool.getPlaybackPosition() - self._soloTool.setAbLimits(self._aLimit, self._bLimit) - - def _setBLimit(self): - self._bLimit = self._soloTool.getPlaybackPosition() - self._soloTool.setAbLimits(self._aLimit, self._bLimit) - - def _toggleAbLimitEnable(self): - self._soloTool.setAbLimitEnable(not self._soloTool.isAbLimitEnabled()) - def _updatePlayPauseButton(self, playing): if playing: self._setButtonLED(7, 0, MidiController.LED_GREEN) @@ -128,12 +103,12 @@ class MidiController: def _createSetPlaybackRateCallback(self, rate): def f(): - self._soloTool.setPlaybackRate(rate) + self._soloTool.rate = rate return f def _createSetPlaybackVolumeCallback(self, volume): def f(): - self._soloTool.setPlaybackVolume(volume) + self._soloTool.volume = volume return f def _setButtonLED(self, row, col, colour): @@ -153,23 +128,19 @@ class MidiController: self._allLEDsOff() # volume buttons - self._updateVolumeRow(self._soloTool.getPlaybackVolume()) + self._updateVolumeRow(self._soloTool.volume) # playback rate buttons - self._updateRateRow(self._soloTool.getPlaybackRate()) + self._updateRateRow(self._soloTool.rate) # playback control self._setButtonLED(6, 0, MidiController.LED_RED) self._updatePlayPauseButton(self._soloTool.isPlaying()) - # AB repeat toggle - self._updateToggleAbLimitEnableButton(self._soloTool.isAbLimitEnabled()) - # AB control self._setButtonLED(7, 2, MidiController.LED_YELLOW) self._setButtonLED(7, 6, MidiController.LED_RED) self._setButtonLED(7, 7, MidiController.LED_GREEN) - self._setButtonLED(7, 4, MidiController.LED_YELLOW) self._setButtonLED(7, 5, MidiController.LED_YELLOW) # Song control diff --git a/solo-tool-project/src/solo_tool/solo_tool.py b/solo-tool-project/src/solo_tool/solo_tool.py index 884721b..97c3495 100644 --- a/solo-tool-project/src/solo_tool/solo_tool.py +++ b/solo-tool-project/src/solo_tool/solo_tool.py @@ -40,9 +40,10 @@ class SoloTool: @song.setter def song(self, new: int) -> None: - if new is None or new < 0 or new >= len(self._songs): - raise ValueError() - if new != self._song: + if new is not None \ + and new >= 0 \ + and new < len(self._songs) \ + and new != self._song: self._updateSong(new) @property @@ -53,9 +54,7 @@ class SoloTool: @keyPoints.setter def keyPoints(self, new: list[float]) -> None: - if new is None: - raise ValueError() - if self._song is not None: + if new is not None and self._song is not None: sanitized = sorted(list(set([p for p in new if SoloTool._keyPointValid(p)]))) self._keyPoints[self._song] = sanitized @@ -65,9 +64,7 @@ class SoloTool: @keyPoint.setter def keyPoint(self, new: float) -> None: - if not SoloTool._keyPointValid(new): - raise ValueError() - if self._song is not None and new != self._keyPoint: + if self._song is not None and SoloTool._keyPointValid(new) and new != self._keyPoint: self._keyPoint = new self._notifier.notify(Notifier.CURRENT_KEY_POINT_EVENT, new) @@ -92,9 +89,7 @@ class SoloTool: @rate.setter def rate(self, new: float) -> None: - if new is None or new <= 0.0: - raise ValueError() - if new != self._player.getPlaybackRate(): + if new is not None and new >= 0.0 and new != self._player.getPlaybackRate(): self._player.setPlaybackRate(new) self._notifier.notify(Notifier.PLAYBACK_RATE_EVENT, new) @@ -104,9 +99,7 @@ class SoloTool: @volume.setter def volume(self, new: float) -> None: - if new is None or new < 0.0: - raise ValueError() - if new != self._player.getPlaybackVolume(): + if new is not None and new >= 0.0 and new != self._player.getPlaybackVolume(): self._player.setPlaybackVolume(new) self._notifier.notify(Notifier.PLAYBACK_VOLUME_EVENT, new) @@ -116,11 +109,9 @@ class SoloTool: @position.setter def position(self, new: float) -> None: - if new is None or new < 0.0 or new >= 1.0: - raise ValueError() # TODO stop playback before changing position? - if new != self._player.getPlaybackPosition(): - self._player.setPlaybackPosition(new) + if new is not None and new != self._player.getPlaybackPosition(): + self._player.setPlaybackPosition(min(max(0.0, new), 1.0)) def registerPlayingStateCallback(self, callback): self._notifier.registerCallback(Notifier.PLAYING_STATE_EVENT, callback) diff --git a/solo-tool-project/test/midi_launchpad_mini_integrationtest.py b/solo-tool-project/test/midi_launchpad_mini_integrationtest.py index ec41ab2..9588f9f 100644 --- a/solo-tool-project/test/midi_launchpad_mini_integrationtest.py +++ b/solo-tool-project/test/midi_launchpad_mini_integrationtest.py @@ -1,8 +1,6 @@ import pytest from mido import Message -pytestmark = pytest.mark.skip(reason="not yet implemented") - from solo_tool.midi_controller_launchpad_mini import MidiController from solo_tool.solo_tool import SoloTool from player_mock import Player as PlayerMock @@ -125,7 +123,7 @@ def test_jumpToKeyPositionButton(uut, midiWrapperMock, soloTool, playerMock): soloTool.song = 0 uut.connect() - soloTool.keyPosition = 0.5 + soloTool.keyPoint = 0.5 assert playerMock.position == 0.0 midiWrapperMock.simulateInput(jumpToKeyPositionButton) @@ -147,6 +145,9 @@ def test_previousAndNextSongButtons(uut, midiWrapperMock, soloTool, playerMock): midiWrapperMock.simulateInput(nextSongButton) assert playerMock.currentSong == songs[1] + midiWrapperMock.simulateInput(nextSongButton) + assert playerMock.currentSong == songs[1] + midiWrapperMock.simulateInput(previousSongButton) assert playerMock.currentSong == songs[0] @@ -155,27 +156,27 @@ def test_previousAndNextSongButtons(uut, midiWrapperMock, soloTool, playerMock): def test_previousAndNextKeyPositionButtons(uut, midiWrapperMock, soloTool, playerMock): song = "test.flac" - keyPositions = [0.2, 0.1] + keyPoints = [0.2, 0.1] soloTool.addSong(song) soloTool.song = 0 - soloTool.keyPositions = keyPositions + soloTool.keyPoints = keyPoints uut.connect() - assert soloTool.keyPosition == 0.0 + assert soloTool.keyPoint == 0.0 midiWrapperMock.simulateInput(nextKeyPositionButton) - soloTool.keyPosition == 0.1 + soloTool.keyPoint == 0.1 midiWrapperMock.simulateInput(nextKeyPositionButton) - soloTool.keyPosition == 0.2 + soloTool.keyPoint == 0.2 midiWrapperMock.simulateInput(previousKeyPositionButton) - soloTool.keyPosition == 0.1 + soloTool.keyPoint == 0.1 midiWrapperMock.simulateInput(previousKeyPositionButton) - soloTool.keyPosition == 0.1 + soloTool.keyPoint == 0.1 def test_playbackRateButtons(uut, midiWrapperMock, soloTool, playerMock): playbackRateOptions = { @@ -233,9 +234,10 @@ def test_playbackRateLeds(uut, midiWrapperMock, soloTool, playerMock): assert playerMock.rate == 1.0 for t, (rate, leds) in enumerate(playbackRateOptions): + print(t) midiWrapperMock.sentMessages.clear() - soloTool.setPlaybackRate(rate) + soloTool.rate = rate assert playerMock.rate == rate for i, colour in enumerate(leds): @@ -299,7 +301,7 @@ def test_playbackVolumeLeds(uut, midiWrapperMock, soloTool, playerMock): for t, (volume, leds) in enumerate(playbackVolumeOptions): midiWrapperMock.sentMessages.clear() - soloTool.setPlaybackVolume(volume) + soloTool.volume = volume assert playerMock.volume == volume for i, colour in enumerate(leds): @@ -319,22 +321,20 @@ def test_connectDisconnect(uut, midiWrapperMock): [(i, LED_GREEN, 0) for i in range(0, 6)] + # volume row [(i, LED_YELLOW, 0) for i in range(16, 22)] + # playback rate row [ - (stopButton, LED_RED, 0), - (playPauseButton, LED_YELLOW, 0), - (abToggleButton, LED_RED, 0), - (jumpToAButton, LED_YELLOW, 0), - (previousLimitButton, LED_RED, 0), - (nextLimitButton, LED_GREEN, 0), - (setAButton, LED_YELLOW, 0), - (setBButton, LED_YELLOW, 0), - (previousSongButton, LED_RED, 0), - (rwd1PcButton, LED_RED, 0), - (rwd5PcButton, LED_RED, 0), - (rwd25PcButton, LED_RED, 0), - (nextSongButton, LED_GREEN, 0), - (fwd1PcButton, LED_GREEN, 0), - (fwd5PcButton, LED_GREEN, 0), - (fwd25PcButton, LED_GREEN, 0), + (stopButton, LED_RED, 0), + (playPauseButton, LED_YELLOW, 0), + (jumpToKeyPositionButton, LED_YELLOW, 0), + (previousKeyPositionButton, LED_RED, 0), + (nextKeyPositionButton, LED_GREEN, 0), + (setKeyPositionButton, LED_YELLOW, 0), + (previousSongButton, LED_RED, 0), + (rwd1PcButton, LED_RED, 0), + (rwd5PcButton, LED_RED, 0), + (rwd25PcButton, LED_RED, 0), + (nextSongButton, LED_GREEN, 0), + (fwd1PcButton, LED_GREEN, 0), + (fwd5PcButton, LED_GREEN, 0), + (fwd25PcButton, LED_GREEN, 0), ]) teardownMessages = [(int(i / 8) * 16 + (i % 8), LED_OFF, 0) for i in range(0, 64)] # clear all @@ -378,11 +378,11 @@ def test_setKeyPositionButton(uut, midiWrapperMock, soloTool, playerMock): playerMock.position = 0.3 midiWrapperMock.simulateInput(setKeyPositionButton) - assert soloTool.keyPosition == 0.3 + assert soloTool.keyPoint == 0.3 playerMock.position = 0.5 midiWrapperMock.simulateInput(setKeyPositionButton) - assert soloTool.keyPosition == 0.5 + assert soloTool.keyPoint == 0.5 playerMock.position = 0.7 midiWrapperMock.simulateInput(jumpToKeyPositionButton) diff --git a/solo-tool-project/test/solo_tool_controller_integrationtest.py b/solo-tool-project/test/solo_tool_controller_integrationtest.py index e39e5f9..8eb09f9 100644 --- a/solo-tool-project/test/solo_tool_controller_integrationtest.py +++ b/solo-tool-project/test/solo_tool_controller_integrationtest.py @@ -2,11 +2,11 @@ import pathlib import shutil import pytest -pytestmark = pytest.mark.skip(reason="not yet implemented") - from solo_tool.solo_tool_controller import SoloToolController from solo_tool.solo_tool import SoloTool +pytestmark = pytest.mark.skip(reason="not yet implemented") + @pytest.fixture def prepared_tmp_path(tmp_path): testFiles = [ diff --git a/solo-tool-project/test/solo_tool_integrationtest.py b/solo-tool-project/test/solo_tool_integrationtest.py index 94d5cef..2a818ed 100644 --- a/solo-tool-project/test/solo_tool_integrationtest.py +++ b/solo-tool-project/test/solo_tool_integrationtest.py @@ -54,35 +54,58 @@ def test_playerControls(uut, mockPlayer): assert uut.volume == 0.5 def test_sanitizePlaybackRate(uut): - # Valid rates are > 0.0 - with pytest.raises(ValueError): - uut.rate = -0.1 + # Initial value + assert uut.rate == 1.0 - with pytest.raises(ValueError): - uut.rate = 0.0 + # Valid rates are >= 0.0, invalid is ignored + uut.rate = -0.1 + assert uut.rate == 1.0 + + uut.rate = 0.0 + assert uut.rate == 0.0 + + uut.rate = 0.0001 + assert uut.rate == 0.0001 - uut.rate = 1.0 uut.rate = 150.0 + assert uut.rate == 150.0 def test_sanitizePlaybackPosition(uut): - # Valid positions are in [0, 1) - with pytest.raises(ValueError): - uut.position = -0.1 + # Initial value + assert uut.position == 0.0 + + # Valid positions are in [0, 1], invalid is limited + uut.position = 0.2 + assert uut.position == 0.2 + + uut.position = -0.1 + assert uut.position == 0.0 + + uut.position = 1.0 + assert uut.position == 1.0 - uut.position = 0.0 - uut.position = 0.999 + uut.position = 0.4 + assert uut.position == 0.4 - with pytest.raises(ValueError): - uut.position = 1.0 + uut.position = 1.5 + assert uut.position == 1.0 def test_sanitizePlaybackVolume(uut): - # Valid volumes are >= 0.0 - with pytest.raises(ValueError): - uut.volume = -0.1 + # Initial value + assert uut.volume == 1.0 + + # Valid volumes are >= 0.0, invalid is ignored + uut.volume = -0.1 + assert uut.volume == 1.0 uut.volume = 0.0 + assert uut.volume == 0.0 + uut.volume = 1.0 + assert uut.volume == 1.0 + uut.volume = 150.0 + assert uut.volume == 150.0 def test_addAndSelectSongs(uut, mockPlayer): songs = [ @@ -112,17 +135,14 @@ def test_addAndSelectSongs(uut, mockPlayer): assert uut.song == i # The current song cannot be de-selected - with pytest.raises(ValueError): - uut.song = None + uut.song = None assert uut.song == len(uut.songs) - 1 # Non-existent songs cannot be selected - with pytest.raises(ValueError): - uut.song = -1 + uut.song = -1 assert uut.song == len(uut.songs) - 1 - with pytest.raises(ValueError): - uut.song = 2 + uut.song = 2 assert uut.song == len(uut.songs) - 1 def test_addAndJumpToKeyPoints(uut, mockPlayer): @@ -174,22 +194,21 @@ def test_sanitizeKeyPoint(uut): # Key point and key point list cannot be none uut.keyPoint = 0.5 - with pytest.raises(ValueError): - uut.keyPoint = None + uut.keyPoint = None assert uut.keyPoint == 0.5 - with pytest.raises(ValueError): - uut.keyPoints = None + uut.keyPoints = None assert uut.keyPoints == [0.1, 0.2, 0.4] # Valid key points are in [0, 1) - with pytest.raises(ValueError): - uut.keyPoint = -0.1 + uut.keyPoint = -0.1 + assert uut.keyPoint == 0.5 - with pytest.raises(ValueError): - uut.keyPoint = 1.0 + uut.keyPoint = 1.0 + assert uut.keyPoint == 0.5 uut.keyPoint = 0.999 + assert uut.keyPoint == 0.999 def test_keyPointsPerSong(uut, mockPlayer): songs = [ |