aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddy Pedroni <eddy@0xf7.com>2022-01-04 17:55:00 +0100
committerEddy Pedroni <eddy@0xf7.com>2022-01-04 17:55:00 +0100
commit2b4323eca801638f0a305ff29afe815a45e103b1 (patch)
treed130038b86d671d78eb52e56ce8d2b9b3bd16842
parentc4cb9a96342568890dcf1e36d02d6180bdb26ac8 (diff)
Added current value to notification system, fixed Qt hack
-rw-r--r--midi_controller_launchpad_mini.py16
-rw-r--r--notifier.py8
-rw-r--r--notifier_unittest.py40
-rw-r--r--solo_tool.py41
-rw-r--r--solo_tool_integrationtest.py48
-rw-r--r--solo_tool_qt.py6
6 files changed, 98 insertions, 61 deletions
diff --git a/midi_controller_launchpad_mini.py b/midi_controller_launchpad_mini.py
index 10013b5..6790cec 100644
--- a/midi_controller_launchpad_mini.py
+++ b/midi_controller_launchpad_mini.py
@@ -69,21 +69,19 @@ class MidiController:
def _stop(self):
self._soloTool.stop()
- def _updatePlayPauseButton(self):
- if self._soloTool.isPlaying():
+ def _updatePlayPauseButton(self, playing):
+ if playing:
self._setButtonLED(7, 0, MidiController.LED_GREEN)
else:
self._setButtonLED(7, 0, MidiController.LED_YELLOW)
- def _updateVolumeRow(self):
- volume = self._soloTool.getPlaybackVolume()
+ def _updateVolumeRow(self, volume):
t1 = int(round(volume / MidiController.PLAYBACK_VOLUME_STEP, 1))
t2 = int(round(MidiController.MIN_PLAYBACK_VOLUME / MidiController.PLAYBACK_VOLUME_STEP, 1))
lastColumnLit = t1 - t2 + 1
self._lightRowUntilColumn(0, lastColumnLit, MidiController.LED_GREEN)
- def _updateRateRow(self):
- rate = self._soloTool.getPlaybackRate()
+ def _updateRateRow(self, rate):
t1 = int(round(rate / MidiController.PLAYBACK_RATE_STEP, 1))
t2 = int(round(MidiController.MIN_PLAYBACK_RATE / MidiController.PLAYBACK_RATE_STEP, 1))
lastColumnLit = t1 - t2 + 1
@@ -116,14 +114,14 @@ class MidiController:
self._allLEDsOff()
# volume buttons
- self._updateVolumeRow()
+ self._updateVolumeRow(self._soloTool.getPlaybackVolume())
# playback rate buttons
- self._updateRateRow()
+ self._updateRateRow(self._soloTool.getPlaybackRate())
# playback control
self._setButtonLED(6, 0, MidiController.LED_RED)
- self._updatePlayPauseButton()
+ self._updatePlayPauseButton(self._soloTool.isPlaying())
# AB control
self._setButtonLED(6, 5, MidiController.LED_YELLOW)
diff --git a/notifier.py b/notifier.py
index fc91e8c..06b4434 100644
--- a/notifier.py
+++ b/notifier.py
@@ -17,13 +17,13 @@ class Notifier:
self._callbacks[event] = list()
self._callbacks[event].append(callback)
- def notify(self, event):
+ def notify(self, event, value):
for callback in self._callbacks.get(event, list()):
- callback()
+ callback(value)
def _playingStateChangedCallback(self, *args):
- self.notify(Notifier.PLAYING_STATE_EVENT)
+ self.notify(Notifier.PLAYING_STATE_EVENT, self._player.isPlaying())
def _playbackVolumeChangedCallback(self, *args):
- self.notify(Notifier.PLAYBACK_VOLUME_EVENT)
+ self.notify(Notifier.PLAYBACK_VOLUME_EVENT, self._player.getPlaybackVolume())
diff --git a/notifier_unittest.py b/notifier_unittest.py
index 13f2285..4aff8f4 100644
--- a/notifier_unittest.py
+++ b/notifier_unittest.py
@@ -14,20 +14,24 @@ def uut(mockPlayer):
def test_allEvents(uut):
def checkEvent(uut, event):
callbacks = 2
- calledFlags = [False] * 2
+ calledFlags = [False] * callbacks
+ values = [None] * callbacks
def createCallback(i):
- def cb():
- nonlocal calledFlags
+ def cb(value):
+ nonlocal calledFlags, values
calledFlags[i] = True
+ values[i] = value
+
return cb
for i in range(0, callbacks):
uut.registerCallback(event, createCallback(i))
assert not any(calledFlags)
- uut.notify(event)
+ uut.notify(event, 123)
assert all(calledFlags)
+ assert values == [123] * callbacks
checkEvent(uut, Notifier.PLAYING_STATE_EVENT)
checkEvent(uut, Notifier.PLAYBACK_VOLUME_EVENT)
@@ -36,33 +40,39 @@ def test_allEvents(uut):
checkEvent(uut, Notifier.CURRENT_AB_EVENT)
def test_eventWithoutRegisteredCallbacks(uut):
- uut.notify(Notifier.PLAYING_STATE_EVENT)
+ uut.notify(Notifier.PLAYING_STATE_EVENT, 0)
# expect no crash
def test_eventsWithMockPlayer(uut, mockPlayer):
- def checkEvent(eventCode, simulateEvent):
+ def checkEvent(eventCode, simulateEvent, expectedValue):
called = False
- def callback():
- nonlocal called
+ receivedValue = None
+ def callback(value):
+ nonlocal called, receivedValue
called = True
+ receivedValue = value
uut.registerCallback(eventCode, callback)
assert not called
simulateEvent()
assert called
+ assert receivedValue == expectedValue
+
+ mockPlayer.state = 1
+ mockPlayer.volume = 75
- checkEvent(Notifier.PLAYING_STATE_EVENT, mockPlayer.simulatePlayingStateChanged)
- checkEvent(Notifier.PLAYBACK_VOLUME_EVENT, mockPlayer.simulatePlaybackVolumeChanged)
+ checkEvent(Notifier.PLAYING_STATE_EVENT, mockPlayer.simulatePlayingStateChanged, True)
+ checkEvent(Notifier.PLAYBACK_VOLUME_EVENT, mockPlayer.simulatePlaybackVolumeChanged, 75)
def test_singleEventNotification(uut):
playingStateCalled = False
- def playingStateCallback():
+ def playingStateCallback(value):
nonlocal playingStateCalled
playingStateCalled = True
volumeCalled = False
- def volumeCallback():
+ def volumeCallback(value):
nonlocal volumeCalled
volumeCalled = True
@@ -72,18 +82,18 @@ def test_singleEventNotification(uut):
assert not playingStateCalled
assert not volumeCalled
- uut.notify(Notifier.PLAYING_STATE_EVENT)
+ uut.notify(Notifier.PLAYING_STATE_EVENT, 0)
assert playingStateCalled
assert not volumeCalled
playingStateCalled = False
- uut.notify(Notifier.PLAYBACK_VOLUME_EVENT)
+ uut.notify(Notifier.PLAYBACK_VOLUME_EVENT, 0)
assert not playingStateCalled
assert volumeCalled
volumeCalled = False
- uut.notify(Notifier.PLAYBACK_RATE_EVENT)
+ uut.notify(Notifier.PLAYBACK_RATE_EVENT, 0)
assert not playingStateCalled
assert not volumeCalled
diff --git a/solo_tool.py b/solo_tool.py
index fee7e4a..4ea081d 100644
--- a/solo_tool.py
+++ b/solo_tool.py
@@ -30,22 +30,25 @@ class SoloTool:
self._sessionManager.addSong(path)
def setSong(self, index):
- changed = index != self._playlist.getCurrentSongIndex()
+ previous = self._playlist.getCurrentSongIndex()
self._playlist.setCurrentSong(index)
- if changed:
- self._notifier.notify(Notifier.CURRENT_SONG_EVENT)
+ new = self._playlist.getCurrentSongIndex()
+ if previous != new:
+ self._notifier.notify(Notifier.CURRENT_SONG_EVENT, new)
def nextSong(self):
previous = self._playlist.getCurrentSongIndex()
self._playlist.nextSong()
- if previous != self._playlist.getCurrentSongIndex():
- self._notifier.notify(Notifier.CURRENT_SONG_EVENT)
+ new = self._playlist.getCurrentSongIndex()
+ if previous != new:
+ self._notifier.notify(Notifier.CURRENT_SONG_EVENT, new)
def previousSong(self):
previous = self._playlist.getCurrentSongIndex()
self._playlist.previousSong()
- if previous != self._playlist.getCurrentSongIndex():
- self._notifier.notify(Notifier.CURRENT_SONG_EVENT)
+ new = self._playlist.getCurrentSongIndex()
+ if previous != new:
+ self._notifier.notify(Notifier.CURRENT_SONG_EVENT, new)
def getSongs(self):
return self._playlist.getSongs()
@@ -54,10 +57,11 @@ class SoloTool:
self._abController.storeLimits(aLimit, bLimit)
def loadAbLimits(self, index):
- changed = index != self._abController.getLoadedIndex()
+ previous = self._abController.getLoadedIndex()
self._abController.loadLimits(index)
- if changed:
- self._notifier.notify(Notifier.CURRENT_AB_EVENT)
+ new = self._abController.getLoadedIndex()
+ if previous != new:
+ self._notifier.notify(Notifier.CURRENT_AB_EVENT, new)
def setAbLimits(self, aLimit, bLimit):
self._abController.setLimits(aLimit, bLimit)
@@ -75,14 +79,16 @@ class SoloTool:
def nextStoredAbLimits(self):
previous = self._abController.getLoadedIndex()
self._abController.nextStoredAbLimits()
- if previous != self._abController.getLoadedIndex():
- self._notifier.notify(Notifier.CURRENT_AB_EVENT)
+ new = self._abController.getLoadedIndex()
+ if previous != new:
+ self._notifier.notify(Notifier.CURRENT_AB_EVENT, new)
def previousStoredAbLimits(self):
previous = self._abController.getLoadedIndex()
self._abController.previousStoredAbLimits()
- if previous != self._abController.getLoadedIndex():
- self._notifier.notify(Notifier.CURRENT_AB_EVENT)
+ new = self._abController.getLoadedIndex()
+ if previous != new:
+ self._notifier.notify(Notifier.CURRENT_AB_EVENT, new)
def jumpToA(self):
a = self._abController.getCurrentLimits()[0]
@@ -110,10 +116,11 @@ class SoloTool:
return self._player.isPlaying()
def setPlaybackRate(self, rate):
- previousRate = self._player.getPlaybackRate()
+ previous = self._player.getPlaybackRate()
self._player.setPlaybackRate(rate)
- if previousRate != rate:
- self._notifier.notify(Notifier.PLAYBACK_RATE_EVENT)
+ new = self._player.getPlaybackRate()
+ if previous != new:
+ self._notifier.notify(Notifier.PLAYBACK_RATE_EVENT, new)
def getPlaybackRate(self):
return self._player.getPlaybackRate()
diff --git a/solo_tool_integrationtest.py b/solo_tool_integrationtest.py
index 386cb26..2ee4719 100644
--- a/solo_tool_integrationtest.py
+++ b/solo_tool_integrationtest.py
@@ -335,9 +335,11 @@ def test_playingStateNotification(uut, mockPlayer):
uut.setSong(0)
called = False
- def callback():
- nonlocal called
+ receivedValue = None
+ def callback(value):
+ nonlocal called, receivedValue
called = True
+ receivedValue = value
uut.registerPlayingStateCallback(callback)
@@ -346,22 +348,26 @@ def test_playingStateNotification(uut, mockPlayer):
uut.play()
assert called
+ assert receivedValue == True
called = False
uut.play()
assert not called
uut.pause()
assert called
+ assert receivedValue == False
called = False
uut.pause()
assert not called
uut.play()
assert called
+ assert receivedValue == True
called = False
uut.stop()
assert called
+ assert receivedValue == False
called = False
uut.stop()
assert not called
@@ -372,19 +378,22 @@ def test_playbackVolumeNotification(uut, mockPlayer):
uut.setSong(0)
called = False
- def callback():
- nonlocal called
+ receivedValue = None
+ def callback(value):
+ nonlocal called, receivedValue
called = True
+ receivedValue = value
uut.registerPlaybackVolumeCallback(callback)
assert not called
- uut.setPlaybackVolume(0.0)
+ uut.setPlaybackVolume(0.3)
assert called
+ assert receivedValue == 0.3
called = False
- uut.setPlaybackVolume(0.0)
+ uut.setPlaybackVolume(0.3)
assert not called
def test_playbackRateNotification(uut, mockPlayer):
@@ -393,9 +402,11 @@ def test_playbackRateNotification(uut, mockPlayer):
uut.setSong(0)
called = False
- def callback():
- nonlocal called
+ receivedValue = None
+ def callback(value):
+ nonlocal called, receivedValue
called = True
+ receivedValue = value
uut.registerPlaybackRateCallback(callback)
@@ -403,6 +414,7 @@ def test_playbackRateNotification(uut, mockPlayer):
uut.setPlaybackRate(0.5)
assert called
+ assert receivedValue == 0.5
called = False
uut.setPlaybackRate(0.5)
@@ -410,9 +422,11 @@ def test_playbackRateNotification(uut, mockPlayer):
def test_currentSongNotification(uut):
called = False
- def callback():
- nonlocal called
+ receivedValue = None
+ def callback(value):
+ nonlocal called, receivedValue
called = True
+ receivedValue = value
uut.registerCurrentSongCallback(callback)
assert not called
@@ -426,6 +440,7 @@ def test_currentSongNotification(uut):
uut.setSong(0)
assert called
+ assert receivedValue == 0
called = False
uut.addSong(songs[1])
@@ -436,10 +451,12 @@ def test_currentSongNotification(uut):
uut.setSong(1)
assert called
+ assert receivedValue == 1
called = False
uut.previousSong()
assert called
+ assert receivedValue == 0
called = False
uut.previousSong()
@@ -447,6 +464,7 @@ def test_currentSongNotification(uut):
uut.nextSong()
assert called
+ assert receivedValue == 1
called = False
uut.nextSong()
@@ -454,9 +472,11 @@ def test_currentSongNotification(uut):
def test_currentAbNotification(uut):
called = False
- def callback():
- nonlocal called
+ receivedValue = None
+ def callback(value):
+ nonlocal called, receivedValue
called = True
+ receivedValue = value
uut.registerCurrentAbLimitsCallback(callback)
assert not called
@@ -476,6 +496,7 @@ def test_currentAbNotification(uut):
uut.loadAbLimits(0)
assert called
+ assert receivedValue == 0
called = False
uut.loadAbLimits(0)
@@ -483,10 +504,12 @@ def test_currentAbNotification(uut):
uut.loadAbLimits(1)
assert called
+ assert receivedValue == 1
called = False
uut.previousStoredAbLimits()
assert called
+ assert receivedValue == 0
called = False
uut.previousStoredAbLimits()
@@ -494,6 +517,7 @@ def test_currentAbNotification(uut):
uut.nextStoredAbLimits()
assert called
+ assert receivedValue == 1
called = False
uut.nextStoredAbLimits()
diff --git a/solo_tool_qt.py b/solo_tool_qt.py
index a6823e0..25a15fb 100644
--- a/solo_tool_qt.py
+++ b/solo_tool_qt.py
@@ -41,7 +41,7 @@ class ABListModel(QAbstractListModel):
return len(self.soloTool.getStoredAbLimits())
class MainWindow(QMainWindow, Ui_MainWindow):
- songChangeSignal = pyqtSignal()
+ songChangeSignal = pyqtSignal(int)
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
@@ -170,14 +170,12 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.abListModel.layoutChanged.emit()
self.clearListViewSelection(self.abListView)
- def currentSongChanged(self):
+ def currentSongChanged(self, songIndex):
if self.songChangePending == CHANGE_GUI:
self.songChangePending = None
else:
assert self.songChangePending is None
self.songChangePending = CHANGE_INTERNAL
- # TODO fix this hack
- songIndex = self.soloTool._playlist.getCurrentSongIndex()
print(f"Forcing selection to {songIndex}")
i = self.playlistModel.createIndex(songIndex, 0)
self.songListView.selectionModel().select(i, QItemSelectionModel.ClearAndSelect)