Add pause support, as well as "true" position
This commit is contained in:
parent
9a9f9ad234
commit
dc4f1bb14b
2 changed files with 75 additions and 40 deletions
110
player.py
110
player.py
|
@ -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__":
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue