aboutsummaryrefslogtreecommitdiffstats
path: root/solo-tool-project/src/solo_tool/solo_tool.py
blob: 97c3495aeb03980dd1a952513ab45c6ec3cf4b08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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 not None \
           and new >= 0 \
           and new < len(self._songs) \
           and 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 not None and 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 self._song is not None and SoloTool._keyPointValid(new) 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 not None and new >= 0.0 and 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 not None and new >= 0.0 and 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:
        # TODO stop playback before changing position?
        if new is not None and new != self._player.getPlaybackPosition():
            self._player.setPlaybackPosition(min(max(0.0, new), 1.0))

    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)