From 8ed7f061bcc52457dbb50a34a62fe13d9244bc92 Mon Sep 17 00:00:00 2001 From: Tomasz Fluxid Kowalczyk Date: Thu, 2 Feb 2012 23:18:10 +0100 Subject: [PATCH] First stage of MPC support refactoring --- sync_mpc.py | 4 +- syncplay/network_utils.py | 32 ++++++++-- syncplay/players/mpc.py | 126 +++++++++++++++----------------------- 3 files changed, 78 insertions(+), 84 deletions(-) diff --git a/sync_mpc.py b/sync_mpc.py index 3b02610..4bf5bfb 100644 --- a/sync_mpc.py +++ b/sync_mpc.py @@ -17,8 +17,6 @@ if __name__ == '__main__': else: port = 8999 - manager = client.Manager(host, port, name) + manager = client.Manager(host, port, name, lambda: mpc.MPCHCPlayer(manager)) manager.start() - player = mpc.MPCHCPlayer(manager) - reactor.run() diff --git a/syncplay/network_utils.py b/syncplay/network_utils.py index 07cbd11..498a8bb 100644 --- a/syncplay/network_utils.py +++ b/syncplay/network_utils.py @@ -5,11 +5,15 @@ try: except ImportError: from StringIO import StringIO +from twisted.internet.defer import succeed from twisted.internet.protocol import ( ProcessProtocol, Protocol, ) from twisted.protocols.basic import LineReceiver +from twisted.web.iweb import IBodyProducer + +from zope.interface import implements class CommandProtocol(LineReceiver): states = None @@ -87,22 +91,42 @@ class LineProcessProtocol(ProcessProtocol): for line in lines: self.transport.write(line+'\n') - + +class BodyProducer(object): + implements(IBodyProducer) + + def __init__(self, body): + self.body = body + self.length = len(body) + + def startProducing(self, consumer): + consumer.write(self.body) + return succeed(None) + + def pauseProducing(self): + pass + + def stopProducing(self): + pass + class BodyGetter(Protocol): def __init__(self, length, callback): self.length = length self.callback = callback self.body = StringIO() - + def dataReceived(self, data): if self.length > 0: data = data[:self.length] self.body.write(data) self.length -= len(length) - + def connectionLost(self, reason): self.callback(self.body.getvalue()) - + +def null_response_handler(status, headers, body): + pass + def handle_response(callback): def defer_callback(response): status = response.code diff --git a/syncplay/players/mpc.py b/syncplay/players/mpc.py index 29732a8..d30ea64 100644 --- a/syncplay/players/mpc.py +++ b/syncplay/players/mpc.py @@ -1,16 +1,16 @@ #coding:utf8 - + import re - + from twisted.internet import reactor -from twisted.internet.defer import Deferred, succeed from twisted.web.client import Agent from twisted.web.http_headers import Headers - -from zope.interface import implements -from twisted.web.iweb import IBodyProducer -from ..network_utils import handle_response +from ..network_utils import ( + BodyProducer, + handle_response, + null_response_handler, +) #RE_MPC_STATUS = re.compile("^OnStatus\('(.+)', '(Paused|Playing)', (\d+), '\d{2}:\d{2}:\d{2}', \d+, '\d{2}:\d{2}:\d{2}', \d+, \d+, '.+'\)$") RE_MPC_STATUS = re.compile(r"^OnStatus\('((?:[^']*(?:\\\\)*\\')*[^']*)', '(.+?)', (\d+),") @@ -64,88 +64,60 @@ PLAYING_STATUSES = { 'Duraklatıldı': True, 'Пауза': True, } - + class MPCHCPlayer(object): - def __init__(self, manager): + def __init__(self, manager, host = None): self.manager = manager + self.host = 'localhost:13579' + + self.filename = None # To be moved to Manager + manager.player = self - - def send_set_paused(self, value): - self.set_property('Paused', value) + self.agent = Agent(reactor) - def send_get_paused(self): - self.get_property('Paused') - - def send_set_position(self, value): - self.set_property('Position', '%d'%(value*1000)) + def set_paused(self, value): + self.send_post_request('wm_command=%d' % (888 if value else 887)) - def send_get_position(self): - self.get_property('Position') + def set_position(self, value): + value = int(value*1000) + seconds, mseconds = divmod(value, 1000) + minutes, seconds = divmod(seconds, 60) + hours, minutes = divmod(minutes, 60) + self.send_post_request('wm_command=-1&position=%d.%d.%d.%d' % ( + hours, minutes, seconds, mseconds + )) - def send_set_speed(self, value): - pass + self.send_post_request(body) - def send_get_speed(self): - pass - - def set_property(self, name, value): - requestData = { - 'Paused': lambda value: 'wm_command=888&null=0' if value else 'wm_command=887&null=0', - 'Position': lambda value: "wm_command=-1&position="+ '%d.%d.%d.%d' % ((int(value)/3600000), (int(value)/60000)%60, (int(value)/1000)%60, int(value)%1000) - }[name](value) + def status_response(self, status, headers, body): + m = RE_MPC_STATUS.match(body) + if not m: + return + filename, paused, position = m.group(1), m.group(2), m.group(3) - body = StringBodyProducer(requestData) - self.sendPostRequest(body) - - def get_property(self, propertyName): - agent = Agent(reactor) - request = agent.request( + paused = PLAYING_STATUSES.get(paused) + if paused is None: + return + if self.filename is None: + self.filename = filename + position = float(position)/1000 + self.manager.update_player_status(paused, position) + + def ask_for_status(self, propertyName): + request = self.agent.request( 'GET', 'http://localhost:13579/status.html', Headers(), - None) - - def cbRequest(status, headers, body): - m = RE_MPC_STATUS.match(body) - if not m: - return - fileName, playerStatus, currentTime = m.group(1), m.group(2), m.group(3) - playerStatus = PLAYING_STATUSES.get(playerStatus) - if playerStatus is None: - return - if(propertyName == "Paused"): - self.manager.update_player_paused(playerStatus) - if(propertyName == "Position"): - self.manager.update_player_position(float(currentTime)/1000.0) - - request.addCallback(handle_response(cbRequest)) + None, + ) + request.addCallback(handle_response(self.status_response)) - def sendPostRequest(self, body): - agent = Agent(reactor) - request = agent.request( + def send_post_request(self, body): + request = self.agent.request( 'POST', - 'http://localhost:13579/command.html', + 'http://%s/command.html' % self.host, Headers({'Content-Type': ['application/x-www-form-urlencoded']}), - body) - - def cbRequest(ignored): - return - request.addCallback(cbRequest) - -class StringBodyProducer(object): - implements(IBodyProducer) - - def __init__(self, body): - self.body = body - self.length = len(body) - - def startProducing(self, consumer): - consumer.write(self.body) - return succeed(None) - - def pauseProducing(self): - pass - - def stopProducing(self): - pass + BodyProducer(body), + ) + request.addCallback(handle_response(null_response_handler))