aboutsummaryrefslogtreecommitdiffstats
path: root/solo-tool-project/src/solo_tool
diff options
context:
space:
mode:
Diffstat (limited to 'solo-tool-project/src/solo_tool')
-rw-r--r--solo-tool-project/src/solo_tool/abcontroller.py82
-rw-r--r--solo-tool-project/src/solo_tool/notifier.py3
-rw-r--r--solo-tool-project/src/solo_tool/solo_tool.py167
3 files changed, 77 insertions, 175 deletions
diff --git a/solo-tool-project/src/solo_tool/abcontroller.py b/solo-tool-project/src/solo_tool/abcontroller.py
deleted file mode 100644
index cec9fb2..0000000
--- a/solo-tool-project/src/solo_tool/abcontroller.py
+++ /dev/null
@@ -1,82 +0,0 @@
-from collections import namedtuple
-
-_AB = namedtuple("_AB", ["a", "b"])
-
-class ABController:
- def __init__(self, enabled=True, callback=None):
- self._setPositionCallback = callback
- self._limits = {} # dictionary of all songs
- self._songLimits = None # list of limits for selected song
- self._currentLimits = _AB(0.0, 0.0) # a/b positions of active limit
- self._loadedIndex = None
- self._enabled = enabled
-
- def _ensureSongExists(self, path):
- if path not in self._limits:
- self._limits[path] = []
-
- def setCurrentSong(self, path):
- self._ensureSongExists(path)
- self._songLimits = self._limits[path]
- self._loadedIndex = None
-
- def storeLimits(self, aLimit, bLimit, song=None):
- if song is not None:
- self._ensureSongExists(song)
- songLimits = self._limits[song]
- else:
- songLimits = self._songLimits
-
- if songLimits is None:
- return
-
- ab = _AB(aLimit, bLimit)
- songLimits.append(ab)
-
- def loadLimits(self, index):
- if not self._songLimits:
- return
-
- if index >= 0 and index < len(self._songLimits):
- self._currentLimits = self._songLimits[index]
- self._loadedIndex = index
-
- def nextStoredAbLimits(self):
- if self._loadedIndex is None:
- nextIndex = 0
- else:
- nextIndex = self._loadedIndex + 1
- self.loadLimits(nextIndex)
-
- def previousStoredAbLimits(self):
- if self._loadedIndex is None:
- previousIndex = 0
- else:
- previousIndex = self._loadedIndex - 1
- self.loadLimits(previousIndex)
-
- def setLimits(self, aLimit, bLimit):
- self._currentLimits = _AB(aLimit, bLimit)
- self._loadedIndex = None
-
- def positionChanged(self, position):
- if position > self._currentLimits.b and self._setPositionCallback and self._enabled:
- self._setPositionCallback(self._currentLimits.a)
-
- def setEnable(self, enable):
- self._enabled = enable
-
- def isEnabled(self):
- return self._enabled
-
- def getStoredLimits(self, song):
- return self._limits.get(song)
-
- def getCurrentLimits(self):
- return self._currentLimits
-
- def getLoadedIndex(self):
- return self._loadedIndex
-
- def clear(self):
- self.__init__(enabled=self._enabled, callback=self._setPositionCallback)
diff --git a/solo-tool-project/src/solo_tool/notifier.py b/solo-tool-project/src/solo_tool/notifier.py
index 9f445b6..73b84b7 100644
--- a/solo-tool-project/src/solo_tool/notifier.py
+++ b/solo-tool-project/src/solo_tool/notifier.py
@@ -3,8 +3,7 @@ class Notifier:
PLAYBACK_VOLUME_EVENT = 1
PLAYBACK_RATE_EVENT = 2
CURRENT_SONG_EVENT = 3
- CURRENT_AB_EVENT = 4
- AB_LIMIT_ENABLED_EVENT = 5
+ CURRENT_KEY_POINT_EVENT = 3
def __init__(self, player):
self._callbacks = dict()
diff --git a/solo-tool-project/src/solo_tool/solo_tool.py b/solo-tool-project/src/solo_tool/solo_tool.py
index a4c7af8..884721b 100644
--- a/solo-tool-project/src/solo_tool/solo_tool.py
+++ b/solo-tool-project/src/solo_tool/solo_tool.py
@@ -1,6 +1,5 @@
import os
-from .abcontroller import ABController
from .session_manager import loadSession, saveSession
from .notifier import Notifier
from .player_vlc import Player
@@ -8,32 +7,32 @@ from .player_vlc import Player
class SoloTool:
def __init__(self, playerOverride=None):
self._player = Player() if playerOverride is None else playerOverride
- self._abController = ABController(enabled=False, callback=self._abControllerCallback)
self._notifier = Notifier(self._player)
- self._songList = []
+ self._songs = []
self._song = None
+ self._keyPoints = []
+ self._keyPoint = None
def _updateSong(self, index):
self._song = index
- path = self._songList[index]
+ path = self._songs[index]
self._player.setCurrentSong(path)
- self._abController.setCurrentSong(path)
self._notifier.notify(Notifier.CURRENT_SONG_EVENT, index)
+ self._keyPoint = 0.0
- def _abControllerCallback(self, position):
- self._player.setPlaybackPosition(position)
-
- def tick(self):
- position = self._player.getPlaybackPosition()
- self._abController.positionChanged(position)
+ @staticmethod
+ def _keyPointValid(kp: float) -> bool:
+ return kp is not None and kp >= 0.0 and kp < 1.0
@property
- def songList(self) -> list[str]:
- return self._songList
+ def songs(self) -> list[str]:
+ return self._songs.copy()
def addSong(self, path: str) -> None:
- if os.path.isfile(path):
- self._songList.append(path)
+ if not os.path.isfile(path):
+ raise FileNotFoundError()
+ self._songs.append(path)
+ self._keyPoints.append([])
@property
def song(self) -> int:
@@ -41,64 +40,36 @@ class SoloTool:
@song.setter
def song(self, new: int) -> None:
- if new >= 0 and new < len(self._songList) and new != self._song:
+ if new is None or new < 0 or new >= len(self._songs):
+ raise ValueError()
+ if new != self._song:
self._updateSong(new)
- def storeAbLimits(self, aLimit, bLimit):
- self._abController.storeLimits(aLimit, bLimit)
+ @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
- def loadAbLimits(self, index):
- previous = self._abController.getLoadedIndex()
- self._abController.loadLimits(index)
- 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)
+ @property
+ def keyPoint(self) -> float:
+ return self._keyPoint
- def getStoredAbLimits(self):
- if self._song is not None:
- return self._abController.getStoredLimits(self.songList[self._song])
- else:
- return list()
-
- def setAbLimitEnable(self, enable):
- previous = self._abController.isEnabled()
- self._abController.setEnable(enable)
- new = self._abController.isEnabled()
- if previous != new:
- self._notifier.notify(Notifier.AB_LIMIT_ENABLED_EVENT, new)
-
- def isAbLimitEnabled(self):
- return self._abController.isEnabled()
-
- def nextStoredAbLimits(self):
- previous = self._abController.getLoadedIndex()
- self._abController.nextStoredAbLimits()
- 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()
- new = self._abController.getLoadedIndex()
- if previous != new:
- self._notifier.notify(Notifier.CURRENT_AB_EVENT, new)
-
- def jumpToA(self):
- a = self._abController.getCurrentLimits()[0]
- # XXX assumes that player.setPlaybackPosition is thread-safe!
- self._player.setPlaybackPosition(a)
-
- def loadSession(self, path):
- with open(path, "r") as f:
- loadSession(f, self._songList, self._abController)
-
- def saveSession(self, path):
- with open(path, "w") as f:
- saveSession(f, self._songList, self._abController)
+ @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()
@@ -112,43 +83,57 @@ class SoloTool:
def isPlaying(self):
return self._player.isPlaying()
- def setPlaybackRate(self, rate):
- previous = self._player.getPlaybackRate()
- self._player.setPlaybackRate(rate)
- new = self._player.getPlaybackRate()
- if previous != new:
- self._notifier.notify(Notifier.PLAYBACK_RATE_EVENT, new)
+ def jump(self):
+ self._player.setPlaybackPosition(self._keyPoint)
- def getPlaybackRate(self):
+ @property
+ def rate(self) -> float:
return self._player.getPlaybackRate()
- def setPlaybackPosition(self, position):
- self._player.setPlaybackPosition(position)
+ @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()
- def getPlaybackPosition(self):
- return self._player.getPlaybackPosition()
+ @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)
- def setPlaybackVolume(self, volume):
- self._player.setPlaybackVolume(volume)
+ @property
+ def position(self) -> float:
+ return self._player.getPlaybackPosition()
- def getPlaybackVolume(self):
- return self._player.getPlaybackVolume()
+ @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 registerPlaybackVolumeCallback(self, callback):
+ def registerVolumeCallback(self, callback):
self._notifier.registerCallback(Notifier.PLAYBACK_VOLUME_EVENT, callback)
- def registerPlaybackRateCallback(self, 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 registerCurrentAbLimitsCallback(self, callback):
- self._notifier.registerCallback(Notifier.CURRENT_AB_EVENT, callback)
-
- def registerAbLimitEnabledCallback(self, callback):
- self._notifier.registerCallback(Notifier.AB_LIMIT_ENABLED_EVENT, callback)
+ def registerCurrentKeyPointCallback(self, callback):
+ self._notifier.registerCallback(Notifier.CURRENT_KEY_POINT_EVENT, callback)