2020-10-23 20:10:32 +00:00
|
|
|
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,
|
2020-10-23 21:58:53 +00:00
|
|
|
"loop": False,
|
|
|
|
"output": None
|
2020-10-23 20:10:32 +00:00
|
|
|
}
|
|
|
|
|
2020-10-23 21:58:53 +00:00
|
|
|
def isInit(self):
|
|
|
|
try:
|
|
|
|
pygame.mixer.music.get_busy()
|
|
|
|
except:
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
|
|
|
|
2020-10-23 20:10:32 +00:00
|
|
|
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
|
|
|
|
|
2020-10-23 21:58:53 +00:00
|
|
|
def output(self, name = None):
|
|
|
|
pygame.mixer.quit()
|
|
|
|
try:
|
|
|
|
if name:
|
|
|
|
pygame.mixer.init(44100, -16, 1, 1024, devicename=name)
|
|
|
|
else:
|
|
|
|
pygame.mixer.init(44100, -16, 1, 1024)
|
|
|
|
except:
|
|
|
|
return "FAIL:Failed to init mixer, check sound devices."
|
|
|
|
else:
|
|
|
|
if name:
|
|
|
|
self.state["output"] = name
|
|
|
|
else:
|
|
|
|
self.state["output"] = "default"
|
|
|
|
return "OK"
|
2020-10-23 20:10:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2020-10-23 21:58:53 +00:00
|
|
|
self.output()
|
2020-10-23 20:10:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
time.sleep(0.01)
|
|
|
|
incoming_msg = in_q.get()
|
|
|
|
if (not incoming_msg):
|
|
|
|
continue
|
2020-10-23 21:58:53 +00:00
|
|
|
if self.isInit():
|
|
|
|
self.updateState()
|
|
|
|
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())
|
|
|
|
|
|
|
|
|
|
|
|
if (incoming_msg.startswith("OUTPUT")):
|
2020-10-23 20:10:32 +00:00
|
|
|
split = incoming_msg.split(":")
|
2020-10-23 21:58:53 +00:00
|
|
|
out_q.put(self.output(split[1]))
|
2020-10-23 20:10:32 +00:00
|
|
|
|