You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
6.3 KiB
178 lines
6.3 KiB
#!/usr/bin/python
|
|
|
|
from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket
|
|
import json
|
|
import socket
|
|
import os
|
|
import threading
|
|
import select
|
|
import random
|
|
import SimpleHTTPServer
|
|
import SocketServer
|
|
|
|
|
|
SOCKPATH='/home/dario/.mpv.sock'
|
|
global mpvParser
|
|
mpvParser = None
|
|
|
|
class SocketPoller(threading.Thread):
|
|
def __init__(self, sockParser):
|
|
super(SocketPoller, self).__init__()
|
|
self.sockParser = sockParser
|
|
self.stop=False
|
|
|
|
if not os.path.exists(SOCKPATH):
|
|
raise Exception("Could not find server socket ~/.mpv.sock, exiting")
|
|
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
self.sock.connect(SOCKPATH)
|
|
self.buf=""
|
|
|
|
def run(self):
|
|
while not self.stop:
|
|
if len( select.select([self.sock], [], [])[0] ) > 0:
|
|
self.buf += self.sock.recv(1)
|
|
if '\n' in self.buf:
|
|
self.sockParser.newData(self.buf)
|
|
self.buf=""
|
|
|
|
def sendData(self, data):
|
|
print "sending data '%s'"%data
|
|
if not '\n' in data:
|
|
data+='\n'
|
|
self.sock.sendall(data)
|
|
|
|
class MpvSockParser(object):
|
|
def __init__(self):
|
|
self.listeners = []
|
|
self.playerState = {
|
|
"totalDuration": 42.0,
|
|
"currentDuration": 23.0,
|
|
"volume": 66,
|
|
"fileName": "No Data Yet",
|
|
"isPlaying": False
|
|
}
|
|
self.poller = None
|
|
self.waitingForCommand = None
|
|
|
|
def registerListener(self, listener):
|
|
self.listeners.append(listener)
|
|
def unregisterListener(self, listener):
|
|
self.listeners.remove(listener)
|
|
def notifyListeners(self):
|
|
for l in self.listeners:
|
|
l.dataNotify(self.playerState)
|
|
|
|
def startPoll(self):
|
|
self.poller = SocketPoller(self)
|
|
|
|
self.poller.sendData('{"command":["observe_property",1,"time-pos"]}')
|
|
self.poller.sendData('{"command":["observe_property",2,"volume"]}')
|
|
self.poller.sendData('{"command":["observe_property",3,"filename"]}')
|
|
self.poller.sendData('{"command":["observe_property",4,"duration"]}')
|
|
self.poller.sendData('{"command":["observe_property",5,"mute"]}')
|
|
self.poller.sendData('{"command":["get_property","pause"],"request_id":10}')
|
|
self.poller.sendData('{"command":["get_property","mute"],"request_id":11}')
|
|
|
|
self.poller.daemon = True
|
|
self.poller.start()
|
|
|
|
def newData(self, data):
|
|
data = json.loads(data)
|
|
# mpv-generated event
|
|
if "event" in data:
|
|
self.processEvent(data)
|
|
# answer to our request
|
|
if 'error' in data:
|
|
self.processCommand(data)
|
|
|
|
def processEvent(self, data):
|
|
sendNotify = True
|
|
if "data" in data and data["data"]==None:
|
|
return
|
|
|
|
if data['event'] == 'property-change' and data['name'] == 'time-pos':
|
|
oldCur = self.playerState['currentDuration']
|
|
curCur = int(data['data'])
|
|
if curCur - oldCur < 1:
|
|
sendNotify = False
|
|
self.playerState['currentDuration'] = curCur
|
|
if data['event'] == 'property-change' and data['name'] == 'volume':
|
|
self.playerState['volume'] = int(data['data'])
|
|
if data['event'] == 'property-change' and data['name'] == 'mute':
|
|
self.playerState['isMuted'] = data['data']
|
|
if data['event'] == 'property-change' and data['name'] == 'filename':
|
|
self.playerState['fileName'] = data['data']
|
|
if data['event'] == 'property-change' and data['name'] == 'duration':
|
|
self.playerState['totalDuration'] = int(data['data'])
|
|
if data['event'] == 'pause':
|
|
self.playerState['isPlaying'] = False
|
|
if data['event'] == 'unpause':
|
|
self.playerState['isPlaying'] = True
|
|
|
|
if sendNotify:
|
|
print self.playerState
|
|
self.notifyListeners()
|
|
|
|
def processCommand(self, data):
|
|
if "request_id" in data and data['request_id'] == 10:
|
|
self.playerState['isPlaying'] = not data["data"]
|
|
if "request_id" in data and data['request_id'] == 11:
|
|
self.playerState['isMuted'] = data["data"]
|
|
|
|
def sendCommand(self, command):
|
|
if command["command"] == "play":
|
|
self.poller.sendData('{ "command": ["set_property", "pause", false] }')
|
|
if command["command"] == "pause":
|
|
self.poller.sendData('{ "command": ["set_property", "pause", true] }')
|
|
if command["command"] == "mute":
|
|
self.poller.sendData('{ "command": ["set_property", "mute", true] }')
|
|
if command["command"] == "unmute":
|
|
self.poller.sendData('{ "command": ["set_property", "mute", false] }')
|
|
if command["command"] == "seek":
|
|
self.poller.sendData('{ "command": ["seek", "%s", "absolute"] }'%command['seekValue'])
|
|
if command["command"] == "volume":
|
|
self.poller.sendData('{ "command": ["set", "volume", "%s"] }'%command['volume'])
|
|
if command["command"] == "seekChapter":
|
|
if command['direction'] == 'forward':
|
|
direction = +1
|
|
elif command['direction'] == 'backward':
|
|
direction = -1
|
|
self.poller.sendData('{ "command": ["add", "chapter", %s] }'%direction)
|
|
|
|
class WSHandler(WebSocket):
|
|
def handleMessage(self):
|
|
global mpvParser
|
|
command = json.loads(self.data)
|
|
print 'got command %s'%command
|
|
mpvParser.sendCommand(command)
|
|
def handleConnected(self):
|
|
global mpvParser
|
|
mpvParser.registerListener(self)
|
|
print self.address, 'connected'
|
|
def handleClose(self):
|
|
global mpvParser
|
|
print self.address, 'closed'
|
|
mpvParser.unregisterListener(self)
|
|
def dataNotify(self, data):
|
|
data['type'] = 'status'
|
|
self.sendMessage(unicode( json.dumps(data) ))
|
|
|
|
|
|
|
|
if __name__=='__main__':
|
|
global mpvParser
|
|
mpvParser = MpvSockParser()
|
|
mpvParser.startPoll()
|
|
|
|
os.chdir('../client/')
|
|
SocketServer.TCPServer.allow_reuse_address = True
|
|
httpd = SocketServer.TCPServer(("", 8001), SimpleHTTPServer.SimpleHTTPRequestHandler)
|
|
|
|
wsd = SimpleWebSocketServer('', 8000, WSHandler)
|
|
|
|
wsThread = threading.Thread(target=wsd.serveforever)
|
|
wsThread.daemon=True
|
|
wsThread.start()
|
|
|
|
httpd.serve_forever()
|