diff --git a/buildPy2exe.py b/buildPy2exe.py index 6c81bff..3f7e0b5 100644 --- a/buildPy2exe.py +++ b/buildPy2exe.py @@ -676,7 +676,7 @@ info = dict( options={'py2exe': { 'dist_dir': OUT_DIR, 'packages': 'PySide.QtUiTools', - 'includes': 'twisted, sys, encodings, datetime, os, time, math, PySide, liburl', + 'includes': 'twisted, sys, encodings, datetime, os, time, math, PySide, liburl, ast', 'excludes': 'venv, _ssl, doctest, pdb, unittest, win32clipboard, win32file, win32pdh, win32security, win32trace, win32ui, winxpgui, win32pipe, win32process, Tkinter', 'dll_excludes': 'msvcr71.dll, MSVCP90.dll, POWRPROF.dll', 'optimize': 2, diff --git a/syncplay/__init__.py b/syncplay/__init__.py index 8e02ebc..cfcf059 100644 --- a/syncplay/__init__.py +++ b/syncplay/__init__.py @@ -1,4 +1,4 @@ version = '1.3.1' milestone = 'Chami' -release_number = '12' +release_number = '13' projectURL = 'http://syncplay.pl/' diff --git a/syncplay/client.py b/syncplay/client.py index 5b151d7..7ac9b56 100644 --- a/syncplay/client.py +++ b/syncplay/client.py @@ -497,7 +497,10 @@ class SyncplayClient(object): return self._running = True if self._playerClass: - reactor.callLater(0.1, self._playerClass.run, self, self._config['playerPath'], self._config['file'], self._config['playerArgs']) + perPlayerArguments = utils.getPlayerArgumentsByPathAsArray(self._config['perPlayerArguments'],self._config['playerPath']) + if perPlayerArguments: + self._config['playerArgs'].extend(perPlayerArguments) + reactor.callLater(0.1, self._playerClass.run, self, self._config['playerPath'], self._config['file'], self._config['playerArgs'], ) self._playerClass = None self.protocolFactory = SyncClientFactory(self) port = int(port) diff --git a/syncplay/messages.py b/syncplay/messages.py index bdf6957..def8500 100755 --- a/syncplay/messages.py +++ b/syncplay/messages.py @@ -169,6 +169,7 @@ en = { "media-setting-title" : "Media player settings", "executable-path-label" : "Path to media player:", "media-path-label" : "Path to media file:", + "player-arguments-label" : "Player arguments (if any):", "browse-label" : "Browse", "more-title" : "Show more settings", @@ -284,6 +285,7 @@ en = { "executable-path-tooltip" : "Location of your chosen supported media player (MPC-HC, VLC, mplayer2 or mpv).", "media-path-tooltip" : "Location of video or stream to be opened. Necessary for mpv and mplayer2.", + "player-arguments-tooltip" : "Additional command line arguments / switches to pass on to this media player.", "more-tooltip" : "Display less frequently used settings.", "filename-privacy-tooltip" : "Privacy mode for sending currently playing filename to server.", @@ -527,6 +529,7 @@ ru = { "media-setting-title" : u"Параметры проигрывателя", "executable-path-label" : u"Путь к проигрывателю:", "media-path-label" : u"Путь к видеофайлу:", + "player-arguments-label" : "Player arguments:", # TODO: Translate into Russian "browse-label" : u"Выбрать", "more-title" : u"Больше настроек", @@ -642,6 +645,7 @@ ru = { "executable-path-tooltip" : u"Расположение Вашего видеопроигрывателя (MPC-HC, VLC, mplayer2 или mpv).", "media-path-tooltip" : u"Расположение видеофайла или потока для просмотра. Обязательно для mpv и mplayer2.", + "player-arguments-tooltip" : "Additional command line arguments / switches to pass on to this media player.", # TODO: Translate into Russian "more-tooltip" : u"Показать дополнительные настройки.", "filename-privacy-tooltip" : u"Режим приватности для передачи имени воспроизводимого файла на сервер.", @@ -885,6 +889,7 @@ de = { "media-setting-title" : u"Media-Player Einstellungen", "executable-path-label" : u"Pfad zum Media-Player:", "media-path-label" : u"Pfad zur Datei:", + "player-arguments-label" : "Player arguments:", # TODO: Translate into German "browse-label" : u"Durchsuchen", "more-title" : u"Mehr Einstellungen zeigen", @@ -998,6 +1003,7 @@ de = { "executable-path-tooltip" : u"Pfad zum ausgewählten, unterstützten Mediaplayer (MPC-HC, VLC, mplayer2 or mpv).", "media-path-tooltip" : u"Pfad zum wiederzugebenden Video oder Stream. Notwendig für mpv und mplayer2.", + "player-arguments-tooltip" : "Additional command line arguments / switches to pass on to this media player.", # TODO: Translate into German "more-tooltip" : u"Weitere Einstellungen anzeigen.", "filename-privacy-tooltip" : u"Privatheitsmodus beim Senden des Namens der aktuellen Datei zum Server.", diff --git a/syncplay/ui/ConfigurationGetter.py b/syncplay/ui/ConfigurationGetter.py index 55323d1..c73cf60 100755 --- a/syncplay/ui/ConfigurationGetter.py +++ b/syncplay/ui/ConfigurationGetter.py @@ -2,6 +2,7 @@ from ConfigParser import SafeConfigParser, DEFAULTSECT import argparse import os import sys +import ast from syncplay import constants, utils, version, milestone from syncplay.messages import getMessage, setLanguage, isValidLanguage from syncplay.players.playerFactory import PlayerFactory @@ -31,6 +32,7 @@ class ConfigurationGetter(object): "room": "", "password": None, "playerPath": None, + "perPlayerArguments": None, "file": None, "playerArgs": [], "playerClass": None, @@ -104,6 +106,10 @@ class ConfigurationGetter(object): "autoplayInitialState", ] + self._serialised = [ + "perPlayerArguments", + ] + self._numeric = [ "slowdownThreshold", "rewindThreshold", @@ -113,7 +119,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", "unpauseAction", "pauseOnLeave", "readyAtStart", "autoplayMinUsers", "autoplayInitialState"], + "client_settings": ["name", "room", "playerPath", "perPlayerArguments", "slowdownThreshold", "rewindThreshold", "fastforwardThreshold", "slowOnDesync", "rewindOnDesync", "fastforwardOnDesync", "dontSlowDownWithMe", "forceGuiPrompt", "filenamePrivacyMode", "filesizePrivacyMode", "unpauseAction", "pauseOnLeave", "readyAtStart", "autoplayMinUsers", "autoplayInitialState"], "gui": ["showOSD", "showOSDWarnings", "showSlowdownOSD", "showDifferentRoomOSD", "showSameRoomOSD", "showNonControllerOSD", "showDurationNotification"], "general": ["language", "checkForUpdatesAutomatically", "lastCheckedForUpdates"] } @@ -150,6 +156,12 @@ class ConfigurationGetter(object): elif self._config[key] == "False": self._config[key] = False + for key in self._serialised: + if self._config[key] is None or self._config[key] == "": + self._config[key] = {} + elif isinstance(self._config[key], (str, unicode)): + self._config[key] = ast.literal_eval(self._config[key]) + for key in self._tristate: if self._config[key] == "True": self._config[key] = True diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index 935b4d7..5ec1a7e 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -134,13 +134,27 @@ class ConfigDialog(QtGui.QDialog): return foundpath def updateExecutableIcon(self): - currentplayerpath = unicode(self.executablepathCombobox.currentText()) + currentplayerpath = self.executablepathCombobox.currentText() iconpath = PlayerFactory().getPlayerIconByPath(currentplayerpath) if iconpath != None and iconpath != "": self.executableiconImage.load(self.resourcespath + iconpath) self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(self.executableiconImage)) else: self.executableiconLabel.setPixmap(QtGui.QPixmap.fromImage(QtGui.QImage())) + self.updatePlayerArguments(currentplayerpath) + + def updatePlayerArguments(self, currentplayerpath): + argumentsForPath = utils.getPlayerArgumentsByPathAsText(self.perPlayerArgs, currentplayerpath) + self.playerargsTextbox.blockSignals(True) + self.playerargsTextbox.setText(argumentsForPath) + self.playerargsTextbox.blockSignals(False) + + def changedPlayerArgs(self): + currentplayerpath = self.executablepathCombobox.currentText() + + if currentplayerpath: + NewPlayerArgs = self.playerargsTextbox.text().split(u" ") if self.playerargsTextbox.text() else "" + self.perPlayerArgs[self.executablepathCombobox.currentText()]=NewPlayerArgs def languageChanged(self): setLanguage(unicode(self.languageCombobox.itemData(self.languageCombobox.currentIndex()))) @@ -235,6 +249,8 @@ class ConfigDialog(QtGui.QDialog): self.automaticUpdatePromptCheck() self.loadLastUpdateCheckDate() + self.config["perPlayerArguments"] = self.perPlayerArgs + 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) @@ -364,6 +380,8 @@ class ConfigDialog(QtGui.QDialog): else: host = config['host'] + ":" + str(config['port']) + self.perPlayerArgs = self.config["perPlayerArguments"] + self.connectionSettingsGroup = QtGui.QGroupBox(getMessage("connection-group-title")) self.hostTextbox = QLineEdit(host, self) self.hostLabel = QLabel(getMessage("host-label"), self) @@ -396,6 +414,10 @@ class ConfigDialog(QtGui.QDialog): self.connectionSettingsGroup.setLayout(self.connectionSettingsLayout) self.connectionSettingsGroup.setMaximumHeight(self.connectionSettingsGroup.minimumSizeHint().height()) + self.playerargsTextbox = QLineEdit("", self) + self.playerargsTextbox.textEdited.connect(self.changedPlayerArgs) + self.playerargsLabel = QLabel(getMessage("player-arguments-label"), self) + self.mediaplayerSettingsGroup = QtGui.QGroupBox(getMessage("media-setting-title")) self.executableiconImage = QtGui.QImage() self.executableiconLabel = QLabel(self) @@ -419,6 +441,8 @@ class ConfigDialog(QtGui.QDialog): self.executablepathCombobox.setObjectName("executable-path") self.mediapathLabel.setObjectName("media-path") self.mediapathTextbox.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "media-path") + self.playerargsLabel.setObjectName("player-arguments") + self.playerargsTextbox.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "player-arguments") self.mediaplayerSettingsLayout = QtGui.QGridLayout() self.mediaplayerSettingsLayout.addWidget(self.executablepathLabel, 0, 0) @@ -428,6 +452,8 @@ class ConfigDialog(QtGui.QDialog): self.mediaplayerSettingsLayout.addWidget(self.mediapathLabel, 1, 0) self.mediaplayerSettingsLayout.addWidget(self.mediapathTextbox , 1, 2) self.mediaplayerSettingsLayout.addWidget(self.mediabrowseButton , 1, 3) + self.mediaplayerSettingsLayout.addWidget(self.playerargsLabel, 2, 0, 1, 2) + self.mediaplayerSettingsLayout.addWidget(self.playerargsTextbox, 2, 2, 1, 2) self.mediaplayerSettingsGroup.setLayout(self.mediaplayerSettingsLayout) self.showmoreCheckbox = QCheckBox(getMessage("more-title")) diff --git a/syncplay/utils.py b/syncplay/utils.py index 86a2d85..6bc2828 100644 --- a/syncplay/utils.py +++ b/syncplay/utils.py @@ -225,6 +225,16 @@ def isURL(path): if "://" in path: return True +def getPlayerArgumentsByPathAsArray(arguments, path): + if arguments and not isinstance(arguments, (str, unicode)) and arguments.has_key(path): + return arguments[path] + else: + return None + +def getPlayerArgumentsByPathAsText(arguments, path): + argsToReturn = getPlayerArgumentsByPathAsArray(arguments, path) + return " ".join(argsToReturn) if argsToReturn else "" + class RoomPasswordProvider(object): CONTROLLED_ROOM_REGEX = re.compile("^\+(.*):(\w{12})$") PASSWORD_REGEX = re.compile("[A-Z]{2}-\d{3}-\d{3}")