Completly new setup

This commit is contained in:
Uriziel 2012-07-11 10:41:23 +02:00
parent 321fb5a3a5
commit aba2117344
8 changed files with 126 additions and 113 deletions

View File

@ -4,10 +4,10 @@ from setuptools import find_packages
common_info = dict( common_info = dict(
name = 'SyncPlay', name = 'SyncPlay',
version = '0.7', version = '1.9',
author = 'Tomasz Kowalczyk, Uriziel', author = 'Tomasz Kowalczyk, Uriziel',
author_email = 'code@fluxid.pl, urizieli@gmail.com', author_email = 'code@fluxid.pl, urizieli@gmail.com',
description = 'Solution to synchronize playback of multiple MPlayer and MPC-HC instances over the network.', description = 'Syncplay',
packages = find_packages(exclude=['venv']), packages = find_packages(exclude=['venv']),
install_requires = ['Twisted>=11.1'], install_requires = ['Twisted>=11.1'],
) )

View File

@ -45,7 +45,7 @@ class SyncClientProtocol(CommandProtocol):
print message print message
self._syncplayClient.name = args[0] self._syncplayClient.name = args[0]
self._syncplayClient.protocol.sender.send_list() self._syncplayClient.protocol.sender.send_list()
self._syncplayClient.schedule_send_status() self._syncplayClient.scheduleSendStatus()
@argumentCount(2, 3) @argumentCount(2, 3)
def present(self, args): def present(self, args):
@ -71,7 +71,7 @@ class SyncClientProtocol(CommandProtocol):
counter, ctime, paused, position, name = args counter, ctime, paused, position, name = args
self._syncplayClient.update_global_state(counter, ctime, paused, position, name) self._syncplayClient.updateGlobalState(counter, ctime, paused, position, name)
@argumentCount(3) @argumentCount(3)
def seek(self, args): def seek(self, args):
@ -152,7 +152,7 @@ class SyncClientProtocol(CommandProtocol):
def send_state(self, counter, ctime, paused, position): def send_state(self, counter, ctime, paused, position):
self._protocol.sendMessage('state', counter, int(ctime*1000), ('paused' if paused else 'playing'), int(position*1000)) self._protocol.sendMessage('state', counter, int(ctime*1000), ('paused' if paused else 'playing'), int(position*1000))
def send_seek(self, counter, ctime, position): def sendSeek(self, counter, ctime, position):
self._protocol.sendMessage('seek', counter, int(ctime*1000), int(position*1000)) self._protocol.sendMessage('seek', counter, int(ctime*1000), int(position*1000))
def send_room(self, where): def send_room(self, where):
@ -246,7 +246,7 @@ class SyncplayClientManager(object):
reactor.callLater(0.1, reactor.stop) reactor.callLater(0.1, reactor.stop)
def get_player_position(self): def getPlayerPosition(self):
if not self.last_player_update: if not self.last_player_update:
return 0.0 return 0.0
position = self.player_position position = self.player_position
@ -254,7 +254,7 @@ class SyncplayClientManager(object):
position += time.time() - self.last_player_update position += time.time() - self.last_player_update
return position return position
def get_global_position(self): def getGlobalPosition(self):
if not self.last_global_update: if not self.last_global_update:
return 0.0 return 0.0
position = self.global_position position = self.global_position
@ -263,12 +263,12 @@ class SyncplayClientManager(object):
return position return position
def init_player(self, player): def initPlayer(self, player):
self.player = player self.player = player
if self.last_global_update: if self.last_global_update:
self.player.set_position(self.get_global_position()) self.player.set_position(self.getGlobalPosition())
self.player.set_paused(True) self.player.set_paused(True)
self.schedule_ask_player() self.scheduleAskPlayer()
def initProtocol(self, protocol): def initProtocol(self, protocol):
self.protocol = protocol self.protocol = protocol
@ -281,30 +281,30 @@ class SyncplayClientManager(object):
self.protocol.drop() self.protocol.drop()
self.protocol = None self.protocol = None
def schedule_ask_player(self, when=0.2): def scheduleAskPlayer(self, when=0.2):
if self.ask_delayed and self.ask_delayed.active(): if self.ask_delayed and self.ask_delayed.active():
self.ask_delayed.reset(when) self.ask_delayed.reset(when)
else: else:
self.ask_delayed = reactor.callLater(when, self.ask_player) self.ask_delayed = reactor.callLater(when, self.askPlayer)
def ask_player(self): def askPlayer(self):
if not self.running: if not self.running:
return return
if self.player: if self.player:
self.status_ask_sent += 1 self.status_ask_sent += 1
self.player.ask_for_status() self.player.ask_for_status()
self.schedule_ask_player() self.scheduleAskPlayer()
def schedule_send_status(self, when=1): def scheduleSendStatus(self, when=1):
if self.send_delayed and self.send_delayed.active(): if self.send_delayed and self.send_delayed.active():
self.send_delayed.reset(when) self.send_delayed.reset(when)
else: else:
self.send_delayed = reactor.callLater(when, self.send_status) self.send_delayed = reactor.callLater(when, self.sendStatus)
def send_status(self, force = False): def sendStatus(self, force = False):
if not (self.running and self.protocol): if not (self.running and self.protocol):
return return
self.schedule_send_status() self.scheduleSendStatus()
if self.counter > self.counter_recv and not force: if self.counter > self.counter_recv and not force:
return return
self.counter += 1 self.counter += 1
@ -315,20 +315,20 @@ class SyncplayClientManager(object):
if self.protocol: if self.protocol:
self.protocol.sender.send_state(self.counter, curtime, self.player_paused, self.player_position) self.protocol.sender.send_state(self.counter, curtime, self.player_paused, self.player_position)
def send_seek(self): def sendSeek(self):
if not (self.running and self.protocol): if not (self.running and self.protocol):
return return
self.counter += 10 self.counter += 10
self.protocol.sender.send_seek(self.counter, time.time(), self.player_position) self.protocol.sender.sendSeek(self.counter, time.time(), self.player_position)
message = self.name +' seeked to ' + format_time(self.player_position) message = self.name +' seeked to ' + format_time(self.player_position)
print message print message
self.player.display_message(message) self.player.display_message(message)
def send_filename(self): def sendFilename(self):
if self.protocol and self.player_filename: if self.protocol and self.player_filename:
self.protocol.sender.send_playing(self.player_filename) self.protocol.sender.send_playing(self.player_filename)
def __exectue_seek_cmd(self, seek_type, minutes, seconds): def __exectueSeekCmd(self, seek_type, minutes, seconds):
self.player_position_before_last_seek = self.player_position self.player_position_before_last_seek = self.player_position
if seek_type == 's': if seek_type == 's':
seconds = int(seconds) if seconds <> None else 0 seconds = int(seconds) if seconds <> None else 0
@ -339,13 +339,13 @@ class SyncplayClientManager(object):
seconds += int(minutes) * 60 if minutes <> None else 60 seconds += int(minutes) * 60 if minutes <> None else 60
self.player.set_position(self.player_position+seconds) self.player.set_position(self.player_position+seconds)
def execute_command(self, data): def executeCommand(self, data):
RE_SEEK = re.compile("^(s[+s]?) ?(-?\d+)?([^0-9](\d+))?$") RE_SEEK = re.compile("^(s[+s]?) ?(-?\d+)?([^0-9](\d+))?$")
RE_ROOM = re.compile("^room( (\w+))?") RE_ROOM = re.compile("^room( (\w+))?")
matched_seek = RE_SEEK.match(data) matched_seek = RE_SEEK.match(data)
matched_room = RE_ROOM.match(data) matched_room = RE_ROOM.match(data)
if matched_seek : if matched_seek :
self.__exectue_seek_cmd(matched_seek.group(1), matched_seek.group(2), matched_seek.group(4)) self.__exectueSeekCmd(matched_seek.group(1), matched_seek.group(2), matched_seek.group(4))
elif matched_room: elif matched_room:
room = matched_room.group(2) room = matched_room.group(2)
if room == None: if room == None:
@ -366,7 +366,7 @@ class SyncplayClientManager(object):
print "\tp - toggle pause" print "\tp - toggle pause"
print "\troom [room] - change room, if no supplied go to default" print "\troom [room] - change room, if no supplied go to default"
def update_player_status(self, paused, position): def updatePlayerStatus(self, paused, position):
self.status_ask_received += 1 self.status_ask_received += 1
if self.status_ask_received < self.status_ask_sent: if self.status_ask_received < self.status_ask_sent:
return return
@ -374,18 +374,18 @@ class SyncplayClientManager(object):
self.player_paused = paused self.player_paused = paused
self.player_position = position self.player_position = position
self.last_player_update = time.time() self.last_player_update = time.time()
diff = position - self.get_global_position() diff = position - self.getGlobalPosition()
if old_paused and not paused: if old_paused and not paused:
self.player_paused_at = None self.player_paused_at = None
if old_paused != paused and self.global_paused != paused: if old_paused != paused and self.global_paused != paused:
self.send_status(True) self.sendStatus(True)
if paused: if paused:
message = '%s paused' % self.name message = '%s paused' % self.name
print message print message
self.player.display_message(message) self.player.display_message(message)
if(diff > 0): if(diff > 0):
self.player.set_position(self.get_global_position()) self.player.set_position(self.getGlobalPosition())
self.ask_player() self.askPlayer()
else: else:
message = '%s unpaused' % self.name message = '%s unpaused' % self.name
print message print message
@ -402,19 +402,19 @@ class SyncplayClientManager(object):
self.player.set_speed(1) self.player.set_speed(1)
self.player_speed_fix = False self.player_speed_fix = False
if abs(diff) > 8:# and not self.seek_sent_wait: if abs(diff) > 8:# and not self.seek_sent_wait:
self.send_seek() self.sendSeek()
self.seek_sent_wait = True self.seek_sent_wait = True
if not paused and self.player_paused_at is not None and position >= self.player_paused_at: if not paused and self.player_paused_at is not None and position >= self.player_paused_at:
#print 'Pausing %0.2fs after pause point' % (position - self.player_paused_at) #print 'Pausing %0.2fs after pause point' % (position - self.player_paused_at)
self.player.set_paused(True) self.player.set_paused(True)
self.ask_player() self.askPlayer()
def update_filename(self, filename): def updateFilename(self, filename):
filename = unicode(filename, errors='replace') filename = unicode(filename, errors='replace')
self.player_filename = filename.encode('ascii','replace') self.player_filename = filename.encode('ascii','replace')
self.send_filename() self.sendFilename()
def update_global_state(self, counter, ctime, paused, position, name): def updateGlobalState(self, counter, ctime, paused, position, name):
self.counter_recv = max(self.counter_recv, counter) self.counter_recv = max(self.counter_recv, counter)
counter_valid = self.counter and counter >= self.counter counter_valid = self.counter and counter >= self.counter
@ -443,7 +443,7 @@ class SyncplayClientManager(object):
changed = True changed = True
if counter_valid: if counter_valid:
diff = self.get_player_position() - position diff = self.getPlayerPosition() - position
if abs(diff) > 4: if abs(diff) > 4:
self.player.set_position(position) self.player.set_position(position)
#self.player.set_paused(True) #self.player.set_paused(True)
@ -467,15 +467,15 @@ class SyncplayClientManager(object):
print message print message
self.player.display_message(message) self.player.display_message(message)
if(diff > 0): if(diff > 0):
self.player.set_position(self.get_global_position()) self.player.set_position(self.getGlobalPosition())
self.ask_player() self.askPlayer()
if diff < 0: if diff < 0:
self.player.set_paused(True) self.player.set_paused(True)
self.global_noted_pause_change = paused self.global_noted_pause_change = paused
changed = True changed = True
if changed: if changed:
self.ask_player() self.askPlayer()
def seek(self, ctime, position, who): def seek(self, ctime, position, who):
@ -486,7 +486,7 @@ class SyncplayClientManager(object):
if self.player: if self.player:
self.player_position_before_last_seek = self.player_position self.player_position_before_last_seek = self.player_position
self.player.set_position(position) self.player.set_position(position)
self.ask_player() self.askPlayer()
message = who + ' seeked to ' + format_time(position) message = who + ' seeked to ' + format_time(position)
print message print message
self.player.display_message(message) self.player.display_message(message)

View File

@ -5,6 +5,7 @@ import win32con, win32api, win32gui, ctypes, ctypes.wintypes
class MPC_API: class MPC_API:
def __init__(self, enforce_custom_handler = False): def __init__(self, enforce_custom_handler = False):
self.enforce_custom_handler = enforce_custom_handler
''' '''
List of callbacks that can be set List of callbacks that can be set
on_connected (0 args) on_connected (0 args)
@ -15,8 +16,7 @@ class MPC_API:
on_update_playstate (playstate) on_update_playstate (playstate)
on_file_ready (filename) on_file_ready (filename)
custom_handler (cmd, value) custom_handler (cmd, value)
''' '''
self.enforce_custom_handler = enforce_custom_handler
self.callbacks = self.__CALLBACKS() self.callbacks = self.__CALLBACKS()
self.loadstate = None self.loadstate = None
self.playstate = None self.playstate = None
@ -50,7 +50,6 @@ class MPC_API:
''' '''
Checks if api is ready to receive commands Checks if api is ready to receive commands
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
''' '''
def is_api_ready(self): def is_api_ready(self):
file_state_ok = self.loadstate == self.__MPC_LOADSTATE.MLS_CLOSED or self.loadstate == self.__MPC_LOADSTATE.MLS_LOADED or self.loadstate == None file_state_ok = self.loadstate == self.__MPC_LOADSTATE.MLS_CLOSED or self.loadstate == self.__MPC_LOADSTATE.MLS_LOADED or self.loadstate == None
@ -59,28 +58,28 @@ class MPC_API:
''' '''
Checks if file is loaded in player Checks if file is loaded in player
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
''' '''
def is_file_ready(self): def is_file_ready(self):
return (self.loadstate == self.__MPC_LOADSTATE.MLS_LOADED and self.fileplaying and self.playstate <> None) return (self.loadstate == self.__MPC_LOADSTATE.MLS_LOADED and self.fileplaying and self.playstate <> None)
''' '''
Opens a file given in an argument in player Opens a file given in an argument in player
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
''' '''
def open_file(self, file_path): def open_file(self, file_path):
self.__listener.SendCommand(MPC_API_COMMANDS.CMD_OPENFILE, file_path) self.__listener.SendCommand(MPC_API_COMMANDS.CMD_OPENFILE, file_path)
''' '''
Is player paused (Stop is considered pause) Is player paused (Stop is considered pause)
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
''' '''
def is_paused(self): def is_paused(self):
return (self.playstate <> self.__MPC_PLAYSTATE.PS_PLAY and self.playstate <> None) return (self.playstate <> self.__MPC_PLAYSTATE.PS_PLAY and self.playstate <> None)
''' '''
Pause playing file Pause playing file
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
''' '''
def pause(self): def pause(self):
if(not self.is_file_ready()): raise MPC_API.PlayerNotReadyException("Playstate change on no file") if(not self.is_file_ready()): raise MPC_API.PlayerNotReadyException("Playstate change on no file")
@ -88,7 +87,7 @@ class MPC_API:
self.playpause() self.playpause()
''' '''
Play paused file Play paused file
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
''' '''
def unpause(self): def unpause(self):
if(not self.is_file_ready()): raise MPC_API.PlayerNotReadyException("Playstate change on no file") if(not self.is_file_ready()): raise MPC_API.PlayerNotReadyException("Playstate change on no file")
@ -96,7 +95,7 @@ class MPC_API:
self.playpause() self.playpause()
''' '''
Toggle play/pause Toggle play/pause
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
''' '''
def playpause(self): def playpause(self):
if(not self.is_file_ready()): raise MPC_API.PlayerNotReadyException("Playstate change on no file") if(not self.is_file_ready()): raise MPC_API.PlayerNotReadyException("Playstate change on no file")
@ -112,7 +111,7 @@ class MPC_API:
''' '''
Asks mpc for it's current file position, if on_update_position callback is set Asks mpc for it's current file position, if on_update_position callback is set
developers should rather rely on that rather than on a return value developers should rather rely on that rather than on a return value
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
''' '''
def ask_for_current_position(self): def ask_for_current_position(self):
if(not self.is_file_ready()): if(not self.is_file_ready()):
@ -125,7 +124,7 @@ class MPC_API:
return self.lastfileposition return self.lastfileposition
''' '''
Given a position in seconds will ask client to seek there Given a position in seconds will ask client to seek there
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
''' '''
def seek(self, position): def seek(self, position):
self.__locks.seek.clear() self.__locks.seek.clear()
@ -136,7 +135,7 @@ class MPC_API:
@param message: unicode string to display in player @param message: unicode string to display in player
@param MsgPos: Either 1, left top corner or 2, right top corner, defaults to 2 @param MsgPos: Either 1, left top corner or 2, right top corner, defaults to 2
@param DurationMs: Duration of osd display, defaults to 3000 @param DurationMs: Duration of osd display, defaults to 3000
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
''' '''
def send_osd(self, message, MsgPos = 2, DurationMs = 3000): def send_osd(self, message, MsgPos = 2, DurationMs = 3000):
class __OSDDATASTRUCT(ctypes.Structure): class __OSDDATASTRUCT(ctypes.Structure):
@ -155,7 +154,7 @@ class MPC_API:
Send raw cmd and value to mpc Send raw cmd and value to mpc
Commands are available in MPC_API_COMMANDS class Commands are available in MPC_API_COMMANDS class
Value has to be either ctype.Structure or unicode string Value has to be either ctype.Structure or unicode string
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
''' '''
def send_raw_command(self, cmd, value): def send_raw_command(self, cmd, value):
self.__listener.SendCommand(cmd, value) self.__listener.SendCommand(cmd, value)
@ -178,6 +177,7 @@ class MPC_API:
elif(cmd == MPC_API_COMMANDS.CMD_STATE): elif(cmd == MPC_API_COMMANDS.CMD_STATE):
self.loadstate = int(value) self.loadstate = int(value)
if(self.callbacks.on_fileStateChange): thread.start_new_thread(self.callbacks.on_fileStateChange, (self.loadstate,))
elif(cmd == MPC_API_COMMANDS.CMD_PLAYMODE): elif(cmd == MPC_API_COMMANDS.CMD_PLAYMODE):
self.playstate = int(value) self.playstate = int(value)
@ -188,7 +188,6 @@ class MPC_API:
if(self.callbacks.on_update_filename): thread.start_new_thread(self.callbacks.on_update_filename,(self.fileplaying,)) if(self.callbacks.on_update_filename): thread.start_new_thread(self.callbacks.on_update_filename,(self.fileplaying,))
self.fileduration = int(value.split('|')[4]) self.fileduration = int(value.split('|')[4])
if(self.callbacks.on_update_file_duration): thread.start_new_thread(self.callbacks.on_update_file_duration,(self.fileplaying,)) if(self.callbacks.on_update_file_duration): thread.start_new_thread(self.callbacks.on_update_file_duration,(self.fileplaying,))
if(self.callbacks.on_file_ready): thread.start_new_thread(self.callbacks.on_file_ready, ())
elif(cmd == MPC_API_COMMANDS.CMD_CURRENTPOSITION): elif(cmd == MPC_API_COMMANDS.CMD_CURRENTPOSITION):
self.lastfileposition = float(value) self.lastfileposition = float(value)
@ -211,7 +210,6 @@ class MPC_API:
def __init__(self, message): def __init__(self, message):
Exception.__init__(self, message) Exception.__init__(self, message)
class __CALLBACKS: class __CALLBACKS:
def __init__(self): def __init__(self):
self.on_connected = None self.on_connected = None
@ -220,7 +218,7 @@ class MPC_API:
self.on_update_file_duration = None self.on_update_file_duration = None
self.on_update_position = None self.on_update_position = None
self.on_update_playstate = None self.on_update_playstate = None
self.on_file_ready = None self.on_fileStateChange = None
self.custom_handler = None self.custom_handler = None
self.on_mpc_closed = None self.on_mpc_closed = None
@ -295,12 +293,11 @@ class MPC_API:
def OnCopyData(self, hwnd, msg, wparam, lparam): def OnCopyData(self, hwnd, msg, wparam, lparam):
pCDS = ctypes.cast(lparam, self.__PCOPYDATASTRUCT) pCDS = ctypes.cast(lparam, self.__PCOPYDATASTRUCT)
# print ">>> 0x%X" % int(pCDS.contents.dwData), ctypes.wstring_at(pCDS.contents.lpData) #print "API:\tin>\t 0x%X\t" % int(pCDS.contents.dwData), ctypes.wstring_at(pCDS.contents.lpData)
self.__mpc_api.handle_command(pCDS.contents.dwData, ctypes.wstring_at(pCDS.contents.lpData)) self.__mpc_api.handle_command(pCDS.contents.dwData, ctypes.wstring_at(pCDS.contents.lpData))
def SendCommand(self, cmd, message = u''): def SendCommand(self, cmd, message = u''):
# print "<<< 0x%X" % int(cmd), message #print "API:\t<out\t 0x%X\t" % int(cmd), message
if not win32gui.IsWindow(self.mpc_handle): if not win32gui.IsWindow(self.mpc_handle):
raise MPC_API.NoSlaveDetectedException("MPC Slave Window not detected") raise MPC_API.NoSlaveDetectedException("MPC Slave Window not detected")
cs = self.__COPYDATASTRUCT() cs = self.__COPYDATASTRUCT()
@ -316,7 +313,7 @@ class MPC_API:
cs.cbData = ctypes.sizeof(message) cs.cbData = ctypes.sizeof(message)
ptr= ctypes.addressof(cs) ptr= ctypes.addressof(cs)
win32api.SendMessage(self.mpc_handle, win32con.WM_COPYDATA, self.hwnd, ptr) win32api.SendMessage(self.mpc_handle, win32con.WM_COPYDATA, self.hwnd, ptr)
class __COPYDATASTRUCT(ctypes.Structure): class __COPYDATASTRUCT(ctypes.Structure):
_fields_ = [ _fields_ = [
('dwData', ctypes.wintypes.LPARAM), ('dwData', ctypes.wintypes.LPARAM),

View File

@ -2,6 +2,7 @@
from ..mpc_api import MPC_API from ..mpc_api import MPC_API
import time import time
import threading
class MPCHCAPIPlayer(object): class MPCHCAPIPlayer(object):
def __init__(self, manager): def __init__(self, manager):
@ -9,17 +10,25 @@ class MPCHCAPIPlayer(object):
self.mpc_api = MPC_API() self.mpc_api = MPC_API()
self.pinged = False self.pinged = False
self.tmp_filename = None
self.tmp_position = None self.mpc_api.callbacks.on_update_filename = lambda _: self.make_ping()
self.mpc_api.callbacks.on_file_ready = lambda: self.make_ping()
self.mpc_api.callbacks.on_mpc_closed = lambda: self.mpc_error("MPC closed") self.mpc_api.callbacks.on_mpc_closed = lambda: self.mpc_error("MPC closed")
self.semaphore_filename = False self.mpc_api.callbacks.on_fileStateChange = self.lockAsking
self.mpc_api.callbacks.on_update_playstate = self.unlockAsking
self.askSemaphore = False
self.askLock = threading.RLock()
def drop(self): def drop(self):
pass pass
def lockAsking(self, state):
self.askSemaphore = True
def unlockAsking(self, state):
self.askSemaphore = False
def set_speed(self, value): def set_speed(self, value):
pass pass
@ -32,9 +41,10 @@ class MPCHCAPIPlayer(object):
return return
def make_ping(self): def make_ping(self):
self.mpc_api.callbacks.on_file_ready = None
self.test_mpc_ready() self.test_mpc_ready()
self._syncplayClient.init_player(self) self.mpc_api.callbacks.on_update_filename = self.handle_updated_filename
self._syncplayClient.initPlayer(self)
self.handle_updated_filename(self.mpc_api.fileplaying)
self.pinged = True self.pinged = True
self.ask_for_status() self.ask_for_status()
@ -66,55 +76,58 @@ class MPCHCAPIPlayer(object):
except Exception, err: except Exception, err:
self.mpc_error(err) self.mpc_error(err)
def ask_for_status(self): def __askForPositionUntilPlayerReady(self):
position = self.tmp_position if self.tmp_position else 0
paused = None
try: try:
if(self.mpc_api.is_file_ready() and not self.semaphore_filename): return self.mpc_api.ask_for_current_position()
try: except MPC_API.PlayerNotReadyException:
position = self.mpc_api.ask_for_current_position() time.sleep(0.1)
except MPC_API.PlayerNotReadyException: return self.__askForPositionUntilPlayerReady()
time.sleep(0.1)
self.ask_for_status() def ask_for_status(self):
return try:
if(self.tmp_filename <> self.mpc_api.fileplaying): self.askLock.acquire()
self.handle_updated_filename(self.mpc_api.fileplaying) if(self.mpc_api.is_file_ready() and not self.askSemaphore):
return position = self.__askForPositionUntilPlayerReady()
paused = self.mpc_api.is_paused() paused = self.mpc_api.is_paused()
position = float(position) position = float(position)
self.tmp_position = position if(not self.askSemaphore):
self._syncplayClient.update_player_status(paused, position) self._syncplayClient.updatePlayerStatus(paused, position)
else: return
self._syncplayClient.update_player_status(True, self._syncplayClient.get_global_position()) self._syncplayClient.updatePlayerStatus(True, self._syncplayClient.getGlobalPosition())
except Exception, err: except Exception, err:
self.mpc_error(err) self.mpc_error(err)
finally:
def __force_pause(self, filename, position): self.askLock.release()
self.set_paused(True)
def __pauseChangeCheckLoop(self, i, changeFrom):
time.sleep(0.1) time.sleep(0.1)
if (not self.mpc_api.is_paused()): if(i < 10):
self.__set_up_newly_opened_file(filename, position) if(self.mpc_api.is_paused() <> changeFrom):
return
else:
self.__pauseChangeCheckLoop(i+1, True)
def __force_pause(self):
self.__pauseChangeCheckLoop(0, True)
self.set_paused(True)
def __set_up_newly_opened_file(self, filename, position): def __set_up_newly_opened_file(self, filename, position):
self.test_mpc_ready()
try: try:
self.__force_pause()
self.mpc_api.seek(position) self.mpc_api.seek(position)
except MPC_API.PlayerNotReadyException: except MPC_API.PlayerNotReadyException:
time.sleep(0.1) time.sleep(0.1)
self.__set_up_newly_opened_file(filename, position) self.__set_up_newly_opened_file(filename, position)
self.__force_pause(filename, position)
def handle_updated_filename(self, filename): def handle_updated_filename(self, filename):
position = self._syncplayClient.get_global_position() try:
if(self.semaphore_filename): self.askLock.acquire()
self._syncplayClient.update_player_status(True, position) position = self._syncplayClient.getGlobalPosition()
return self.__set_up_newly_opened_file(filename, position)
self.semaphore_filename = True self._syncplayClient.updateFilename(str(filename))
self.__set_up_newly_opened_file(filename, position) finally:
self.tmp_filename = filename self.askLock.release()
self._syncplayClient.update_filename(str(self.tmp_filename))
self._syncplayClient.update_player_status(True, position)
self.semaphore_filename = False
def mpc_error(self, err=""): def mpc_error(self, err=""):
print "ERROR:", str(err) + ',', "desu" print "ERROR:", str(err) + ',', "desu"

View File

@ -106,8 +106,8 @@ class MplayerProtocol(LineProcessProtocol):
self.send_get_property('filename') self.send_get_property('filename')
def mplayer_answer_filename(self, value): def mplayer_answer_filename(self, value):
self._syncplayClient.init_player(self) self._syncplayClient.initPlayer(self)
self._syncplayClient.update_filename(value) self._syncplayClient.updateFilename(value)
def set_paused(self, value): def set_paused(self, value):
@ -130,7 +130,7 @@ class MplayerProtocol(LineProcessProtocol):
def mplayer_answer_time_pos(self, value): def mplayer_answer_time_pos(self, value):
value = float(value) value = float(value)
self._syncplayClient.update_player_status(self.tmp_paused, value) self._syncplayClient.updatePlayerStatus(self.tmp_paused, value)
def set_speed(self, value): def set_speed(self, value):

View File

@ -29,7 +29,7 @@ class ConsoleUI(threading.Thread):
self.PromptResult = data self.PromptResult = data
self.promptMode.set() self.promptMode.set()
elif(self._syncplayClient): elif(self._syncplayClient):
self._syncplayClient.execute_command(data) self._syncplayClient.executeCommand(data)
except: except:
raise raise

View File

@ -75,7 +75,7 @@ def stdin_thread(manager):
data = os.read(fd, 1024) data = os.read(fd, 1024)
if not data: if not data:
break break
manager.execute_command(data.rstrip('\n\r')) manager.executeCommand(data.rstrip('\n\r'))
except: except:
pass pass
@ -97,7 +97,7 @@ class ConfigurationGetter(object):
raise Exception('Working dir not found') raise Exception('Working dir not found')
def _prepareArgParser(self): def _prepareArgParser(self):
self._parser = argparse.ArgumentParser(description='Syncplay', self._parser = argparse.ArgumentParser(description='Solution to synchronize playback of multiple MPlayer and MPC-HC instances over the network.',
epilog='If no options supplied _config values will be used') epilog='If no options supplied _config values will be used')
self._parser.add_argument('--no-gui', action='store_true', help='show no GUI') self._parser.add_argument('--no-gui', action='store_true', help='show no GUI')
self._parser.add_argument('--host', metavar='hostname', type=str, help='server\'s address') self._parser.add_argument('--host', metavar='hostname', type=str, help='server\'s address')
@ -126,6 +126,7 @@ class ConfigurationGetter(object):
self._config.write(configfile) self._config.write(configfile)
def _setUpValuesToSave(self, section_name): def _setUpValuesToSave(self, section_name):
self._splitPortAndHost()
self._config.set(section_name, 'host', self._args.host) self._config.set(section_name, 'host', self._args.host)
self._config.set(section_name, 'name', self._args.name) self._config.set(section_name, 'name', self._args.name)
@ -146,11 +147,12 @@ class ConfigurationGetter(object):
self._args.name = self._config.get(section_name, 'name') self._args.name = self._config.get(section_name, 'name')
def _splitPortAndHost(self): def _splitPortAndHost(self):
if ':' in self._args.host: if(self._args.host):
self._args.host, port = self._args.host.split(':', 1) if ':' in self._args.host:
self._args.port = int(port) self._args.host, port = self._args.host.split(':', 1)
else: self._args.port = int(port)
self._args.port = 8999 else:
self._args.port = 8999
def prepareClientConfiguration(self): def prepareClientConfiguration(self):
self._findWorkingDirectory() self._findWorkingDirectory()

View File

@ -7,7 +7,8 @@ from syncplay import utils
class SyncplayMPC: class SyncplayMPC:
def runClient(self): def runClient(self):
self._prepareArguments() self._prepareArguments()
self.interface = ui.getUi(graphical = not self.args.no_gui) # self.interface = ui.getUi(graphical = not self.args.no_gui)
self.interface = ui.getUi(graphical = False) #TODO: add gui
self._promptForMissingArguments() self._promptForMissingArguments()
syncplayClient = client.SyncplayClientManager(self.args.name, lambda m: mpc.run_mpc(m, self.args.mpc_path, self.args.file, self.args._args), self.interface, self.args.debug) syncplayClient = client.SyncplayClientManager(self.args.name, lambda m: mpc.run_mpc(m, self.args.mpc_path, self.args.file, self.args._args), self.interface, self.args.debug)
self.interface.addClient(syncplayClient) self.interface.addClient(syncplayClient)