199 lines
5.8 KiB
Python
199 lines
5.8 KiB
Python
#coding:utf8
|
|
|
|
from ..utils import find_exec_path
|
|
from collections import deque
|
|
from twisted.internet import reactor
|
|
from twisted.internet.protocol import ProcessProtocol
|
|
import re
|
|
|
|
RE_ANSWER = re.compile('^ANS_([a-zA-Z_]+)=(.+)$')
|
|
|
|
class LineProcessProtocol(ProcessProtocol):
|
|
_leftover_out = ''
|
|
_leftover_err = ''
|
|
|
|
def parse_lines(self, leftovers, data):
|
|
data = leftovers+data
|
|
lines = data.split('\n')
|
|
leftovers = lines.pop(-1)
|
|
return leftovers, lines
|
|
|
|
def errLineReceived(self, line):
|
|
pass
|
|
|
|
def outLineReceived(self, line):
|
|
pass
|
|
|
|
def outReceived(self, data):
|
|
self._leftover_out, lines = self.parse_lines(self._leftover_out, data)
|
|
for line in lines:
|
|
self.outLineReceived(line)
|
|
|
|
def errReceived(self, data):
|
|
self._leftover_err, lines = self.parse_lines(self._leftover_err, data)
|
|
for line in lines:
|
|
self.errLineReceived(line)
|
|
|
|
def writeLines(self, *lines):
|
|
for line in lines:
|
|
self.transport.write(line+'\n')
|
|
|
|
|
|
class MplayerProtocol(LineProcessProtocol):
|
|
speed_supported = True
|
|
|
|
def __init__(self, manager):
|
|
self.__syncplayClient = manager
|
|
self.ignore_end = False
|
|
self.error_lines = deque(maxlen=50)
|
|
self.tmp_paused = None
|
|
self.set_pause = False
|
|
|
|
self.duration = None
|
|
self.filename = None
|
|
self.filepath = None
|
|
self.fileupdatesteps = 0
|
|
|
|
def connectionMade(self):
|
|
reactor.callLater(0.1, self.prepare_player)
|
|
|
|
def processEnded(self, reason):
|
|
self.__syncplayClient.player = None
|
|
if not self.ignore_end:
|
|
if reason.value.signal is not None:
|
|
print 'Mplayer interrupted by signal %d.' % reason.value.signal
|
|
elif reason.value.exitCode is not None:
|
|
print 'Mplayer quit with exit code %d.' % reason.value.exitCode
|
|
else:
|
|
print 'Mplayer quit unexpectedly.'
|
|
if self.error_lines:
|
|
print 'Up to 50 last lines from its error output below:'
|
|
for line in self.error_lines:
|
|
print line
|
|
self.__syncplayClient.stop()
|
|
|
|
def errLineReceived(self, line):
|
|
if line:
|
|
self.error_lines.append(line)
|
|
|
|
def outLineReceived(self, line):
|
|
if not (line and line.startswith('ANS_')):
|
|
return
|
|
m = RE_ANSWER.match(line)
|
|
if not m:
|
|
return
|
|
|
|
name, value = m.group(1).lower(), m.group(2)
|
|
handler = getattr(self, 'mplayer_answer_' + name, None)
|
|
if handler:
|
|
handler(value)
|
|
|
|
|
|
def prepare_player(self):
|
|
self.set_paused(True)
|
|
|
|
self.set_position(0)
|
|
self.send_get_filename()
|
|
|
|
def ask_for_status(self):
|
|
self.send_get_paused()
|
|
self.send_get_position()
|
|
|
|
|
|
def send_set_property(self, name, value):
|
|
self.writeLines('%s %s %s' % ('set_property', name, value))
|
|
|
|
def send_get_property(self, name):
|
|
self.writeLines('%s %s' % ('get_property', name))
|
|
|
|
def display_message(self, message):
|
|
self.writeLines('%s %s %s %s' % ('osd_show_text', '"%s"'% str(message), 3000, 1))
|
|
|
|
def send_get_filename(self):
|
|
self.send_get_property('filename')
|
|
|
|
def send_get_length(self):
|
|
self.send_get_property('length')
|
|
|
|
def send_get_filepath(self):
|
|
self.send_get_property('path')
|
|
|
|
def setUpFileInPlayer(self):
|
|
self.fileupdatesteps = 0
|
|
self.__syncplayClient.initPlayer(self)
|
|
self.__syncplayClient.updateFile(self.filename, self.duration, self.filespath)
|
|
if self.__syncplayClient.last_global_update:
|
|
self.set_position(self.__syncplayClient.getGlobalPosition())
|
|
self.set_paused(True)
|
|
|
|
def mplayer_answer_filename(self, value):
|
|
self.filename = value
|
|
self.fileupdatesteps += 1
|
|
if(self.fileupdatesteps == 3):
|
|
self.setUpFileInPlayer()
|
|
|
|
def mplayer_answer_path(self, value):
|
|
self.filepath = value
|
|
self.fileupdatesteps += 1
|
|
if(self.fileupdatesteps == 3):
|
|
self.setUpFileInPlayer()
|
|
|
|
def mplayer_answer_length(self, value):
|
|
self.duration = value
|
|
self.fileupdatesteps += 1
|
|
if(self.fileupdatesteps == 3):
|
|
self.setUpFileInPlayer()
|
|
|
|
def set_paused(self, value):
|
|
self.set_pause = value
|
|
self.send_get_paused()
|
|
|
|
def send_get_paused(self):
|
|
self.send_get_property('pause')
|
|
|
|
def mplayer_answer_pause(self, value):
|
|
value = value == 'yes'
|
|
if(self.set_pause <> None and self.set_pause <> value):
|
|
self.writeLines('pause')
|
|
self.set_pause = None
|
|
self.tmp_paused = value
|
|
|
|
def set_position(self, value):
|
|
self.send_set_property('time_pos', '%0.2f'%value)
|
|
|
|
def send_get_position(self):
|
|
self.send_get_property('time_pos')
|
|
|
|
def mplayer_answer_time_pos(self, value):
|
|
value = float(value)
|
|
self.__syncplayClient.updatePlayerStatus(self.tmp_paused, value)
|
|
|
|
|
|
def set_speed(self, value):
|
|
self.send_set_property('speed', '%0.2f'%value)
|
|
|
|
#def send_get_speed(self):
|
|
# self.send_get_property('speed')
|
|
|
|
#def mplayer_answer_speed(self, value):
|
|
# value = float(value)
|
|
# self.__syncplayClient.update_player_speed(value)
|
|
|
|
|
|
def drop(self):
|
|
self.ignore_end = True
|
|
self.writeLines('quit')
|
|
|
|
|
|
def run_mplayer(manager, mplayer_path, args):
|
|
exec_path = find_exec_path(mplayer_path)
|
|
print 'Running', exec_path
|
|
if not exec_path:
|
|
raise Exception('Mplayer executable not found')
|
|
|
|
args = list(args)
|
|
args.insert(0, mplayer_path)
|
|
process_protocol = MplayerProtocol(manager)
|
|
reactor.spawnProcess(process_protocol, exec_path, args=args, env=None)
|
|
|