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
|
import os
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)
|