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

#!/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()