From db91c348a47d2c2b11efaf9b0ceed7423ff46ddc Mon Sep 17 00:00:00 2001 From: Uriziel Date: Sat, 6 Dec 2014 16:14:24 +0100 Subject: [PATCH] Added 'readiness' toggle to protocols and console UI --- syncplay/client.py | 59 +++++++++++++++++++++++++++++----------- syncplay/constants.py | 1 + syncplay/protocols.py | 27 ++++++++++++++++-- syncplay/server.py | 13 +++++++++ syncplay/ui/consoleUI.py | 7 ++++- 5 files changed, 88 insertions(+), 19 deletions(-) diff --git a/syncplay/client.py b/syncplay/client.py index 5fafbc6..23e9ac7 100644 --- a/syncplay/client.py +++ b/syncplay/client.py @@ -459,6 +459,17 @@ class SyncplayClient(object): if promptForAction: self.ui.promptFor(getMessage("enter-to-exit-prompt")) + def toggleReady(self): + self._protocol.setReady(not self.userlist.currentUser.isReady()) + + def setReady(self, username, isReady): + self.userlist.setReady(username, isReady) + if isReady: + message = "<{}> I'm ready".format(username) + else: + message = "<{}> I'm not ready".format(username) + self.ui.showMessage(message) + def requireMinServerVersion(minVersion): def requireMinVersionDecorator(f): @wraps(f) @@ -523,17 +534,17 @@ class SyncplayClient(object): self._userlist = userlist self._ui = ui self._warnings = { - "room-files-not-same": { - "timer": task.LoopingCall(self.__displayMessageOnOSD, - "room-files-not-same",), - "displayedFor": 0, - }, - "alone-in-the-room": { - "timer": task.LoopingCall(self.__displayMessageOnOSD, - "alone-in-the-room",), - "displayedFor": 0, - }, - } + "room-files-not-same": { + "timer": task.LoopingCall(self.__displayMessageOnOSD, + "room-files-not-same", ), + "displayedFor": 0, + }, + "alone-in-the-room": { + "timer": task.LoopingCall(self.__displayMessageOnOSD, + "alone-in-the-room", ), + "displayedFor": 0, + }, + } def checkWarnings(self): self._checkIfYouReAloneInTheRoom() self._checkRoomForSameFiles() @@ -566,6 +577,7 @@ class SyncplayClient(object): class SyncplayUser(object): def __init__(self, username=None, room=None, file_=None): + self.ready = False self.username = username self.room = room self.file = file_ @@ -573,10 +585,10 @@ class SyncplayUser(object): def setFile(self, filename, duration, size): file_ = { - "name": filename, - "duration": duration, - "size":size - } + "name": filename, + "duration": duration, + "size": size + } self.file = file_ def isFileSame(self, file_): @@ -611,6 +623,12 @@ class SyncplayUser(object): else: return False + def isReady(self): + return self.ready + + def setReady(self, ready): + self.ready = ready + class SyncplayUserlist(object): def __init__(self, ui, client): self.currentUser = SyncplayUser() @@ -659,15 +677,18 @@ class SyncplayUserlist(object): message = getMessage("file-differences-notification") + ", ".join(differences) self.ui.showMessage(message, hideFromOSD) - def addUser(self, username, room, file_, noMessage=False, isController=None): + def addUser(self, username, room, file_, noMessage=False, isController=None, isReady=False): if username == self.currentUser.username: if isController is not None: self.currentUser.setControllerStatus(isController) + self.currentUser.setReady(isReady) return user = SyncplayUser(username, room, file_) if isController is not None: user.setControllerStatus(isController) self._users[username] = user + user.setReady(isReady) + if not noMessage: self.__showUserChangeMessage(username, room, file_) self.userListChange(room) @@ -744,6 +765,12 @@ class SyncplayUserlist(object): return True return False + def setReady(self, username, isReady): + if self.currentUser.username == username: + self.currentUser.setReady(isReady) + elif self._users.has_key(username): + self._users[username].setReady(isReady) + def userListChange(self, room = None): if room is not None and self.isRoomSame(room): self._roomUsersChanged = True diff --git a/syncplay/constants.py b/syncplay/constants.py index 7bbb7ec..6e85c61 100644 --- a/syncplay/constants.py +++ b/syncplay/constants.py @@ -58,6 +58,7 @@ COMMANDS_ROOM = ["r", "room"] COMMANDS_HELP = ['help', 'h', '?', '/?', r'\?'] COMMANDS_CREATE = ['c','create'] COMMANDS_AUTH = ['a','auth'] +COMMANDS_READY = ['re'] MPC_MIN_VER = "1.6.4" VLC_MIN_VERSION = "2.0.0" VLC_INTERFACE_MIN_VERSION = "0.2.1" diff --git a/syncplay/protocols.py b/syncplay/protocols.py index 8271a2b..f262623 100644 --- a/syncplay/protocols.py +++ b/syncplay/protocols.py @@ -136,6 +136,9 @@ class SyncClientProtocol(JSONCommandProtocol): controlPassword = values['password'] roomName = values['roomName'] self._client.controlledRoomCreated(roomName, controlPassword) + elif command == "ready": + user, isReady = values["username"], values["isReady"] + self._client.setReady(user, isReady) def sendSet(self, setting): self.sendMessage({"Set": setting}) @@ -158,7 +161,8 @@ class SyncClientProtocol(JSONCommandProtocol): userName = user[0] file_ = user[1]['file'] if user[1]['file'] <> {} else None isController = user[1]['controller'] if 'controller' in user[1] else False - self._client.userlist.addUser(userName, roomName, file_, noMessage=True, isController=isController) + isReady = user[1]['isReady'] if 'isReady' in user[1] else False + self._client.userlist.addUser(userName, roomName, file_, noMessage=True, isController=isController, isReady=isReady) self._client.userlist.showUserList() def sendList(self): @@ -234,6 +238,13 @@ class SyncClientProtocol(JSONCommandProtocol): } }) + def setReady(self, isReady): + self.sendSet({ + "ready": { + "isReady": isReady + } + }) + def handleError(self, error): self.dropWithError(error["message"]) @@ -342,6 +353,8 @@ class SyncServerProtocol(JSONCommandProtocol): password = set_[1]["password"] if set_[1].has_key("password") else None room = set_[1]["room"] if set_[1].has_key("room") else None self._factory.authRoomController(self._watcher, password, room) + elif command == "ready": + self._factory.setReady(self._watcher, set_[1]['isReady']) def sendSet(self, setting): self.sendMessage({"Set": setting}) @@ -363,6 +376,15 @@ class SyncServerProtocol(JSONCommandProtocol): } }) + + def sendSetReady(self, username, isReady): + self.sendSet({ + "ready": { + "username": username, + "isReady": isReady + } + }) + def sendUserSetting(self, username, room, file_, event): room = {"name": room.getName()} user = {username: {}} @@ -381,7 +403,8 @@ class SyncServerProtocol(JSONCommandProtocol): userFile = { "position": 0, "file": watcher.getFile() if watcher.getFile() else {}, - "controller": watcher.isController() + "controller": watcher.isController(), + "isReady": watcher.isReady() } userlist[room.getName()][watcher.getName()] = userFile diff --git a/syncplay/server.py b/syncplay/server.py index 221b262..b743ea9 100644 --- a/syncplay/server.py +++ b/syncplay/server.py @@ -125,6 +125,9 @@ class SyncFactory(Factory): except ValueError: self._roomManager.broadcastRoom(watcher, lambda w: w.sendControlledRoomAuthStatus(False, watcher.getName(), room._name)) + def setReady(self, watcher, isReady): + watcher.setReady(isReady) + self._roomManager.broadcastRoom(watcher, lambda w: w.sendSetReady(watcher.getName(), isReady)) class RoomManager(object): def __init__(self): @@ -299,6 +302,7 @@ class ControlledRoom(Room): class Watcher(object): def __init__(self, server, connector, name): + self._ready = False self._server = server self._connector = connector self._name = name @@ -322,6 +326,12 @@ class Watcher(object): self._resetStateTimer() self._askForStateUpdate(True, True) + def setReady(self, ready): + self._ready = ready + + def isReady(self): + return self._ready + def getRoom(self): return self._room @@ -352,6 +362,9 @@ class Watcher(object): def sendControlledRoomAuthStatus(self, success, username, room): self._connector.sendControlledRoomAuthStatus(success, username, room) + def sendSetReady(self, username, isReady): + self._connector.sendSetReady(username, isReady) + def __lt__(self, b): if self.getPosition() is None or self._file is None: return False diff --git a/syncplay/ui/consoleUI.py b/syncplay/ui/consoleUI.py index 1b060ef..f113d80 100644 --- a/syncplay/ui/consoleUI.py +++ b/syncplay/ui/consoleUI.py @@ -54,7 +54,10 @@ class ConsoleUI(threading.Thread): for user in rooms[room]: userflags = u"" if user.isController(): - userflags = userflags + u"(Controller) " + userflags += u"(Controller) " + if user.isReady(): + userflags += u"(Ready) " + username = userflags + u"*<{}>*".format(user.username) if user == currentUser else userflags + u"<{}>".format(user.username) if user.file: message = u"{} is playing:".format(username) @@ -149,6 +152,8 @@ class ConsoleUI(threading.Thread): elif command.group('command') in constants.COMMANDS_AUTH: controlpassword = command.group('parameter') self._syncplayClient.identifyAsController(controlpassword) + elif command.group('command') in constants.COMMANDS_READY: + self._syncplayClient.toggleReady() else: if self._tryAdvancedCommands(data): return