From 6b23d5fef7ab1a936e133d620bd277274882b3a7 Mon Sep 17 00:00:00 2001 From: Eddy Pedroni Date: Mon, 3 Jan 2022 20:29:51 +0100 Subject: Added playing state callback to player, refactored notifier to use it --- midi_launchpad_mini_integrationtest.py | 16 ++++++++-------- notifier.py | 7 ++++++- notifier_unittest.py | 22 +++++++++++++++++++--- player_mock.py | 15 +++++++++++++++ player_vlc.py | 11 +++++++++++ solo_tool.py | 14 ++++---------- 6 files changed, 63 insertions(+), 22 deletions(-) diff --git a/midi_launchpad_mini_integrationtest.py b/midi_launchpad_mini_integrationtest.py index 0bb9a82..c10a3f5 100644 --- a/midi_launchpad_mini_integrationtest.py +++ b/midi_launchpad_mini_integrationtest.py @@ -94,21 +94,21 @@ def test_startPauseButtonLed(uut, midiWrapperMock, playerMock, soloTool): assert playerMock.state == PlayerMock.STOPPED - soloTool.play() - assert playerMock.state == PlayerMock.PLAYING + playerMock.state = PlayerMock.PLAYING + playerMock.simulatePlayingStateChanged() assert midiWrapperMock.getLatestMessage() == (playPauseButton, MidiController.LED_GREEN, 0) - soloTool.stop() - assert playerMock.state == PlayerMock.STOPPED + playerMock.state = PlayerMock.STOPPED + playerMock.simulatePlayingStateChanged() assert midiWrapperMock.getLatestMessage() == (playPauseButton, MidiController.LED_YELLOW, 0) - soloTool.pause() + playerMock.state = PlayerMock.PAUSED + playerMock.simulatePlayingStateChanged() assert midiWrapperMock.getLatestMessage() == (playPauseButton, MidiController.LED_YELLOW, 0) - assert playerMock.state == PlayerMock.PAUSED - soloTool.play() + playerMock.state = PlayerMock.PLAYING + playerMock.simulatePlayingStateChanged() assert midiWrapperMock.getLatestMessage() == (playPauseButton, MidiController.LED_GREEN, 0) - assert playerMock.state == PlayerMock.PLAYING def test_jumpToAButton(uut, midiWrapperMock, soloTool, playerMock): ab = (0.5, 0.6) diff --git a/notifier.py b/notifier.py index 1a68c56..e052b5c 100644 --- a/notifier.py +++ b/notifier.py @@ -2,8 +2,10 @@ class Notifier: PLAYING_STATE_EVENT = 0 - def __init__(self): + def __init__(self, player): self._callbacks = dict() + self._player = player + self._player.setPlayingStateChangedCallback(self._playingStateChangedCallback) def registerCallback(self, event, callback): if event not in self._callbacks: @@ -13,3 +15,6 @@ class Notifier: def notify(self, event): for callback in self._callbacks.get(event, list()): callback() + + def _playingStateChangedCallback(self, *args): + self.notify(Notifier.PLAYING_STATE_EVENT) diff --git a/notifier_unittest.py b/notifier_unittest.py index 721a5fd..b840c16 100644 --- a/notifier_unittest.py +++ b/notifier_unittest.py @@ -1,10 +1,15 @@ import pytest from notifier import Notifier +from player_mock import Player @pytest.fixture -def uut(): - return Notifier() +def mockPlayer(): + return Player() + +@pytest.fixture +def uut(mockPlayer): + return Notifier(mockPlayer) def checkEvent(uut, event): callbacks = 2 @@ -29,4 +34,15 @@ def test_allEvents(uut): def test_eventWithoutRegisteredCallbacks(uut): uut.notify(Notifier.PLAYING_STATE_EVENT) # expect no crash - + +def test_playingStateEventWithMockPlayer(uut, mockPlayer): + called = False + def callback(): + nonlocal called + called = True + + uut.registerCallback(Notifier.PLAYING_STATE_EVENT, callback) + + assert not called + mockPlayer.simulatePlayingStateChanged() + assert called diff --git a/player_mock.py b/player_mock.py index 5aad769..92da675 100644 --- a/player_mock.py +++ b/player_mock.py @@ -9,15 +9,25 @@ class Player(): self.position = 0.0 self.volume = 1.0 self.currentSong = None + self.playingStateChangedCallback = None def play(self): + previousState = self.state self.state = Player.PLAYING + if previousState != Player.PLAYING: + self.playingStateChangedCallback() def stop(self): + previousState = self.state self.state = Player.STOPPED + if previousState != Player.STOPPED: + self.playingStateChangedCallback() def pause(self): + previousState = self.state self.state = Player.PAUSED + if previousState != Player.PAUSED: + self.playingStateChangedCallback() def isPlaying(self): return self.state == Player.PLAYING @@ -43,3 +53,8 @@ class Player(): def setCurrentSong(self, path): self.currentSong = path + def setPlayingStateChangedCallback(self, callback): + self.playingStateChangedCallback = callback + + def simulatePlayingStateChanged(self): + self.playingStateChangedCallback() diff --git a/player_vlc.py b/player_vlc.py index c0eadf9..9f8bb56 100644 --- a/player_vlc.py +++ b/player_vlc.py @@ -38,3 +38,14 @@ class Player: def setCurrentSong(self, path): media = vlc.Media(path) self._player.set_media(media) + + def setPlayingStateChangedCallback(self, callback): + events = [ + vlc.EventType.MediaPlayerStopped, + vlc.EventType.MediaPlayerPlaying, + vlc.EventType.MediaPlayerPaused + ] + manager = self._player.event_manager() + for e in events: + manager.event_attach(e, callback) + self._playingStateChangedCallback = callback diff --git a/solo_tool.py b/solo_tool.py index 5e3a1fd..f52e074 100644 --- a/solo_tool.py +++ b/solo_tool.py @@ -12,7 +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() + self._notifier = Notifier(self._player) def _playlistCallback(self, path): self._player.setCurrentSong(path) @@ -80,19 +80,13 @@ class SoloTool: self._sessionManager.saveSession(f) def play(self): - self._playerCommand(self._player.play) + self._player.play() def pause(self): - self._playerCommand(self._player.pause) + self._player.pause() def stop(self): - self._playerCommand(self._player.stop) - - def _playerCommand(self, f): - playing = self.isPlaying() - f() - if playing != self.isPlaying(): - self._notifier.notify(Notifier.PLAYING_STATE_EVENT) + self._player.stop() def isPlaying(self): return self._player.isPlaying() -- cgit v1.2.3