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