From db91c348a47d2c2b11efaf9b0ceed7423ff46ddc Mon Sep 17 00:00:00 2001
From: Uriziel
Date: Sat, 6 Dec 2014 16:14:24 +0100
Subject: [PATCH 01/63] 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
From 383d0b65c2c83d29de5466e48e9cbc6c9f0bffe5 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 6 Dec 2014 16:40:10 +0000
Subject: [PATCH 02/63] Initial readiness GUI code + none state (back compat_ +
1.3.1 ver-up/ver-check
---
syncplay/__init__.py | 4 ++--
syncplay/client.py | 43 +++++++++++++++++++++++++++++++------------
syncplay/constants.py | 1 +
syncplay/protocols.py | 2 +-
syncplay/server.py | 2 +-
syncplay/ui/gui.py | 20 +++++++++++++++++++-
6 files changed, 55 insertions(+), 17 deletions(-)
diff --git a/syncplay/__init__.py b/syncplay/__init__.py
index a1fa3eb..ff59e5a 100644
--- a/syncplay/__init__.py
+++ b/syncplay/__init__.py
@@ -1,3 +1,3 @@
-version = '1.3.0'
-milestone = 'Akki'
+version = '1.3.1'
+milestone = 'Chami'
projectURL = 'http://syncplay.pl/'
diff --git a/syncplay/client.py b/syncplay/client.py
index 23e9ac7..855b73f 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -402,6 +402,10 @@ class SyncplayClient(object):
self.identifyAsController(storedRoomPassword)
def connected(self):
+ if self.userlist.currentUser.isReady() is not None:
+ self._protocol.setReady(self.userlist.currentUser.isReady())
+ else:
+ self._protocol.setReady(False)
self.reIdentifyAsController()
def getRoom(self):
@@ -459,17 +463,6 @@ 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)
@@ -481,6 +474,23 @@ class SyncplayClient(object):
return wrapper
return requireMinVersionDecorator
+ @requireMinServerVersion(constants.USER_READY_MIN_VERSION)
+ def toggleReady(self):
+ self._protocol.setReady(not self.userlist.currentUser.isReady())
+
+ def setReady(self, username, isReady):
+ oldReadyState = self.userlist.isReady(username)
+ if oldReadyState is None:
+ oldReadyState = False
+ self.userlist.setReady(username, isReady)
+ self.ui.userListChange()
+ if oldReadyState != isReady:
+ if isReady:
+ message = "<{}> I'm ready".format(username)
+ else:
+ message = "<{}> I'm not ready".format(username)
+ self.ui.showMessage(message)
+
@requireMinServerVersion(constants.CONTROLLED_ROOMS_MIN_VERSION)
def createControlledRoom(self, roomName):
controlPassword = utils.RandomStringGenerator.generate_room_password()
@@ -577,7 +587,7 @@ class SyncplayClient(object):
class SyncplayUser(object):
def __init__(self, username=None, room=None, file_=None):
- self.ready = False
+ self.ready = None
self.username = username
self.room = room
self.file = file_
@@ -765,6 +775,15 @@ class SyncplayUserlist(object):
return True
return False
+ def isReady(self, username):
+ if self.currentUser.username == username:
+ return self.currentUser.isReady()
+
+ for user in self._users.itervalues():
+ if user.username == username:
+ return user.isReady()
+ return False
+
def setReady(self, username, isReady):
if self.currentUser.username == username:
self.currentUser.setReady(isReady)
diff --git a/syncplay/constants.py b/syncplay/constants.py
index 6e85c61..19d9dfe 100644
--- a/syncplay/constants.py
+++ b/syncplay/constants.py
@@ -63,6 +63,7 @@ MPC_MIN_VER = "1.6.4"
VLC_MIN_VERSION = "2.0.0"
VLC_INTERFACE_MIN_VERSION = "0.2.1"
CONTROLLED_ROOMS_MIN_VERSION = "1.3.0"
+USER_READY_MIN_VERSION = "1.3.1"
MPC_PATHS = [
r"c:\program files (x86)\mpc-hc\mpc-hc.exe",
r"c:\program files\mpc-hc\mpc-hc.exe",
diff --git a/syncplay/protocols.py b/syncplay/protocols.py
index f262623..cd1ead6 100644
--- a/syncplay/protocols.py
+++ b/syncplay/protocols.py
@@ -161,7 +161,7 @@ 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
- isReady = user[1]['isReady'] if 'isReady' in user[1] else False
+ isReady = user[1]['isReady'] if 'isReady' in user[1] else None
self._client.userlist.addUser(userName, roomName, file_, noMessage=True, isController=isController, isReady=isReady)
self._client.userlist.showUserList()
diff --git a/syncplay/server.py b/syncplay/server.py
index b743ea9..6e61ef9 100644
--- a/syncplay/server.py
+++ b/syncplay/server.py
@@ -302,7 +302,7 @@ class ControlledRoom(Room):
class Watcher(object):
def __init__(self, server, connector, name):
- self._ready = False
+ self._ready = None
self._server = server
self._connector = connector
self._name = name
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 5b02d8b..dd51ecd 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -125,7 +125,13 @@ class MainWindow(QtGui.QMainWindow):
for user in rooms[room]:
useritem = QtGui.QStandardItem(user.username)
isController = user.isController()
+ sameRoom = room == currentUser.room
+ if sameRoom:
+ isReady = user.isReady()
+ else:
+ isReady = None
useritem.setData(isController, Qt.UserRole + constants.USERITEM_CONTROLLER_ROLE)
+ useritem.setData(isReady, Qt.UserRole + constants.USERITEM_READY_ROLE)
if user.file:
filesizeitem = QtGui.QStandardItem(formatSize(user.file['size']))
filedurationitem = QtGui.QStandardItem("({})".format(formatTime(user.file['duration'])))
@@ -134,7 +140,6 @@ class MainWindow(QtGui.QMainWindow):
sameName = sameFilename(user.file['name'], currentUser.file['name'])
sameSize = sameFilesize(user.file['size'], currentUser.file['size'])
sameDuration = sameFileduration(user.file['duration'], currentUser.file['duration'])
- sameRoom = room == currentUser.room
underlinefont = QtGui.QFont()
underlinefont.setUnderline(True)
if sameRoom:
@@ -446,6 +451,15 @@ class MainWindow(QtGui.QMainWindow):
window.listLayout.setContentsMargins(0, 0, 0, 0)
window.listLayout.addWidget(window.listlabel)
window.listLayout.addWidget(window.listTreeView)
+
+ window.readyCheckbox = QtGui.QCheckBox()
+ readyFont = QtGui.QFont()
+ readyFont.setWeight(QtGui.QFont.Bold)
+ window.readyCheckbox.setText("I'm ready to watch!")
+ window.readyCheckbox.setFont(readyFont)
+ window.readyCheckbox.toggled.connect(self.changeReadyState)
+ window.listLayout.addWidget(window.readyCheckbox, Qt.AlignRight)
+
window.contactLabel = QtGui.QLabel()
window.contactLabel.setWordWrap(True)
window.contactLabel.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Sunken)
@@ -606,6 +620,10 @@ class MainWindow(QtGui.QMainWindow):
self.listbox.insertHtml(item)
self.listbox.moveCursor(QtGui.QTextCursor.End)
+ def changeReadyState(self):
+ if self.readyCheckbox.isChecked() != self._syncplayClient.userlist.currentUser.isReady():
+ self._syncplayClient.toggleReady()
+
def dragEnterEvent(self, event):
data = event.mimeData()
urls = data.urls()
From 90c3ca2ab0f98b7cb76b4858e403e6f9765ab8fc Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 6 Dec 2014 18:39:32 +0000
Subject: [PATCH 03/63] Change ready state automatically on manual
pause/unpause
---
syncplay/client.py | 14 ++++++++++++++
syncplay/constants.py | 1 +
syncplay/ui/gui.py | 9 +++++++--
3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/syncplay/client.py b/syncplay/client.py
index 855b73f..fba023a 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -68,6 +68,7 @@ class SyncplayClient(object):
self.serverVersion = "0.0.0"
self.lastLeftTime = 0
+ self.lastPausedOnLeaveTime = None
self.lastLeftUser = u""
self.protocolFactory = SyncClientFactory(self)
self.ui = UiManager(self, ui)
@@ -158,6 +159,12 @@ class SyncplayClient(object):
pauseChange, seeked = self._determinePlayerStateChange(paused, position)
self._playerPosition = position
self._playerPaused = paused
+ if pauseChange and utils.meetsMinVersion(self.serverVersion, constants.USER_READY_MIN_VERSION):
+ lastPausedDiff = time.time() - self.lastPausedOnLeaveTime if self.lastPausedOnLeaveTime else None
+ if lastPausedDiff is not None and lastPausedDiff < constants.LAST_PAUSED_DIFF_THRESHOLD:
+ self.lastPausedOnLeaveTime = None
+ else:
+ self.changeReadyState(not self.getPlayerPaused())
if self._lastGlobalUpdate:
self._lastPlayerUpdate = time.time()
if (pauseChange or seeked) and self._protocol:
@@ -303,6 +310,7 @@ class SyncplayClient(object):
def onDisconnect(self):
if self._config['pauseOnLeave']:
self.setPaused(True)
+ self.lastPausedOnLeaveTime = time.time()
def removeUser(self, username):
if self.userlist.isUserInYourRoom(username):
@@ -478,6 +486,12 @@ class SyncplayClient(object):
def toggleReady(self):
self._protocol.setReady(not self.userlist.currentUser.isReady())
+ @requireMinServerVersion(constants.USER_READY_MIN_VERSION)
+ def changeReadyState(self, newState):
+ oldState = self.userlist.currentUser.isReady()
+ if newState != oldState:
+ self.toggleReady()
+
def setReady(self, username, isReady):
oldReadyState = self.userlist.isReady(username)
if oldReadyState is None:
diff --git a/syncplay/constants.py b/syncplay/constants.py
index 19d9dfe..7f389f3 100644
--- a/syncplay/constants.py
+++ b/syncplay/constants.py
@@ -48,6 +48,7 @@ WARNING_OSD_MESSAGES_LOOP_INTERVAL = 1
MERGE_PLAYPAUSE_BUTTONS = False
SYNC_ON_PAUSE = True # Client seek to global position - subtitles may disappear on some media players
#Usually there's no need to adjust these
+LAST_PAUSED_DIFF_THRESHOLD = 2
FILENAME_STRIP_REGEX = u"[-~_\.\[\](): ]"
CONTROL_PASSWORD_STRIP_REGEX = u"[^a-zA-Z0-9\-]"
ROOM_NAME_STRIP_REGEX = u"^(\+)(?P.*)(:)(\w{12})$"
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index dd51ecd..7075319 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -163,6 +163,7 @@ class MainWindow(QtGui.QMainWindow):
font = QtGui.QFont()
if currentUser.username == user.username:
font.setWeight(QtGui.QFont.Bold)
+ self.updateReadyState(currentUser.isReady())
if isControlledRoom and not isController:
useritem.setForeground(QtGui.QBrush(QtGui.QColor(constants.STYLE_NOTCONTROLLER_COLOR)))
useritem.setFont(font)
@@ -199,6 +200,11 @@ class MainWindow(QtGui.QMainWindow):
except:
pass
+ def updateReadyState(self, newState):
+ oldState = self.readyCheckbox.isChecked()
+ if newState != oldState:
+ self.readyCheckbox.setChecked(newState)
+
def roomClicked(self, item):
while item.parent().row() != -1:
item = item.parent()
@@ -621,8 +627,7 @@ class MainWindow(QtGui.QMainWindow):
self.listbox.moveCursor(QtGui.QTextCursor.End)
def changeReadyState(self):
- if self.readyCheckbox.isChecked() != self._syncplayClient.userlist.currentUser.isReady():
- self._syncplayClient.toggleReady()
+ self._syncplayClient.changeReadyState(self.readyCheckbox.isChecked())
def dragEnterEvent(self, event):
data = event.mimeData()
From 0a924ac299a11a55cfa0f374be18805d5651b704 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 6 Dec 2014 19:01:46 +0000
Subject: [PATCH 04/63] Ignore manual pause if can't control + (mostly) honour
OSD options for isReady
---
syncplay/client.py | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/syncplay/client.py b/syncplay/client.py
index fba023a..aa3ee1b 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -159,7 +159,7 @@ class SyncplayClient(object):
pauseChange, seeked = self._determinePlayerStateChange(paused, position)
self._playerPosition = position
self._playerPaused = paused
- if pauseChange and utils.meetsMinVersion(self.serverVersion, constants.USER_READY_MIN_VERSION):
+ if pauseChange and utils.meetsMinVersion(self.serverVersion, constants.USER_READY_MIN_VERSION) and self.userlist.currentUser.canControl():
lastPausedDiff = time.time() - self.lastPausedOnLeaveTime if self.lastPausedOnLeaveTime else None
if lastPausedDiff is not None and lastPausedDiff < constants.LAST_PAUSED_DIFF_THRESHOLD:
self.lastPausedOnLeaveTime = None
@@ -499,11 +499,16 @@ class SyncplayClient(object):
self.userlist.setReady(username, isReady)
self.ui.userListChange()
if oldReadyState != isReady:
+ showOnOSD = constants.SHOW_OSD_WARNINGS
+ if constants.SHOW_NONCONTROLLER_OSD == False and self.userlist.canControl(username) == False and self.userlist.currentUser.isController() == False:
+ # Ignore SHOW_NONCONTROLLER_OSD setting if user is controller, because they need to know who is/isn't ready
+ showOnOSD = False
+ hideFromOSD = not showOnOSD
if isReady:
message = "<{}> I'm ready".format(username)
else:
message = "<{}> I'm not ready".format(username)
- self.ui.showMessage(message)
+ self.ui.showMessage(message, hideFromOSD)
@requireMinServerVersion(constants.CONTROLLED_ROOMS_MIN_VERSION)
def createControlledRoom(self, roomName):
From ebeaa92724cd5d9075a94cf855cd1893c8cbd166 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 6 Dec 2014 19:14:52 +0000
Subject: [PATCH 05/63] Add readyAtStart config option
---
syncplay/client.py | 2 +-
syncplay/messages.py | 2 ++
syncplay/ui/ConfigurationGetter.py | 4 +++-
syncplay/ui/GuiConfiguration.py | 12 ++++++++----
4 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/syncplay/client.py b/syncplay/client.py
index aa3ee1b..dfac60c 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -413,7 +413,7 @@ class SyncplayClient(object):
if self.userlist.currentUser.isReady() is not None:
self._protocol.setReady(self.userlist.currentUser.isReady())
else:
- self._protocol.setReady(False)
+ self._protocol.setReady(self._config['readyAtStart'])
self.reIdentifyAsController()
def getRoom(self):
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 0d6d06b..1bf5f37 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -156,6 +156,7 @@ en = {
"fastforwardondesync-label" : "Fast-forward if lagging behind (recommended)",
"dontslowdownwithme-label" : "Never slow down or rewind others (experimental)",
"pauseonleave-label" : "Pause when user leaves (e.g. if they are disconnected)",
+ "readyatstart-label" : "Set me as 'ready to watch' by default",
"forceguiprompt-label" : "Don't always show this dialog", # (Inverted)
"nostore-label" : "Don't store this configuration", # (Inverted)
"showosd-label" : "Enable OSD Messages",
@@ -250,6 +251,7 @@ en = {
"slowondesync-tooltip" : "Reduce playback rate temporarily when needed to bring you back in sync with other viewers. Not supported on MPC-HC.",
"dontslowdownwithme-tooltip" : "Means others do not get slowed down or rewinded if your playback is lagging. Useful for room controllers.",
"pauseonleave-tooltip" : "Pause playback if you get disconnected or someone leaves from your room.",
+ "readyatstart-tooltip" : "Set yourself as 'ready' at start (otherwise you are set as 'not ready' until you change your readiness state)",
"forceguiprompt-tooltip" : "Configuration dialogue is not shown when opening a file with Syncplay.", # (Inverted)
"nostore-tooltip" : "Run Syncplay with the given configuration, but do not permanently store the changes.", # (Inverted)
"rewindondesync-tooltip" : "Jump back when needed to get back in sync. Disabling this option can result in major desyncs!",
diff --git a/syncplay/ui/ConfigurationGetter.py b/syncplay/ui/ConfigurationGetter.py
index 9feec05..89ce26b 100755
--- a/syncplay/ui/ConfigurationGetter.py
+++ b/syncplay/ui/ConfigurationGetter.py
@@ -44,6 +44,7 @@ class ConfigurationGetter(object):
"filenamePrivacyMode": constants.PRIVACY_SENDRAW_MODE,
"filesizePrivacyMode": constants.PRIVACY_SENDRAW_MODE,
"pauseOnLeave": False,
+ "readyAtStart": False,
"clearGUIData": False,
"language" : "",
"resetConfig" : False,
@@ -77,6 +78,7 @@ class ConfigurationGetter(object):
"noStore",
"dontSlowDownWithMe",
"pauseOnLeave",
+ "readyAtStart",
"clearGUIData",
"rewindOnDesync",
"slowOnDesync",
@@ -102,7 +104,7 @@ class ConfigurationGetter(object):
self._iniStructure = {
"server_data": ["host", "port", "password"],
- "client_settings": ["name", "room", "playerPath", "slowdownThreshold", "rewindThreshold", "fastforwardThreshold", "slowOnDesync", "rewindOnDesync", "fastforwardOnDesync", "dontSlowDownWithMe", "forceGuiPrompt", "filenamePrivacyMode", "filesizePrivacyMode", "pauseOnLeave"],
+ "client_settings": ["name", "room", "playerPath", "slowdownThreshold", "rewindThreshold", "fastforwardThreshold", "slowOnDesync", "rewindOnDesync", "fastforwardOnDesync", "dontSlowDownWithMe", "forceGuiPrompt", "filenamePrivacyMode", "filesizePrivacyMode", "pauseOnLeave", "readyAtStart"],
"gui": ["showOSD", "showOSDWarnings", "showSlowdownOSD", "showDifferentRoomOSD", "showSameRoomOSD", "showNonControllerOSD", "showContactInfo" , "showDurationNotification"],
"general": ["language"]
}
diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py
index 21c69c8..9c1b0f1 100644
--- a/syncplay/ui/GuiConfiguration.py
+++ b/syncplay/ui/GuiConfiguration.py
@@ -545,17 +545,21 @@ class ConfigDialog(QtGui.QDialog):
self.othersyncSettingsLayout.addWidget(self.pauseonleaveCheckbox, 1, 0, 1, 2, Qt.AlignLeft)
self.pauseonleaveCheckbox.setObjectName("pauseOnLeave")
+ self.readyatstartCheckbox = QCheckBox(getMessage("readyatstart-label"))
+ self.othersyncSettingsLayout.addWidget(self.readyatstartCheckbox, 2, 0, 1, 2, Qt.AlignLeft)
+ self.readyatstartCheckbox.setObjectName("readyAtStart")
+
self.dontslowwithmeCheckbox = QCheckBox(getMessage("dontslowdownwithme-label"))
self.dontslowwithmeCheckbox.setObjectName("dontSlowDownWithMe")
- self.othersyncSettingsLayout.addWidget(self.dontslowwithmeCheckbox, 2, 0, 1, 2, Qt.AlignLeft)
+ self.othersyncSettingsLayout.addWidget(self.dontslowwithmeCheckbox, 3, 0, 1, 2, Qt.AlignLeft)
self.fastforwardThresholdLabel.setObjectName("fastforward-threshold")
self.fastforwardThresholdSpinbox.setObjectName("fastforward-threshold")
- self.othersyncSettingsLayout.addWidget(self.fastforwardCheckbox, 3, 0,1,2, Qt.AlignLeft)
- self.othersyncSettingsLayout.addWidget(self.fastforwardThresholdLabel, 4, 0, 1, 1, Qt.AlignLeft)
- self.othersyncSettingsLayout.addWidget(self.fastforwardThresholdSpinbox, 4, 1, Qt.AlignLeft)
+ self.othersyncSettingsLayout.addWidget(self.fastforwardCheckbox, 4, 0,1,2, Qt.AlignLeft)
+ self.othersyncSettingsLayout.addWidget(self.fastforwardThresholdLabel, 5, 0, 1, 1, Qt.AlignLeft)
+ self.othersyncSettingsLayout.addWidget(self.fastforwardThresholdSpinbox, 5, 1, Qt.AlignLeft)
self.subitems['fastforwardOnDesync'] = ["fastforward-threshold"]
self.othersyncSettingsGroup.setLayout(self.othersyncSettingsLayout)
From b9374adc6cbb13e51c5c3a404e2f3024ec1497f5 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 6 Dec 2014 19:29:43 +0000
Subject: [PATCH 06/63] Handle ready none status in checkbox update
---
syncplay/ui/gui.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 7075319..c60ea11 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -202,7 +202,7 @@ class MainWindow(QtGui.QMainWindow):
def updateReadyState(self, newState):
oldState = self.readyCheckbox.isChecked()
- if newState != oldState:
+ if newState != oldState and newState != None:
self.readyCheckbox.setChecked(newState)
def roomClicked(self, item):
From fe040438f55fa0f55f71c55f73f6cd4c4eca3758 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 6 Dec 2014 19:38:34 +0000
Subject: [PATCH 07/63] Move ready/not-ready messages into messages.py
---
syncplay/client.py | 4 ++--
syncplay/messages.py | 3 +++
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/syncplay/client.py b/syncplay/client.py
index dfac60c..907d243 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -505,9 +505,9 @@ class SyncplayClient(object):
showOnOSD = False
hideFromOSD = not showOnOSD
if isReady:
- message = "<{}> I'm ready".format(username)
+ message = getMessage("user-ready-notification").format(username)
else:
- message = "<{}> I'm not ready".format(username)
+ message = getMessage("user-not-ready-notification").format(username)
self.ui.showMessage(message, hideFromOSD)
@requireMinServerVersion(constants.CONTROLLED_ROOMS_MIN_VERSION)
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 1bf5f37..aee0f99 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -33,6 +33,9 @@ en = {
"playing-notification" : "<{}> is playing '{}' ({})", # User, file, duration
"playing-notification/room-addendum" : " in room: '{}'", # Room
+ "user-ready-notification" : "<{}> I'm ready", # Username
+ "user-not-ready-notification" : "<{}> I'm ready", # Username
+
"identifying-as-controller-notification" : u"Identifying as room controller with password '{}'...",
"failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room controller.",
"authenticated-as-controller-notification" : u"<{}> authenticated as a room controller",
From d3be1f0917134f9e68faedda3a7380fb38a00ac7 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 6 Dec 2014 19:39:12 +0000
Subject: [PATCH 08/63] Fix not-ready message
---
syncplay/messages.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/syncplay/messages.py b/syncplay/messages.py
index aee0f99..450a074 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -34,7 +34,7 @@ en = {
"playing-notification/room-addendum" : " in room: '{}'", # Room
"user-ready-notification" : "<{}> I'm ready", # Username
- "user-not-ready-notification" : "<{}> I'm ready", # Username
+ "user-not-ready-notification" : "<{}> I'm not ready", # Username
"identifying-as-controller-notification" : u"Identifying as room controller with password '{}'...",
"failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room controller.",
From cabadec4e7e97a0cfb0b6282ab3ec54a58458128 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sun, 7 Dec 2014 01:38:05 +0000
Subject: [PATCH 09/63] Move from readyCheckbox to readyPushButton
---
resources/cross_checkbox.png | Bin 0 -> 671 bytes
resources/tick_checkbox.png | Bin 0 -> 556 bytes
syncplay/constants.py | 1 +
syncplay/ui/gui.py | 29 +++++++++++++++++++++--------
4 files changed, 22 insertions(+), 8 deletions(-)
create mode 100644 resources/cross_checkbox.png
create mode 100644 resources/tick_checkbox.png
diff --git a/resources/cross_checkbox.png b/resources/cross_checkbox.png
new file mode 100644
index 0000000000000000000000000000000000000000..785a5293ff074071b220d7d9c7a44e9df67a0d8f
GIT binary patch
literal 671
zcmV;Q0$}}#P)pF8gxZibW?9;ba!ELWdKlNX>N2bPDNB8
zb~7$DE-^4L^m3s900J9HL_t(IPoedeFoe{}kg*k6buvh(;3>J+!rmNgujlY_PoYwUI2Vq0!L{xB74
zu6X9GPofAsZ2RrIK*=G(w0sgppy+?lB84hWGeV(I=r6^0HpC2D{>A_R002ovPDHLk
FV1iWEFpvNM
literal 0
HcmV?d00001
diff --git a/resources/tick_checkbox.png b/resources/tick_checkbox.png
new file mode 100644
index 0000000000000000000000000000000000000000..d434c7f14eed680af0da2081d2328a92cb5e0cf4
GIT binary patch
literal 556
zcmV+{0@MA8P)pF8gxZibW?9;ba!ELWdKlNX>N2bPDNB8
zb~7$DE-^4L^m3s900F2;L_t(IPsPy5OM*ch#_{)WY9TEuZ_z0%X|=Kp+VobY=JKk&
zg@x78R-@HJi&-9m3aLZBmPXP-b?X{+%=gvc$$1k)%*Z_Sg@Ktle3;)*B$}p??-G!F
z^ZWh(47q}{aEDiur$0iA>
z?=g7P51n6)g9o2*N19I{J=<-thm05t8PL8~j|!_Og^*Iv&2t2rLls6@9UNgAEgN<4
z-R@$EokRDQ9HSQoFy}h7uF6nuDM>>}DTsgPq4YFClX%f|WCRSWN1s;#^}Z4|RtxL7
z7V?!kl+nc*2q|qeF3zEOT?(~NDg49O#V{;E4J@n%&C9hYH5Gk}kTO1-i$@`ytwz^o
z3#`E*m;wW6T9QI+EX<0KG9Xek7Dd&hBr%E%4Xzr93}7>WQU2{$2
Date: Sun, 7 Dec 2014 01:42:59 +0000
Subject: [PATCH 10/63] Include tick and cross checkbox images within Windows
installer
---
buildPy2exe.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/buildPy2exe.py b/buildPy2exe.py
index 49f1d46..b9b586b 100644
--- a/buildPy2exe.py
+++ b/buildPy2exe.py
@@ -624,7 +624,7 @@ guiIcons = ['resources/accept.png', 'resources/arrow_undo.png', 'resources/clock
'resources/mpv.png','resources/vlc.png', 'resources/house.png', 'resources/film_link.png',
'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/chevrons_right.png',
'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png',
- 'resources/tick.png', 'resources/lock_open.png'
+ 'resources/tick.png', 'resources/lock_open.png', 'resources/cross_checkbox.png', 'resources/tick_checkbox.png'
]
resources = ["resources/icon.ico", "resources/syncplay.png"]
resources.extend(guiIcons)
From 29f109f1fb21ee9b46b500742244c19108862719 Mon Sep 17 00:00:00 2001
From: Uriziel
Date: Sun, 7 Dec 2014 16:16:29 +0100
Subject: [PATCH 11/63] Changed default program to run syncplay (python to
python2) in *nix
---
syncplayClient.py | 2 +-
syncplayServer.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/syncplayClient.py b/syncplayClient.py
index 236df21..107d942 100755
--- a/syncplayClient.py
+++ b/syncplayClient.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
import site, sys
diff --git a/syncplayServer.py b/syncplayServer.py
index c127fbf..23b5381 100755
--- a/syncplayServer.py
+++ b/syncplayServer.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
#coding:utf8
import site, sys
From 440c79f1a3690d70050bcf73453b89baf3f99a7c Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 13 Dec 2014 11:30:11 +0000
Subject: [PATCH 12/63] Specify whether change in ready state is manually
initiated or automatic
---
syncplay/client.py | 20 +++++++++-----------
syncplay/protocols.py | 16 ++++++++++------
syncplay/server.py | 8 ++++----
3 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/syncplay/client.py b/syncplay/client.py
index 907d243..11f05b2 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -164,7 +164,7 @@ class SyncplayClient(object):
if lastPausedDiff is not None and lastPausedDiff < constants.LAST_PAUSED_DIFF_THRESHOLD:
self.lastPausedOnLeaveTime = None
else:
- self.changeReadyState(not self.getPlayerPaused())
+ self.changeReadyState(not self.getPlayerPaused(), manuallyInitiated=False)
if self._lastGlobalUpdate:
self._lastPlayerUpdate = time.time()
if (pauseChange or seeked) and self._protocol:
@@ -410,10 +410,8 @@ class SyncplayClient(object):
self.identifyAsController(storedRoomPassword)
def connected(self):
- if self.userlist.currentUser.isReady() is not None:
- self._protocol.setReady(self.userlist.currentUser.isReady())
- else:
- self._protocol.setReady(self._config['readyAtStart'])
+ readyState = self._config['readyAtStart'] if self.userlist.currentUser.isReady() is None else self.userlist.currentUser.isReady()
+ self._protocol.setReady(readyState, manuallyInitiated=False)
self.reIdentifyAsController()
def getRoom(self):
@@ -483,22 +481,22 @@ class SyncplayClient(object):
return requireMinVersionDecorator
@requireMinServerVersion(constants.USER_READY_MIN_VERSION)
- def toggleReady(self):
- self._protocol.setReady(not self.userlist.currentUser.isReady())
+ def toggleReady(self, manuallyInitiated=True):
+ self._protocol.setReady(not self.userlist.currentUser.isReady(), manuallyInitiated)
@requireMinServerVersion(constants.USER_READY_MIN_VERSION)
- def changeReadyState(self, newState):
+ def changeReadyState(self, newState, manuallyInitiated=True):
oldState = self.userlist.currentUser.isReady()
if newState != oldState:
- self.toggleReady()
+ self.toggleReady(manuallyInitiated)
- def setReady(self, username, isReady):
+ def setReady(self, username, isReady, manuallyInitiated=True):
oldReadyState = self.userlist.isReady(username)
if oldReadyState is None:
oldReadyState = False
self.userlist.setReady(username, isReady)
self.ui.userListChange()
- if oldReadyState != isReady:
+ if manuallyInitiated and oldReadyState != isReady:
showOnOSD = constants.SHOW_OSD_WARNINGS
if constants.SHOW_NONCONTROLLER_OSD == False and self.userlist.canControl(username) == False and self.userlist.currentUser.isController() == False:
# Ignore SHOW_NONCONTROLLER_OSD setting if user is controller, because they need to know who is/isn't ready
diff --git a/syncplay/protocols.py b/syncplay/protocols.py
index cd1ead6..a91d429 100644
--- a/syncplay/protocols.py
+++ b/syncplay/protocols.py
@@ -138,7 +138,8 @@ class SyncClientProtocol(JSONCommandProtocol):
self._client.controlledRoomCreated(roomName, controlPassword)
elif command == "ready":
user, isReady = values["username"], values["isReady"]
- self._client.setReady(user, isReady)
+ manuallyInitiated = values["manuallyInitiated"] if values.has_key("manuallyInitiated") else True
+ self._client.setReady(user, isReady, manuallyInitiated)
def sendSet(self, setting):
self.sendMessage({"Set": setting})
@@ -238,10 +239,11 @@ class SyncClientProtocol(JSONCommandProtocol):
}
})
- def setReady(self, isReady):
+ def setReady(self, isReady, manuallyInitiated=True):
self.sendSet({
"ready": {
- "isReady": isReady
+ "isReady": isReady,
+ "manuallyInitiated": manuallyInitiated
}
})
@@ -354,7 +356,8 @@ class SyncServerProtocol(JSONCommandProtocol):
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'])
+ manuallyInitiated = set_[1]['manuallyInitiated'] if set_[1].has_key("manuallyInitiated") else False
+ self._factory.setReady(self._watcher, set_[1]['isReady'], manuallyInitiated=manuallyInitiated)
def sendSet(self, setting):
self.sendMessage({"Set": setting})
@@ -377,11 +380,12 @@ class SyncServerProtocol(JSONCommandProtocol):
})
- def sendSetReady(self, username, isReady):
+ def sendSetReady(self, username, isReady, manuallyInitiated=True):
self.sendSet({
"ready": {
"username": username,
- "isReady": isReady
+ "isReady": isReady,
+ "manuallyInitiated": manuallyInitiated
}
})
diff --git a/syncplay/server.py b/syncplay/server.py
index 6e61ef9..f2bded0 100644
--- a/syncplay/server.py
+++ b/syncplay/server.py
@@ -125,9 +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):
+ def setReady(self, watcher, isReady, manuallyInitiated=True):
watcher.setReady(isReady)
- self._roomManager.broadcastRoom(watcher, lambda w: w.sendSetReady(watcher.getName(), isReady))
+ self._roomManager.broadcastRoom(watcher, lambda w: w.sendSetReady(watcher.getName(), isReady, manuallyInitiated))
class RoomManager(object):
def __init__(self):
@@ -362,8 +362,8 @@ 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 sendSetReady(self, username, isReady, manuallyInitiated=True):
+ self._connector.sendSetReady(username, isReady, manuallyInitiated)
def __lt__(self, b):
if self.getPosition() is None or self._file is None:
From 3ff43473eb9ac332e5f9b4a14cb2618f6311396b Mon Sep 17 00:00:00 2001
From: Et0h
Date: Mon, 29 Dec 2014 12:47:31 +0000
Subject: [PATCH 13/63] Add secondaryOSD (w/ VLC support & fallback code),
re-work warnings, fix misc. VLC bugs, allow longer offsets
---
resources/lua/intf/syncplay.lua | 76 ++++++++++----
syncplay/client.py | 179 ++++++++++++++++++++++++--------
syncplay/constants.py | 7 +-
syncplay/messages.py | 18 +++-
syncplay/players/mpc.py | 3 +-
syncplay/players/mplayer.py | 4 +-
syncplay/players/vlc.py | 18 +++-
7 files changed, 232 insertions(+), 73 deletions(-)
diff --git a/resources/lua/intf/syncplay.lua b/resources/lua/intf/syncplay.lua
index 0dacaf7..3c8df92 100644
--- a/resources/lua/intf/syncplay.lua
+++ b/resources/lua/intf/syncplay.lua
@@ -5,7 +5,7 @@
Principal author: Etoh
Other contributors: DerGenaue, jb
Project: http://syncplay.pl/
- Version: 0.2.3
+ Version: 0.2.4
Note:
* This interface module is intended to be used in conjunction with Syncplay.
@@ -68,6 +68,9 @@ You may also need to re-copy the syncplay.lua file when you update VLC.
display-osd: [placement on screen
], [duration in seconds], [message]
? >> display-osd-error: no-input
+ display-secondary-osd: [placement on screen
], [duration in seconds], [message]
+ ? >> display-secondary-osd-error: no-input
+
load-file: [filepath]
* >> load-file-attempted
@@ -78,7 +81,7 @@ You may also need to re-copy the syncplay.lua file when you update VLC.
--]==========================================================================]
-local connectorversion = "0.2.3"
+local connectorversion = "0.2.4"
local durationdelay = 500000 -- Pause for get_duration command etc for increased reliability (uses microseconds)
local loopsleepduration = 5000 -- Pause for every event loop (uses microseconds)
local quitcheckfrequency = 20 -- Check whether VLC has closed every X loops
@@ -108,12 +111,18 @@ local newinputstate
local oldtitle = 0
local newtitle = 0
+local channel1
+local channel2
+local l
+
local running = true
+
function radixsafe_tonumber(str)
-- Version of tonumber that works with any radix character (but not thousand seperators)
-- Based on the public domain VLC common.lua us_tonumber() function
- str = string.gsub(tostring(str), "[^0-9]", ".")
+
+ str = string.gsub(tostring(str), "[^0-9]", ".")
local s, i, d = string.match(str, "^([+-]?)(%d*)%.?(%d*)$")
if not s or not i or not d then
return nil
@@ -277,8 +286,8 @@ function set_time ( timetoset)
end
errormsg = set_var("time", radixsafe_tonumber(realtime))
return errormsg
- else
- return noinput
+ else
+ return noinput
end
end
@@ -379,17 +388,19 @@ function get_duration ()
if input then
local item = vlc.input.item()
- if (item and item:duration()) then
-- Try to get duration, which might not be available straight away
- local i = 0
- repeat
- vlc.misc.mwait(vlc.misc.mdate() + durationdelay)
+ local i = 0
+ response = 0
+ repeat
+ vlc.misc.mwait(vlc.misc.mdate() + durationdelay)
+ if item and item:duration() then
response = item:duration()
- i = i + 1
- until response > 0 or i > 5
- else
- errormsg = noinput
- end
+ if response < 1 then
+ response = 0
+ end
+ end
+ i = i + 1
+ until response > 1 or i > 5
else
errormsg = noinput
end
@@ -400,11 +411,16 @@ end
function display_osd ( argument )
-- [Used by display-osd command]
-
local errormsg
local osdarray
local input = vlc.object.input()
- if input then
+ if input and vlc.osd and vlc.object.vout() then
+ if not channel1 then
+ channel1 = vlc.osd.channel_register()
+ end
+ if not channel2 then
+ channel2 = vlc.osd.channel_register()
+ end
osdarray = get_args(argument,3)
--position, duration, message -> message, , position, duration (converted from seconds to microseconds)
local osdduration = radixsafe_tonumber(osdarray[2]) * 1000 * 1000
@@ -415,6 +431,28 @@ function display_osd ( argument )
return errormsg
end
+function display_secondary_osd ( argument )
+ -- [Used by display-secondary-osd command]
+ local errormsg
+ local osdarray
+ local input = vlc.object.input()
+ if input and vlc.osd and vlc.object.vout() then
+ if not channel1 then
+ channel1 = vlc.osd.channel_register()
+ end
+ if not channel2 then
+ channel2 = vlc.osd.channel_register()
+ end
+ osdarray = get_args(argument,3)
+ --position, duration, message -> message, , position, duration (converted from seconds to microseconds)
+ local osdduration = radixsafe_tonumber(osdarray[2]) * 1000 * 1000
+ vlc.osd.message(osdarray[3],channel2,osdarray[1],osdduration)
+ else
+ errormsg = noinput
+ end
+ return errormsg
+end
+
function load_file (filepath)
-- [Used by load-file command]
@@ -445,6 +483,7 @@ function do_command ( command, argument)
elseif command == "set-rate" then errormsg = set_var("rate", radixsafe_tonumber(argument))
elseif command == "set-title" then errormsg = set_var("title", radixsafe_tonumber(argument))
elseif command == "display-osd" then errormsg = display_osd(argument)
+ elseif command == "display-secondary-osd" then errormsg = display_secondary_osd(argument)
elseif command == "load-file" then response = load_file(argument)
elseif command == "close-vlc" then quit_vlc()
else errormsg = unknowncommand
@@ -498,7 +537,7 @@ while running == true do
--accept new connections and select active clients
local quitcheckcounter = 0
local fd = l:accept()
- local buffer, inputbuffer, responsebuffer = ""
+ local buffer, inputbuffer, responsebuffer = "", "", ""
while fd >= 0 and running == true do
-- handle read mode
@@ -560,7 +599,6 @@ while running == true do
quitcheckcounter = 0
end
-
end
-end
+end
\ No newline at end of file
diff --git a/syncplay/client.py b/syncplay/client.py
index 11f05b2..f2a5a6e 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -106,7 +106,7 @@ class SyncplayClient(object):
self._speedChanged = False
self.behindFirstDetected = None
- self._warnings = self._WarningManager(self._player, self.userlist, self.ui)
+ self._warnings = self._WarningManager(self._player, self.userlist, self.ui, self)
if constants.LIST_RELATIVE_CONFIGS and self._config.has_key('loadedRelativePaths') and self._config['loadedRelativePaths']:
paths = "; ".join(self._config['loadedRelativePaths'])
self.ui.showMessage(getMessage("relative-config-notification").format(paths), noPlayer=True, noTimestamp=True)
@@ -126,6 +126,8 @@ class SyncplayClient(object):
def initPlayer(self, player):
self._player = player
+ if not self._player.secondaryOSDSupported:
+ constants.OSD_WARNING_MESSAGE_DURATION = constants.NO_SECONDARY_OSD_WARNING_DURATION
self.scheduleAskPlayer()
def scheduleAskPlayer(self, when=constants.PLAYER_ASK_DELAY):
@@ -496,17 +498,20 @@ class SyncplayClient(object):
oldReadyState = False
self.userlist.setReady(username, isReady)
self.ui.userListChange()
- if manuallyInitiated and oldReadyState != isReady:
- showOnOSD = constants.SHOW_OSD_WARNINGS
- if constants.SHOW_NONCONTROLLER_OSD == False and self.userlist.canControl(username) == False and self.userlist.currentUser.isController() == False:
- # Ignore SHOW_NONCONTROLLER_OSD setting if user is controller, because they need to know who is/isn't ready
- showOnOSD = False
- hideFromOSD = not showOnOSD
- if isReady:
- message = getMessage("user-ready-notification").format(username)
- else:
- message = getMessage("user-not-ready-notification").format(username)
- self.ui.showMessage(message, hideFromOSD)
+ if oldReadyState != isReady:
+ self._warnings.checkReadyStates()
+ if manuallyInitiated:
+ showOnOSD = constants.SHOW_OSD_WARNINGS
+ if constants.SHOW_NONCONTROLLER_OSD == False and self.userlist.canControl(username) == False and self.userlist.currentUser.isController() == False:
+ # Ignore SHOW_NONCONTROLLER_OSD setting if user is controller, because they need to know who is/isn't ready
+ showOnOSD = False
+ hideFromOSD = not showOnOSD
+ if isReady:
+ message = getMessage("user-ready-notification").format(username)
+ else:
+ message = getMessage("user-not-ready-notification").format(username)
+ self.ui.showMessage(message, hideFromOSD, False)
+
@requireMinServerVersion(constants.CONTROLLED_ROOMS_MIN_VERSION)
def createControlledRoom(self, roomName):
@@ -556,51 +561,107 @@ class SyncplayClient(object):
return self.controlpasswords[room]
class _WarningManager(object):
- def __init__(self, player, userlist, ui):
+ def __init__(self, player, userlist, ui, client):
+ self._client = client
self._player = player
self._userlist = userlist
self._ui = ui
self._warnings = {
"room-files-not-same": {
- "timer": task.LoopingCall(self.__displayMessageOnOSD,
- "room-files-not-same", ),
+ "timer": task.LoopingCall(self.__displayMessageOnOSD, "room-files-not-same",
+ lambda: self._checkRoomForSameFiles(OSDOnly=True),),
"displayedFor": 0,
},
"alone-in-the-room": {
- "timer": task.LoopingCall(self.__displayMessageOnOSD,
- "alone-in-the-room", ),
+ "timer": task.LoopingCall(self.__displayMessageOnOSD, "alone-in-the-room",
+ lambda: self._checkIfYouReAloneInTheRoom(OSDOnly=True)),
+ "displayedFor": 0,
+ },
+ "not-all-ready": {
+ "timer": task.LoopingCall(self.__displayMessageOnOSD, "not-all-ready",
+ lambda: self.checkReadyStates(),),
"displayedFor": 0,
},
}
- def checkWarnings(self):
- self._checkIfYouReAloneInTheRoom()
- self._checkRoomForSameFiles()
+ self.pausedTimer = task.LoopingCall(self.__displayPausedMessagesOnOSD)
+ self.pausedTimer.start(constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL, True)
- def _checkRoomForSameFiles(self):
+ def checkWarnings(self):
+ self._checkIfYouReAloneInTheRoom(OSDOnly=False)
+ self._checkRoomForSameFiles(OSDOnly=False)
+ self.checkReadyStates()
+
+ def _checkRoomForSameFiles(self, OSDOnly):
if not self._userlist.areAllFilesInRoomSame():
- self._ui.showMessage(getMessage("room-files-not-same"), True)
- if constants.SHOW_OSD_WARNINGS and not self._warnings["room-files-not-same"]['timer'].running:
- self._warnings["room-files-not-same"]['timer'].start(constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL, True)
+ self._displayReadySameWarning()
+ if not OSDOnly:
+ self._ui.showMessage(getMessage("room-files-not-same"), True)
+ if constants.SHOW_OSD_WARNINGS and not self._warnings["room-files-not-same"]['timer'].running:
+ self._warnings["room-files-not-same"]['timer'].start(constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL, True)
elif self._warnings["room-files-not-same"]['timer'].running:
self._warnings["room-files-not-same"]['timer'].stop()
- def _checkIfYouReAloneInTheRoom(self):
+ def _checkIfYouReAloneInTheRoom(self, OSDOnly):
if self._userlist.areYouAloneInRoom():
- self._ui.showMessage(getMessage("alone-in-the-room"), True)
- if constants.SHOW_OSD_WARNINGS and not self._warnings["alone-in-the-room"]['timer'].running:
- self._warnings["alone-in-the-room"]['timer'].start(constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL, True)
+ self._ui.showOSDMessage(getMessage("alone-in-the-room"), constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL, secondaryOSD=True)
+ if not OSDOnly:
+ self._ui.showMessage(getMessage("alone-in-the-room"), True)
+ if constants.SHOW_OSD_WARNINGS and not self._warnings["alone-in-the-room"]['timer'].running:
+ self._warnings["alone-in-the-room"]['timer'].start(constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL, True)
elif self._warnings["alone-in-the-room"]['timer'].running:
self._warnings["alone-in-the-room"]['timer'].stop()
- def __displayMessageOnOSD(self, warningName):
+ def checkReadyStates(self):
+ if not self._client:
+ return
+
+ if self._client.getPlayerPaused() or not self._userlist.currentUser.isReady():
+ self._warnings["not-all-ready"]["displayedFor"] = 0
+ if self._userlist.areYouAloneInRoom() or not self._userlist.currentUser.canControl():
+ if self._warnings["not-all-ready"]['timer'].running:
+ self._warnings["not-all-ready"]['timer'].stop()
+ elif not self._userlist.areAllUsersInRoomReady():
+ self._displayReadySameWarning()
+ if constants.SHOW_OSD_WARNINGS and not self._warnings["not-all-ready"]['timer'].running:
+ self._warnings["not-all-ready"]['timer'].start(constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL, True)
+ elif self._warnings["not-all-ready"]['timer'].running:
+ self._warnings["not-all-ready"]['timer'].stop()
+ self._displayReadySameWarning()
+ elif self._client.getPlayerPaused() or not self._userlist.currentUser.isReady():
+ self._displayReadySameWarning()
+
+ def _displayReadySameWarning(self):
+ if not self._userlist.areAllFilesInRoomSame():
+ if self._userlist.currentUser.canControl():
+ if self._userlist.areAllUsersInRoomReady():
+ osdMessage = u"{}; {}".format(getMessage("room-files-not-same"), getMessage("all-users-ready"))
+ else:
+ osdMessage = u"{}; {}".format(getMessage("room-files-not-same"), getMessage("not-all-ready").format(self._userlist.usersInRoomNotReady()))
+ else:
+ osdMessage = getMessage("room-files-not-same")
+ elif self._userlist.areAllUsersInRoomReady():
+ osdMessage = getMessage("all-users-ready")
+ else:
+ osdMessage = getMessage("not-all-ready").format(self._userlist.usersInRoomNotReady())
+ self._ui.showOSDMessage(osdMessage, constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL, secondaryOSD=True)
+
+ def __displayMessageOnOSD(self, warningName, warningFunction):
if constants.OSD_WARNING_MESSAGE_DURATION > self._warnings[warningName]["displayedFor"]:
- self._ui.showOSDMessage(getMessage(warningName), constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL)
+ warningFunction()
self._warnings[warningName]["displayedFor"] += constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL
else:
self._warnings[warningName]["displayedFor"] = 0
- self._warnings[warningName]["timer"].stop()
-
+ try:
+ self._warnings[warningName]["timer"].stop()
+ except:
+ pass
+ def __displayPausedMessagesOnOSD(self):
+ if self._client and self._client._player and self._client._player.secondaryOSDSupported and self._userlist.currentUser.file and self._client.getPlayerPaused():
+ self._checkRoomForSameFiles(OSDOnly=True)
+ self.checkReadyStates()
+ elif not self._userlist.currentUser.isReady(): # CurrentUser should always be reminded they are set to not ready
+ self.checkReadyStates()
class SyncplayUser(object):
def __init__(self, username=None, room=None, file_=None):
@@ -764,11 +825,31 @@ class SyncplayUserlist(object):
user = self._users[username]
user.setControllerStatus(True)
- def areAllFilesInRoomSame(self):
+ def areAllUsersInRoomReady(self):
+ if not self.currentUser.canControl():
+ return True
+ if not self.currentUser.isReady():
+ return False
for user in self._users.itervalues():
- if user.room == self.currentUser.room and user.file and not self.currentUser.isFileSame(user.file):
- if user.canControl():
- return False
+ if user.room == self.currentUser.room and user.isReady() == False:
+ return False
+ return True
+
+ def usersInRoomNotReady(self):
+ notReady = []
+ if not self.currentUser.isReady():
+ notReady.append(self.currentUser.username)
+ for user in self._users.itervalues():
+ if user.room == self.currentUser.room and user.isReady() == False:
+ notReady.append(user.username)
+ return ", ".join(notReady)
+
+ def areAllFilesInRoomSame(self):
+ if self.currentUser.file:
+ for user in self._users.itervalues():
+ if user.room == self.currentUser.room and user.file and not self.currentUser.isFileSame(user.file):
+ if user.canControl():
+ return False
return True
def areYouAloneInRoom(self):
@@ -843,22 +924,38 @@ class UiManager(object):
def __init__(self, client, ui):
self._client = client
self.__ui = ui
+ self.lastPrimaryOSDMessage = None
+ self.lastPrimaryOSDEndTime = None
+ self.lastSecondaryOSDMessage = None
+ self.lastSecondaryOSDEndTime = None
self.lastError = ""
def showDebugMessage(self, message):
if constants.DEBUG_MODE and message.rstrip():
print "{}{}".format(time.strftime(constants.UI_TIME_FORMAT, time.localtime()),message.rstrip())
- def showMessage(self, message, noPlayer=False, noTimestamp=False):
- if not noPlayer: self.showOSDMessage(message)
+ def showMessage(self, message, noPlayer=False, noTimestamp=False, secondaryOSD=False):
+ if not noPlayer: self.showOSDMessage(message, duration=constants.OSD_DURATION, secondaryOSD=secondaryOSD)
self.__ui.showMessage(message, noTimestamp)
def showUserList(self, currentUser, rooms):
self.__ui.showUserList(currentUser, rooms)
- def showOSDMessage(self, message, duration=constants.OSD_DURATION):
- if constants.SHOW_OSD and self._client._player:
- self._client._player.displayMessage(message, duration * 1000)
+ def showOSDMessage(self, message, duration=constants.OSD_DURATION, secondaryOSD=False):
+ if constants.SHOW_OSD and self._client and self._client._player:
+ if not self._client._player.secondaryOSDSupported:
+ if secondaryOSD:
+ message = u"({})".format(message)
+ self.lastSecondaryOSDMessage = message
+ self.lastSecondaryOSDEndTime = time.time() + constants.NO_SECONDARY_OSD_WARNING_DURATION
+ if self.lastPrimaryOSDEndTime and time.time() < self.lastPrimaryOSDEndTime:
+ message = u"{}; {}".format(message, self.lastPrimaryOSDMessage)
+ else:
+ self.lastPrimaryOSDMessage = message
+ self.lastPrimaryOSDEndTime = time.time() + constants.OSD_DURATION
+ if self.lastSecondaryOSDEndTime and time.time() < self.lastSecondaryOSDEndTime:
+ message = u"{}; {}".format(self.lastSecondaryOSDMessage, message)
+ self._client._player.displayMessage(message, duration * 1000, secondaryOSD)
def setControllerStatus(self, username, isController):
self.__ui.setControllerStatus(username, isController)
diff --git a/syncplay/constants.py b/syncplay/constants.py
index 5866fe0..191116b 100644
--- a/syncplay/constants.py
+++ b/syncplay/constants.py
@@ -1,7 +1,8 @@
# You might want to change these
DEFAULT_PORT = 8999
OSD_DURATION = 3
-OSD_WARNING_MESSAGE_DURATION = 15
+OSD_WARNING_MESSAGE_DURATION = 5
+NO_SECONDARY_OSD_WARNING_DURATION = 15
MPC_OSD_POSITION = 2 #Right corner, 1 for left
MPLAYER_OSD_LEVEL = 1
UI_TIME_FORMAT = "[%X] "
@@ -62,7 +63,7 @@ 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"
+VLC_INTERFACE_MIN_VERSION = "0.2.4"
CONTROLLED_ROOMS_MIN_VERSION = "1.3.0"
USER_READY_MIN_VERSION = "1.3.1"
MPC_PATHS = [
@@ -141,7 +142,7 @@ VLC_SLAVE_NONOSX_ARGS = ['--no-one-instance', '--no-one-instance-when-started-fr
MPLAYER_ANSWER_REGEX = "^ANS_([a-zA-Z_-]+)=(.+)$|^(Exiting)\.\.\. \((.+)\)$"
VLC_ANSWER_REGEX = r"(?:^(?P[a-zA-Z_]+)(?:\: )?(?P.*))"
UI_COMMAND_REGEX = r"^(?P[^\ ]+)(?:\ (?P.+))?"
-UI_OFFSET_REGEX = r"^(?:o|offset)\ ?(?P[/+-])?(?P
","").replace(" ","").replace("“","\"").replace("”","\"") # Fix Wordpress
+ response = json.loads(response)
+ return response["version-status"], response["version-message"] if response.has_key("version-message") else None, response["version-url"] if response.has_key("version-url") else None
+ except:
+ return "failed", getMessage("update-check-failed-notification").format(syncplay.version), constants.SYNCPLAY_DOWNLOAD_URL
+
class _WarningManager(object):
def __init__(self, player, userlist, ui, client):
self._client = client
diff --git a/syncplay/constants.py b/syncplay/constants.py
index c99355a..3e741f1 100644
--- a/syncplay/constants.py
+++ b/syncplay/constants.py
@@ -29,6 +29,7 @@ SHOW_DURATION_NOTIFICATION = True
DEBUG_MODE = False
#Changing these might be ok
+AUTOMATIC_UPDATE_CHECK_FREQUENCY = 7 * 86400 # Days converted into seconds
DEFAULT_REWIND_THRESHOLD = 4
MINIMUM_REWIND_THRESHOLD = 3
DEFAULT_FASTFORWARD_THRESHOLD = 5
@@ -157,3 +158,6 @@ CONFIG_NAME_MARKER = ":"
CONFIG_VALUE_MARKER = "="
USERITEM_CONTROLLER_ROLE = 0
USERITEM_READY_ROLE = 1
+
+SYNCPLAY_UPDATE_URL = u"http://syncplay.pl/checkforupdate?{}" # Params
+SYNCPLAY_DOWNLOAD_URL = "http://syncplay.pl/download/"
\ No newline at end of file
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 0f3532e..3e4b0bf 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -57,6 +57,10 @@ en = {
"userlist-file-notification" : "File",
"controller-userlist-userflag" : "Controller",
"ready-userlist-userflag" : "Ready",
+
+ "update-check-failed-notification" : u"Could not automatically check whether Syncplay {} is up to date. Want to visit http://syncplay.pl/ to manually check for updates?", #Syncplay version
+ "syncplay-uptodate-notification" : u"Syncplay is up to date",
+ "syncplay-updateavailable-notification" : u"A new version of Syncplay is available. Do you want to download it?",
"mplayer-file-required-notification" : "Syncplay using mplayer requires you to provide file when starting",
"mplayer-file-required-notification/example" : "Usage example: syncplay [options] [url|path/]filename",
@@ -78,6 +82,7 @@ en = {
"gui-data-cleared-notification" : "Syncplay has cleared the path and window state data used by the GUI.",
"language-changed-msgbox-label" : "Language will be changed when you run Syncplay.",
+ "promptforupdate-label" : u"Is it okay for Syncplay to automatically check for updates from time to time?",
"vlc-version-mismatch": "Warning: You are running VLC version {}, but Syncplay is designed to run on VLC {} and above.", # VLC version, VLC min version
"vlc-interface-version-mismatch": "Warning: You are running version {} of the Syncplay interface module for VLC, but Syncplay is designed to run with version {} and above.", # VLC interface version, VLC interface min version
@@ -163,6 +168,7 @@ en = {
"privacy-dontsend-option" : "Don't send",
"filename-privacy-label" : "Filename information:",
"filesize-privacy-label" : "File size information:",
+ "checkforupdatesautomatically-label" : "Check for updates automatically",
"slowondesync-label" : "Slow down on minor desync (not supported on MPC-HC)",
"rewindondesync-label" : "Rewind on major desync (highly recommended)",
"fastforwardondesync-label" : "Fast-forward if lagging behind (recommended)",
@@ -231,6 +237,7 @@ en = {
"help-menu-label" : "&Help",
"userguide-menu-label" : "Open user &guide",
+ "update-menu-label" : "Check for &update",
"setoffset-msgbox-label" : "Set offset",
"offsetinfo-msgbox-label" : "Offset (see http://syncplay.pl/guide/ for usage instructions):",
@@ -265,6 +272,7 @@ en = {
"privacy-sendraw-tooltip" : "Send this information without obfuscation. This is the default option with most functionality.",
"privacy-sendhashed-tooltip" : "Send a hashed version of the information, making it less visible to other clients.",
"privacy-dontsend-tooltip" : "Do not send this information to the server. This provides for maximum privacy.",
+ "checkforupdatesautomatically-tooltip" : "Regularly check with the Syncplay website to see whether a new version of Syncplay is available.",
"slowondesync-tooltip" : "Reduce playback rate temporarily when needed to bring you back in sync with other viewers. Not supported on MPC-HC.",
"dontslowdownwithme-tooltip" : "Means others do not get slowed down or rewinded if your playback is lagging. Useful for room controllers.",
"pauseonleave-tooltip" : "Pause playback if you get disconnected or someone leaves from your room.",
@@ -386,6 +394,10 @@ ru = {
"userlist-file-notification" : u"File", # TODO: Translate into Russian (Файл?)
"controller-userlist-userflag" : u"Controller", # TODO: Translate into Russian (this is to indicate a user is a controller in the ConsoleUI userlist)
"ready-userlist-userflag" : u"Ready", # TODO: Translate into Russian (this is to indicate a user is ready to watch in the ConsoleUI userlist)
+
+ "update-check-failed-notification" : u"Could not automatically check whether Syncplay {} is up to date. Want to visit http://syncplay.pl/ to manually check for updates?", #Syncplay version # TODO: Translate into Russian
+ "syncplay-uptodate-notification" : u"Syncplay is up to date", # TODO: Translate into Russian
+ "syncplay-updateavailable-notification" : u"A new version of Syncplay is available. Do you want to download it?", # TODO: Translate into Russian
"mplayer-file-required-notification" : u"Для использования Syncplay с mplayer необходимо передать файл в качестве параметра",
"mplayer-file-required-notification/example" : u"Пример использования: syncplay [options] [url|path/]filename",
@@ -406,7 +418,8 @@ ru = {
"more-info-notification" : u"Больше информации на {}", # projectURL
"gui-data-cleared-notification" : u"Syncplay очистил путь и информацию о состоянии окна, использованного GUI.",
- "language-changed-msgbox-label" : u"Language will be changed when you run Syncplay.",
+ "language-changed-msgbox-label" : u"Language will be changed when you run Syncplay.", # TODO: Translate into Russian
+ "promptforupdate-label" : u"Is it okay for Syncplay to automatically check for updates from time to time?", # TODO: Translate into Russian
"vlc-version-mismatch" : u"Внимание: Вы используете VLC устаревшей версии {}. К сожалению, Syncplay способен работать с VLC {} и выше.", # VLC version, VLC min version
"vlc-interface-version-mismatch" : u"Внимание: В используете модуль интерфейса Syncplay устаревшей версии {} для VLC. К сожалению, Syncplay способен работать с версией {} и выше.", # VLC interface version, VLC interface min version
@@ -492,6 +505,7 @@ ru = {
"privacy-dontsend-option" : u"не отпр.",
"filename-privacy-label" : u"Имя файла:",
"filesize-privacy-label" : u"Размер файла:",
+ "checkforupdatesautomatically-label" : u"Проверять обновления автоматически", # TODO: Confirm Russian translation
"slowondesync-label" : u"Замедлять при небольших рассинхронизациях (не поддерживаетя в MPC-HC)",
"rewindondesync-label" : u"Перемотка при больших рассинхронизациях (настоятельно рекомендуется)",
"dontslowdownwithme-label" : u"Никогда не замедлять или перематывать видео другим", # TODO: Update new wording into Russian (should state "Experimental" in brackets at the end)
@@ -560,6 +574,7 @@ ru = {
"help-menu-label" : u"&Помощь",
"userguide-menu-label" : u"&Руководство Пользователя",
+ "update-menu-label" : u"Check for &update", # TODO: Translate into Russian
"setoffset-msgbox-label" : u"Установить смещение",
"offsetinfo-msgbox-label" : u"Смещение (см. как использовать на http://syncplay.pl/guide/):",
@@ -594,6 +609,7 @@ ru = {
"privacy-sendraw-tooltip" : u"Отправляет эту информацию без шифрования. Рекомендуемая опция с наибольшей функциональностью.",
"privacy-sendhashed-tooltip" : u"Отправляет хэш-сумму этой информации, делая ее невидимой для других пользователей.",
"privacy-dontsend-tooltip" : u"Не отправлять эту информацию на сервер. Предоставляет наибольшую приватность.",
+ "checkforupdatesautomatically-tooltip" : u"Regularly check with the Syncplay website to see whether a new version of Syncplay is available.", # TODO: Translate into Russian
"slowondesync-tooltip" : u"Временно уменьшить скорость воспроизведения в целях синхронизации с другими зрителями. Не поддерживается в MPC-HC.",
"dontslowdownwithme-tooltip" : u"Ваши лаги не будут влиять на других зрителей.",
"pauseonleave-tooltip" : u"Приостановить воспроизведение, если Вы покинули комнату или кто-то из зрителей отключился от сервера.",
@@ -714,7 +730,11 @@ de = {
"userlist-room-notification" : u"In Raum '{}':", # Room
"userlist-file-notification" : u"File", # TODO: Translate into German (Datei?)
"controller-userlist-userflag" : u"Controller", # TODO: Translate into German (this is to indicate a user is a controller in the ConsoleUI userlist)
- "ready-userlist-userflag" : u"Ready", # TODO: Translate into Germany (this is to indicate a user is ready to watch in the ConsoleUI userlist)
+ "ready-userlist-userflag" : u"Ready", # TODO: Translate into German (this is to indicate a user is ready to watch in the ConsoleUI userlist)
+
+ "update-check-failed-notification" : u"Could not automatically check whether Syncplay {} is up to date. Want to visit http://syncplay.pl/ to manually check for updates?", #Syncplay version # TODO: Translate into German
+ "syncplay-uptodate-notification" : u"Syncplay is up to date", # TODO: Translate into German
+ "syncplay-updateavailable-notification" : u"A new version of Syncplay is available. Do you want to download it?", # TODO: Translate into German
"mplayer-file-required-notification" : u"Syncplay für mplayer benötigt eine Datei-Angabe beim Start",
"mplayer-file-required-notification/example" : u"Anwendungsbeispiel: syncplay [optionen] [url|pfad/]Dateiname",
@@ -736,6 +756,7 @@ de = {
"gui-data-cleared-notification" : u"Syncplay hat die Pfad und Fensterdaten der Syncplay-GUI zurückgesetzt.",
"language-changed-msgbox-label" : u"Die Sprache wird geändert, wenn du Syncplay neu startest.",
+ "promptforupdate-label" : u"Is it okay for Syncplay to automatically check for updates from time to time?", # TODO: Translate into German
"vlc-version-mismatch": u"Warnung: Du nutzt VLC Version {}, aber Syncplay wurde für VLC ab Version {} entwickelt.", # VLC version, VLC min version
"vlc-interface-version-mismatch": u"Warnung: Du nutzt Version {} des VLC-Syncplay Interface-Moduls, Syncplay benötigt aber mindestens Version {}.", # VLC interface version, VLC interface min version
@@ -821,6 +842,7 @@ de = {
"privacy-dontsend-option" : u"Nicht senden",
"filename-privacy-label" : u"Dateiname:",
"filesize-privacy-label" : u"Dateigröße:",
+ "checkforupdatesautomatically-label" : u"Automatisch nach Updates suche", # TODO: Confirm German translation
"slowondesync-label" : u"Verlangsamen wenn nicht synchron (nicht unterstützt mit MPC-HC)",
"dontslowdownwithme-label" : u"Nie verlangsamen oder andere zurückspulen (Experimentell)",
"pauseonleave-label" : u"Pausieren wenn ein Benutzer austritt",
@@ -887,6 +909,7 @@ de = {
"help-menu-label" : u"&Hilfe",
"userguide-menu-label" : u"&Benutzerhandbuch öffnen",
+ "update-menu-label" : u"Check for &update", # TODO: Translate into Russian
"setoffset-msgbox-label" : u"Offset einstellen",
"offsetinfo-msgbox-label" : u"Offset (siehe http://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
@@ -921,6 +944,7 @@ de = {
"privacy-sendraw-tooltip" : u"Die Information im Klartext übertragen. Dies ist die Standard-Einstellung mit der besten Funktionalität.",
"privacy-sendhashed-tooltip" : u"Die Informationen gehasht übertragen, um sie für andere Clients schwerer lesbar zu machen.",
"privacy-dontsend-tooltip" : u"Diese Information nicht übertragen. Dies garantiert den größtmöglichen Datanschutz.",
+ "checkforupdatesautomatically-tooltip" : u"Regularly check with the Syncplay website to see whether a new version of Syncplay is available.", # TODO: Translate into German
"slowondesync-tooltip" : u"Reduziert die Abspielgeschwindigkeit zeitweise, um die Synchronität zu den anderen Clients wiederherzustellen.",
"rewindondesync-label" : u"Zurückspulen bei großer Zeitdifferenz (empfohlen)",
"fastforwardondesync-label" : u"Vorspulen wenn das Video lagt (empfohlen)",
diff --git a/syncplay/ui/ConfigurationGetter.py b/syncplay/ui/ConfigurationGetter.py
index 89ce26b..adcb86a 100755
--- a/syncplay/ui/ConfigurationGetter.py
+++ b/syncplay/ui/ConfigurationGetter.py
@@ -47,6 +47,8 @@ class ConfigurationGetter(object):
"readyAtStart": False,
"clearGUIData": False,
"language" : "",
+ "checkForUpdatesAutomatically" : None,
+ "lastCheckedForUpdates" : "",
"resetConfig" : False,
"showOSD" : True,
"showOSDWarnings" : True,
@@ -95,6 +97,9 @@ class ConfigurationGetter(object):
"showContactInfo" ,
"showDurationNotification"
]
+ self._tristate = [
+ "checkForUpdatesAutomatically"
+ ]
self._numeric = [
"slowdownThreshold",
@@ -106,7 +111,7 @@ class ConfigurationGetter(object):
"server_data": ["host", "port", "password"],
"client_settings": ["name", "room", "playerPath", "slowdownThreshold", "rewindThreshold", "fastforwardThreshold", "slowOnDesync", "rewindOnDesync", "fastforwardOnDesync", "dontSlowDownWithMe", "forceGuiPrompt", "filenamePrivacyMode", "filesizePrivacyMode", "pauseOnLeave", "readyAtStart"],
"gui": ["showOSD", "showOSDWarnings", "showSlowdownOSD", "showDifferentRoomOSD", "showSameRoomOSD", "showNonControllerOSD", "showContactInfo" , "showDurationNotification"],
- "general": ["language"]
+ "general": ["language", "checkForUpdatesAutomatically", "lastCheckedForUpdates"]
}
self._playerFactory = PlayerFactory()
@@ -139,6 +144,14 @@ class ConfigurationGetter(object):
elif self._config[key] == "False":
self._config[key] = False
+ for key in self._tristate:
+ if self._config[key] == "True":
+ self._config[key] = True
+ elif self._config[key] == "False":
+ self._config[key] = False
+ elif self._config[key] == "None":
+ self._config[key] = None
+
for key in self._numeric:
self._config[key] = float(self._config[key])
diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py
index 9c1b0f1..adbf1b6 100644
--- a/syncplay/ui/GuiConfiguration.py
+++ b/syncplay/ui/GuiConfiguration.py
@@ -1,8 +1,8 @@
from PySide import QtCore, QtGui
-from PySide.QtCore import QSettings, Qt, QCoreApplication
+from PySide.QtCore import QSettings, Qt, QCoreApplication, QUrl
from PySide.QtGui import QApplication, QLineEdit, QCursor, QLabel, QCheckBox, QDesktopServices, QIcon, QImage, QButtonGroup, QRadioButton, QDoubleSpinBox
from syncplay.players.playerFactory import PlayerFactory
-
+from datetime import datetime
import os
import sys
from syncplay.messages import getMessage, getLanguages, setLanguage, getInitialLanguage
@@ -35,6 +35,15 @@ class ConfigDialog(QtGui.QDialog):
pressedclosebutton = False
moreToggling = False
+ def automaticUpdatePromptCheck(self):
+ if self.automaticupdatesCheckbox.checkState() == Qt.PartiallyChecked and not self.nostoreCheckbox.isChecked():
+ reply = QtGui.QMessageBox.question(self, "Syncplay",
+ getMessage("promptforupdate-label"), QtGui.QMessageBox.StandardButton.Yes | QtGui.QMessageBox.StandardButton.No)
+ if reply == QtGui.QMessageBox.Yes:
+ self.automaticupdatesCheckbox.setChecked(True)
+ else:
+ self.automaticupdatesCheckbox.setChecked(False)
+
def moreToggled(self):
if self.moreToggling == False:
self.moreToggling = True
@@ -68,7 +77,7 @@ class ConfigDialog(QtGui.QDialog):
self.runButton.setText(getMessage("storeandrun-label"))
def openHelp(self):
- self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/client/")
+ self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/client/"))
def _isURL(self, path):
if path is None:
@@ -170,6 +179,17 @@ class ConfigDialog(QtGui.QDialog):
if fileName:
self.executablepathCombobox.setEditText(os.path.normpath(fileName))
+ def loadLastUpdateCheckDate(self):
+ settings = QSettings("Syncplay", "Interface")
+ settings.beginGroup("Update")
+ self.lastCheckedForUpdates = settings.value("lastChecked", None)
+ if self.lastCheckedForUpdates:
+ if self.config["lastCheckedForUpdates"] is not None and self.config["lastCheckedForUpdates"] is not "":
+ if self.lastCheckedForUpdates > datetime.strptime(self.config["lastCheckedForUpdates"], "%Y-%m-%d %H:%M:%S.%f"):
+ self.config["lastCheckedForUpdates"] = str(self.lastCheckedForUpdates)
+ else:
+ self.config["lastCheckedForUpdates"] = str(self.lastCheckedForUpdates)
+
def loadMediaBrowseSettings(self):
settings = QSettings("Syncplay", "MediaBrowseDialog")
settings.beginGroup("MediaBrowseDialog")
@@ -218,6 +238,9 @@ class ConfigDialog(QtGui.QDialog):
self.saveMediaBrowseSettings()
def _saveDataAndLeave(self):
+ self.automaticUpdatePromptCheck()
+ self.loadLastUpdateCheckDate()
+
self.processWidget(self, lambda w: self.saveValues(w))
if self.hostTextbox.text():
self.config['host'] = self.hostTextbox.text() if ":" in self.hostTextbox.text() else self.hostTextbox.text() + ":" + unicode(constants.DEFAULT_PORT)
@@ -293,7 +316,12 @@ class ConfigDialog(QtGui.QDialog):
inverted = True
else:
inverted = False
- widget.setChecked(self.config[valueName] != inverted)
+ if self.config[valueName] is None:
+ widget.setTristate(True)
+ widget.setCheckState(Qt.PartiallyChecked)
+ widget.stateChanged.connect(lambda: widget.setTristate(False))
+ else:
+ widget.setChecked(self.config[valueName] != inverted)
elif isinstance(widget, QRadioButton):
radioName, radioValue = valueName.split(constants.CONFIG_NAME_MARKER)[1].split(constants.CONFIG_VALUE_MARKER)
if self.config[radioName] == radioValue:
@@ -307,12 +335,15 @@ class ConfigDialog(QtGui.QDialog):
return
if isinstance(widget, QCheckBox) and widget.objectName():
- if valueName[:1] == constants.INVERTED_STATE_MARKER:
- valueName = valueName[1:]
- inverted = True
+ if widget.checkState() == Qt.PartiallyChecked:
+ self.config[valueName] = None
else:
- inverted = False
- self.config[valueName] = widget.isChecked() != inverted
+ if valueName[:1] == constants.INVERTED_STATE_MARKER:
+ valueName = valueName[1:]
+ inverted = True
+ else:
+ inverted = False
+ self.config[valueName] = widget.isChecked() != inverted
elif isinstance(widget, QRadioButton):
radioName, radioValue = valueName.split(constants.CONFIG_NAME_MARKER)[1].split(constants.CONFIG_VALUE_MARKER)
if widget.isChecked():
@@ -691,6 +722,9 @@ class ConfigDialog(QtGui.QDialog):
self.filesizeprivacySendHashedOption.setObjectName("privacy-sendhashed" + constants.CONFIG_NAME_MARKER + "filesizePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_SENDHASHED_MODE)
self.filesizeprivacyDontSendOption.setObjectName("privacy-dontsend" + constants.CONFIG_NAME_MARKER + "filesizePrivacyMode" + constants.CONFIG_VALUE_MARKER + constants.PRIVACY_DONTSEND_MODE)
+ self.automaticupdatesCheckbox = QCheckBox(getMessage("checkforupdatesautomatically-label"))
+ self.automaticupdatesCheckbox.setObjectName("checkForUpdatesAutomatically")
+
self.privacyLayout.addWidget(self.filenameprivacyLabel, 1, 0)
self.privacyLayout.addWidget(self.filenameprivacySendRawOption, 1, 1, Qt.AlignLeft)
self.privacyLayout.addWidget(self.filenameprivacySendHashedOption, 1, 2, Qt.AlignLeft)
@@ -699,6 +733,7 @@ class ConfigDialog(QtGui.QDialog):
self.privacyLayout.addWidget(self.filesizeprivacySendRawOption, 2, 1, Qt.AlignLeft)
self.privacyLayout.addWidget(self.filesizeprivacySendHashedOption, 2, 2, Qt.AlignLeft)
self.privacyLayout.addWidget(self.filesizeprivacyDontSendOption, 2, 3, Qt.AlignLeft)
+ self.privacyLayout.addWidget(self.automaticupdatesCheckbox, 3, 0, 1, 3, Qt.AlignLeft)
self.privacyFrame.setLayout(self.privacyLayout)
self.privacySettingsGroup.setLayout(self.privacyLayout)
@@ -796,6 +831,10 @@ class ConfigDialog(QtGui.QDialog):
settings.clear()
settings = QSettings("Syncplay", "MainWindow")
settings.clear()
+ settings = QSettings("Syncplay", "Interface")
+ settings.beginGroup("Update")
+ settings.setValue("lastChecked", None)
+ settings.endGroup()
if not leaveMore:
settings = QSettings("Syncplay", "MoreSettings")
settings.clear()
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index c8f11af..06927c4 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -1,12 +1,14 @@
from PySide import QtGui
-from PySide.QtCore import Qt, QSettings, QSize, QPoint
+from PySide.QtCore import Qt, QSettings, QSize, QPoint, QUrl
from syncplay import utils, constants, version
from syncplay.messages import getMessage
import sys
import time
+from datetime import datetime
import re
import os
from syncplay.utils import formatTime, sameFilename, sameFilesize, sameFileduration, RoomPasswordProvider, formatSize
+lastCheckedForUpdates = None
class UserlistItemDelegate(QtGui.QStyledItemDelegate):
def __init__(self):
@@ -81,6 +83,7 @@ class MainWindow(QtGui.QMainWindow):
self.hideMiscLabels()
except ():
pass
+ self.automaticUpdateCheck()
def promptFor(self, prompt=">", message=""):
# TODO: Prompt user
@@ -428,11 +431,11 @@ class MainWindow(QtGui.QMainWindow):
def openUserGuide(self):
if sys.platform.startswith('linux'):
- self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/linux/")
+ self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/linux/"))
elif sys.platform.startswith('win'):
- self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/windows/")
+ self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/windows/"))
else:
- self.QtGui.QDesktopServices.openUrl("http://syncplay.pl/guide/")
+ self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/"))
def drop(self):
self.close()
@@ -613,6 +616,9 @@ class MainWindow(QtGui.QMainWindow):
window.userguideAction = window.helpMenu.addAction(QtGui.QIcon(self.resourcespath + 'help.png'),
getMessage("userguide-menu-label"))
window.userguideAction.triggered.connect(self.openUserGuide)
+ window.updateAction = window.helpMenu.addAction(QtGui.QIcon(self.resourcespath + 'application_get.png'),
+ getMessage("update-menu-label"))
+ window.updateAction.triggered.connect(self.userCheckForUpdates)
window.menuBar.addMenu(window.helpMenu)
window.mainLayout.setMenuBar(window.menuBar)
@@ -652,6 +658,47 @@ class MainWindow(QtGui.QMainWindow):
self.readyPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'cross_checkbox.png'))
self.readyPushButton.setText(getMessage("notready-guipushbuttonlabel"))
+ def automaticUpdateCheck(self):
+ if not self.config['checkForUpdatesAutomatically']:
+ return
+ if self.config['lastCheckedForUpdates']:
+ configLastChecked = datetime.strptime(self.config["lastCheckedForUpdates"], "%Y-%m-%d %H:%M:%S.%f")
+ if self.lastCheckedForUpdates is None or configLastChecked > self.lastCheckedForUpdates:
+ self.lastCheckedForUpdates = configLastChecked
+ currentDateTime = datetime.utcnow()
+ if self.lastCheckedForUpdates is None:
+ self.checkForUpdates()
+ else:
+ timeDelta = currentDateTime - self.lastCheckedForUpdates
+ if timeDelta.total_seconds() > constants.AUTOMATIC_UPDATE_CHECK_FREQUENCY:
+ self.checkForUpdates()
+
+ def userCheckForUpdates(self):
+ self.checkForUpdates(userInitiated=True)
+
+ def checkForUpdates(self, userInitiated=False):
+ self.lastCheckedForUpdates = datetime.utcnow()
+ updateStatus, updateMessage, updateURL = self._syncplayClient.checkForUpdate()
+ if updateMessage is None:
+ if updateStatus == "uptodate":
+ updateMessage = getMessage("syncplay-uptodate-notification")
+ elif updateStatus == "updateavailale":
+ updateMessage = getMessage("syncplay-updateavailable-notification")
+ else:
+ import syncplay
+ updateMessage = getMessage("update-check-failed-notification").format(syncplay.version)
+ if userInitiated == True:
+ updateURL = constants.SYNCPLAY_DOWNLOAD_URL
+ if updateURL is not None:
+ reply = QtGui.QMessageBox.question(self, "Syncplay",
+ updateMessage, QtGui.QMessageBox.StandardButton.Yes | QtGui.QMessageBox.StandardButton.No)
+ if reply == QtGui.QMessageBox.Yes:
+ self.QtGui.QDesktopServices.openUrl(QUrl(updateURL))
+ elif userInitiated:
+ QtGui.QMessageBox.information(self, "Syncplay", updateMessage)
+ else:
+ self.showMessage(updateMessage)
+
def dragEnterEvent(self, event):
data = event.mimeData()
urls = data.urls()
@@ -680,6 +727,10 @@ class MainWindow(QtGui.QMainWindow):
settings.setValue("size", self.size())
settings.setValue("pos", self.pos())
settings.endGroup()
+ settings = QSettings("Syncplay", "Interface")
+ settings.beginGroup("Update")
+ settings.setValue("lastChecked", self.lastCheckedForUpdates)
+ settings.endGroup()
def loadSettings(self):
settings = QSettings("Syncplay", "MainWindow")
@@ -687,6 +738,9 @@ class MainWindow(QtGui.QMainWindow):
self.resize(settings.value("size", QSize(700, 500)))
self.move(settings.value("pos", QPoint(200, 200)))
settings.endGroup()
+ settings = QSettings("Syncplay", "Interface")
+ settings.beginGroup("Update")
+ self.lastCheckedForUpdates = settings.value("lastChecked", None)
def __init__(self):
super(MainWindow, self).__init__()
From 6acf0a3b63f3c56d5a7908eb8fb4cfd3afb62e10 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 3 Jan 2015 14:07:13 +0000
Subject: [PATCH 31/63] Specify whether update check was user initiated
---
syncplay/client.py | 5 ++---
syncplay/ui/gui.py | 2 +-
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/syncplay/client.py b/syncplay/client.py
index 00899b8..c675c3c 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -548,12 +548,11 @@ class SyncplayClient(object):
if self.controlpasswords.has_key(room):
return self.controlpasswords[room]
- def checkForUpdate(self):
+ def checkForUpdate(self, userInitiated):
try:
import urllib, syncplay, sys, messages, json
params = urllib.urlencode({'version': syncplay.version, 'milestone': syncplay.milestone, 'release_number': syncplay.release_number,
- 'language': messages.messages["CURRENT"], 'platform': sys.platform})
- print params
+ 'language': messages.messages["CURRENT"], 'platform': sys.platform, 'userInitiated': userInitiated})
f = urllib.urlopen(constants.SYNCPLAY_UPDATE_URL.format(params))
response = f.read()
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 06927c4..98c2ab2 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -678,7 +678,7 @@ class MainWindow(QtGui.QMainWindow):
def checkForUpdates(self, userInitiated=False):
self.lastCheckedForUpdates = datetime.utcnow()
- updateStatus, updateMessage, updateURL = self._syncplayClient.checkForUpdate()
+ updateStatus, updateMessage, updateURL = self._syncplayClient.checkForUpdate(userInitiated)
if updateMessage is None:
if updateStatus == "uptodate":
updateMessage = getMessage("syncplay-uptodate-notification")
From 90f7719322f3cb0b326ff9158e30ce0ce8c1776b Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 3 Jan 2015 15:47:32 +0000
Subject: [PATCH 32/63] Add 'auto-play when everyone is ready' feature + make
readiness pushbutton more prominent
---
syncplay/client.py | 40 ++++++++++++++++++++++++++++++----------
syncplay/constants.py | 3 ++-
syncplay/messages.py | 6 ++++++
syncplay/ui/consoleUI.py | 3 +++
syncplay/ui/gui.py | 32 +++++++++++++++++++++++++++++++-
5 files changed, 72 insertions(+), 12 deletions(-)
diff --git a/syncplay/client.py b/syncplay/client.py
index c675c3c..f5b4da6 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -105,6 +105,7 @@ class SyncplayClient(object):
self._userOffset = 0.0
self._speedChanged = False
self.behindFirstDetected = None
+ self.autoPlay = False
self._warnings = self._WarningManager(self._player, self.userlist, self.ui, self)
if constants.LIST_RELATIVE_CONFIGS and self._config.has_key('loadedRelativePaths') and self._config['loadedRelativePaths']:
@@ -310,6 +311,7 @@ class SyncplayClient(object):
self.ui.showMessage(getMessage("current-offset-notification").format(self._userOffset))
def onDisconnect(self):
+ self.resetAutoPlayState()
if self._config['pauseOnLeave']:
self.setPaused(True)
self.lastPausedOnLeaveTime = time.time()
@@ -396,6 +398,7 @@ class SyncplayClient(object):
def setRoom(self, roomName):
self.userlist.currentUser.room = roomName
+ self.resetAutoPlayState()
def sendRoom(self):
room = self.userlist.currentUser.room
@@ -482,6 +485,18 @@ class SyncplayClient(object):
return wrapper
return requireMinVersionDecorator
+ def changeAutoPlayState(self, newState):
+ self.autoPlay = newState
+ self.autoPlayCheck()
+
+ def autoPlayCheck(self):
+ if self.autoPlay and self.userlist.currentUser.canControl() and self.userlist.isReadinessSupported() and self.userlist.areAllUsersInRoomReady():
+ self.setPaused(False)
+
+ def resetAutoPlayState(self):
+ self.autoPlay = False
+ self.ui.updateAutoPlayState(False)
+
@requireMinServerVersion(constants.USER_READY_MIN_VERSION)
def toggleReady(self, manuallyInitiated=True):
self._protocol.setReady(not self.userlist.currentUser.isReady(), manuallyInitiated)
@@ -613,14 +628,6 @@ class SyncplayClient(object):
self._warnings["alone-in-the-room"]['timer'].start(constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL, True)
elif self._warnings["alone-in-the-room"]['timer'].running:
self._warnings["alone-in-the-room"]['timer'].stop()
-
- def isReadinessSupported(self):
- if not utils.meetsMinVersion(self._client.serverVersion,constants.USER_READY_MIN_VERSION):
- return False
- elif self._userlist.onlyUserInRoomWhoSupportsReadiness():
- return False
- else:
- return True
def checkReadyStates(self):
if not self._client:
@@ -646,14 +653,14 @@ class SyncplayClient(object):
osdMessage = None
if not self._userlist.areAllFilesInRoomSame():
fileDifferencesMessage = getMessage("room-file-differences").format(self._userlist.getFileDifferencesForRoom())
- if self._userlist.currentUser.canControl() and self.isReadinessSupported():
+ if self._userlist.currentUser.canControl() and self._userlist.isReadinessSupported():
if self._userlist.areAllUsersInRoomReady():
osdMessage = u"{}{}{}".format(fileDifferencesMessage, self._client._player.osdMessageSeparator, getMessage("all-users-ready"))
else:
osdMessage = u"{}{}{}".format(fileDifferencesMessage, self._client._player.osdMessageSeparator, getMessage("not-all-ready").format(self._userlist.usersInRoomNotReady()))
else:
osdMessage = fileDifferencesMessage
- elif self.isReadinessSupported():
+ elif self._userlist.isReadinessSupported():
if self._userlist.areAllUsersInRoomReady():
osdMessage = getMessage("all-users-ready")
else:
@@ -741,6 +748,14 @@ class SyncplayUserlist(object):
self._client = client
self._roomUsersChanged = True
+ def isReadinessSupported(self):
+ if not utils.meetsMinVersion(self._client.serverVersion,constants.USER_READY_MIN_VERSION):
+ return False
+ elif self.onlyUserInRoomWhoSupportsReadiness():
+ return False
+ else:
+ return True
+
def isRoomSame(self, room):
if room and self.currentUser.room and self.currentUser.room == room:
return True
@@ -925,6 +940,7 @@ class SyncplayUserlist(object):
self.currentUser.setReady(isReady)
elif self._users.has_key(username):
self._users[username].setReady(isReady)
+ self._client.autoPlayCheck()
def userListChange(self, room = None):
if room is not None and self.isRoomSame(room):
@@ -948,6 +964,7 @@ class SyncplayUserlist(object):
rooms[self.currentUser.room].append(self.currentUser)
rooms = self.sortList(rooms)
self.ui.showUserList(self.currentUser, rooms)
+ self._client.autoPlayCheck()
def clearList(self):
self._users = {}
@@ -976,6 +993,9 @@ class UiManager(object):
if not noPlayer: self.showOSDMessage(message, duration=constants.OSD_DURATION, secondaryOSD=secondaryOSD)
self.__ui.showMessage(message, noTimestamp)
+ def updateAutoPlayState(self, newState):
+ self.__ui.updateAutoPlayState(newState)
+
def showUserList(self, currentUser, rooms):
self.__ui.showUserList(currentUser, rooms)
diff --git a/syncplay/constants.py b/syncplay/constants.py
index 3e741f1..4a04326 100644
--- a/syncplay/constants.py
+++ b/syncplay/constants.py
@@ -120,7 +120,8 @@ STYLE_SUBCHECKBOX = "QCheckBox, QLabel {{ margin-left: 6px; padding-left: 21px;
STYLE_SUBLABEL = "QCheckBox, QLabel {{ margin-left: 6px; padding-left: 16px; background:url('{}') left no-repeat }}" #Graphic path
STYLE_ERRORLABEL = "QLabel { color : black; border-style: outset; border-width: 2px; border-radius: 7px; border-color: red; padding: 2px; background: #FFAAAA; }"
STYLE_SUCCESSLABEL = "QLabel { color : black; border-style: outset; border-width: 2px; border-radius: 7px; border-color: green; padding: 2px; background: #AAFFAA; }"
-STYLE_READY_PUSHBUTTON = "QPushButton { text-align: left; color : black; border-style: outset; border-width: 2px; border-radius: 7px; padding: 2px; } QPushButton::Checked {border-color: green; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00CC00, stop: 1 #00FF00); } QPushButton::!Checked { border-color: maroon; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FF0000, stop: 1 #BB0000); } QPushButton::hover:Checked {border-color: green; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00FF00, stop: 1 #00DD00); } QPushButton::hover:!Checked { border-color: maroon; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #BB0000, stop: 1 #FF0000); } QPushButton::pressed { border-style: inset; }"
+STYLE_READY_PUSHBUTTON = "QPushButton { text-align: left; color : black; border-style: outset; border-width: 2px; border-radius: 7px; padding: 5px 3px 5px 3px; font-size: 11pt; font-weight: bold; } QPushButton::Checked {border-color: green; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00CC00, stop: 1 #00FF00); } QPushButton::!Checked { border-color: maroon; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FF0000, stop: 1 #BB0000); } QPushButton::hover:Checked {border-color: green; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00FF00, stop: 1 #00DD00); } QPushButton::hover:!Checked { border-color: maroon; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #BB0000, stop: 1 #FF0000); } QPushButton::pressed { border-style: inset; }"
+STYLE_AUTO_PLAY_PUSHBUTTON = "QPushButton { text-align: left; color : black; border-style: outset; border-width: 2px; border-radius: 7px; padding: 2px; margin-left: 10px; } QPushButton::Checked {border-color: green; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00CC00, stop: 1 #00FF00); } QPushButton::!Checked { border-color: maroon; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FF0000, stop: 1 #BB0000); } QPushButton::hover:Checked {border-color: green; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00FF00, stop: 1 #00DD00); } QPushButton::hover:!Checked { border-color: maroon; background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #BB0000, stop: 1 #FF0000); } QPushButton::pressed { border-style: inset; }"
STYLE_NOTIFICATIONBOX = "Username { color: #367AA9; font-weight:bold; }"
STYLE_USERNAME = "color: #367AA9; font-weight:bold;"
STYLE_ERRORNOTIFICATION = "color: red;"
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 3e4b0bf..00cf861 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -213,6 +213,8 @@ en = {
"pause-guibuttonlabel" : "Pause",
"ready-guipushbuttonlabel" : u"I'm ready to watch! (Click to toggle)",
"notready-guipushbuttonlabel" : u"I'm not ready to watch! (Click to toggle)",
+ "autoplay-guipushbuttonlabel" : u"Auto-play when everyone is ready",
+ "noautoplay-guipushbuttonlabel" : u"Don't auto-play when everyone is ready",
"roomuser-heading-label" : "Room / User",
"size-heading-label" : "Size",
@@ -550,6 +552,8 @@ ru = {
"pause-guibuttonlabel" : u"Пауза",
"ready-guipushbuttonlabel" : u"I'm ready to watch! (Click to toggle)", # TODO: Translate into Russian
"notready-guipushbuttonlabel" : u"I'm not ready to watch! (Click to toggle)", # TODO: Translate into Russian
+ "autoplay-guipushbuttonlabel" : u"Auto-play when everyone is ready", # TODO: Translate into Russian
+ "noautoplay-guipushbuttonlabel" : u"Don't auto-play when everyone is ready", # TODO: Translate into Russian
"roomuser-heading-label" : u"Комната / Пользователь",
"size-heading-label" : u"Size", # TODO: Translate into Russian
@@ -885,6 +889,8 @@ de = {
"pause-guibuttonlabel" : u"Pause",
"ready-guipushbuttonlabel" : u"I'm ready to watch! (Click to toggle)", # TODO: Translate into German
"notready-guipushbuttonlabel" : u"I'm not ready to watch! (Click to toggle)", # TODO: Translate into German
+ "autoplay-guipushbuttonlabel" : u"Auto-play when everyone is ready", # TODO: Translate into German
+ "noautoplay-guipushbuttonlabel" : u"Don't auto-play when everyone is ready", # TODO: Translate into German
"roomuser-heading-label" : u"Raum / Benutzer",
"size-heading-label" : u"Größe",
diff --git a/syncplay/ui/consoleUI.py b/syncplay/ui/consoleUI.py
index b912e57..8f42bfd 100644
--- a/syncplay/ui/consoleUI.py
+++ b/syncplay/ui/consoleUI.py
@@ -39,6 +39,9 @@ class ConsoleUI(threading.Thread):
def updateRoomName(self, room=""):
pass
+ def updateAutoPlayState(self, newState):
+ pass
+
def promptFor(self, prompt=">", message=""):
if message <> "":
print(message)
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 98c2ab2..51105db 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -209,6 +209,12 @@ class MainWindow(QtGui.QMainWindow):
self.readyPushButton.setChecked(newState)
self.updateReadyIcon()
+ def updateAutoPlayState(self, newState):
+ oldState = self.autoPlayPushButton.isChecked()
+ if newState != oldState and newState != None:
+ self.autoPlayPushButton.setChecked(newState)
+ self.updateAutoPlayIcon()
+
def roomClicked(self, item):
while item.parent().row() != -1:
item = item.parent()
@@ -473,12 +479,23 @@ class MainWindow(QtGui.QMainWindow):
readyFont = QtGui.QFont()
readyFont.setWeight(QtGui.QFont.Bold)
window.readyPushButton.setCheckable(True)
- window.readyPushButton.setAutoExclusive(True)
+ window.readyPushButton.setAutoExclusive(False)
window.readyPushButton.toggled.connect(self.changeReadyState)
window.readyPushButton.setFont(readyFont)
window.readyPushButton.setStyleSheet(constants.STYLE_READY_PUSHBUTTON)
window.listLayout.addWidget(window.readyPushButton, Qt.AlignRight)
+ window.autoPlayPushButton = QtGui.QPushButton()
+ autoPlayFont = QtGui.QFont()
+ autoPlayFont.setWeight(QtGui.QFont.Bold)
+ window.autoPlayPushButton.setCheckable(True)
+ window.autoPlayPushButton.setAutoExclusive(False)
+ window.autoPlayPushButton.toggled.connect(self.changeAutoPlayState)
+ window.autoPlayPushButton.setFont(autoPlayFont)
+ window.autoPlayPushButton.setStyleSheet(constants.STYLE_AUTO_PLAY_PUSHBUTTON)
+ window.listLayout.addWidget(window.autoPlayPushButton, Qt.AlignRight)
+ self.updateAutoPlayIcon()
+
window.contactLabel = QtGui.QLabel()
window.contactLabel.setWordWrap(True)
window.contactLabel.setFrameStyle(QtGui.QFrame.Box | QtGui.QFrame.Sunken)
@@ -649,6 +666,10 @@ class MainWindow(QtGui.QMainWindow):
self.updateReadyIcon()
self._syncplayClient.changeReadyState(self.readyPushButton.isChecked())
+ def changeAutoPlayState(self):
+ self.updateAutoPlayIcon()
+ self._syncplayClient.changeAutoPlayState(self.autoPlayPushButton.isChecked())
+
def updateReadyIcon(self):
ready = self.readyPushButton.isChecked()
if ready:
@@ -658,6 +679,15 @@ class MainWindow(QtGui.QMainWindow):
self.readyPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'cross_checkbox.png'))
self.readyPushButton.setText(getMessage("notready-guipushbuttonlabel"))
+ def updateAutoPlayIcon(self):
+ ready = self.autoPlayPushButton.isChecked()
+ if ready:
+ self.autoPlayPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'tick_checkbox.png'))
+ self.autoPlayPushButton.setText(getMessage("autoplay-guipushbuttonlabel"))
+ else:
+ self.autoPlayPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'cross_checkbox.png'))
+ self.autoPlayPushButton.setText(getMessage("noautoplay-guipushbuttonlabel"))
+
def automaticUpdateCheck(self):
if not self.config['checkForUpdatesAutomatically']:
return
From 61e27ce3a2d2826663bc3f2801920c47c2c5f8e7 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 3 Jan 2015 20:32:55 +0000
Subject: [PATCH 33/63] Fix update check bug
---
syncplay/ui/gui.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 51105db..9a95070 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -689,13 +689,13 @@ class MainWindow(QtGui.QMainWindow):
self.autoPlayPushButton.setText(getMessage("noautoplay-guipushbuttonlabel"))
def automaticUpdateCheck(self):
+ currentDateTime = datetime.utcnow()
if not self.config['checkForUpdatesAutomatically']:
return
if self.config['lastCheckedForUpdates']:
configLastChecked = datetime.strptime(self.config["lastCheckedForUpdates"], "%Y-%m-%d %H:%M:%S.%f")
if self.lastCheckedForUpdates is None or configLastChecked > self.lastCheckedForUpdates:
self.lastCheckedForUpdates = configLastChecked
- currentDateTime = datetime.utcnow()
if self.lastCheckedForUpdates is None:
self.checkForUpdates()
else:
From ee5ce80332cadbee1c6342a1e25f4631114b5dd4 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 3 Jan 2015 21:35:13 +0000
Subject: [PATCH 34/63] Change pushbutton style
---
resources/empty_checkbox.png | Bin 0 -> 179 bytes
syncplay/constants.py | 4 ++--
syncplay/messages.py | 12 +++---------
syncplay/ui/gui.py | 10 ++++------
4 files changed, 9 insertions(+), 17 deletions(-)
create mode 100644 resources/empty_checkbox.png
diff --git a/resources/empty_checkbox.png b/resources/empty_checkbox.png
new file mode 100644
index 0000000000000000000000000000000000000000..e8ad9d72f8e4207e50da6d42715273f4b980a317
GIT binary patch
literal 179
zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|mUKs7M+S!VC(K#9UIO`?1s;*b
z3=DjSL74G){)!Z!pj3%#L`iUdT1k0gQ7S_~VrE{6o}X)oLYc9ish**M!Iz?iKvnvl
zE{-7<{>d2`84M5qPf6OKIHif1ov%mAg#m~qz?h*~!hy%Dz}cCZnW6OJu0K3KJ
Date: Sat, 3 Jan 2015 21:36:28 +0000
Subject: [PATCH 35/63] replace move_crossbox.png to empty_checkbox.png
---
buildPy2exe.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/buildPy2exe.py b/buildPy2exe.py
index fa428f9..20caad1 100644
--- a/buildPy2exe.py
+++ b/buildPy2exe.py
@@ -643,7 +643,7 @@ guiIcons = ['resources/accept.png', 'resources/arrow_undo.png', 'resources/clock
'resources/mpv.png','resources/vlc.png', 'resources/house.png', 'resources/film_link.png',
'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/chevrons_right.png',
'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png',
- 'resources/tick.png', 'resources/lock_open.png', 'resources/cross_checkbox.png', 'resources/tick_checkbox.png',
+ 'resources/tick.png', 'resources/lock_open.png', 'resources/empty_checkbox.png', 'resources/tick_checkbox.png',
'resources/world_explore.png', 'resources/application_get.png'
]
resources = ["resources/icon.ico", "resources/syncplay.png"]
From 23fb2435a13c982e78180d9a949462112466b360 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Mon, 5 Jan 2015 02:07:47 +0000
Subject: [PATCH 36/63] GuiConfig: Move various settings into new Misc tab +
move language into bottom layout
---
buildPy2exe.py | 2 +-
resources/cog.png | Bin 0 -> 512 bytes
syncplay/messages.py | 35 +++--
syncplay/ui/GuiConfiguration.py | 230 ++++++++++++++++++--------------
4 files changed, 153 insertions(+), 114 deletions(-)
create mode 100644 resources/cog.png
diff --git a/buildPy2exe.py b/buildPy2exe.py
index 20caad1..9f3113a 100644
--- a/buildPy2exe.py
+++ b/buildPy2exe.py
@@ -644,7 +644,7 @@ guiIcons = ['resources/accept.png', 'resources/arrow_undo.png', 'resources/clock
'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/chevrons_right.png',
'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png',
'resources/tick.png', 'resources/lock_open.png', 'resources/empty_checkbox.png', 'resources/tick_checkbox.png',
- 'resources/world_explore.png', 'resources/application_get.png'
+ 'resources/world_explore.png', 'resources/application_get.png', 'resources/cog.png'
]
resources = ["resources/icon.ico", "resources/syncplay.png"]
resources.extend(guiIcons)
diff --git a/resources/cog.png b/resources/cog.png
new file mode 100644
index 0000000000000000000000000000000000000000..67de2c6ccbeac17742f56cf7391e72b2bf5033ba
GIT binary patch
literal 512
zcmV+b0{{JqP)CQDsH?WF>AIFt
zQuJ}i;w2$ZUU#3SZ6RY0Gw;kZ&ol1~2ky^QZ(fom$=jNJZt!z7w_pH~wdQ;R)Gh%BbQFCx+Nm!4SuS-vkr`vhhrX
zM*>w%e+v~?m@q~ImPAgtLkR_3U<2F8LP3W5=LJ*ZN|S5p#sf4YFr$p~Q~Z*0Ngxf2
zjk#J#<7EAlhzlrV53~GF&pIzcCN_lz9@05UeoUXiK%N
z#x+4o*i_c|6_Uu1+&TIho?3@y4k-#b8Y_o94zW*B3a1ne2-Y5s0uke$$|@=}OP-i=
zNYZQA=>PrZu0MfSL=b8UhD_={W4IY1{b{)U)*gc45xtL%IYLY&hF;d`@GzI&7H&D#
zh;z_BX$#hqh@q?AY3sJTod2%*Yd)_>YM0#q&ixGuh+PQsneK)F0000
Date: Mon, 5 Jan 2015 02:26:36 +0000
Subject: [PATCH 37/63] Use term "Default" instead of "Automatic" for
locale-identified language
---
syncplay/messages.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 7e0504a..8fd6384 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -186,7 +186,7 @@ en = {
"showslowdownosd-label" :"Include slowing down / reverting notifications",
"showcontactinfo-label" : "Show contact info box",
"language-label" : "Language:",
- "automatic-language" : "Automatic ({})", # Automatic language #
+ "automatic-language" : "Default ({})", # Default language
"showdurationnotification-label" : "Warn about media duration mismatches",
"basics-label" : "Basics",
"misc-label" : u"Misc",
@@ -526,7 +526,7 @@ ru = {
"showslowdownosd-label" : u"Показывать уведомления о замедлении/перемотке",
"showcontactinfo-label" : u"Отображать контактную информацию разработчиков",
"language-label" : u"Language:", # TODO: Translate into Russian
- "automatic-language" : u"Automatic ({})", # Automatic language # TODO: Translate into Russian
+ "automatic-language" : u"Default ({})", # Automatic language # TODO: Translate into Russian
"showdurationnotification-label" : u"Предупреждать о несовпадении продолжительности видео",
"basics-label" : u"Основное",
"misc-label" : u"Misc", # TODO: Translate into Russian
@@ -864,7 +864,7 @@ de = {
"showslowdownosd-label" : u"Zeige Verlangsamungs/Zurücksetzungs-Benachrichtigung",
"showcontactinfo-label" : u"Zeige Kontaktinformationen",
"language-label" : u"Sprache:",
- "automatic-language" : u"Automatisch ({})", # Automatic language
+ "automatic-language" : u"Automatisch ({})", # Default language # TODO: Change to German translation of "default"
"showdurationnotification-label" : u"Zeige Warnung wegen unterschiedlicher Dauer",
"basics-label" : u"Basics",
"misc-label" : u"Misc", # TODO: Translate into German
From 81fbd740e5f46a59f39e3c2e36f06640e400dbc9 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Mon, 5 Jan 2015 21:13:28 +0000
Subject: [PATCH 38/63] Replace contact box with contact message
---
syncplay/messages.py | 12 +++---------
syncplay/ui/ConfigurationGetter.py | 3 +--
syncplay/ui/GuiConfiguration.py | 4 ----
syncplay/ui/gui.py | 24 ++++++++++--------------
4 files changed, 14 insertions(+), 29 deletions(-)
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 8fd6384..a6833e1 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -184,7 +184,6 @@ en = {
"shownoncontrollerosd-label" : "Include events from non-controllers in controlled rooms",
"showdifferentroomosd-label" : "Include events in other rooms",
"showslowdownosd-label" :"Include slowing down / reverting notifications",
- "showcontactinfo-label" : "Show contact info box",
"language-label" : "Language:",
"automatic-language" : "Default ({})", # Default language
"showdurationnotification-label" : "Warn about media duration mismatches",
@@ -206,7 +205,7 @@ en = {
"run-label" : "Run Syncplay",
"storeandrun-label" : "Store configuration and run Syncplay",
- "contact-label" : "Have an idea, bug report or feedback? E-mail dev@syncplay.pl, chat via the #Syncplay IRC channel on irc.freenode.net or raise an issue via GitHub. Also check out http://syncplay.pl/ for info, help and updates.",
+ "contact-label" : "Have an idea, bug report or feedback? E-mail dev@syncplay.pl, chat via the #Syncplay IRC channel on irc.freenode.net or raise an issue via GitHub. Also check out http://syncplay.pl/ for info, help and updates.
",
"joinroom-guibuttonlabel" : "Join room",
"seektime-guibuttonlabel" : "Seek to time",
@@ -290,7 +289,6 @@ en = {
"shownoncontrollerosd-tooltip" : "Show OSD notifications for events relating to non-controllers who are in controlled rooms.",
"showdifferentroomosd-tooltip" : "Show OSD notifications for events relating to room user is not in.",
"showslowdownosd-tooltip" :"Show notifications of slowing down / reverting on time difference.",
- "showcontactinfo-tooltip" : "Show information box about contacting Syncplay developers in main Syncplay window.",
"showdurationnotification-tooltip" : "Useful for when a segment in a multi-part file is missing, but can result in false positives.",
"language-tooltip" : u"Language to be used by Syncplay.",
@@ -524,7 +522,6 @@ ru = {
"shownoncontrollerosd-label" : u"Include events from non-controllers in controlled rooms", # TODO: Translate into Russiann
"showdifferentroomosd-label" : u"Показывать события других комнат",
"showslowdownosd-label" : u"Показывать уведомления о замедлении/перемотке",
- "showcontactinfo-label" : u"Отображать контактную информацию разработчиков",
"language-label" : u"Language:", # TODO: Translate into Russian
"automatic-language" : u"Default ({})", # Automatic language # TODO: Translate into Russian
"showdurationnotification-label" : u"Предупреждать о несовпадении продолжительности видео",
@@ -546,7 +543,7 @@ ru = {
"run-label" : u"Запустить Syncplay",
"storeandrun-label" : u"Сохранить настройки и зап. Syncplay",
- "contact-label" : u"Есть идея, нашли ошибку или хотите оставить отзыв? Пишите на dev@syncplay.pl, в IRC канал #Syncplay на irc.freenode.net или задавайте вопросы через GitHub. Кроме того, заходите на http://syncplay.pl/ за инорфмацией, помощью и обновлениями!",
+ "contact-label" : u"Есть идея, нашли ошибку или хотите оставить отзыв? Пишите на dev@syncplay.pl, в IRC канал #Syncplay на irc.freenode.net или задавайте вопросы через GitHub. Кроме того, заходите на http://syncplay.pl/ за инорфмацией, помощью и обновлениями!
",
"joinroom-guibuttonlabel" : u"Зайти в комнату",
"seektime-guibuttonlabel" : u"Перемотать",
@@ -630,7 +627,6 @@ ru = {
"shownoncontrollerosd-tooltip" : u"Show OSD notifications for events relating to non-controllers who are in controllerd rooms.", # TODO: Translate into Russian
"showdifferentroomosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к любым другим комнатам.",
"showslowdownosd-tooltip" : u"Показывать уведомления о замедлении или перемотке в целях синхронизации.",
- "showcontactinfo-tooltip" : u"Показывать информационных блок с контактной информацией разработчиков Syncplay на главном окне Syncplay.",
"showdurationnotification-tooltip" : u"Полезно, когда сегмент составного файла отсутствует. Возможны ложные срабатывания.",
"language-tooltip" : u"Language to be used by Syncplay.", # TODO: Translate into Russian
@@ -862,7 +858,6 @@ de = {
"shownoncontrollerosd-label" : u"Zeige Ereignisse von nicht geführten Räumen in geführten Räumen.",
"showdifferentroomosd-label" : u"Zeige Ereignisse in anderen Räumen",
"showslowdownosd-label" : u"Zeige Verlangsamungs/Zurücksetzungs-Benachrichtigung",
- "showcontactinfo-label" : u"Zeige Kontaktinformationen",
"language-label" : u"Sprache:",
"automatic-language" : u"Automatisch ({})", # Default language # TODO: Change to German translation of "default"
"showdurationnotification-label" : u"Zeige Warnung wegen unterschiedlicher Dauer",
@@ -884,7 +879,7 @@ de = {
"run-label" : u"Syncplay starten",
"storeandrun-label" : u"Konfiguration speichern und Syncplay starten",
- "contact-label" : u"Du hast eine Idee, einen Bug gefunden oder möchtest Feedback geben? Sende eine E-Mail an dev@syncplay.pl, chatte auf dem #Syncplay IRC-Kanal auf irc.freenode.net oder öffne eine Fehlermeldung auf GitHub. Außerdem findest du auf http://syncplay.pl/ weitere Informationen, Hilfestellungen und Updates.",
+ "contact-label" : u"Du hast eine Idee, einen Bug gefunden oder möchtest Feedback geben? Sende eine E-Mail an dev@syncplay.pl, chatte auf dem #Syncplay IRC-Kanal auf irc.freenode.net oder öffne eine Fehlermeldung auf GitHub. Außerdem findest du auf http://syncplay.pl/ weitere Informationen, Hilfestellungen und Updates.
" # Contact info message
STYLE_USERNAME = "color: #367AA9; font-weight:bold;"
STYLE_ERRORNOTIFICATION = "color: red;"
STYLE_DIFFERENTITEM_COLOR = 'red'
diff --git a/syncplay/messages.py b/syncplay/messages.py
index a6833e1..2b77eed 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -205,7 +205,7 @@ en = {
"run-label" : "Run Syncplay",
"storeandrun-label" : "Store configuration and run Syncplay",
- "contact-label" : "Have an idea, bug report or feedback? E-mail dev@syncplay.pl, chat via the #Syncplay IRC channel on irc.freenode.net or raise an issue via GitHub. Also check out http://syncplay.pl/ for info, help and updates.
" # Contact info message
+STYLE_CONTACT_INFO = u"{}
" # Contact info message
STYLE_USERNAME = "color: #367AA9; font-weight:bold;"
STYLE_ERRORNOTIFICATION = "color: red;"
STYLE_DIFFERENTITEM_COLOR = 'red'
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 2b77eed..39ab961 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -543,7 +543,7 @@ ru = {
"run-label" : u"Запустить Syncplay",
"storeandrun-label" : u"Сохранить настройки и зап. Syncplay",
- "contact-label" : u"Есть идея, нашли ошибку или хотите оставить отзыв? Пишите на dev@syncplay.pl, в IRC канал #Syncplay на irc.freenode.net или задавайте вопросы через GitHub. Кроме того, заходите на http://syncplay.pl/ за инорфмацией, помощью и обновлениями!
",
+ "contact-label" : u"Есть идея, нашли ошибку или хотите оставить отзыв? Пишите на dev@syncplay.pl, в IRC канал #Syncplay на irc.freenode.net или задавайте вопросы через GitHub. Кроме того, заходите на http://syncplay.pl/ за инорфмацией, помощью и обновлениями!",
"joinroom-guibuttonlabel" : u"Зайти в комнату",
"seektime-guibuttonlabel" : u"Перемотать",
@@ -879,7 +879,7 @@ de = {
"run-label" : u"Syncplay starten",
"storeandrun-label" : u"Konfiguration speichern und Syncplay starten",
- "contact-label" : u"Du hast eine Idee, einen Bug gefunden oder möchtest Feedback geben? Sende eine E-Mail an dev@syncplay.pl, chatte auf dem #Syncplay IRC-Kanal auf irc.freenode.net oder öffne eine Fehlermeldung auf GitHub. Außerdem findest du auf http://syncplay.pl/ weitere Informationen, Hilfestellungen und Updates.
" # Contact info message
STYLE_USERNAME = "color: #367AA9; font-weight:bold;"
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 39ab961..e2a546e 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -123,6 +123,9 @@ en = {
"vlc-failed-versioncheck": "This version of VLC is not supported by Syncplay. Please use VLC 2.",
"vlc-failed-other" : "When trying to load the syncplay.lua interface script VLC has provided the following error: {}", # Syncplay Error
+ "invalid-seek-value" : u"Invalid seek value",
+ "invalid-offset-value" : u"Invalid offset value",
+
# Client arguments
"argument-description" : 'Solution to synchronize playback of multiple MPlayer and MPC-HC instances over the network.',
"argument-epilog" : 'If no options supplied _config values will be used',
@@ -207,14 +210,15 @@ en = {
"contact-label" : "Feel free to e-mail dev@syncplay.pl, chat via the #Syncplay IRC channel on irc.freenode.net, raise an issue via GitHub or visit http://syncplay.pl/",
- "joinroom-guibuttonlabel" : "Join room",
- "seektime-guibuttonlabel" : "Seek to time",
- "undoseek-guibuttonlabel" : "Undo seek",
- "togglepause-guibuttonlabel" : "Toggle pause",
- "play-guibuttonlabel" : "Play",
- "pause-guibuttonlabel" : "Pause",
+ "joinroom-menu-label" : "Join room",
+ "seektime-menu-label" : "Seek to time",
+ "undoseek-menu-label" : "Undo seek",
+ "togglepause-menu-label" : "Toggle pause",
+ "play-menu-label" : "Play",
+ "pause-menu-label" : "Pause",
+ "autoplay-menu-label" : u"Auto-play when everyone is ready",
+
"ready-guipushbuttonlabel" : u"I'm ready to watch!",
- "autoplay-guipushbuttonlabel" : u"Auto-play when everyone is ready",
"roomuser-heading-label" : "Room / User",
"size-heading-label" : "Size",
@@ -222,9 +226,6 @@ en = {
"filename-heading-label" : "Filename",
"notifications-heading-label" : "Notifications",
"userlist-heading-label" : "List of who is playing what",
- "othercommands-heading-label" : "Other commands",
- "room-heading-label" : "Room",
- "seek-heading-label" : "Seek",
"browseformedia-label" : "Browse for media files",
@@ -237,6 +238,8 @@ en = {
"createcontrolledroom-menu-label" : "&Create controlled room",
"identifyascontroller-menu-label" : "&Identify as room controller",
+ "playback-menu-label" : u"&Playback",
+
"help-menu-label" : "&Help",
"userguide-menu-label" : "Open user &guide",
"update-menu-label" : "Check for &update",
@@ -295,12 +298,8 @@ en = {
"help-tooltip" : "Opens the Syncplay.pl user guide.",
"reset-tooltip" : "Reset all settings to the default configuration.",
- "togglepause-tooltip" : "Pause/unpause media.",
- "play-tooltip" : "Unpause media.",
- "pause-tooltip" : "Pause media.",
- "undoseek-tooltip" : "Seek to where you were before the most recent seek.",
"joinroom-tooltip" : "Leave current room and joins specified room.",
- "seektime-tooltip" : "Jump to specified time (in seconds / min:sec). Use +/- for relative seek.",
+ "seektime-msgbox-label" : "Jump to specified time (in seconds / min:sec). Use +/- for relative seek.",
# In-userlist notes (GUI)
"differentsize-note" : "Different size!",
@@ -461,6 +460,9 @@ ru = {
"vlc-failed-versioncheck" : u"Данная версия VLC не поддерживается Syncplay. Пожалуйста, используйте VLC версии 2 или выше.",
"vlc-failed-other" : u"Во время загрузки скрипта интерфейса syncplay.lua в VLC произошла следующая ошибка: {}", # Syncplay Error
+ "invalid-seek-value" : u"Invalid seek value", # TODO: Translate into Russian
+ "invalid-offset-value" : u"Invalid offset value", # TODO: Translate into Russian
+
# Client arguments
"argument-description" : u'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC через Интернет.',
"argument-epilog" : u'Если параметр не будет передан, то будет использоваться значение, указанное в _config.',
@@ -545,14 +547,14 @@ ru = {
"contact-label" : u"Есть идея, нашли ошибку или хотите оставить отзыв? Пишите на dev@syncplay.pl, в IRC канал #Syncplay на irc.freenode.net или задавайте вопросы через GitHub. Кроме того, заходите на http://syncplay.pl/ за инорфмацией, помощью и обновлениями!",
- "joinroom-guibuttonlabel" : u"Зайти в комнату",
- "seektime-guibuttonlabel" : u"Перемотать",
- "undoseek-guibuttonlabel" : u"Отменить перемотку",
- "togglepause-guibuttonlabel" : u"Вкл./выкл. паузу",
- "play-guibuttonlabel" : u"Play",
- "pause-guibuttonlabel" : u"Пауза",
+ "joinroom-menu-label" : u"Зайти в комнату",
+ "seektime-menu-label" : u"Перемотать",
+ "undoseek-menu-label" : u"Отменить перемотку",
+ "play-menu-label" : u"Play",
+ "pause-menu-label" : u"Пауза",
+ "autoplay-menu-label" : u"Auto-play when everyone is ready", # TODO: Translate into Russian
+
"ready-guipushbuttonlabel" : u"I'm ready to watch!", # TODO: Translate into Russian
- "autoplay-guipushbuttonlabel" : u"Auto-play when everyone is ready", # TODO: Translate into Russian
"roomuser-heading-label" : u"Комната / Пользователь",
"size-heading-label" : u"Size", # TODO: Translate into Russian
@@ -560,9 +562,6 @@ ru = {
"filename-heading-label" : u"Filename", # TODO: Translate into Russian
"notifications-heading-label" : u"Уведомления",
"userlist-heading-label" : u"Кто что смотрит",
- "othercommands-heading-label" : u"Другие команды",
- "room-heading-label" : u"Комната",
- "seek-heading-label" : u"Перемотка",
"browseformedia-label" : u"Выбрать видеофайл",
@@ -633,12 +632,8 @@ ru = {
"help-tooltip" : u"Открыть Руководство Пользователя на Syncplay.pl.",
"reset-tooltip" : u"Сбрасывает все настройки Syncplay в начальное состояние.",
- "togglepause-tooltip" : u"Приостановить/продолжить просмотр.",
- "play-tooltip" : u"Продолжить просмотр.",
- "pause-tooltip" : u"Приостановить просмотр.",
- "undoseek-tooltip" : u"Перейти к тому месту, которое Вы просматривали до перемотки.",
"joinroom-tooltip" : u"Покинуть комнату и зайти в другую, указанную комнату.",
- "seektime-tooltip" : u"Перемотать к определенному моменту времени (указывать в секундах или мин:сек). Используйте +/-, чтобы перемотать вперед/назад относительно настоящего момента.",
+ "seektime-msgbox-label" : u"Перемотать к определенному моменту времени (указывать в секундах или мин:сек). Используйте +/-, чтобы перемотать вперед/назад относительно настоящего момента.",
# In-userlist notes (GUI)
"differentsize-note" : u"Размер файла не совпадает!",
@@ -799,6 +794,9 @@ de = {
"vlc-failed-versioncheck": u"Diese VLC-Version wird von Syncplay nicht unterstützt. Bitte nutze VLC 2.0",
"vlc-failed-other" : u"Beim Laden des syncplay.lua Interface-Skripts durch VLC trat folgender Fehler auf: {}", # Syncplay Error
+ "invalid-seek-value" : u"Invalid seek value", # TODO: Translate into German
+ "invalid-offset-value" : u"Invalid offset value", # TODO: Translate into German
+
# Client arguments
"argument-description" : u'Anwendung, um mehrere MPlayer, MPC-HC und VLC-Instanzen über das Internet zu synchronisieren.',
"argument-epilog" : u'Wenn keine Optionen angegeben sind, werden die _config-Werte verwendet',
@@ -881,14 +879,15 @@ de = {
"contact-label" : u"Du hast eine Idee, einen Bug gefunden oder möchtest Feedback geben? Sende eine E-Mail an dev@syncplay.pl, chatte auf dem #Syncplay IRC-Kanal auf irc.freenode.net oder öffne eine Fehlermeldung auf GitHub. Außerdem findest du auf http://syncplay.pl/ weitere Informationen, Hilfestellungen und Updates.",
- "joinroom-guibuttonlabel" : u"Raum beitreten",
- "seektime-guibuttonlabel" : u"Spule zu Zeit",
- "undoseek-guibuttonlabel" : u"Rückgängig",
- "togglepause-guibuttonlabel" : u"Pause umschalten",
- "play-guibuttonlabel" : u"Wiedergabe",
- "pause-guibuttonlabel" : u"Pause",
+ "joinroom-menu-label" : u"Raum beitreten",
+ "seektime-menu-label" : u"Spule zu Zeit",
+ "undoseek-menu-label" : u"Rückgängig",
+ "togglepause-menu-label" : u"Pause umschalten",
+ "play-menu-label" : u"Wiedergabe",
+ "pause-menu-label" : u"Pause",
+ "autoplay-menu-label" : u"Auto-play when everyone is ready", # TODO: Translate into German
+
"ready-guipushbuttonlabel" : u"I'm ready to watch!", # TODO: Translate into German
- "autoplay-guipushbuttonlabel" : u"Auto-play when everyone is ready", # TODO: Translate into German
"roomuser-heading-label" : u"Raum / Benutzer",
"size-heading-label" : u"Größe",
@@ -896,9 +895,6 @@ de = {
"filename-heading-label" : u"Dateiname",
"notifications-heading-label" : u"Benachrichtigungen",
"userlist-heading-label" : u"Liste der gespielten Dateien",
- "othercommands-heading-label" : u"Andere Befehle",
- "room-heading-label" : u"Raum",
- "seek-heading-label" : u"Spulen",
"browseformedia-label" : u"Nach Mediendateien durchsuchen",
@@ -971,12 +967,8 @@ de = {
"help-tooltip" : u"Öffnet Hilfe auf syncplay.pl [Englisch]",
"reset-tooltip" : u"Alle Einstellungen auf Standardwerte zurücksetzen.",
- "togglepause-tooltip" : u"Datei starten/pausieren",
- "play-tooltip" : u"Fortsetzen",
- "pause-tooltip" : u"Pausieren",
- "undoseek-tooltip" : u"Den letzten Spulvorgang rückgängig machen.",
"joinroom-tooltip" : u"Den aktuellen Raum verlassen und stattdessen den angegebenen betreten.",
- "seektime-tooltip" : u"Springe zur angegebenen Zeit (in Sekunden oder min:sek). Verwende +/- zum relativen Springen.",
+ "seektime-msgbox-label" : u"Springe zur angegebenen Zeit (in Sekunden oder min:sek). Verwende +/- zum relativen Springen.",
# In-userlist notes (GUI)
"differentsize-note" : u"Verschiedene Größe!",
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 03e9d09..45a3102 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -208,10 +208,9 @@ class MainWindow(QtGui.QMainWindow):
self.updateReadyIcon()
def updateAutoPlayState(self, newState):
- oldState = self.autoPlayPushButton.isChecked()
+ oldState = self.autoplayAction.isChecked()
if newState != oldState and newState != None:
- self.autoPlayPushButton.setChecked(newState)
- self.updateAutoPlayIcon()
+ self.autoplayAction.setChecked(newState)
def roomClicked(self, item):
while item.parent().row() != -1:
@@ -250,18 +249,21 @@ class MainWindow(QtGui.QMainWindow):
self._syncplayClient.sendRoom()
def seekPosition(self):
- s = re.match(constants.UI_SEEK_REGEX, self.seekInput.text())
- if s:
- sign = self._extractSign(s.group('sign'))
- t = utils.parseTime(s.group('time'))
- if t is None:
- return
- if sign:
- t = self._syncplayClient.getGlobalPosition() + sign * t
- self._syncplayClient.setPosition(t)
-
- else:
- self.showErrorMessage("Invalid seek value")
+ seekTime, ok = QtGui.QInputDialog.getText(self, getMessage("seektime-menu-label"),
+ getMessage("seektime-msgbox-label"), QtGui.QLineEdit.Normal,
+ "0:00")
+ if ok and seekTime != '':
+ s = re.match(constants.UI_SEEK_REGEX, seekTime)
+ if s:
+ sign = self._extractSign(s.group('sign'))
+ t = utils.parseTime(s.group('time'))
+ if t is None:
+ return
+ if sign:
+ t = self._syncplayClient.getGlobalPosition() + sign * t
+ self._syncplayClient.setPosition(t)
+ else:
+ self.showErrorMessage(getMessage("invalid-seek-value"))
def undoSeek(self):
tmp_pos = self._syncplayClient.getPlayerPosition()
@@ -284,69 +286,6 @@ class MainWindow(QtGui.QMainWindow):
self.exitSyncplay()
self.saveSettings()
- def setupSizes(self):
- self.hideRoomSeekLabels()
- self.miscThreshold = self.seekGroup.sizeHint().width()+self.roomGroup.sizeHint().width()+self.miscGroup.sizeHint().width()+30
- self.hideMiscLabels()
- self.setMinimumWidth(self.seekGroup.sizeHint().width()+self.roomGroup.sizeHint().width()+self.miscGroup.sizeHint().width()+30)
- self.seekGroup.setMinimumWidth(self.seekGroup.sizeHint().width())
- self.roomGroup.setMinimumWidth(self.roomGroup.sizeHint().width())
- self.miscGroup.setMinimumWidth(self.miscGroup.sizeHint().width())
- self.showRoomSeekLabels()
- self.showMiscLabels()
- windowMaximumWidth = self.maximumWidth()
- self.seekGroup.setMaximumWidth(self.seekGroup.sizeHint().width())
- self.roomGroup.setMaximumWidth(self.roomGroup.sizeHint().width())
- self.miscGroup.setMaximumWidth(self.miscGroup.sizeHint().width())
- self.setMaximumWidth(windowMaximumWidth)
- self.roomSeekThreshold = self.mainLayout.sizeHint().width()
-
- def hideRoomSeekLabels(self):
- self.roomButton.setText("")
- self.seekButton.setText("")
-
- def hideMiscLabels(self):
- self.unseekButton.setText("")
- if constants.MERGE_PLAYPAUSE_BUTTONS:
- self.playpauseButton.setText("")
- else:
- self.playButton.setText("")
- self.pauseButton.setText("")
-
- def showRoomSeekLabels(self):
- if not constants.SHOW_BUTTON_LABELS:
- return
- self.roomButton.setText(getMessage("joinroom-guibuttonlabel"))
- self.seekButton.setText(getMessage("seektime-guibuttonlabel"))
-
- def showMiscLabels(self):
- self.unseekButton.setText(getMessage("undoseek-guibuttonlabel"))
- if not constants.SHOW_BUTTON_LABELS:
- return
- if constants.MERGE_PLAYPAUSE_BUTTONS:
- self.playpauseButton.setText(getMessage("togglepause-guibuttonlabel"))
- else:
- self.playButton.setText(getMessage("play-guibuttonlabel"))
- self.pauseButton.setText(getMessage("pause-guibuttonlabel"))
-
- def resizeEvent(self,resizeEvent):
- self.updateListGeometry()
- if self.roomGroup and self.miscThreshold:
- currentWidth = self.mainFrame.size().width()
- if currentWidth < self.miscThreshold:
- if self.unseekButton.text() != "":
- self.hideMiscLabels()
- else:
- if self.unseekButton.text() == "":
- self.showMiscLabels()
-
- if currentWidth < self.roomSeekThreshold:
- if self.roomButton.text() != "":
- self.hideRoomSeekLabels()
- else:
- if self.roomButton.text() == "":
- self.showRoomSeekLabels()
-
def loadMediaBrowseSettings(self):
settings = QSettings("Syncplay", "MediaBrowseDialog")
settings.beginGroup("MediaBrowseDialog")
@@ -431,7 +370,7 @@ class MainWindow(QtGui.QMainWindow):
t = self._syncplayClient.getUserOffset() + sign * t
self._syncplayClient.setUserOffset(t)
else:
- self.showErrorMessage("Invalid offset value")
+ self.showErrorMessage(getMessage("invalid-offset-value"))
def openUserGuide(self):
if sys.platform.startswith('linux'):
@@ -456,6 +395,7 @@ class MainWindow(QtGui.QMainWindow):
window.outputbox.moveCursor(QtGui.QTextCursor.End)
window.outputbox.insertHtml(constants.STYLE_CONTACT_INFO.format(getMessage("contact-label")))
window.outputbox.moveCursor(QtGui.QTextCursor.End)
+ window.outputbox.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
window.outputlabel = QtGui.QLabel(getMessage("notifications-heading-label"))
window.outputFrame = QtGui.QFrame()
@@ -476,10 +416,28 @@ class MainWindow(QtGui.QMainWindow):
window.listFrame = QtGui.QFrame()
window.listFrame.setLineWidth(0)
window.listFrame.setMidLineWidth(0)
+ window.listFrame.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
window.listLayout.setContentsMargins(0, 0, 0, 0)
window.listLayout.addWidget(window.listlabel)
window.listLayout.addWidget(window.listTreeView)
+ window.roomInput = QtGui.QLineEdit()
+ window.roomInput.returnPressed.connect(self.joinRoom)
+ window.roomButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'door_in.png'),
+ getMessage("joinroom-menu-label"))
+ window.roomButton.pressed.connect(self.joinRoom)
+ window.roomLayout = QtGui.QHBoxLayout()
+ window.roomFrame = QtGui.QFrame()
+ window.roomFrame.setLayout(self.roomLayout)
+ window.roomFrame.setContentsMargins(0,0,0,0)
+ window.roomFrame.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
+ window.roomLayout.setContentsMargins(0,0,0,0)
+ self.roomButton.setToolTip(getMessage("joinroom-tooltip"))
+ window.roomLayout.addWidget(window.roomInput)
+ window.roomLayout.addWidget(window.roomButton)
+ window.roomFrame.setMaximumHeight(window.roomFrame.sizeHint().height())
+ window.listLayout.addWidget(window.roomFrame, Qt.AlignRight)
+
window.readyPushButton = QtGui.QPushButton()
readyFont = QtGui.QFont()
readyFont.setWeight(QtGui.QFont.Bold)
@@ -491,18 +449,6 @@ class MainWindow(QtGui.QMainWindow):
window.readyPushButton.setStyleSheet(constants.STYLE_READY_PUSHBUTTON)
window.listLayout.addWidget(window.readyPushButton, Qt.AlignRight)
- window.autoPlayPushButton = QtGui.QPushButton()
- autoPlayFont = QtGui.QFont()
- autoPlayFont.setWeight(QtGui.QFont.Bold)
- window.autoPlayPushButton.setText(getMessage("autoplay-guipushbuttonlabel"))
- window.autoPlayPushButton.setCheckable(True)
- window.autoPlayPushButton.setAutoExclusive(False)
- window.autoPlayPushButton.toggled.connect(self.changeAutoPlayState)
- window.autoPlayPushButton.setFont(autoPlayFont)
- window.autoPlayPushButton.setStyleSheet(constants.STYLE_AUTO_PLAY_PUSHBUTTON)
- window.listLayout.addWidget(window.autoPlayPushButton, Qt.AlignRight)
- self.updateAutoPlayIcon()
-
window.listFrame.setLayout(window.listLayout)
window.topSplit.addWidget(window.outputFrame)
@@ -512,94 +458,11 @@ class MainWindow(QtGui.QMainWindow):
window.mainLayout.addWidget(window.topSplit)
window.topSplit.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
- def addBottomLayout(self, window):
- window.bottomLayout = QtGui.QHBoxLayout()
-
- window.addSeekBox(MainWindow)
- window.addMiscBox(MainWindow)
- window.addRoomBox(MainWindow)
-
- window.bottomLayout.addWidget(window.seekGroup)
- window.bottomLayout.addWidget(window.miscGroup)
- window.bottomLayout.addWidget(window.roomGroup)
-
- window.mainLayout.addLayout(window.bottomLayout, Qt.AlignLeft)
-
- def addRoomBox(self, window):
- window.roomGroup = QtGui.QGroupBox(getMessage("room-heading-label"))
-
- window.roomInput = QtGui.QLineEdit()
- window.roomInput.returnPressed.connect(self.joinRoom)
- window.roomButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'door_in.png'),
- getMessage("joinroom-guibuttonlabel"))
- window.roomButton.pressed.connect(self.joinRoom)
- window.roomLayout = QtGui.QHBoxLayout()
- window.roomInput.setFixedWidth(150)
-
- self.roomButton.setToolTip(getMessage("joinroom-tooltip"))
-
- window.roomLayout.addWidget(window.roomInput)
- window.roomLayout.addWidget(window.roomButton)
-
- window.roomGroup.setLayout(window.roomLayout)
- window.roomGroup.setFixedHeight(window.roomGroup.sizeHint().height())
-
- def addSeekBox(self, window):
- window.seekGroup = QtGui.QGroupBox(getMessage("seek-heading-label"))
-
- window.seekInput = QtGui.QLineEdit()
- window.seekInput.returnPressed.connect(self.seekPosition)
- window.seekButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'clock_go.png'),
- getMessage("seektime-guibuttonlabel"))
- window.seekButton.pressed.connect(self.seekPosition)
-
- self.seekButton.setToolTip(getMessage("seektime-tooltip"))
-
- window.seekLayout = QtGui.QHBoxLayout()
- window.seekInput.setText("0:00")
- window.seekInput.setFixedWidth(60)
-
- window.seekLayout.addWidget(window.seekInput)
- window.seekLayout.addWidget(window.seekButton)
-
- window.seekGroup.setLayout(window.seekLayout)
- window.seekGroup.setFixedHeight(window.seekGroup.sizeHint().height())
-
- def addMiscBox(self, window):
- window.miscGroup = QtGui.QGroupBox(getMessage("othercommands-heading-label"))
-
- window.unseekButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'arrow_undo.png'),
- getMessage("undoseek-guibuttonlabel"))
- window.unseekButton.pressed.connect(self.undoSeek)
- self.unseekButton.setToolTip(getMessage("undoseek-tooltip"))
-
- window.miscLayout = QtGui.QHBoxLayout()
- window.miscLayout.addWidget(window.unseekButton)
- if constants.MERGE_PLAYPAUSE_BUTTONS == True:
- window.playpauseButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'control_pause_blue.png'),
- getMessage("togglepause-guibuttonlabel"))
- window.playpauseButton.pressed.connect(self.togglePause)
- window.miscLayout.addWidget(window.playpauseButton)
- self.playpauseButton.setToolTip(getMessage("togglepause-tooltip"))
- else:
- window.playButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'control_play_blue.png'),
- getMessage("play-guibuttonlabel"))
- window.playButton.pressed.connect(self.play)
- window.miscLayout.addWidget(window.playButton)
- window.pauseButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'control_pause_blue.png'),
- getMessage("pause-guibuttonlabel"))
- window.pauseButton.pressed.connect(self.pause)
- window.miscLayout.addWidget(window.pauseButton)
- self.playButton.setToolTip(getMessage("play-tooltip"))
- self.pauseButton.setToolTip(getMessage("pause-tooltip"))
-
- window.miscGroup.setLayout(window.miscLayout)
- window.miscGroup.setFixedHeight(window.miscGroup.sizeHint().height())
-
-
def addMenubar(self, window):
window.menuBar = QtGui.QMenuBar()
+ # File menu
+
window.fileMenu = QtGui.QMenu(getMessage("file-menu-label"), self)
window.openAction = window.fileMenu.addAction(QtGui.QIcon(self.resourcespath + 'folder_explore.png'),
getMessage("openmedia-menu-label"))
@@ -613,6 +476,22 @@ class MainWindow(QtGui.QMainWindow):
window.exitAction.triggered.connect(self.exitSyncplay)
window.menuBar.addMenu(window.fileMenu)
+ # Playback menu
+
+ window.playbackMenu = QtGui.QMenu(getMessage("playback-menu-label"), self)
+ window.playAction = window.playbackMenu.addAction(QtGui.QIcon(self.resourcespath + 'control_play_blue.png'), getMessage("play-menu-label"))
+ window.playAction.triggered.connect(self.play)
+ window.pauseAction = window.playbackMenu.addAction(QtGui.QIcon(self.resourcespath + 'control_pause_blue.png'), getMessage("pause-menu-label"))
+ window.pauseAction.triggered.connect(self.pause)
+ window.seekAction = window.playbackMenu.addAction(QtGui.QIcon(self.resourcespath + 'clock_go.png'), getMessage("seektime-menu-label"))
+ window.seekAction.triggered.connect(self.seekPosition)
+ window.unseekAction = window.playbackMenu.addAction(QtGui.QIcon(self.resourcespath + 'arrow_undo.png'), getMessage("undoseek-menu-label"))
+ window.unseekAction.triggered.connect(self.undoSeek)
+
+ window.menuBar.addMenu(window.playbackMenu)
+
+ # Advanced menu
+
window.advancedMenu = QtGui.QMenu(getMessage("advanced-menu-label"), self)
window.setoffsetAction = window.advancedMenu.addAction(QtGui.QIcon(self.resourcespath + 'timeline_marker.png'),
getMessage("setoffset-menu-label"))
@@ -626,6 +505,12 @@ class MainWindow(QtGui.QMainWindow):
window.identifyascontroller.triggered.connect(self.identifyAsController)
window.menuBar.addMenu(window.advancedMenu)
+ window.autoplayAction = window.advancedMenu.addAction(getMessage("autoplay-menu-label"))
+ window.autoplayAction.setCheckable(True)
+ window.autoplayAction.triggered.connect(self.changeAutoPlayState)
+
+ # Help menu
+
window.helpMenu = QtGui.QMenu(getMessage("help-menu-label"), self)
window.userguideAction = window.helpMenu.addAction(QtGui.QIcon(self.resourcespath + 'help.png'),
getMessage("userguide-menu-label"))
@@ -664,8 +549,7 @@ class MainWindow(QtGui.QMainWindow):
self._syncplayClient.changeReadyState(self.readyPushButton.isChecked())
def changeAutoPlayState(self):
- self.updateAutoPlayIcon()
- self._syncplayClient.changeAutoPlayState(self.autoPlayPushButton.isChecked())
+ self._syncplayClient.changeAutoPlayState(self.autoplayAction.isChecked())
def updateReadyIcon(self):
ready = self.readyPushButton.isChecked()
@@ -674,13 +558,6 @@ class MainWindow(QtGui.QMainWindow):
else:
self.readyPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'empty_checkbox.png'))
- def updateAutoPlayIcon(self):
- ready = self.autoPlayPushButton.isChecked()
- if ready:
- self.autoPlayPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'tick_checkbox.png'))
- else:
- self.autoPlayPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'empty_checkbox.png'))
-
def automaticUpdateCheck(self):
currentDateTime = datetime.utcnow()
if not self.config['checkForUpdatesAutomatically']:
@@ -776,10 +653,8 @@ class MainWindow(QtGui.QMainWindow):
self.setWindowTitle("Syncplay v" + version)
self.mainLayout = QtGui.QVBoxLayout()
self.addTopLayout(self)
- self.addBottomLayout(self)
self.addMenubar(self)
self.addMainFrame(self)
- self.setupSizes()
self.loadSettings()
self.setWindowIcon(QtGui.QIcon(self.resourcespath + "syncplay.png"))
self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & Qt.AA_DontUseNativeMenuBar & Qt.WindowMinimizeButtonHint & ~Qt.WindowContextHelpButtonHint)
From 16c46ef179fc3f3687eb29d5023f64b4b3d16f83 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 10 Jan 2015 18:29:38 +0000
Subject: [PATCH 45/63] Remove unused messages; add/fix translation stubs
---
syncplay/messages.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/syncplay/messages.py b/syncplay/messages.py
index e2a546e..c861a5c 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -213,7 +213,6 @@ en = {
"joinroom-menu-label" : "Join room",
"seektime-menu-label" : "Seek to time",
"undoseek-menu-label" : "Undo seek",
- "togglepause-menu-label" : "Toggle pause",
"play-menu-label" : "Play",
"pause-menu-label" : "Pause",
"autoplay-menu-label" : u"Auto-play when everyone is ready",
@@ -574,6 +573,8 @@ ru = {
"createcontrolledroom-menu-label" : u"&Create controlled room", # TODO: Translate into Russian
"identifyascontroller-menu-label" : u"&Identify as room controller", # TODO: Translate into Russian
+ "playback-menu-label" : u"&Playback", # TODO: Translate into Russian
+
"help-menu-label" : u"&Помощь",
"userguide-menu-label" : u"&Руководство Пользователя",
"update-menu-label" : u"Check for &update", # TODO: Translate into Russian
@@ -882,7 +883,6 @@ de = {
"joinroom-menu-label" : u"Raum beitreten",
"seektime-menu-label" : u"Spule zu Zeit",
"undoseek-menu-label" : u"Rückgängig",
- "togglepause-menu-label" : u"Pause umschalten",
"play-menu-label" : u"Wiedergabe",
"pause-menu-label" : u"Pause",
"autoplay-menu-label" : u"Auto-play when everyone is ready", # TODO: Translate into German
@@ -907,9 +907,11 @@ de = {
"createcontrolledroom-menu-label" : u"&Zentral gesteuerten Raum erstellen",
"identifyascontroller-menu-label" : u"Als Raumleiter &identifizieren",
+ "playback-menu-label" : u"&Playback", # TODO: Translate into German
+
"help-menu-label" : u"&Hilfe",
"userguide-menu-label" : u"&Benutzerhandbuch öffnen",
- "update-menu-label" : u"Check for &update", # TODO: Translate into Russian
+ "update-menu-label" : u"Check for &update", # TODO: Translate into German
"setoffset-msgbox-label" : u"Offset einstellen",
"offsetinfo-msgbox-label" : u"Offset (siehe http://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
From 14deec4db50c724a96c307ca71861fc677a211ea Mon Sep 17 00:00:00 2001
From: Et0h
Date: Thu, 22 Jan 2015 21:34:17 +0000
Subject: [PATCH 46/63] Use menu options for showing playback and autoplay
buttons
---
syncplay/constants.py | 1 +
syncplay/messages.py | 13 +++--
syncplay/ui/gui.py | 118 ++++++++++++++++++++++++++++++++++++------
3 files changed, 114 insertions(+), 18 deletions(-)
diff --git a/syncplay/constants.py b/syncplay/constants.py
index a61deb6..6281f0d 100644
--- a/syncplay/constants.py
+++ b/syncplay/constants.py
@@ -120,6 +120,7 @@ STYLE_SUBLABEL = "QCheckBox, QLabel {{ margin-left: 6px; padding-left: 16px; ba
STYLE_ERRORLABEL = "QLabel { color : black; border-style: outset; border-width: 2px; border-radius: 7px; border-color: red; padding: 2px; background: #FFAAAA; }"
STYLE_SUCCESSLABEL = "QLabel { color : black; border-style: outset; border-width: 2px; border-radius: 7px; border-color: green; padding: 2px; background: #AAFFAA; }"
STYLE_READY_PUSHBUTTON = "QPushButton { text-align: left; padding: 10px 5px 10px 5px;}"
+STYLE_AUTO_PLAY_PUSHBUTTON = "QPushButton { text-align: left; padding: 5px 5px 5px 5px; }"
STYLE_NOTIFICATIONBOX = "Username { color: #367AA9; font-weight:bold; }"
STYLE_CONTACT_INFO = u"{}
" # Contact info message
STYLE_USERNAME = "color: #367AA9; font-weight:bold;"
diff --git a/syncplay/messages.py b/syncplay/messages.py
index c861a5c..23f4e00 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -215,7 +215,9 @@ en = {
"undoseek-menu-label" : "Undo seek",
"play-menu-label" : "Play",
"pause-menu-label" : "Pause",
- "autoplay-menu-label" : u"Auto-play when everyone is ready",
+ "playbackbuttons-menu-label" : u"Show playback buttons",
+ "autoplay-menu-label" : u"Show auto-play button",
+ "autoplay-guipushbuttonlabel" : u"Auto-play when everyone is ready",
"ready-guipushbuttonlabel" : u"I'm ready to watch!",
@@ -551,7 +553,10 @@ ru = {
"undoseek-menu-label" : u"Отменить перемотку",
"play-menu-label" : u"Play",
"pause-menu-label" : u"Пауза",
- "autoplay-menu-label" : u"Auto-play when everyone is ready", # TODO: Translate into Russian
+ "playbackbuttons-menu-label" : u"Show playback buttons", # TODO: Translate into Russian
+ "autoplay-menu-label" : u"Show auto-play button", # TODO: Translate into Russian
+ "autoplay-guipushbuttonlabel" : u"Auto-play when everyone is ready", # TODO: Translate into Russian
+
"ready-guipushbuttonlabel" : u"I'm ready to watch!", # TODO: Translate into Russian
@@ -885,7 +890,9 @@ de = {
"undoseek-menu-label" : u"Rückgängig",
"play-menu-label" : u"Wiedergabe",
"pause-menu-label" : u"Pause",
- "autoplay-menu-label" : u"Auto-play when everyone is ready", # TODO: Translate into German
+ "playbackbuttons-menu-label" : u"Show playback buttons", # TODO: Translate into German
+ "autoplay-menu-label" : u"Show auto-play button", # TODO: Translate into German
+ "autoplay-guipushbuttonlabel" : u"Auto-play when everyone is ready", # TODO: Translate into German
"ready-guipushbuttonlabel" : u"I'm ready to watch!", # TODO: Translate into German
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 45a3102..8c40781 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -207,11 +207,6 @@ class MainWindow(QtGui.QMainWindow):
self.readyPushButton.setChecked(newState)
self.updateReadyIcon()
- def updateAutoPlayState(self, newState):
- oldState = self.autoplayAction.isChecked()
- if newState != oldState and newState != None:
- self.autoplayAction.setChecked(newState)
-
def roomClicked(self, item):
while item.parent().row() != -1:
item = item.parent()
@@ -438,6 +433,23 @@ class MainWindow(QtGui.QMainWindow):
window.roomFrame.setMaximumHeight(window.roomFrame.sizeHint().height())
window.listLayout.addWidget(window.roomFrame, Qt.AlignRight)
+ window.listFrame.setLayout(window.listLayout)
+
+ window.topSplit.addWidget(window.outputFrame)
+ window.topSplit.addWidget(window.listFrame)
+ window.topSplit.setStretchFactor(0,4)
+ window.topSplit.setStretchFactor(1,5)
+ window.mainLayout.addWidget(window.topSplit)
+ window.topSplit.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
+
+ def addBottomLayout(self, window):
+ window.bottomLayout = QtGui.QHBoxLayout()
+ window.bottomFrame = QtGui.QFrame()
+ window.bottomFrame.setLayout(window.bottomLayout)
+ window.bottomLayout.setContentsMargins(0,0,0,0)
+
+ self.addPlaybackLayout(window)
+
window.readyPushButton = QtGui.QPushButton()
readyFont = QtGui.QFont()
readyFont.setWeight(QtGui.QFont.Bold)
@@ -448,15 +460,55 @@ class MainWindow(QtGui.QMainWindow):
window.readyPushButton.setFont(readyFont)
window.readyPushButton.setStyleSheet(constants.STYLE_READY_PUSHBUTTON)
window.listLayout.addWidget(window.readyPushButton, Qt.AlignRight)
+ window.autoPlayPushButton = QtGui.QPushButton()
+ window.autoPlayPushButton.setVisible(False)
+ autoPlayFont = QtGui.QFont()
+ autoPlayFont.setWeight(QtGui.QFont.Bold)
+ window.autoPlayPushButton.setText(getMessage("autoplay-guipushbuttonlabel"))
+ window.autoPlayPushButton.setCheckable(True)
+ window.autoPlayPushButton.setAutoExclusive(False)
+ window.autoPlayPushButton.toggled.connect(self.changeAutoPlayState)
+ window.autoPlayPushButton.setFont(autoPlayFont)
+ window.autoPlayPushButton.setStyleSheet(constants.STYLE_AUTO_PLAY_PUSHBUTTON)
+ window.listLayout.addWidget(window.autoPlayPushButton, Qt.AlignRight)
+ self.updateAutoPlayIcon()
+ window.mainLayout.addWidget(window.bottomFrame, Qt.AlignLeft)
+ window.bottomFrame.setMaximumHeight(window.bottomFrame.minimumSizeHint().height())
- window.listFrame.setLayout(window.listLayout)
+ def addPlaybackLayout(self, window):
+ window.playbackFrame = QtGui.QFrame()
+ window.playbackFrame.setVisible(False)
+ window.playbackFrame.setContentsMargins(0,0,0,0)
+ window.playbackLayout = QtGui.QHBoxLayout()
+ window.playbackLayout.setAlignment(Qt.AlignLeft)
+ window.playbackLayout.setContentsMargins(0,0,0,0)
+ window.playbackFrame.setLayout(window.playbackLayout)
+ window.seekInput = QtGui.QLineEdit()
+ window.seekInput.returnPressed.connect(self.seekPosition)
+ window.seekButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'clock_go.png'), "")
+ window.seekButton.setToolTip(getMessage("seektime-menu-label"))
+ window.seekButton.pressed.connect(self.seekPosition)
+ window.seekInput.setText("0:00")
+ window.seekInput.setFixedWidth(60)
+ window.playbackLayout.addWidget(window.seekInput)
+ window.playbackLayout.addWidget(window.seekButton)
+ window.unseekButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'arrow_undo.png'), "")
+ window.unseekButton.setToolTip(getMessage("undoseek-menu-label"))
+ window.unseekButton.pressed.connect(self.undoSeek)
- window.topSplit.addWidget(window.outputFrame)
- window.topSplit.addWidget(window.listFrame)
- window.topSplit.setStretchFactor(0,4)
- window.topSplit.setStretchFactor(1,5)
- window.mainLayout.addWidget(window.topSplit)
- window.topSplit.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding)
+ window.miscLayout = QtGui.QHBoxLayout()
+ window.playbackLayout.addWidget(window.unseekButton)
+ window.playButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'control_play_blue.png'), "")
+ window.playButton.setToolTip(getMessage("play-menu-label"))
+ window.playButton.pressed.connect(self.play)
+ window.playbackLayout.addWidget(window.playButton)
+ window.pauseButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'control_pause_blue.png'), "")
+ window.pauseButton.setToolTip(getMessage("pause-menu-label"))
+ window.pauseButton.pressed.connect(self.pause)
+ window.playbackLayout.addWidget(window.pauseButton)
+ window.playbackFrame.setMaximumHeight(window.playbackFrame.sizeHint().height())
+ window.playbackFrame.setMaximumWidth(window.playbackFrame.sizeHint().width())
+ window.outputLayout.addWidget(window.playbackFrame)
def addMenubar(self, window):
window.menuBar = QtGui.QMenuBar()
@@ -503,11 +555,16 @@ class MainWindow(QtGui.QMainWindow):
window.identifyascontroller = window.advancedMenu.addAction(QtGui.QIcon(self.resourcespath + 'key_go.png'),
getMessage("identifyascontroller-menu-label"))
window.identifyascontroller.triggered.connect(self.identifyAsController)
- window.menuBar.addMenu(window.advancedMenu)
+
+ window.playbackAction = window.advancedMenu.addAction(getMessage("playbackbuttons-menu-label"))
+ window.playbackAction.setCheckable(True)
+ window.playbackAction.triggered.connect(self.updatePlaybackFrameVisibility)
window.autoplayAction = window.advancedMenu.addAction(getMessage("autoplay-menu-label"))
window.autoplayAction.setCheckable(True)
- window.autoplayAction.triggered.connect(self.changeAutoPlayState)
+ window.autoplayAction.triggered.connect(self.updateAutoplayVisibility)
+ window.menuBar.addMenu(window.advancedMenu)
+
# Help menu
@@ -544,12 +601,25 @@ class MainWindow(QtGui.QMainWindow):
self.listbox.insertHtml(item)
self.listbox.moveCursor(QtGui.QTextCursor.End)
+ def updatePlaybackFrameVisibility(self):
+ self.playbackFrame.setVisible(self.playbackAction.isChecked())
+
+ def updateAutoplayVisibility(self):
+ self.autoPlayPushButton.setVisible(self.autoplayAction.isChecked())
+
def changeReadyState(self):
self.updateReadyIcon()
self._syncplayClient.changeReadyState(self.readyPushButton.isChecked())
+ def updateAutoPlayState(self, newState):
+ oldState = self.autoPlayPushButton.isChecked()
+ if newState != oldState and newState != None:
+ self.autoPlayPushButton.setChecked(newState)
+ self.updateAutoPlayIcon()
+
def changeAutoPlayState(self):
- self._syncplayClient.changeAutoPlayState(self.autoplayAction.isChecked())
+ self.updateAutoPlayIcon()
+ self._syncplayClient.changeAutoPlayState(self.autoPlayPushButton.isChecked())
def updateReadyIcon(self):
ready = self.readyPushButton.isChecked()
@@ -558,6 +628,13 @@ class MainWindow(QtGui.QMainWindow):
else:
self.readyPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'empty_checkbox.png'))
+ def updateAutoPlayIcon(self):
+ ready = self.autoPlayPushButton.isChecked()
+ if ready:
+ self.autoPlayPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'tick_checkbox.png'))
+ else:
+ self.autoPlayPushButton.setIcon(QtGui.QIcon(self.resourcespath + 'empty_checkbox.png'))
+
def automaticUpdateCheck(self):
currentDateTime = datetime.utcnow()
if not self.config['checkForUpdatesAutomatically']:
@@ -626,6 +703,9 @@ class MainWindow(QtGui.QMainWindow):
settings.beginGroup("MainWindow")
settings.setValue("size", self.size())
settings.setValue("pos", self.pos())
+ settings.setValue("showPlaybackButtons", self.playbackAction.isChecked())
+ print settings.value("showPlaybackButtons")
+ settings.setValue("showAutoPlayButton", self.autoplayAction.isChecked())
settings.endGroup()
settings = QSettings("Syncplay", "Interface")
settings.beginGroup("Update")
@@ -637,6 +717,13 @@ class MainWindow(QtGui.QMainWindow):
settings.beginGroup("MainWindow")
self.resize(settings.value("size", QSize(700, 500)))
self.move(settings.value("pos", QPoint(200, 200)))
+ print settings.value("showPlaybackButtons", "False")
+ if settings.value("showPlaybackButtons", "false") == "true":
+ self.playbackAction.setChecked(True)
+ self.updatePlaybackFrameVisibility()
+ if settings.value("showAutoPlayButton", "false") == "true":
+ self.autoplayAction.setChecked(True)
+ self.updateAutoplayVisibility()
settings.endGroup()
settings = QSettings("Syncplay", "Interface")
settings.beginGroup("Update")
@@ -653,6 +740,7 @@ class MainWindow(QtGui.QMainWindow):
self.setWindowTitle("Syncplay v" + version)
self.mainLayout = QtGui.QVBoxLayout()
self.addTopLayout(self)
+ self.addBottomLayout(self)
self.addMenubar(self)
self.addMainFrame(self)
self.loadSettings()
From 09fb34bd9f7688521dd1f34af0176139909db66c Mon Sep 17 00:00:00 2001
From: Et0h
Date: Thu, 22 Jan 2015 21:53:07 +0000
Subject: [PATCH 47/63] Remove redundant SHOW_BUTTON_LABELS code, and set ready
checkbox sooner
---
syncplay/constants.py | 1 -
syncplay/messages.py | 3 ---
syncplay/ui/gui.py | 8 ++++----
3 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/syncplay/constants.py b/syncplay/constants.py
index 6281f0d..3b9c437 100644
--- a/syncplay/constants.py
+++ b/syncplay/constants.py
@@ -13,7 +13,6 @@ RECENT_CLIENT_THRESHOLD = "1.2.9" #This and higher considered 'recent' clients
WARN_OLD_CLIENTS = True #Use MOTD to inform old clients to upgrade
LIST_RELATIVE_CONFIGS = True # Print list of relative configs loaded
SHOW_CONTACT_INFO = True # Displays dev contact details below list in GUI
-SHOW_BUTTON_LABELS = True # If disabled, only shows icons for main GUI buttons
SHOW_TOOLTIPS = True
WARN_ABOUT_MISSING_STRINGS = False # (If debug mode is enabled)
FALLBACK_INITIAL_LANGUAGE = "en"
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 23f4e00..06ca3e1 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -1059,9 +1059,6 @@ def isValidLanguage(language):
return messages.has_key(language)
def getMessage(type_, locale=None):
- if constants.SHOW_BUTTON_LABELS == False:
- if "-guibuttonlabel" in type_:
- return ""
if constants.SHOW_TOOLTIPS == False:
if "-tooltip" in type_:
return ""
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 8c40781..f35c667 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -76,10 +76,8 @@ class MainWindow(QtGui.QMainWindow):
self.roomInput.setText(self._syncplayClient.getRoom())
self.config = self._syncplayClient.getConfig()
try:
- if not constants.SHOW_BUTTON_LABELS:
- self.hideRoomSeekLabels()
- self.hideMiscLabels()
- except ():
+ self.updateReadyState(self.config['readyAtStart'])
+ except:
pass
self.automaticUpdateCheck()
@@ -204,7 +202,9 @@ class MainWindow(QtGui.QMainWindow):
def updateReadyState(self, newState):
oldState = self.readyPushButton.isChecked()
if newState != oldState and newState != None:
+ self.readyPushButton.blockSignals(True)
self.readyPushButton.setChecked(newState)
+ self.readyPushButton.blockSignals(False)
self.updateReadyIcon()
def roomClicked(self, item):
From 598bc912351e5c9cccc07bb77e3c347fba85d308 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Thu, 22 Jan 2015 22:12:45 +0000
Subject: [PATCH 48/63] Move Window items into their own menu
---
syncplay/messages.py | 3 +++
syncplay/ui/gui.py | 10 +++++++---
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 06ca3e1..c1b88d1 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -235,6 +235,7 @@ en = {
"openstreamurl-menu-label" : "Open &media stream URL",
"exit-menu-label" : "E&xit",
"advanced-menu-label" : "&Advanced",
+ "window-menu-label" : "&Window",
"setoffset-menu-label" : "Set &offset",
"createcontrolledroom-menu-label" : "&Create controlled room",
"identifyascontroller-menu-label" : "&Identify as room controller",
@@ -574,6 +575,7 @@ ru = {
"openstreamurl-menu-label" : u"Open &media stream URL", # TODO: Translate into Russian
"exit-menu-label" : u"&Выход",
"advanced-menu-label" : u"&Дополнительно",
+ "window-menu-label" : u"&Window", # TODO: Translate into Russian
"setoffset-menu-label" : u"Установить &смещение",
"createcontrolledroom-menu-label" : u"&Create controlled room", # TODO: Translate into Russian
"identifyascontroller-menu-label" : u"&Identify as room controller", # TODO: Translate into Russian
@@ -910,6 +912,7 @@ de = {
"openstreamurl-menu-label" : u"Open &media stream URL", # TODO: Translate into German
"exit-menu-label" : u"&Beenden",
"advanced-menu-label" : u"&Erweitert",
+ "window-menu-label" : u"&Window", # TODO: Translate into German
"setoffset-menu-label" : u"&Offset einstellen",
"createcontrolledroom-menu-label" : u"&Zentral gesteuerten Raum erstellen",
"identifyascontroller-menu-label" : u"Als Raumleiter &identifizieren",
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index f35c667..ac4e9be 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -556,14 +556,18 @@ class MainWindow(QtGui.QMainWindow):
getMessage("identifyascontroller-menu-label"))
window.identifyascontroller.triggered.connect(self.identifyAsController)
- window.playbackAction = window.advancedMenu.addAction(getMessage("playbackbuttons-menu-label"))
+ # Window menu
+
+ window.windowMenu = QtGui.QMenu(getMessage("window-menu-label"), self)
+
+ window.playbackAction = window.windowMenu.addAction(getMessage("playbackbuttons-menu-label"))
window.playbackAction.setCheckable(True)
window.playbackAction.triggered.connect(self.updatePlaybackFrameVisibility)
- window.autoplayAction = window.advancedMenu.addAction(getMessage("autoplay-menu-label"))
+ window.autoplayAction = window.windowMenu.addAction(getMessage("autoplay-menu-label"))
window.autoplayAction.setCheckable(True)
window.autoplayAction.triggered.connect(self.updateAutoplayVisibility)
- window.menuBar.addMenu(window.advancedMenu)
+ window.menuBar.addMenu(window.windowMenu)
# Help menu
From 31c6fcc0885c11ee99738962dabf082189d3ed3e Mon Sep 17 00:00:00 2001
From: Et0h
Date: Thu, 22 Jan 2015 22:13:31 +0000
Subject: [PATCH 49/63] Remove test prints
---
syncplay/ui/gui.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index ac4e9be..258bf71 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -708,7 +708,6 @@ class MainWindow(QtGui.QMainWindow):
settings.setValue("size", self.size())
settings.setValue("pos", self.pos())
settings.setValue("showPlaybackButtons", self.playbackAction.isChecked())
- print settings.value("showPlaybackButtons")
settings.setValue("showAutoPlayButton", self.autoplayAction.isChecked())
settings.endGroup()
settings = QSettings("Syncplay", "Interface")
@@ -721,7 +720,6 @@ class MainWindow(QtGui.QMainWindow):
settings.beginGroup("MainWindow")
self.resize(settings.value("size", QSize(700, 500)))
self.move(settings.value("pos", QPoint(200, 200)))
- print settings.value("showPlaybackButtons", "False")
if settings.value("showPlaybackButtons", "false") == "true":
self.playbackAction.setChecked(True)
self.updatePlaybackFrameVisibility()
From 9b054a685f2c7c2870aaa2a32653ab062f816b02 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Thu, 22 Jan 2015 22:15:03 +0000
Subject: [PATCH 50/63] Display advanced menu
---
syncplay/ui/gui.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 258bf71..9c1b073 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -556,6 +556,8 @@ class MainWindow(QtGui.QMainWindow):
getMessage("identifyascontroller-menu-label"))
window.identifyascontroller.triggered.connect(self.identifyAsController)
+ window.menuBar.addMenu(window.advancedMenu)
+
# Window menu
window.windowMenu = QtGui.QMenu(getMessage("window-menu-label"), self)
From 09d515e97fd6cb2683da321725afeedfb0179357 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Fri, 23 Jan 2015 23:50:40 +0000
Subject: [PATCH 51/63] Don't reset automatic update choice
---
syncplay/ui/ConfigurationGetter.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/syncplay/ui/ConfigurationGetter.py b/syncplay/ui/ConfigurationGetter.py
index feabd20..df3e1ab 100755
--- a/syncplay/ui/ConfigurationGetter.py
+++ b/syncplay/ui/ConfigurationGetter.py
@@ -118,8 +118,10 @@ class ConfigurationGetter(object):
def _validateArguments(self):
if self._config['resetConfig']:
language = self._config['language']
+ checkForUpdatesAutomatically = self._config['checkForUpdatesAutomatically']
self._config = self._defaultConfig
self._config['language'] = language
+ self._config['checkForUpdatesAutomatically'] = checkForUpdatesAutomatically
raise InvalidConfigValue("*"+getMessage("config-cleared-notification"))
if not isValidLanguage(self._config['language']):
From c7ae68c5bf1aab2b7b7930db9e1d758c6d72e96a Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 24 Jan 2015 00:17:48 +0000
Subject: [PATCH 52/63] Show number of users who are ready
---
syncplay/client.py | 13 +++++++++++--
syncplay/messages.py | 6 +++---
2 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/syncplay/client.py b/syncplay/client.py
index f5b4da6..c37649c 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -655,14 +655,14 @@ class SyncplayClient(object):
fileDifferencesMessage = getMessage("room-file-differences").format(self._userlist.getFileDifferencesForRoom())
if self._userlist.currentUser.canControl() and self._userlist.isReadinessSupported():
if self._userlist.areAllUsersInRoomReady():
- osdMessage = u"{}{}{}".format(fileDifferencesMessage, self._client._player.osdMessageSeparator, getMessage("all-users-ready"))
+ osdMessage = u"{}{}{}".format(fileDifferencesMessage, self._client._player.osdMessageSeparator, getMessage("all-users-ready").format(self._userlist.readyUserCount()))
else:
osdMessage = u"{}{}{}".format(fileDifferencesMessage, self._client._player.osdMessageSeparator, getMessage("not-all-ready").format(self._userlist.usersInRoomNotReady()))
else:
osdMessage = fileDifferencesMessage
elif self._userlist.isReadinessSupported():
if self._userlist.areAllUsersInRoomReady():
- osdMessage = getMessage("all-users-ready")
+ osdMessage = getMessage("all-users-ready").format(self._userlist.readyUserCount())
else:
osdMessage = getMessage("not-all-ready").format(self._userlist.usersInRoomNotReady())
if osdMessage:
@@ -882,6 +882,15 @@ class SyncplayUserlist(object):
return False
return True
+ def readyUserCount(self):
+ readyCount = 0
+ if self.currentUser.isReady():
+ readyCount += 1
+ for user in self._users.itervalues():
+ if user.room == self.currentUser.room and user.isReady():
+ readyCount += 1
+ return readyCount
+
def usersInRoomNotReady(self):
notReady = []
if not self.currentUser.isReady():
diff --git a/syncplay/messages.py b/syncplay/messages.py
index c1b88d1..b8eb27c 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -34,7 +34,7 @@ en = {
"playing-notification/room-addendum" : u" in room: '{}'", # Room
"not-all-ready" : u"Not ready: {}", # Usernames
- "all-users-ready" : u"Everyone is ready",
+ "all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users
"identifying-as-controller-notification" : u"Identifying as room controller with password '{}'...",
"failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room controller.",
@@ -373,7 +373,7 @@ ru = {
"playing-notification/room-addendum" : u" в комнате: '{}'", # Room
"not-all-ready" : u"Not ready: {}", # Usernames # TODO: Translate into Russian
- "all-users-ready" : u"Everyone is ready", # TODO: Translate into Russian
+ "all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users # TODO: Translate into Russian
"identifying-as-controller-notification" : u"Identifying as room controller with password '{}'...", # TODO: Translate into Russian
"failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room controller.", # TODO: Translate into Russian
@@ -713,7 +713,7 @@ de = {
"playing-notification/room-addendum" : u" in Raum: '{}'", # Room
"not-all-ready" : u"Not ready: {}", # Usernames # TODO: Translate into German
- "all-users-ready" : u"Everyone is ready", # TODO: Translate into German
+ "all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users # TODO: Translate into German
"identifying-as-controller-notification" : u"Identifiziere als Raumleiter mit Passwort '{}'...", # TODO: find a better translation to "room controller"
"failed-to-identify-as-controller-notification" : u"<{}> konnte sich nicht als Raumleiter identifizieren.",
From 457b6bc63309242a1cc063e1c6ad1125ca915f0c Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 24 Jan 2015 10:35:54 +0000
Subject: [PATCH 53/63] Add --disable-ready server arg to turn off readiness
feature
---
syncplay/messages.py | 3 +++
syncplay/server.py | 8 ++++++--
syncplayServer.py | 2 +-
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/syncplay/messages.py b/syncplay/messages.py
index b8eb27c..fff09cb 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -326,6 +326,7 @@ en = {
"server-password-argument" : 'server password',
"server-isolate-room-argument" : 'should rooms be isolated?',
"server-salt-argument" : "random string used to generate controlled room passwords",
+ "server-disable-ready-argument" : u"disable readiness feature",
"server-motd-argument": "path to file from which motd will be fetched",
"server-messed-up-motd-unescaped-placeholders": "Message of the Day has unescaped placeholders. All $ signs should be doubled ($$).",
"server-messed-up-motd-too-long": "Message of the Day is too long - maximum of {} chars, {} given.",
@@ -665,6 +666,7 @@ ru = {
"server-password-argument" : u'пароль к серверу',
"server-isolate-room-argument" : u'должны ли комнаты быть изолированными?',
"server-salt-argument" : u"random string used to generate controlled room passwords", # TODO: Translate into Russian (note: as you may already be aware, 'salt' means Соль (криптография))
+ "server-disable-ready-argument" : u"disable readiness feature", # TODO: Translate into Russian
"server-motd-argument" : u"путь к файлу, из которого будет извлекаться MOTD-сообщение",
"server-messed-up-motd-unescaped-placeholders" : u"MOTD-сообщение содержит неэкранированные спец.символы. Все знаки $ должны быть продублированы ($$).",
"server-messed-up-motd-too-long" : u"MOTD-сообщение слишком длинное: максимальная длина - {} символ(ов), текущая длина - {} символ(ов).",
@@ -1004,6 +1006,7 @@ de = {
"server-password-argument" : u'Server Passwort',
"server-isolate-room-argument" : u'Sollen die Räume isoliert sein?',
"server-salt-argument" : u"zufällige Zeichenkette, die zur Erstellung von Passwörtern verwendet wird",
+ "server-disable-ready-argument" : u"disable readiness feature", # TODO: Translate into German
"server-motd-argument": u"Pfad zur Datei, von der die Nachricht des Tages geladen wird",
"server-messed-up-motd-unescaped-placeholders": u"Die Nachricht des Tages hat unmaskierte Platzhalter. Alle $-Zeichen sollten verdoppelt werden ($$).",
"server-messed-up-motd-too-long": u"Die Nachricht des Tages ist zu lang - Maximal {} Zeichen, aktuell {}.",
diff --git a/syncplay/server.py b/syncplay/server.py
index 7a38681..3996311 100644
--- a/syncplay/server.py
+++ b/syncplay/server.py
@@ -14,7 +14,7 @@ import argparse
from syncplay.utils import RoomPasswordProvider, NotControlledRoom, RandomStringGenerator, meetsMinVersion
class SyncFactory(Factory):
- def __init__(self, password='', motdFilePath=None, isolateRooms=False, salt=None):
+ def __init__(self, password='', motdFilePath=None, isolateRooms=False, salt=None, disableReady=False):
print getMessage("welcome-server-notification").format(syncplay.version)
if password:
password = hashlib.md5(password).hexdigest()
@@ -24,6 +24,7 @@ class SyncFactory(Factory):
print getMessage("no-salt-notification").format(salt)
self._salt = salt
self._motdFilePath = motdFilePath
+ self.disableReady = disableReady
if not isolateRooms:
self._roomManager = RoomManager()
else:
@@ -129,7 +130,7 @@ class SyncFactory(Factory):
def setReady(self, watcher, isReady, manuallyInitiated=True):
watcher.setReady(isReady)
- self._roomManager.broadcastRoom(watcher, lambda w: w.sendSetReady(watcher.getName(), isReady, manuallyInitiated))
+ self._roomManager.broadcastRoom(watcher, lambda w: w.sendSetReady(watcher.getName(), watcher.isReady(), manuallyInitiated))
class RoomManager(object):
def __init__(self):
@@ -332,6 +333,8 @@ class Watcher(object):
self._ready = ready
def isReady(self):
+ if self._server.disableReady:
+ return None
return self._ready
def getRoom(self):
@@ -437,5 +440,6 @@ class ConfigurationGetter(object):
self._argparser.add_argument('--port', metavar='port', type=str, nargs='?', help=getMessage("server-port-argument"))
self._argparser.add_argument('--password', metavar='password', type=str, nargs='?', help=getMessage("server-password-argument"))
self._argparser.add_argument('--isolate-rooms', action='store_true', help=getMessage("server-isolate-room-argument"))
+ self._argparser.add_argument('--disable-ready', action='store_true', help=getMessage("server-disable-ready-argument"))
self._argparser.add_argument('--salt', metavar='salt', type=str, nargs='?', help=getMessage("server-salt-argument"))
self._argparser.add_argument('--motd-file', metavar='file', type=str, nargs='?', help=getMessage("server-motd-argument"))
\ No newline at end of file
diff --git a/syncplayServer.py b/syncplayServer.py
index 23b5381..b4456d7 100755
--- a/syncplayServer.py
+++ b/syncplayServer.py
@@ -20,5 +20,5 @@ if __name__ == '__main__':
argsGetter = ConfigurationGetter()
args = argsGetter.getConfiguration()
- reactor.listenTCP(int(args.port), SyncFactory(args.password, args.motd_file, args.isolate_rooms, args.salt))
+ reactor.listenTCP(int(args.port), SyncFactory(args.password, args.motd_file, args.isolate_rooms, args.salt, args.disable_ready))
reactor.run()
From 7aee87d6ef630e9e5e494bfce05d471c692e4804 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 24 Jan 2015 10:52:52 +0000
Subject: [PATCH 54/63] Rename "controlled room" / "room controller" to
"managed room" / "room manager" & delete message for attempting to create
room
---
syncplay/client.py | 3 +-
syncplay/messages.py | 71 +++++++++++++++++++++++---------------------
2 files changed, 38 insertions(+), 36 deletions(-)
diff --git a/syncplay/client.py b/syncplay/client.py
index c37649c..7192e03 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -519,12 +519,11 @@ class SyncplayClient(object):
@requireMinServerVersion(constants.CONTROLLED_ROOMS_MIN_VERSION)
def createControlledRoom(self, roomName):
controlPassword = utils.RandomStringGenerator.generate_room_password()
- self.ui.showMessage(u"Attempting to create controlled room '{}' with password '{}'...".format(roomName, controlPassword))
self.lastControlPasswordAttempt = controlPassword
self._protocol.requestControlledRoom(roomName, controlPassword)
def controlledRoomCreated(self, roomName, controlPassword):
- self.ui.showMessage(u"Created controlled room '{}' with password '{}'. Please save this information for future reference!".format(roomName, controlPassword))
+ self.ui.showMessage(getMessage("created-controlled-room-notification").format(roomName, controlPassword))
self.setRoom(roomName)
self.sendRoom()
self._protocol.requestControlledRoom(roomName, controlPassword)
diff --git a/syncplay/messages.py b/syncplay/messages.py
index fff09cb..5c7fc7f 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -36,9 +36,10 @@ en = {
"not-all-ready" : u"Not ready: {}", # Usernames
"all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users
- "identifying-as-controller-notification" : u"Identifying as room controller with password '{}'...",
- "failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room controller.",
- "authenticated-as-controller-notification" : u"<{}> authenticated as a room controller",
+ "identifying-as-controller-notification" : u"Identifying as room manager with password '{}'...",
+ "failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room manager.",
+ "authenticated-as-controller-notification" : u"<{}> authenticated as a room manager",
+ "created-controlled-room-notification" : u"Created managed room '{}' with password '{}'. Please save this information for future reference!", # RoomName, controlPassword
"file-different-notification" : "File you are playing appears to be different from <{}>'s", # User
"file-differences-notification" : u"Your file differs in the following way(s): {}", # Differences
@@ -55,7 +56,7 @@ en = {
"notplaying-notification" : "People who are not playing any file:",
"userlist-room-notification" : u"In room '{}':", # Room
"userlist-file-notification" : "File",
- "controller-userlist-userflag" : "Controller",
+ "controller-userlist-userflag" : "Manager",
"ready-userlist-userflag" : "Ready",
"update-check-failed-notification" : u"Could not automatically check whether Syncplay {} is up to date. Want to visit http://syncplay.pl/ to manually check for updates?", #Syncplay version
@@ -75,8 +76,8 @@ en = {
"commandlist-notification/seek" : "\t[s][+-]time - seek to the given value of time, if + or - is not specified it's absolute time in seconds or min:sec",
"commandlist-notification/help" : "\th - this help",
"commandlist-notification/toggle" : u"\tt - toggles whether you are ready to watch or not",
- "commandlist-notification/create" : "\tc [name] - create controlled room using name of current room",
- "commandlist-notification/auth" : "\ta [password] - authenticate as room controller with controller password",
+ "commandlist-notification/create" : "\tc [name] - create managed room using name of current room",
+ "commandlist-notification/auth" : "\ta [password] - authenticate as room manager with controller password",
"syncplay-version-notification" : "Syncplay version: {}", # syncplay.version
"more-info-notification" : "More info available at: {}", # projectURL
@@ -184,7 +185,7 @@ en = {
"showosdwarnings-label" : "Include warnings (e.g. when files are different, users not ready)",
"showsameroomosd-label" : "Include events in your room",
- "shownoncontrollerosd-label" : "Include events from non-controllers in controlled rooms",
+ "shownoncontrollerosd-label" : "Include events from non-controllers in managed rooms",
"showdifferentroomosd-label" : "Include events in other rooms",
"showslowdownosd-label" :"Include slowing down / reverting notifications",
"language-label" : "Language:",
@@ -237,8 +238,8 @@ en = {
"advanced-menu-label" : "&Advanced",
"window-menu-label" : "&Window",
"setoffset-menu-label" : "Set &offset",
- "createcontrolledroom-menu-label" : "&Create controlled room",
- "identifyascontroller-menu-label" : "&Identify as room controller",
+ "createcontrolledroom-menu-label" : "&Create managed room",
+ "identifyascontroller-menu-label" : "&Identify as room manager",
"playback-menu-label" : u"&Playback",
@@ -252,10 +253,10 @@ en = {
"promptforstreamurl-msgbox-label" : "Open media stream URL",
"promptforstreamurlinfo-msgbox-label" : "Stream URL",
- "createcontrolledroom-msgbox-label" : "Create controlled room",
- "controlledroominfo-msgbox-label" : "Enter name of controlled room\r\n(see http://syncplay.pl/guide/ for usage instructions):",
+ "createcontrolledroom-msgbox-label" : "Create managed room",
+ "controlledroominfo-msgbox-label" : "Enter name of managed room\r\n(see http://syncplay.pl/guide/ for usage instructions):",
- "identifyascontroller-msgbox-label" : "Identify as Room Controller",
+ "identifyascontroller-msgbox-label" : "Identify as room manager",
"identifyinfo-msgbox-label" : "Enter controller password for this room\r\n(see http://syncplay.pl/guide/ for usage instructions):",
"megabyte-suffix" : " MB",
@@ -273,7 +274,7 @@ en = {
"more-tooltip" : "Display less frequently used settings.",
"slowdown-threshold-tooltip" : "Time ahead of slowest client before temporarily reducing playback speed (default: {} secs).".format(constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD),
"rewind-threshold-tooltip" : "Time ahead slowest client before seeking to get back in sync (default: {} secs).".format(constants.DEFAULT_REWIND_THRESHOLD),
- "fastforward-threshold-tooltip" : "Time behind room controller before seeking to get back in sync (default: {} secs).".format(constants.DEFAULT_FASTFORWARD_THRESHOLD),
+ "fastforward-threshold-tooltip" : "Time behind room manager before seeking to get back in sync (default: {} secs).".format(constants.DEFAULT_FASTFORWARD_THRESHOLD),
"filename-privacy-tooltip" : "Privacy mode for sending currently playing filename to server.",
"filesize-privacy-tooltip" : "Privacy mode for sending size of currently playing file to server.",
"privacy-sendraw-tooltip" : "Send this information without obfuscation. This is the default option with most functionality.",
@@ -281,17 +282,17 @@ en = {
"privacy-dontsend-tooltip" : "Do not send this information to the server. This provides for maximum privacy.",
"checkforupdatesautomatically-tooltip" : "Regularly check with the Syncplay website to see whether a new version of Syncplay is available.",
"slowondesync-tooltip" : "Reduce playback rate temporarily when needed to bring you back in sync with other viewers. Not supported on MPC-HC.",
- "dontslowdownwithme-tooltip" : "Means others do not get slowed down or rewinded if your playback is lagging. Useful for room controllers.",
+ "dontslowdownwithme-tooltip" : "Means others do not get slowed down or rewinded if your playback is lagging. Useful for room managers.",
"pauseonleave-tooltip" : "Pause playback if you get disconnected or someone leaves from your room.",
"readyatstart-tooltip" : "Set yourself as 'ready' at start (otherwise you are set as 'not ready' until you change your readiness state)",
"forceguiprompt-tooltip" : "Configuration dialogue is not shown when opening a file with Syncplay.", # (Inverted)
"nostore-tooltip" : "Run Syncplay with the given configuration, but do not permanently store the changes.", # (Inverted)
"rewindondesync-tooltip" : "Jump back when needed to get back in sync. Disabling this option can result in major desyncs!",
- "fastforwardondesync-tooltip" : "Jump forward when out of sync with room controller (or your pretend position if 'Never slow down or rewind others' enabled).",
+ "fastforwardondesync-tooltip" : "Jump forward when out of sync with room manager (or your pretend position if 'Never slow down or rewind others' enabled).",
"showosd-tooltip" : "Sends Syncplay messages to media player OSD.",
"showosdwarnings-tooltip" : "Show warnings if playing different file, alone in room, users not ready, etc.",
"showsameroomosd-tooltip" : "Show OSD notifications for events relating to room user is in.",
- "shownoncontrollerosd-tooltip" : "Show OSD notifications for events relating to non-controllers who are in controlled rooms.",
+ "shownoncontrollerosd-tooltip" : "Show OSD notifications for events relating to non-controllers who are in managed rooms.",
"showdifferentroomosd-tooltip" : "Show OSD notifications for events relating to room user is not in.",
"showslowdownosd-tooltip" :"Show notifications of slowing down / reverting on time difference.",
"showdurationnotification-tooltip" : "Useful for when a segment in a multi-part file is missing, but can result in false positives.",
@@ -325,7 +326,7 @@ en = {
"server-port-argument" : 'server TCP port',
"server-password-argument" : 'server password',
"server-isolate-room-argument" : 'should rooms be isolated?',
- "server-salt-argument" : "random string used to generate controlled room passwords",
+ "server-salt-argument" : "random string used to generate managed room passwords",
"server-disable-ready-argument" : u"disable readiness feature",
"server-motd-argument": "path to file from which motd will be fetched",
"server-messed-up-motd-unescaped-placeholders": "Message of the Day has unescaped placeholders. All $ signs should be doubled ($$).",
@@ -376,9 +377,10 @@ ru = {
"not-all-ready" : u"Not ready: {}", # Usernames # TODO: Translate into Russian
"all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users # TODO: Translate into Russian
- "identifying-as-controller-notification" : u"Identifying as room controller with password '{}'...", # TODO: Translate into Russian
- "failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room controller.", # TODO: Translate into Russian
- "authenticated-as-controller-notification" : u"<{}> authenticated as a room controller", # TODO: Translate into Russian
+ "identifying-as-controller-notification" : u"Identifying as room manager with password '{}'...", # TODO: Translate into Russian
+ "failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room manager.", # TODO: Translate into Russian
+ "authenticated-as-controller-notification" : u"<{}> authenticated as a room manager", # TODO: Translate into Russian
+ "created-controlled-room-notification" : u"Created managed room '{}' with password '{}'. Please save this information for future reference!", # RoomName, controlPassword # TODO: Translate into Russian
"file-different-notification" : u"Вероятно, файл, который Вы смотрите, отличается от того, который смотрит <{}>.", # User
"file-differences-notification" : u"Ваш файл отличается: {}", # Differences
@@ -395,7 +397,7 @@ ru = {
"notplaying-notification" : u"Люди, которые не смотрят ничего:",
"userlist-room-notification" : u"В комнате '{}':", # Room
"userlist-file-notification" : u"File", # TODO: Translate into Russian (Файл?)
- "controller-userlist-userflag" : u"Controller", # TODO: Translate into Russian (this is to indicate a user is a controller in the ConsoleUI userlist)
+ "controller-userlist-userflag" : u"Manager", # TODO: Translate into Russian (this is to indicate a user is a controller in the ConsoleUI userlist)
"ready-userlist-userflag" : u"Ready", # TODO: Translate into Russian (this is to indicate a user is ready to watch in the ConsoleUI userlist)
"update-check-failed-notification" : u"Could not automatically check whether Syncplay {} is up to date. Want to visit http://syncplay.pl/ to manually check for updates?", #Syncplay version # TODO: Translate into Russian
@@ -415,8 +417,8 @@ ru = {
"commandlist-notification/seek" : u"\t[s][+-]time - перемотать к заданному моменту времени, если не указан + или -, то время считается абсолютным (от начала файла) в секундах или мин:сек",
"commandlist-notification/help" : u"\th - помощь",
"commandlist-notification/toggle" : u"\tt - toggles whether you are ready to watch or not", # TODO: Translate into Russian
- "commandlist-notification/create" : u"\tc [name] - create controlled room using name of current room", # TODO: Translate into Russian
- "commandlist-notification/auth" : u"\ta [password] - authenticate as room controller with controller password", # TODO: Translate into Russian
+ "commandlist-notification/create" : u"\tc [name] - create managed room using name of current room", # TODO: Translate into Russian
+ "commandlist-notification/auth" : u"\ta [password] - authenticate as room manager with controller password", # TODO: Translate into Russian
"syncplay-version-notification" : u"Версия Syncplay: {}", # syncplay.version
"more-info-notification" : u"Больше информации на {}", # projectURL
@@ -524,7 +526,7 @@ ru = {
"showosdwarnings-label" : u"Показывать предупреждения (напр., когда файлы не совпадают)",
"showsameroomosd-label" : u"Показывать события Вашей комнаты",
- "shownoncontrollerosd-label" : u"Include events from non-controllers in controlled rooms", # TODO: Translate into Russiann
+ "shownoncontrollerosd-label" : u"Include events from non-controllers in managed rooms", # TODO: Translate into Russiann
"showdifferentroomosd-label" : u"Показывать события других комнат",
"showslowdownosd-label" : u"Показывать уведомления о замедлении/перемотке",
"language-label" : u"Language:", # TODO: Translate into Russian
@@ -578,8 +580,8 @@ ru = {
"advanced-menu-label" : u"&Дополнительно",
"window-menu-label" : u"&Window", # TODO: Translate into Russian
"setoffset-menu-label" : u"Установить &смещение",
- "createcontrolledroom-menu-label" : u"&Create controlled room", # TODO: Translate into Russian
- "identifyascontroller-menu-label" : u"&Identify as room controller", # TODO: Translate into Russian
+ "createcontrolledroom-menu-label" : u"&Create managed room", # TODO: Translate into Russian
+ "identifyascontroller-menu-label" : u"&Identify as room manager", # TODO: Translate into Russian
"playback-menu-label" : u"&Playback", # TODO: Translate into Russian
@@ -593,10 +595,10 @@ ru = {
"promptforstreamurl-msgbox-label" : u"Open media stream URL", # TODO: Translate into Russian
"promptforstreamurlinfo-msgbox-label" : u"Stream URL", # TODO: Translate into Russian
- "createcontrolledroom-msgbox-label" : u"Create controlled room", # TODO: Translate into Russian
- "controlledroominfo-msgbox-label" : u"Enter name of controlled room\r\n(see http://syncplay.pl/guide/ for usage instructions):", # TODO: Translate into Russian
+ "createcontrolledroom-msgbox-label" : u"Create managed room", # TODO: Translate into Russian
+ "controlledroominfo-msgbox-label" : u"Enter name of managed room\r\n(see http://syncplay.pl/guide/ for usage instructions):", # TODO: Translate into Russian
- "identifyascontroller-msgbox-label" : u"Identify as Room Controller", # TODO: Translate into Russian
+ "identifyascontroller-msgbox-label" : u"Identify as room manager", # TODO: Translate into Russian
"identifyinfo-msgbox-label" : u"Enter controller password for this room\r\n(see http://syncplay.pl/guide/ for usage instructions):", # TODO: Translate into Russian
"megabyte-suffix" : u" MB", # Technically it is a mebibyte # TODO: Translate into Russian
@@ -614,7 +616,7 @@ ru = {
"more-tooltip" : u"Показать дополнительные настройки.",
"slowdown-threshold-tooltip" : u"Отставание самого медленного клиента, необходимое для временного уменьшения скорости видео (по умолчанию: {} сек.).".format(constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD),
"rewind-threshold-tooltip" : u"Отставание самого медленного клиента, необходимое для перемотки назад в целях синхронизации (по умолчанию: {} сек.).".format(constants.DEFAULT_REWIND_THRESHOLD),
- "fastforward-threshold-tooltip" : u"Time behind room controller before seeking to get back in sync (default: {} secs).".format(constants.DEFAULT_FASTFORWARD_THRESHOLD), # TODO: Translate into Russian
+ "fastforward-threshold-tooltip" : u"Time behind room manager before seeking to get back in sync (default: {} secs).".format(constants.DEFAULT_FASTFORWARD_THRESHOLD), # TODO: Translate into Russian
"filename-privacy-tooltip" : u"Режим приватности для передачи имени воспроизводимого файла на сервер.",
"filesize-privacy-tooltip" : u"Режим приватности для передачи размера воспроизводимого файла на сервер.",
"privacy-sendraw-tooltip" : u"Отправляет эту информацию без шифрования. Рекомендуемая опция с наибольшей функциональностью.",
@@ -628,7 +630,7 @@ ru = {
"forceguiprompt-tooltip" : u"Окно настройки не будет отображаться при открытии файла в Syncplay.", # (Inverted)
"nostore-tooltip" : u"Запустить Syncplay с данной конфигурацией, но не сохранять изменения навсегда.", # (Inverted)
"rewindondesync-tooltip" : u"Перематывать назад, когда это необходимо для синхронизации. Отключение этой опции может привести к большим рассинхронизациям!",
- "fastforwardondesync-tooltip" : u"Jump forward when out of sync with room controller (or your pretend position if 'Never slow down or rewind others' enabled).", # TODO: Translate into Russian
+ "fastforwardondesync-tooltip" : u"Jump forward when out of sync with room manager (or your pretend position if 'Never slow down or rewind others' enabled).", # TODO: Translate into Russian
"showosd-tooltip" : u"Отправлять сообщения Syncplay в видеопроигрыватель и отображать их поверх видео (OSD - On Screen Display).",
"showosdwarnings-tooltip" : u"Показывать OSC-предупреждения, если проигрываются разные файлы или если Вы в комнате больше никого нет.",
"showsameroomosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к комнате, в которой Вы находитесь.",
@@ -665,7 +667,7 @@ ru = {
"server-port-argument" : u'номер TCP порта сервера',
"server-password-argument" : u'пароль к серверу',
"server-isolate-room-argument" : u'должны ли комнаты быть изолированными?',
- "server-salt-argument" : u"random string used to generate controlled room passwords", # TODO: Translate into Russian (note: as you may already be aware, 'salt' means Соль (криптография))
+ "server-salt-argument" : u"random string used to generate managed room passwords", # TODO: Translate into Russian (note: as you may already be aware, 'salt' means Соль (криптография))
"server-disable-ready-argument" : u"disable readiness feature", # TODO: Translate into Russian
"server-motd-argument" : u"путь к файлу, из которого будет извлекаться MOTD-сообщение",
"server-messed-up-motd-unescaped-placeholders" : u"MOTD-сообщение содержит неэкранированные спец.символы. Все знаки $ должны быть продублированы ($$).",
@@ -717,9 +719,10 @@ de = {
"not-all-ready" : u"Not ready: {}", # Usernames # TODO: Translate into German
"all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users # TODO: Translate into German
- "identifying-as-controller-notification" : u"Identifiziere als Raumleiter mit Passwort '{}'...", # TODO: find a better translation to "room controller"
+ "identifying-as-controller-notification" : u"Identifiziere als Raumleiter mit Passwort '{}'...", # TODO: find a better translation to "room manager"
"failed-to-identify-as-controller-notification" : u"<{}> konnte sich nicht als Raumleiter identifizieren.",
"authenticated-as-controller-notification" : u"<{}> authentifizierte sich als Raumleiter",
+ "created-controlled-room-notification" : u"Created managed room '{}' with password '{}'. Please save this information for future reference!", # RoomName, controlPassword # TODO: Translate into German
"file-different-notification" : u"Deine Datei scheint sich von <{}>s zu unterscheiden", # User
"file-differences-notification" : u"Deine Datei unterscheidet sich auf folgende Art: {}",
@@ -736,7 +739,7 @@ de = {
"notplaying-notification" : u"Personen im Raum, die keine Dateien spielen:",
"userlist-room-notification" : u"In Raum '{}':", # Room
"userlist-file-notification" : u"File", # TODO: Translate into German (Datei?)
- "controller-userlist-userflag" : u"Controller", # TODO: Translate into German (this is to indicate a user is a controller in the ConsoleUI userlist)
+ "controller-userlist-userflag" : u"Manager", # TODO: Translate into German (this is to indicate a user is a room manager in the ConsoleUI userlist)
"ready-userlist-userflag" : u"Ready", # TODO: Translate into German (this is to indicate a user is ready to watch in the ConsoleUI userlist)
"update-check-failed-notification" : u"Could not automatically check whether Syncplay {} is up to date. Want to visit http://syncplay.pl/ to manually check for updates?", #Syncplay version # TODO: Translate into German
From 358c6c361066e551f4171552018573085ac03521 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 24 Jan 2015 11:13:12 +0000
Subject: [PATCH 55/63] Ignore others failing to identify as room manager
---
syncplay/client.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/syncplay/client.py b/syncplay/client.py
index 7192e03..efe5a04 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -543,7 +543,8 @@ class SyncplayClient(object):
self._protocol.requestControlledRoom(self.getRoom(), controlPassword)
def controllerIdentificationError(self, username, room):
- self.ui.showErrorMessage(getMessage("failed-to-identify-as-controller-notification").format(username))
+ if username == self.getUsername():
+ self.ui.showErrorMessage(getMessage("failed-to-identify-as-controller-notification").format(username))
def controllerIdentificationSuccess(self, username, roomname):
self.userlist.setUserAsController(username)
From 06a8d5dddf6579f531bd598830bc20e65940b8d1 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 24 Jan 2015 11:20:11 +0000
Subject: [PATCH 56/63] Reduce secondary OSD message duration for players with
single OSD from 15 sec to 13 sec
---
syncplay/constants.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/syncplay/constants.py b/syncplay/constants.py
index 3b9c437..682ca5e 100644
--- a/syncplay/constants.py
+++ b/syncplay/constants.py
@@ -2,7 +2,7 @@
DEFAULT_PORT = 8999
OSD_DURATION = 3
OSD_WARNING_MESSAGE_DURATION = 5
-NO_SECONDARY_OSD_WARNING_DURATION = 15
+NO_SECONDARY_OSD_WARNING_DURATION = 13
MPC_OSD_POSITION = 1 #Right corner, 1 for left
MPLAYER_OSD_LEVEL = 1
UI_TIME_FORMAT = "[%X] "
From 24e9afb2b654f14eb36376637acdcda7671b5f62 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 24 Jan 2015 13:27:38 +0000
Subject: [PATCH 57/63] If user presses unpause when not ready and others not
ready, set to ready rather than unpausing
---
syncplay/client.py | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/syncplay/client.py b/syncplay/client.py
index efe5a04..f7ffcfb 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -162,12 +162,19 @@ class SyncplayClient(object):
pauseChange, seeked = self._determinePlayerStateChange(paused, position)
self._playerPosition = position
self._playerPaused = paused
- if pauseChange and utils.meetsMinVersion(self.serverVersion, constants.USER_READY_MIN_VERSION) and self.userlist.currentUser.canControl():
- lastPausedDiff = time.time() - self.lastPausedOnLeaveTime if self.lastPausedOnLeaveTime else None
- if lastPausedDiff is not None and lastPausedDiff < constants.LAST_PAUSED_DIFF_THRESHOLD:
- self.lastPausedOnLeaveTime = None
+ if pauseChange and utils.meetsMinVersion(self.serverVersion, constants.USER_READY_MIN_VERSION):
+ if not paused and not self.userlist.currentUser.isReady() and not self.userlist.areAllOtherUsersInRoomReady():
+ paused = True
+ self._player.setPaused(paused)
+ self._playerPaused = paused
+ self.changeReadyState(True, manuallyInitiated=True)
+ pauseChange = False
else:
- self.changeReadyState(not self.getPlayerPaused(), manuallyInitiated=False)
+ lastPausedDiff = time.time() - self.lastPausedOnLeaveTime if self.lastPausedOnLeaveTime else None
+ if lastPausedDiff is not None and lastPausedDiff < constants.LAST_PAUSED_DIFF_THRESHOLD:
+ self.lastPausedOnLeaveTime = None
+ else:
+ self.changeReadyState(not self.getPlayerPaused(), manuallyInitiated=False)
if self._lastGlobalUpdate:
self._lastPlayerUpdate = time.time()
if (pauseChange or seeked) and self._protocol:
@@ -882,6 +889,12 @@ class SyncplayUserlist(object):
return False
return True
+ def areAllOtherUsersInRoomReady(self):
+ for user in self._users.itervalues():
+ if user.room == self.currentUser.room and user.isReady() == False:
+ return False
+ return True
+
def readyUserCount(self):
readyCount = 0
if self.currentUser.isReady():
From 305e400eac3b0bad7bce37501047c6dccdf22519 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 24 Jan 2015 14:51:40 +0000
Subject: [PATCH 58/63] Add notification when unpause is replaced with 'set
ready'
---
syncplay/client.py | 1 +
syncplay/messages.py | 3 +++
2 files changed, 4 insertions(+)
diff --git a/syncplay/client.py b/syncplay/client.py
index f7ffcfb..8f32077 100644
--- a/syncplay/client.py
+++ b/syncplay/client.py
@@ -169,6 +169,7 @@ class SyncplayClient(object):
self._playerPaused = paused
self.changeReadyState(True, manuallyInitiated=True)
pauseChange = False
+ self.ui.showMessage(getMessage("ready-to-unpause-notification"))
else:
lastPausedDiff = time.time() - self.lastPausedOnLeaveTime if self.lastPausedOnLeaveTime else None
if lastPausedDiff is not None and lastPausedDiff < constants.LAST_PAUSED_DIFF_THRESHOLD:
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 5c7fc7f..6f815b1 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -35,6 +35,7 @@ en = {
"not-all-ready" : u"Not ready: {}", # Usernames
"all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users
+ "ready-to-unpause-notification" : u"You are now set as ready - unpause again to unpause",
"identifying-as-controller-notification" : u"Identifying as room manager with password '{}'...",
"failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room manager.",
@@ -376,6 +377,7 @@ ru = {
"not-all-ready" : u"Not ready: {}", # Usernames # TODO: Translate into Russian
"all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users # TODO: Translate into Russian
+ "ready-to-unpause-notification" : u"You are now set as ready - unpause again to unpause", # TODO: Translate into Russian
"identifying-as-controller-notification" : u"Identifying as room manager with password '{}'...", # TODO: Translate into Russian
"failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room manager.", # TODO: Translate into Russian
@@ -718,6 +720,7 @@ de = {
"not-all-ready" : u"Not ready: {}", # Usernames # TODO: Translate into German
"all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users # TODO: Translate into German
+ "ready-to-unpause-notification" : u"You are now set as ready - unpause again to unpause", # TODO: Translate into German
"identifying-as-controller-notification" : u"Identifiziere als Raumleiter mit Passwort '{}'...", # TODO: find a better translation to "room manager"
"failed-to-identify-as-controller-notification" : u"<{}> konnte sich nicht als Raumleiter identifizieren.",
From 8f7789655917f1110d903423e69f02ee88ee8212 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 24 Jan 2015 15:35:56 +0000
Subject: [PATCH 59/63] Make user row unselectable (to fix *nix icon glitch)
---
syncplay/ui/gui.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 9c1b073..68044fb 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -170,6 +170,10 @@ class MainWindow(QtGui.QMainWindow):
filenameitem.setFlags(filenameitem.flags() & ~Qt.ItemIsEditable)
filesizeitem.setFlags(filesizeitem.flags() & ~Qt.ItemIsEditable)
filedurationitem.setFlags(filedurationitem.flags() & ~Qt.ItemIsEditable)
+ useritem.setSelectable(False)
+ filesizeitem.setSelectable(False)
+ filedurationitem.setSelectable(False)
+ filenameitem.setSelectable(False)
roomitem.appendRow((useritem, filesizeitem, filedurationitem, filenameitem))
self.listTreeModel = self._usertreebuffer
self.listTreeView.setModel(self.listTreeModel)
From 754e000360d485df085a21650aa8f4ef81a27e0c Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sat, 24 Jan 2015 15:38:33 +0000
Subject: [PATCH 60/63] Refactor code to make user/file row items
non-selectable
---
syncplay/ui/gui.py | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 68044fb..442860b 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -166,14 +166,10 @@ class MainWindow(QtGui.QMainWindow):
if isControlledRoom and not isController:
useritem.setForeground(QtGui.QBrush(QtGui.QColor(constants.STYLE_NOTCONTROLLER_COLOR)))
useritem.setFont(font)
- useritem.setFlags(useritem.flags() & ~Qt.ItemIsEditable)
- filenameitem.setFlags(filenameitem.flags() & ~Qt.ItemIsEditable)
- filesizeitem.setFlags(filesizeitem.flags() & ~Qt.ItemIsEditable)
- filedurationitem.setFlags(filedurationitem.flags() & ~Qt.ItemIsEditable)
- useritem.setSelectable(False)
- filesizeitem.setSelectable(False)
- filedurationitem.setSelectable(False)
- filenameitem.setSelectable(False)
+ useritem.setFlags(useritem.flags() & ~Qt.ItemIsEditable & ~Qt.ItemIsSelectable)
+ filenameitem.setFlags(filenameitem.flags() & ~Qt.ItemIsEditable & ~Qt.ItemIsSelectable)
+ filesizeitem.setFlags(filesizeitem.flags() & ~Qt.ItemIsEditable & ~Qt.ItemIsSelectable)
+ filedurationitem.setFlags(filedurationitem.flags() & ~Qt.ItemIsEditable & ~Qt.ItemIsSelectable)
roomitem.appendRow((useritem, filesizeitem, filedurationitem, filenameitem))
self.listTreeModel = self._usertreebuffer
self.listTreeView.setModel(self.listTreeModel)
From 1dbda3efadf0243839b9ee2edbb15f48ebf941e4 Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sun, 25 Jan 2015 11:05:56 +0000
Subject: [PATCH 61/63] Seek button should use LineEdit input (not prompt)
---
syncplay/ui/gui.py | 36 +++++++++++++++++++++---------------
1 file changed, 21 insertions(+), 15 deletions(-)
diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py
index 442860b..1201d70 100644
--- a/syncplay/ui/gui.py
+++ b/syncplay/ui/gui.py
@@ -243,22 +243,28 @@ class MainWindow(QtGui.QMainWindow):
self._syncplayClient.setRoom(room)
self._syncplayClient.sendRoom()
- def seekPosition(self):
+ def seekPositionDialog(self):
seekTime, ok = QtGui.QInputDialog.getText(self, getMessage("seektime-menu-label"),
getMessage("seektime-msgbox-label"), QtGui.QLineEdit.Normal,
"0:00")
if ok and seekTime != '':
- s = re.match(constants.UI_SEEK_REGEX, seekTime)
- if s:
- sign = self._extractSign(s.group('sign'))
- t = utils.parseTime(s.group('time'))
- if t is None:
- return
- if sign:
- t = self._syncplayClient.getGlobalPosition() + sign * t
- self._syncplayClient.setPosition(t)
- else:
- self.showErrorMessage(getMessage("invalid-seek-value"))
+ self.seekPosition(seekTime)
+
+ def seekFromButton(self):
+ self.seekPosition(self.seekInput.text())
+
+ def seekPosition(self, seekTime):
+ s = re.match(constants.UI_SEEK_REGEX, seekTime)
+ if s:
+ sign = self._extractSign(s.group('sign'))
+ t = utils.parseTime(s.group('time'))
+ if t is None:
+ return
+ if sign:
+ t = self._syncplayClient.getGlobalPosition() + sign * t
+ self._syncplayClient.setPosition(t)
+ else:
+ self.showErrorMessage(getMessage("invalid-seek-value"))
def undoSeek(self):
tmp_pos = self._syncplayClient.getPlayerPosition()
@@ -484,10 +490,10 @@ class MainWindow(QtGui.QMainWindow):
window.playbackLayout.setContentsMargins(0,0,0,0)
window.playbackFrame.setLayout(window.playbackLayout)
window.seekInput = QtGui.QLineEdit()
- window.seekInput.returnPressed.connect(self.seekPosition)
+ window.seekInput.returnPressed.connect(self.seekFromButton)
window.seekButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'clock_go.png'), "")
window.seekButton.setToolTip(getMessage("seektime-menu-label"))
- window.seekButton.pressed.connect(self.seekPosition)
+ window.seekButton.pressed.connect(self.seekFromButton)
window.seekInput.setText("0:00")
window.seekInput.setFixedWidth(60)
window.playbackLayout.addWidget(window.seekInput)
@@ -536,7 +542,7 @@ class MainWindow(QtGui.QMainWindow):
window.pauseAction = window.playbackMenu.addAction(QtGui.QIcon(self.resourcespath + 'control_pause_blue.png'), getMessage("pause-menu-label"))
window.pauseAction.triggered.connect(self.pause)
window.seekAction = window.playbackMenu.addAction(QtGui.QIcon(self.resourcespath + 'clock_go.png'), getMessage("seektime-menu-label"))
- window.seekAction.triggered.connect(self.seekPosition)
+ window.seekAction.triggered.connect(self.seekPositionDialog)
window.unseekAction = window.playbackMenu.addAction(QtGui.QIcon(self.resourcespath + 'arrow_undo.png'), getMessage("undoseek-menu-label"))
window.unseekAction.triggered.connect(self.undoSeek)
From f8f5723c07eb44c2ec95ebdc2bbd27e37e180a3f Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sun, 25 Jan 2015 18:54:15 +0000
Subject: [PATCH 62/63] Rename 'room managers' to 'room operators'
---
syncplay/messages.py | 50 ++++++++++++++++++++++----------------------
1 file changed, 25 insertions(+), 25 deletions(-)
diff --git a/syncplay/messages.py b/syncplay/messages.py
index 6f815b1..ba2b5e0 100755
--- a/syncplay/messages.py
+++ b/syncplay/messages.py
@@ -37,9 +37,9 @@ en = {
"all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users
"ready-to-unpause-notification" : u"You are now set as ready - unpause again to unpause",
- "identifying-as-controller-notification" : u"Identifying as room manager with password '{}'...",
- "failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room manager.",
- "authenticated-as-controller-notification" : u"<{}> authenticated as a room manager",
+ "identifying-as-controller-notification" : u"Identifying as room operator with password '{}'...",
+ "failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room operator.",
+ "authenticated-as-controller-notification" : u"<{}> authenticated as a room operator",
"created-controlled-room-notification" : u"Created managed room '{}' with password '{}'. Please save this information for future reference!", # RoomName, controlPassword
"file-different-notification" : "File you are playing appears to be different from <{}>'s", # User
@@ -57,7 +57,7 @@ en = {
"notplaying-notification" : "People who are not playing any file:",
"userlist-room-notification" : u"In room '{}':", # Room
"userlist-file-notification" : "File",
- "controller-userlist-userflag" : "Manager",
+ "controller-userlist-userflag" : "Operator",
"ready-userlist-userflag" : "Ready",
"update-check-failed-notification" : u"Could not automatically check whether Syncplay {} is up to date. Want to visit http://syncplay.pl/ to manually check for updates?", #Syncplay version
@@ -78,7 +78,7 @@ en = {
"commandlist-notification/help" : "\th - this help",
"commandlist-notification/toggle" : u"\tt - toggles whether you are ready to watch or not",
"commandlist-notification/create" : "\tc [name] - create managed room using name of current room",
- "commandlist-notification/auth" : "\ta [password] - authenticate as room manager with controller password",
+ "commandlist-notification/auth" : "\ta [password] - authenticate as room operator with controller password",
"syncplay-version-notification" : "Syncplay version: {}", # syncplay.version
"more-info-notification" : "More info available at: {}", # projectURL
@@ -186,7 +186,7 @@ en = {
"showosdwarnings-label" : "Include warnings (e.g. when files are different, users not ready)",
"showsameroomosd-label" : "Include events in your room",
- "shownoncontrollerosd-label" : "Include events from non-controllers in managed rooms",
+ "shownoncontrollerosd-label" : "Include events from non-operators in managed rooms",
"showdifferentroomosd-label" : "Include events in other rooms",
"showslowdownosd-label" :"Include slowing down / reverting notifications",
"language-label" : "Language:",
@@ -240,7 +240,7 @@ en = {
"window-menu-label" : "&Window",
"setoffset-menu-label" : "Set &offset",
"createcontrolledroom-menu-label" : "&Create managed room",
- "identifyascontroller-menu-label" : "&Identify as room manager",
+ "identifyascontroller-menu-label" : "&Identify as room operator",
"playback-menu-label" : u"&Playback",
@@ -257,7 +257,7 @@ en = {
"createcontrolledroom-msgbox-label" : "Create managed room",
"controlledroominfo-msgbox-label" : "Enter name of managed room\r\n(see http://syncplay.pl/guide/ for usage instructions):",
- "identifyascontroller-msgbox-label" : "Identify as room manager",
+ "identifyascontroller-msgbox-label" : "Identify as room operator",
"identifyinfo-msgbox-label" : "Enter controller password for this room\r\n(see http://syncplay.pl/guide/ for usage instructions):",
"megabyte-suffix" : " MB",
@@ -275,7 +275,7 @@ en = {
"more-tooltip" : "Display less frequently used settings.",
"slowdown-threshold-tooltip" : "Time ahead of slowest client before temporarily reducing playback speed (default: {} secs).".format(constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD),
"rewind-threshold-tooltip" : "Time ahead slowest client before seeking to get back in sync (default: {} secs).".format(constants.DEFAULT_REWIND_THRESHOLD),
- "fastforward-threshold-tooltip" : "Time behind room manager before seeking to get back in sync (default: {} secs).".format(constants.DEFAULT_FASTFORWARD_THRESHOLD),
+ "fastforward-threshold-tooltip" : "Time behind room operator before seeking to get back in sync (default: {} secs).".format(constants.DEFAULT_FASTFORWARD_THRESHOLD),
"filename-privacy-tooltip" : "Privacy mode for sending currently playing filename to server.",
"filesize-privacy-tooltip" : "Privacy mode for sending size of currently playing file to server.",
"privacy-sendraw-tooltip" : "Send this information without obfuscation. This is the default option with most functionality.",
@@ -283,17 +283,17 @@ en = {
"privacy-dontsend-tooltip" : "Do not send this information to the server. This provides for maximum privacy.",
"checkforupdatesautomatically-tooltip" : "Regularly check with the Syncplay website to see whether a new version of Syncplay is available.",
"slowondesync-tooltip" : "Reduce playback rate temporarily when needed to bring you back in sync with other viewers. Not supported on MPC-HC.",
- "dontslowdownwithme-tooltip" : "Means others do not get slowed down or rewinded if your playback is lagging. Useful for room managers.",
+ "dontslowdownwithme-tooltip" : "Means others do not get slowed down or rewinded if your playback is lagging. Useful for room operators.",
"pauseonleave-tooltip" : "Pause playback if you get disconnected or someone leaves from your room.",
"readyatstart-tooltip" : "Set yourself as 'ready' at start (otherwise you are set as 'not ready' until you change your readiness state)",
"forceguiprompt-tooltip" : "Configuration dialogue is not shown when opening a file with Syncplay.", # (Inverted)
"nostore-tooltip" : "Run Syncplay with the given configuration, but do not permanently store the changes.", # (Inverted)
"rewindondesync-tooltip" : "Jump back when needed to get back in sync. Disabling this option can result in major desyncs!",
- "fastforwardondesync-tooltip" : "Jump forward when out of sync with room manager (or your pretend position if 'Never slow down or rewind others' enabled).",
+ "fastforwardondesync-tooltip" : "Jump forward when out of sync with room operator (or your pretend position if 'Never slow down or rewind others' enabled).",
"showosd-tooltip" : "Sends Syncplay messages to media player OSD.",
"showosdwarnings-tooltip" : "Show warnings if playing different file, alone in room, users not ready, etc.",
"showsameroomosd-tooltip" : "Show OSD notifications for events relating to room user is in.",
- "shownoncontrollerosd-tooltip" : "Show OSD notifications for events relating to non-controllers who are in managed rooms.",
+ "shownoncontrollerosd-tooltip" : "Show OSD notifications for events relating to non-operators who are in managed rooms.",
"showdifferentroomosd-tooltip" : "Show OSD notifications for events relating to room user is not in.",
"showslowdownosd-tooltip" :"Show notifications of slowing down / reverting on time difference.",
"showdurationnotification-tooltip" : "Useful for when a segment in a multi-part file is missing, but can result in false positives.",
@@ -379,9 +379,9 @@ ru = {
"all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users # TODO: Translate into Russian
"ready-to-unpause-notification" : u"You are now set as ready - unpause again to unpause", # TODO: Translate into Russian
- "identifying-as-controller-notification" : u"Identifying as room manager with password '{}'...", # TODO: Translate into Russian
- "failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room manager.", # TODO: Translate into Russian
- "authenticated-as-controller-notification" : u"<{}> authenticated as a room manager", # TODO: Translate into Russian
+ "identifying-as-controller-notification" : u"Identifying as room operator with password '{}'...", # TODO: Translate into Russian
+ "failed-to-identify-as-controller-notification" : u"<{}> failed to identify as a room operator.", # TODO: Translate into Russian
+ "authenticated-as-controller-notification" : u"<{}> authenticated as a room operator", # TODO: Translate into Russian
"created-controlled-room-notification" : u"Created managed room '{}' with password '{}'. Please save this information for future reference!", # RoomName, controlPassword # TODO: Translate into Russian
"file-different-notification" : u"Вероятно, файл, который Вы смотрите, отличается от того, который смотрит <{}>.", # User
@@ -399,7 +399,7 @@ ru = {
"notplaying-notification" : u"Люди, которые не смотрят ничего:",
"userlist-room-notification" : u"В комнате '{}':", # Room
"userlist-file-notification" : u"File", # TODO: Translate into Russian (Файл?)
- "controller-userlist-userflag" : u"Manager", # TODO: Translate into Russian (this is to indicate a user is a controller in the ConsoleUI userlist)
+ "controller-userlist-userflag" : u"Operator", # TODO: Translate into Russian (this is to indicate a user is a controller in the ConsoleUI userlist)
"ready-userlist-userflag" : u"Ready", # TODO: Translate into Russian (this is to indicate a user is ready to watch in the ConsoleUI userlist)
"update-check-failed-notification" : u"Could not automatically check whether Syncplay {} is up to date. Want to visit http://syncplay.pl/ to manually check for updates?", #Syncplay version # TODO: Translate into Russian
@@ -420,7 +420,7 @@ ru = {
"commandlist-notification/help" : u"\th - помощь",
"commandlist-notification/toggle" : u"\tt - toggles whether you are ready to watch or not", # TODO: Translate into Russian
"commandlist-notification/create" : u"\tc [name] - create managed room using name of current room", # TODO: Translate into Russian
- "commandlist-notification/auth" : u"\ta [password] - authenticate as room manager with controller password", # TODO: Translate into Russian
+ "commandlist-notification/auth" : u"\ta [password] - authenticate as room operator with controller password", # TODO: Translate into Russian
"syncplay-version-notification" : u"Версия Syncplay: {}", # syncplay.version
"more-info-notification" : u"Больше информации на {}", # projectURL
@@ -528,7 +528,7 @@ ru = {
"showosdwarnings-label" : u"Показывать предупреждения (напр., когда файлы не совпадают)",
"showsameroomosd-label" : u"Показывать события Вашей комнаты",
- "shownoncontrollerosd-label" : u"Include events from non-controllers in managed rooms", # TODO: Translate into Russiann
+ "shownoncontrollerosd-label" : u"Include events from non-operators in managed rooms", # TODO: Translate into Russiann
"showdifferentroomosd-label" : u"Показывать события других комнат",
"showslowdownosd-label" : u"Показывать уведомления о замедлении/перемотке",
"language-label" : u"Language:", # TODO: Translate into Russian
@@ -583,7 +583,7 @@ ru = {
"window-menu-label" : u"&Window", # TODO: Translate into Russian
"setoffset-menu-label" : u"Установить &смещение",
"createcontrolledroom-menu-label" : u"&Create managed room", # TODO: Translate into Russian
- "identifyascontroller-menu-label" : u"&Identify as room manager", # TODO: Translate into Russian
+ "identifyascontroller-menu-label" : u"&Identify as room operator", # TODO: Translate into Russian
"playback-menu-label" : u"&Playback", # TODO: Translate into Russian
@@ -600,7 +600,7 @@ ru = {
"createcontrolledroom-msgbox-label" : u"Create managed room", # TODO: Translate into Russian
"controlledroominfo-msgbox-label" : u"Enter name of managed room\r\n(see http://syncplay.pl/guide/ for usage instructions):", # TODO: Translate into Russian
- "identifyascontroller-msgbox-label" : u"Identify as room manager", # TODO: Translate into Russian
+ "identifyascontroller-msgbox-label" : u"Identify as room operator", # TODO: Translate into Russian
"identifyinfo-msgbox-label" : u"Enter controller password for this room\r\n(see http://syncplay.pl/guide/ for usage instructions):", # TODO: Translate into Russian
"megabyte-suffix" : u" MB", # Technically it is a mebibyte # TODO: Translate into Russian
@@ -618,7 +618,7 @@ ru = {
"more-tooltip" : u"Показать дополнительные настройки.",
"slowdown-threshold-tooltip" : u"Отставание самого медленного клиента, необходимое для временного уменьшения скорости видео (по умолчанию: {} сек.).".format(constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD),
"rewind-threshold-tooltip" : u"Отставание самого медленного клиента, необходимое для перемотки назад в целях синхронизации (по умолчанию: {} сек.).".format(constants.DEFAULT_REWIND_THRESHOLD),
- "fastforward-threshold-tooltip" : u"Time behind room manager before seeking to get back in sync (default: {} secs).".format(constants.DEFAULT_FASTFORWARD_THRESHOLD), # TODO: Translate into Russian
+ "fastforward-threshold-tooltip" : u"Time behind room operator before seeking to get back in sync (default: {} secs).".format(constants.DEFAULT_FASTFORWARD_THRESHOLD), # TODO: Translate into Russian
"filename-privacy-tooltip" : u"Режим приватности для передачи имени воспроизводимого файла на сервер.",
"filesize-privacy-tooltip" : u"Режим приватности для передачи размера воспроизводимого файла на сервер.",
"privacy-sendraw-tooltip" : u"Отправляет эту информацию без шифрования. Рекомендуемая опция с наибольшей функциональностью.",
@@ -632,11 +632,11 @@ ru = {
"forceguiprompt-tooltip" : u"Окно настройки не будет отображаться при открытии файла в Syncplay.", # (Inverted)
"nostore-tooltip" : u"Запустить Syncplay с данной конфигурацией, но не сохранять изменения навсегда.", # (Inverted)
"rewindondesync-tooltip" : u"Перематывать назад, когда это необходимо для синхронизации. Отключение этой опции может привести к большим рассинхронизациям!",
- "fastforwardondesync-tooltip" : u"Jump forward when out of sync with room manager (or your pretend position if 'Never slow down or rewind others' enabled).", # TODO: Translate into Russian
+ "fastforwardondesync-tooltip" : u"Jump forward when out of sync with room operator (or your pretend position if 'Never slow down or rewind others' enabled).", # TODO: Translate into Russian
"showosd-tooltip" : u"Отправлять сообщения Syncplay в видеопроигрыватель и отображать их поверх видео (OSD - On Screen Display).",
"showosdwarnings-tooltip" : u"Показывать OSC-предупреждения, если проигрываются разные файлы или если Вы в комнате больше никого нет.",
"showsameroomosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к комнате, в которой Вы находитесь.",
- "shownoncontrollerosd-tooltip" : u"Show OSD notifications for events relating to non-controllers who are in controllerd rooms.", # TODO: Translate into Russian
+ "shownoncontrollerosd-tooltip" : u"Show OSD notifications for events relating to non-operators who are in controllerd rooms.", # TODO: Translate into Russian
"showdifferentroomosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к любым другим комнатам.",
"showslowdownosd-tooltip" : u"Показывать уведомления о замедлении или перемотке в целях синхронизации.",
"showdurationnotification-tooltip" : u"Полезно, когда сегмент составного файла отсутствует. Возможны ложные срабатывания.",
@@ -722,7 +722,7 @@ de = {
"all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users # TODO: Translate into German
"ready-to-unpause-notification" : u"You are now set as ready - unpause again to unpause", # TODO: Translate into German
- "identifying-as-controller-notification" : u"Identifiziere als Raumleiter mit Passwort '{}'...", # TODO: find a better translation to "room manager"
+ "identifying-as-controller-notification" : u"Identifiziere als Raumleiter mit Passwort '{}'...", # TODO: find a better translation to "room operator"
"failed-to-identify-as-controller-notification" : u"<{}> konnte sich nicht als Raumleiter identifizieren.",
"authenticated-as-controller-notification" : u"<{}> authentifizierte sich als Raumleiter",
"created-controlled-room-notification" : u"Created managed room '{}' with password '{}'. Please save this information for future reference!", # RoomName, controlPassword # TODO: Translate into German
@@ -742,7 +742,7 @@ de = {
"notplaying-notification" : u"Personen im Raum, die keine Dateien spielen:",
"userlist-room-notification" : u"In Raum '{}':", # Room
"userlist-file-notification" : u"File", # TODO: Translate into German (Datei?)
- "controller-userlist-userflag" : u"Manager", # TODO: Translate into German (this is to indicate a user is a room manager in the ConsoleUI userlist)
+ "controller-userlist-userflag" : u"Operator", # TODO: Translate into German (this is to indicate a user is a room operator in the ConsoleUI userlist)
"ready-userlist-userflag" : u"Ready", # TODO: Translate into German (this is to indicate a user is ready to watch in the ConsoleUI userlist)
"update-check-failed-notification" : u"Could not automatically check whether Syncplay {} is up to date. Want to visit http://syncplay.pl/ to manually check for updates?", #Syncplay version # TODO: Translate into German
From dda04583f75d717f0ea72c474aa3eaffedd4383b Mon Sep 17 00:00:00 2001
From: Et0h
Date: Sun, 25 Jan 2015 18:55:32 +0000
Subject: [PATCH 63/63] Upver release to #2
---
syncplay/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/syncplay/__init__.py b/syncplay/__init__.py
index e84a065..dbe21b3 100644
--- a/syncplay/__init__.py
+++ b/syncplay/__init__.py
@@ -1,4 +1,4 @@
version = '1.3.0'
milestone = 'Chami'
-release_number = '1'
+release_number = '2'
projectURL = 'http://syncplay.pl/'