Basic player
This commit is contained in:
parent
07f4df93a2
commit
fc54058e7f
4 changed files with 209 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
.vscode/
|
||||
|
||||
__pycache__/
|
98
bapsicle_standalone.py
Normal file
98
bapsicle_standalone.py
Normal file
|
@ -0,0 +1,98 @@
|
|||
import pygame
|
||||
import time
|
||||
import json
|
||||
from mutagen.mp3 import MP3
|
||||
|
||||
class bapsicle():
|
||||
state = {
|
||||
"filename": "",
|
||||
"channel": -1,
|
||||
"playing": False,
|
||||
"pos": 0,
|
||||
"remaining": 0,
|
||||
"length": 0,
|
||||
"loop": False
|
||||
}
|
||||
|
||||
def isPlaying(self):
|
||||
return bool(pygame.mixer.music.get_busy())
|
||||
|
||||
def play(self):
|
||||
|
||||
|
||||
pygame.mixer.music.play(0)
|
||||
|
||||
def pause(self):
|
||||
pygame.mixer.music.pause()
|
||||
|
||||
def unpause(self):
|
||||
pygame.mixer.music.play(0, self.state["pos"])
|
||||
|
||||
def stop(self):
|
||||
pygame.mixer.music.stop()
|
||||
|
||||
def seek(self, pos):
|
||||
if self.isPlaying():
|
||||
pygame.mixer.music.play(0, pos)
|
||||
else:
|
||||
self.updateState(pos)
|
||||
|
||||
def load(self, filename):
|
||||
if not self.isPlaying():
|
||||
self.state["filename"] = filename
|
||||
pygame.mixer.music.load(filename)
|
||||
if ".mp3" in filename:
|
||||
song = MP3(filename)
|
||||
self.state["length"] = song.info.length
|
||||
else:
|
||||
self.state["length"] = pygame.mixer.Sound(filename).get_length()/1000
|
||||
|
||||
|
||||
|
||||
def updateState(self, pos = None):
|
||||
self.state["playing"] = self.isPlaying()
|
||||
if (pos):
|
||||
self.state["pos"] = pos
|
||||
else:
|
||||
self.state["pos"] = pygame.mixer.music.get_pos()/1000
|
||||
|
||||
self.state["remaining"] = self.state["length"] - self.state["pos"]
|
||||
|
||||
def getDetails(self):
|
||||
res = "RESP:DETAILS: " + json.dumps(self.state)
|
||||
return res
|
||||
|
||||
|
||||
def __init__(self, channel, in_q, out_q):
|
||||
|
||||
self.state["channel"] = channel
|
||||
|
||||
pygame.mixer.init()
|
||||
|
||||
|
||||
|
||||
|
||||
while True:
|
||||
time.sleep(0.01)
|
||||
incoming_msg = in_q.get()
|
||||
self.updateState()
|
||||
if (not incoming_msg):
|
||||
continue
|
||||
if (incoming_msg == 'PLAY'):
|
||||
self.play()
|
||||
if (incoming_msg == 'PAUSE'):
|
||||
self.pause()
|
||||
if (incoming_msg == 'UNPAUSE'):
|
||||
self.unpause()
|
||||
if (incoming_msg == 'STOP'):
|
||||
self.stop()
|
||||
if (incoming_msg.startswith("SEEK")):
|
||||
split = incoming_msg.split(":")
|
||||
self.seek(float(split[1]))
|
||||
if (incoming_msg.startswith("LOAD")):
|
||||
split = incoming_msg.split(":")
|
||||
self.load(split[1])
|
||||
|
||||
if (incoming_msg == 'DETAILS'):
|
||||
out_q.put(self.getDetails())
|
||||
|
90
multiplay-flask.py
Normal file
90
multiplay-flask.py
Normal file
|
@ -0,0 +1,90 @@
|
|||
import multiprocessing
|
||||
from bapsicle_standalone import bapsicle
|
||||
from flask import Flask, render_template
|
||||
import json
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
channel_to_q = []
|
||||
channel_from_q = []
|
||||
channel_p = []
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def status():
|
||||
data = []
|
||||
for i in range(3):
|
||||
data.append(details(i))
|
||||
return render_template('index.html', data=data)
|
||||
|
||||
|
||||
@app.route("/player/<int:channel>/play")
|
||||
def play(channel):
|
||||
|
||||
channel_to_q[channel].put("PLAY")
|
||||
|
||||
return status()
|
||||
|
||||
|
||||
@app.route("/player/<int:channel>/pause")
|
||||
def pause(channel):
|
||||
|
||||
channel_to_q[channel].put("PAUSE")
|
||||
|
||||
return status()
|
||||
|
||||
|
||||
@app.route("/player/<int:channel>/unpause")
|
||||
def unPause(channel):
|
||||
|
||||
channel_to_q[channel].put("UNPAUSE")
|
||||
|
||||
return status()
|
||||
|
||||
|
||||
@app.route("/player/<int:channel>/stop")
|
||||
def stop(channel):
|
||||
|
||||
channel_to_q[channel].put("STOP")
|
||||
|
||||
return status()
|
||||
|
||||
|
||||
@app.route("/player/<int:channel>/seek/<int:pos>")
|
||||
def seek(channel, pos):
|
||||
|
||||
channel_to_q[channel].put("SEEK:" + str(pos))
|
||||
|
||||
return status()
|
||||
|
||||
|
||||
@app.route("/player/<int:channel>/details")
|
||||
def details(channel):
|
||||
|
||||
channel_to_q[channel].put("DETAILS")
|
||||
while True:
|
||||
response = channel_from_q[channel].get()
|
||||
|
||||
if response and response.startswith("RESP:DETAILS"):
|
||||
return json.loads(response.strip("RESP:DETAILS:"))
|
||||
|
||||
|
||||
@app.route("/player/all/stop")
|
||||
def all_stop():
|
||||
for channel in channel_to_q:
|
||||
channel.put("STOP")
|
||||
status()
|
||||
|
||||
for channel in range(3):
|
||||
channel_to_q.append(multiprocessing.Queue())
|
||||
channel_from_q.append(multiprocessing.Queue())
|
||||
channel_to_q[-1].put_nowait("LOAD:test"+str(channel)+".mp3")
|
||||
channel_p.append(multiprocessing.Process(target=bapsicle, args=(channel, channel_to_q[-1], channel_from_q[-1])).start())
|
||||
|
||||
app.run(host='0.0.0.0', port=5000, debug=True)
|
17
templates/index.html
Normal file
17
templates/index.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>BAPSicle</title>
|
||||
<meta http-equiv="refresh" content="2;url=/" />
|
||||
</head>
|
||||
<body>
|
||||
{% if data %}
|
||||
<code>
|
||||
{% for player in data %}
|
||||
{{player}} <a href="/player/{{player['channel']}}/play">Play</a> <a href="/player/{{player.channel}}/stop">Stop</a></a><br>
|
||||
{% endfor %}
|
||||
</code>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue