import os from .session_manager import loadSession, saveSession from .notifier import Notifier from .player_vlc import Player class SoloTool: def __init__(self, playerOverride=None): self._player = Player() if playerOverride is None else playerOverride self._notifier = Notifier(self._player) self._songs = [] self._song = None self._keyPoints = [] self._keyPoint = None def _updateSong(self, index): self._song = index path = self._songs[index] self._player.setCurrentSong(path) self._notifier.notify(Notifier.CURRENT_SONG_EVENT, index) self._keyPoint = 0.0 @staticmethod def _keyPointValid(kp: float) -> bool: return kp is not None and kp >= 0.0 and kp < 1.0 @property def songs(self) -> list[str]: return self._songs.copy() def addSong(self, path: str) -> None: if not os.path.isfile(path): raise FileNotFoundError() self._songs.append(path) self._keyPoints.append([]) @property def song(self) -> int: return self._song @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: self._updateSong(new) @property def keyPoints(self) -> list[float]: if self._song is None: return None return self._keyPoints[self._song] @keyPoints.setter def keyPoints(self, new: list[float]) -> None: if new is None: raise ValueError() if self._song is not None: sanitized = sorted(list(set([p for p in new if SoloTool._keyPointValid(p)]))) self._keyPoints[self._song] = sanitized @property def keyPoint(self) -> float: return self._keyPoint @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: self._keyPoint = new self._notifier.notify(Notifier.CURRENT_KEY_POINT_EVENT, new) def play(self): self._player.play() def pause(self): self._player.pause() def stop(self): self._player.stop() def isPlaying(self): return self._player.isPlaying() def jump(self): self._player.setPlaybackPosition(self._keyPoint) @property def rate(self) -> float: return self._player.getPlaybackRate() @rate.setter def rate(self, new: float) -> None: if new is None or new <= 0.0: raise ValueError() if new != self._player.getPlaybackRate(): self._player.setPlaybackRate(new) self._notifier.notify(Notifier.PLAYBACK_RATE_EVENT, new) @property def volume(self) -> float: return self._player.getPlaybackVolume() @volume.setter def volume(self, new: float) -> None: if new is None or new < 0.0: raise ValueError() if new != self._player.getPlaybackVolume(): self._player.setPlaybackVolume(new) self._notifier.notify(Notifier.PLAYBACK_VOLUME_EVENT, new) @property def position(self) -> float: return self._player.getPlaybackPosition() @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) def registerPlayingStateCallback(self, callback): self._notifier.registerCallback(Notifier.PLAYING_STATE_EVENT, callback) def registerVolumeCallback(self, callback): self._notifier.registerCallback(Notifier.PLAYBACK_VOLUME_EVENT, callback) def registerRateCallback(self, callback): self._notifier.registerCallback(Notifier.PLAYBACK_RATE_EVENT, callback) def registerCurrentSongCallback(self, callback): self._notifier.registerCallback(Notifier.CURRENT_SONG_EVENT, callback) def registerCurrentKeyPointCallback(self, callback): self._notifier.registerCallback(Notifier.CURRENT_KEY_POINT_EVENT, callback)