aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--notifier.py15
-rw-r--r--notifier_unittest.py32
-rw-r--r--solo_tool.py17
-rw-r--r--solo_tool_integrationtest.py37
4 files changed, 97 insertions, 4 deletions
diff --git a/notifier.py b/notifier.py
new file mode 100644
index 0000000..1a68c56
--- /dev/null
+++ b/notifier.py
@@ -0,0 +1,15 @@
+
+class Notifier:
+ PLAYING_STATE_EVENT = 0
+
+ def __init__(self):
+ self._callbacks = dict()
+
+ def registerCallback(self, event, callback):
+ if event not in self._callbacks:
+ self._callbacks[event] = list()
+ self._callbacks[event].append(callback)
+
+ def notify(self, event):
+ for callback in self._callbacks.get(event, list()):
+ callback()
diff --git a/notifier_unittest.py b/notifier_unittest.py
new file mode 100644
index 0000000..721a5fd
--- /dev/null
+++ b/notifier_unittest.py
@@ -0,0 +1,32 @@
+import pytest
+
+from notifier import Notifier
+
+@pytest.fixture
+def uut():
+ return Notifier()
+
+def checkEvent(uut, event):
+ callbacks = 2
+ calledFlags = [False] * 2
+
+ def createCallback(i):
+ def cb():
+ nonlocal calledFlags
+ calledFlags[i] = True
+ return cb
+
+ for i in range(0, callbacks):
+ uut.registerCallback(event, createCallback(i))
+
+ assert not any(calledFlags)
+ uut.notify(event)
+ assert all(calledFlags)
+
+def test_allEvents(uut):
+ checkEvent(uut, Notifier.PLAYING_STATE_EVENT)
+
+def test_eventWithoutRegisteredCallbacks(uut):
+ uut.notify(Notifier.PLAYING_STATE_EVENT)
+ # expect no crash
+
diff --git a/solo_tool.py b/solo_tool.py
index 6581f5e..5e3a1fd 100644
--- a/solo_tool.py
+++ b/solo_tool.py
@@ -3,6 +3,7 @@ import os
from playlist import Playlist
from abcontroller import ABController
from session_manager import SessionManager
+from notifier import Notifier
from player_vlc import Player
class SoloTool:
@@ -11,6 +12,7 @@ class SoloTool:
self._playlist = Playlist(self._playlistCallback)
self._abController = ABController(enabled=False, callback=self._abControllerCallback)
self._sessionManager = SessionManager(self._playlist, self._abController)
+ self._notifier = Notifier()
def _playlistCallback(self, path):
self._player.setCurrentSong(path)
@@ -78,13 +80,19 @@ class SoloTool:
self._sessionManager.saveSession(f)
def play(self):
- self._player.play()
+ self._playerCommand(self._player.play)
def pause(self):
- self._player.pause()
+ self._playerCommand(self._player.pause)
def stop(self):
- self._player.stop()
+ self._playerCommand(self._player.stop)
+
+ def _playerCommand(self, f):
+ playing = self.isPlaying()
+ f()
+ if playing != self.isPlaying():
+ self._notifier.notify(Notifier.PLAYING_STATE_EVENT)
def isPlaying(self):
return self._player.isPlaying()
@@ -101,3 +109,6 @@ class SoloTool:
def setPlaybackVolume(self, volume):
self._player.setPlaybackVolume(volume)
+ def registerPlayingStateCallback(self, callback):
+ self._notifier.registerCallback(Notifier.PLAYING_STATE_EVENT, callback)
+
diff --git a/solo_tool_integrationtest.py b/solo_tool_integrationtest.py
index 6022454..117e539 100644
--- a/solo_tool_integrationtest.py
+++ b/solo_tool_integrationtest.py
@@ -311,7 +311,6 @@ def test_setTemporaryLimits(uut, mockPlayer):
assert mockPlayer.position == abLimits[1][0]
def test_jumpToA(uut, mockPlayer):
- song = "test.flac"
abLimits = (0.2, 0.4)
initialPosition = 0.8
@@ -324,3 +323,39 @@ def test_jumpToA(uut, mockPlayer):
uut.jumpToA()
assert mockPlayer.position == abLimits[0]
+def test_playingStateNotification(uut, mockPlayer):
+ song = "test.flac"
+ uut.addSong(song)
+ uut.setSong(0)
+
+ called = False
+ def callback():
+ nonlocal called
+ called = True
+
+ uut.registerPlayingStateCallback(callback)
+
+ assert mockPlayer.state == MockPlayer.STOPPED
+ assert not called
+
+ uut.play()
+ assert called
+ called = False
+ uut.play()
+ assert not called
+
+ uut.pause()
+ assert called
+ called = False
+ uut.pause()
+ assert not called
+
+ uut.play()
+ assert called
+ called = False
+
+ uut.stop()
+ assert called
+ called = False
+ uut.stop()
+ assert not called