diff options
author | Eddy Pedroni <epedroni@pm.me> | 2025-07-17 23:24:15 +0200 |
---|---|---|
committer | Eddy Pedroni <epedroni@pm.me> | 2025-07-17 23:24:15 +0200 |
commit | 748f056faf16b08ac41de991b1aeb664f2b86d8e (patch) | |
tree | 451b807a1abd54f99057070423eda6f49f8511ab /solo-tool-project | |
parent | 7fb8e255e2e1cc912b029a5715db5b92258293b6 (diff) |
Diffstat (limited to 'solo-tool-project')
5 files changed, 113 insertions, 11 deletions
diff --git a/solo-tool-project/src/solo_tool/session_manager.py b/solo-tool-project/src/solo_tool/session_manager.py index 1575060..8624207 100644 --- a/solo-tool-project/src/solo_tool/session_manager.py +++ b/solo-tool-project/src/solo_tool/session_manager.py @@ -30,10 +30,10 @@ class SessionManager(): st = SoloTool(player=player) for i, entry in enumerate(session): songPath = entry["path"] - keyPoints = entry["key_points"] + keyPoints = entry.get("key_points", []) + volume = entry.get("vol", 1.0) - st.addSong(songPath) - st._keyPoints[i] = keyPoints + st.addSong(songPath, keyPoints=keyPoints, volume=volume) return st @@ -43,7 +43,8 @@ class SessionManager(): for i, song in enumerate(soloTool.songs): entry = { "path": song, - "key_points" : soloTool._keyPoints[i] + "key_points" : soloTool._keyPoints[i], + "vol" : soloTool._volumes[i] } session.append(entry) diff --git a/solo-tool-project/src/solo_tool/solo_tool.py b/solo-tool-project/src/solo_tool/solo_tool.py index 63fb7f9..e8474e6 100644 --- a/solo-tool-project/src/solo_tool/solo_tool.py +++ b/solo-tool-project/src/solo_tool/solo_tool.py @@ -11,6 +11,7 @@ class SoloTool: self._song = None self._keyPoints = [] self._keyPoint = None + self._volumes = [] def __del__(self): del self._player @@ -30,6 +31,8 @@ class SoloTool: if previousSong is None or self._keyPoints[previousSong] != self._keyPoints[index]: self._notifier.notify(Notifier.KEY_POINT_LIST_EVENT, self.keyPoints) + self.volume = self._volumes[index] + @staticmethod def _keyPointValid(kp: float) -> bool: return kp is not None and kp >= 0.0 and kp < 1.0 @@ -38,11 +41,12 @@ class SoloTool: def songs(self) -> list[str]: return self._songs.copy() - def addSong(self, path: str) -> None: + def addSong(self, path: str, keyPoints: list[float]=[], volume: float=1.0) -> None: if path in self._songs: return self._songs.append(path) - self._keyPoints.append([]) + self._keyPoints.append(keyPoints) + self._volumes.append(volume) self._notifier.notify(Notifier.SONG_LIST_EVENT, self.songs) if self.song is None: self.song = 0 @@ -112,6 +116,8 @@ class SoloTool: @volume.setter def volume(self, new: float) -> None: if new is not None and new >= 0.0 and new != self._player.getPlaybackVolume(): + if self._song is not None: + self._volumes[self._song] = new self._player.setPlaybackVolume(new) self._notifier.notify(Notifier.PLAYBACK_VOLUME_EVENT, new) diff --git a/solo-tool-project/test/session_manager_unittest.py b/solo-tool-project/test/session_manager_unittest.py index bf0d8d9..5786b23 100644 --- a/solo-tool-project/test/session_manager_unittest.py +++ b/solo-tool-project/test/session_manager_unittest.py @@ -10,7 +10,8 @@ def testSessionFile(sessionPath, testSongs): contents = """[ { "path" : "test.flac", - "key_points" : [] + "key_points" : [], + "vol" : 0.5 }, { "path" : "test.mp3", @@ -35,24 +36,29 @@ def test_loadSession(sessionManager, mockPlayer, testSessionFile): soloTool.song = 0 assert soloTool.keyPoints == [] + assert soloTool.volume == 0.5 soloTool.song = 1 assert soloTool.keyPoints == [0.1, 0.3] + assert soloTool.volume == 1.0 def test_saveSession(sessionManager, soloTool, testSessionFile, sessionPath): soloTool.addSong("test.flac") + soloTool.volume = 0.5 + soloTool.addSong("test.mp3") soloTool.song = 1 soloTool.keyPoints = [0.1, 0.3] - sessionKey = "test_session_saved" - sessionManager.saveSession(soloTool, sessionKey) + sessionId = "test_session_saved" + sessionManager.saveSession(soloTool, sessionId) - with open(sessionPath / f"{sessionKey}.json", "r") as f: + with open(sessionPath / f"{sessionId}.json", "r") as f: savedSession = loads(f.read()) with open(testSessionFile, "r") as f: testSession = loads(f.read()) + testSession[1]["vol"] = 1.0 # Needed to handle default behaviour when vol is missing assert savedSession == testSession diff --git a/solo-tool-project/test/solo_tool_integrationtest.py b/solo-tool-project/test/solo_tool_integrationtest.py index b92cd85..e5745bb 100644 --- a/solo-tool-project/test/solo_tool_integrationtest.py +++ b/solo-tool-project/test/solo_tool_integrationtest.py @@ -1,6 +1,6 @@ from fixtures import soloTool as uut, mockPlayer, testSongs -def test_playerControls(uut, mockPlayer): +def test_playerControls(uut, mockPlayer, testSongs): assert not mockPlayer.playing assert not uut.playing uut.play() @@ -130,6 +130,41 @@ def test_playbackVolumeNotification(uut, mockPlayer, testSongs): uut.volume = 0.3 assert not called + # Volume can also change when the song changes + uut.addSong(testSongs[1]) + uut.song = 1 + assert called + assert receivedValue == 1.0 + called = False + + uut.volume = 0.3 + assert called + assert receivedValue == 0.3 + called = False + + uut.song = 0 + assert not called + +def test_playbackVolumeNotificationBeforeFirstSong(uut, mockPlayer, testSongs): + called = False + receivedValue = None + def callback(value): + nonlocal called, receivedValue + called = True + receivedValue = value + + uut.registerVolumeCallback(callback) + assert not called + + uut.volume = 0.3 + assert called + assert receivedValue == 0.3 + called = False + + uut.addSong(testSongs[0]) + assert called + assert receivedValue == 1.0 + def test_playbackRateNotification(uut, mockPlayer, testSongs): uut.addSong(testSongs[0]) diff --git a/solo-tool-project/test/solo_tool_volume_integrationtest.py b/solo-tool-project/test/solo_tool_volume_integrationtest.py new file mode 100644 index 0000000..cc1aeef --- /dev/null +++ b/solo-tool-project/test/solo_tool_volume_integrationtest.py @@ -0,0 +1,54 @@ +import pytest + +from fixtures import soloTool as uut, mockPlayer, testSongs + +def test_perSongVolumeFlow(uut, mockPlayer, testSongs): + # Before a song is added, the volume starts at 100% + assert uut.song is None + assert mockPlayer.currentSong == None + assert uut.volume == 1.0 + assert mockPlayer.volume == 1.0 + + # When songs are added, their volume starts at 100% + uut.addSong(testSongs[0]) + assert uut.song == 0 + assert uut.volume == 1.0 + assert mockPlayer.volume == 1.0 + + # It's possible to change the volume + uut.volume = 0.5 + assert uut.volume == 0.5 + assert mockPlayer.volume == 0.5 + + # New song song is added, volume stays because the new song is not selected + uut.addSong(testSongs[1]) + assert uut.song == 0 + assert uut.volume == 0.5 + assert mockPlayer.volume == 0.5 + + # Select new song, volume is 100% + uut.song = 1 + assert uut.volume == 1.0 + assert mockPlayer.volume == 1.0 + + uut.volume = 0.75 + + # Previous song retains its volume + uut.song = 0 + assert uut.volume == 0.5 + assert mockPlayer.volume == 0.5 + + # New song also + uut.song = 1 + assert uut.volume == 0.75 + assert mockPlayer.volume == 0.75 + +def test_perSongVolumeEdgeCases(uut, mockPlayer, testSongs): + # If the player volume is not 100% when the first song is added, it is set to 100% + uut.volume = 0.5 + assert mockPlayer.volume == 0.5 + + uut.addSong(testSongs[0]) + assert uut.volume == 1.0 + assert mockPlayer.volume == 1.0 + |