Add pause support, as well as "true" position

This commit is contained in:
Matthew Stratford 2020-10-30 19:31:18 +00:00
parent 9a9f9ad234
commit dc4f1bb14b
No known key found for this signature in database
GPG key ID: 5F50E4308A3416E8
2 changed files with 75 additions and 40 deletions

110
player.py
View file

@ -1,3 +1,9 @@
# This is the player. Reliability is critical here, so we're catching
# literally every exception possible and handling it.
# It is key that whenever the parent server tells us to do something
# that we respond with something, FAIL or OKAY. The server doesn't like to be kept waiting.
from queue import Empty from queue import Empty
import multiprocessing import multiprocessing
import setproctitle import setproctitle
@ -22,8 +28,11 @@ class Player():
"filename": "", "filename": "",
"channel": -1, "channel": -1,
"playing": False, "playing": False,
"paused": False,
"loaded": False, "loaded": False,
"pos": 0, "pos": 0,
"pos_offset": 0,
"pos_true": 0,
"remaining": 0, "remaining": 0,
"length": 0, "length": 0,
"loop": False, "loop": False,
@ -42,9 +51,13 @@ class Player():
@property @property
def isPlaying(self): def isPlaying(self):
if self.isInit: if self.isInit:
return bool(mixer.music.get_busy()) return (not self.isPaused) and bool(mixer.music.get_busy())
return False return False
@property
def isPaused(self):
return self.state.state["paused"]
@property @property
def isLoaded(self): def isLoaded(self):
if not self.state.state["filename"]: if not self.state.state["filename"]:
@ -66,9 +79,9 @@ class Player():
pass pass
return False return False
if position > 0: if position > 0:
mixer.music.pause() self.pause()
else: else:
mixer.music.stop() self.stop()
mixer.music.set_volume(1) mixer.music.set_volume(1)
return True return True
@ -77,58 +90,66 @@ class Player():
res = json.dumps(self.state.state) res = json.dumps(self.state.state)
return res return res
def play(self): def play(self, pos=0):
if not self.isPlaying: # if not self.isPlaying:
try: try:
mixer.music.play(0) mixer.music.play(0, pos)
except: self.state.update("pos_offset", pos)
return False except:
return False
return True self.state.update("paused", False)
return False return True
# return False
def pause(self): def pause(self):
if self.isPlaying: # if self.isPlaying:
try:
mixer.music.pause()
except:
return False
return True try:
return False mixer.music.pause()
except:
return False
self.state.update("paused", True)
return True
# return False
def unpause(self): def unpause(self):
if not self.isPlaying: if not self.isPlaying:
try: try:
mixer.music.play(0, self.state.state["pos"]) self.play(self.state.state["pos_true"])
except: except:
return False return False
self.state.update("paused", False)
return True return True
return False return False
def stop(self): def stop(self):
if self.isPlaying: # if self.isPlaying or self.isPaused:
try: try:
mixer.music.stop() mixer.music.stop()
except: except:
return False return False
self.state.update("pos", 0)
return True self.state.update("pos_offset", 0)
return False self.state.update("pos_true", 0)
self.state.update("paused", False)
return True
# return False
def seek(self, pos): def seek(self, pos):
if self.isPlaying: if self.isPlaying:
try: try:
mixer.music.play(0, pos) self.play(pos)
except: except:
return False return False
return True return True
else:
return False self.state.update("paused", True)
self._updateState(pos=pos)
return True
def load(self, filename): def load(self, filename):
if not self.isPlaying: if not self.isPlaying:
self.unload()
self.state.update("filename", filename) self.state.update("filename", filename)
@ -153,6 +174,7 @@ class Player():
if not self.isPlaying: if not self.isPlaying:
try: try:
mixer.music.unload() mixer.music.unload()
self.state.update("paused", False)
self.state.update("filename", "") self.state.update("filename", "")
except: except:
return False return False
@ -160,6 +182,7 @@ class Player():
def quit(self): def quit(self):
mixer.quit() mixer.quit()
self.state.update("paused", False)
def output(self, name=None): def output(self, name=None):
self.quit() self.quit()
@ -178,13 +201,20 @@ class Player():
def _updateState(self, pos=None): def _updateState(self, pos=None):
self.state.update("initialised", self.isInit) self.state.update("initialised", self.isInit)
if self.isInit: if self.isInit:
# TODO: get_pos returns the time since the player started playing
# This is NOT the same as the position through the song.
if self.isPlaying:
# Get one last update in, incase we're about to pause/stop it.
self.state.update("pos", max(0, mixer.music.get_pos()/1000))
self.state.update("playing", self.isPlaying) self.state.update("playing", self.isPlaying)
self.state.update("loaded", self.isLoaded) self.state.update("loaded", self.isLoaded)
if (pos): if (pos):
self.state.update("pos", max(0, pos)) self.state.update("pos", max(0, pos))
else:
self.state.update("pos", max(0, mixer.music.get_pos()/1000)) self.state.update("pos_true", self.state.state["pos"] + self.state.state["pos_offset"])
self.state.update("remaining", self.state.state["length"] - self.state.state["pos"])
self.state.update("remaining", self.state.state["length"] - self.state.state["pos_true"])
def _retMsg(self, msg, okay_str=False): def _retMsg(self, msg, okay_str=False):
response = self.last_msg + ":" response = self.last_msg + ":"
@ -223,9 +253,9 @@ class Player():
print("Loading filename: " + loaded_state["filename"]) print("Loading filename: " + loaded_state["filename"])
self.load(loaded_state["filename"]) self.load(loaded_state["filename"])
if loaded_state["pos"] != 0: if loaded_state["pos_true"] != 0:
print("Seeking to pos: " + str(loaded_state["pos"])) print("Seeking to pos_true: " + str(loaded_state["pos_true"]))
self.seek(loaded_state["pos"]) self.seek(loaded_state["pos_true"])
if loaded_state["playing"] == True: if loaded_state["playing"] == True:
print("Resuming.") print("Resuming.")
@ -313,8 +343,8 @@ def showOutput(in_q, out_q):
print("Starting showOutput().") print("Starting showOutput().")
while True: while True:
time.sleep(0.01) time.sleep(0.01)
self.last_msg = out_q.get() last_msg = out_q.get()
print(self.last_msg) print(last_msg)
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -7,6 +7,11 @@
<code> <code>
{% for player in data.channels %} {% for player in data.channels %}
<a href="/player/{{player.channel}}/play">Play</a> <a href="/player/{{player.channel}}/play">Play</a>
{% if player.paused %}
<a href="/player/{{player.channel}}/unpause">UnPause</a>
{% else %}
<a href="/player/{{player.channel}}/pause">Pause</a>
{% endif %}
<a href="/player/{{player.channel}}/stop">Stop</a> <a href="/player/{{player.channel}}/stop">Stop</a>
<a href="/player/{{player.channel}}/seek/50">Seek 50</a> <a href="/player/{{player.channel}}/seek/50">Seek 50</a>
{{player}}<br> {{player}}<br>