diff --git a/syncplay/client.py b/syncplay/client.py index 22da494..df0d668 100644 --- a/syncplay/client.py +++ b/syncplay/client.py @@ -178,7 +178,7 @@ class SyncplayClient(object): def updatePlayerStatus(self, paused, position, cookie=None): # Ignore status report if the cookie is stale if cookie is not None and \ - cookie < constants.PLAYER_COMMAND_DELAY + self._lastPlayerCommand: + cookie < self._lastPlayerCommand + self._config['playerCommandDelay']: return position -= self.getUserOffset() diff --git a/syncplay/constants.py b/syncplay/constants.py index a39ec6a..eadacac 100644 --- a/syncplay/constants.py +++ b/syncplay/constants.py @@ -49,6 +49,7 @@ SERVER_STATE_INTERVAL = 1 WARNING_OSD_MESSAGES_LOOP_INTERVAL = 1 AUTOPLAY_DELAY = 3.0 SYNC_ON_PAUSE = True # Client seek to global position - subtitles may disappear on some media players +DEFAULT_PLAYER_COMMAND_DELAY = 0.05 # Options for the File Switch feature: FOLDER_SEARCH_TIMEOUT = 60.0 # Secs - How long to wait until searches in folder to update cache are aborted (may be longer than this if hard drive needs to spin up) diff --git a/syncplay/messages.py b/syncplay/messages.py index 7abe1ad..ff71183 100755 --- a/syncplay/messages.py +++ b/syncplay/messages.py @@ -194,6 +194,9 @@ en = { "forceguiprompt-label" : "Don't always show the Syncplay configuration window", # (Inverted) "nostore-label" : "Don't store this configuration", # (Inverted) "showosd-label" : "Enable OSD Messages", + "playercommanddelay-title" : "Player latency compensation", + "playercommanddelay-label" : "Seconds to ignore player status after commands", + "playercommanddelay-tooltip" : "Larger values are less likely to spuriously (un)pause but tend to sync less accurately.", "showosdwarnings-label" : "Include warnings (e.g. when files are different, users not ready)", "showsameroomosd-label" : "Include events in your room", diff --git a/syncplay/ui/ConfigurationGetter.py b/syncplay/ui/ConfigurationGetter.py index 0fa6284..b27af5c 100755 --- a/syncplay/ui/ConfigurationGetter.py +++ b/syncplay/ui/ConfigurationGetter.py @@ -63,7 +63,8 @@ class ConfigurationGetter(object): "showSameRoomOSD" : True, "showNonControllerOSD" : False, "showContactInfo" : True, - "showDurationNotification" : True + "showDurationNotification" : True, + "playerCommandDelay": constants.DEFAULT_PLAYER_COMMAND_DELAY } self._defaultConfig = self._config.copy() @@ -117,11 +118,21 @@ class ConfigurationGetter(object): "rewindThreshold", "fastforwardThreshold", "autoplayMinUsers", + "playerCommandDelay", ] self._iniStructure = { "server_data": ["host", "port", "password"], - "client_settings": ["name", "room", "playerPath", "perPlayerArguments", "slowdownThreshold", "rewindThreshold", "fastforwardThreshold", "slowOnDesync", "rewindOnDesync", "fastforwardOnDesync", "dontSlowDownWithMe", "forceGuiPrompt", "filenamePrivacyMode", "filesizePrivacyMode", "unpauseAction", "pauseOnLeave", "readyAtStart", "autoplayMinUsers", "autoplayInitialState", "mediaSearchDirectories"], + "client_settings": ["name", "room", "playerPath", + "perPlayerArguments", "slowdownThreshold", + "rewindThreshold", "fastforwardThreshold", + "slowOnDesync", "rewindOnDesync", + "fastforwardOnDesync", "dontSlowDownWithMe", + "forceGuiPrompt", "filenamePrivacyMode", + "filesizePrivacyMode", "unpauseAction", + "pauseOnLeave", "readyAtStart", "autoplayMinUsers", + "autoplayInitialState", "mediaSearchDirectories", + "playerCommandDelay"], "gui": ["showOSD", "showOSDWarnings", "showSlowdownOSD", "showDifferentRoomOSD", "showSameRoomOSD", "showNonControllerOSD", "showDurationNotification"], "general": ["language", "checkForUpdatesAutomatically", "lastCheckedForUpdates"] } @@ -425,4 +436,4 @@ class SafeConfigParserUnicode(SafeConfigParser): if (value is not None) or (self._optcre == self.OPTCRE): key = " = ".join((key, unicode(value).replace('\n', '\n\t'))) fp.write("%s\n" % key) - fp.write("\n") \ No newline at end of file + fp.write("\n") diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index bfa92ec..ad8f80c 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -365,6 +365,8 @@ class ConfigDialog(QtGui.QDialog): widget.setChecked(True) elif isinstance(widget, QLineEdit): widget.setText(self.config[valueName]) + elif isinstance(widget, QDoubleSpinBox): + widget.setValue(self.config[valueName]) def saveValues(self, widget): valueName = str(widget.objectName()) @@ -682,6 +684,10 @@ class ConfigDialog(QtGui.QDialog): self.rewindCheckbox.setObjectName("rewindOnDesync") self.fastforwardCheckbox = QCheckBox(getMessage("fastforwardondesync-label")) self.fastforwardCheckbox.setObjectName("fastforwardOnDesync") + self.commandDelaySpinbox = QDoubleSpinBox() + self.commandDelaySpinbox.setObjectName("playerCommandDelay") + self.commandDelaySpinbox.setMaximum(10) + self.commandDelaySpinbox.setSingleStep(.01) self.desyncSettingsLayout = QtGui.QGridLayout() self.desyncSettingsLayout.setSpacing(2) @@ -710,10 +716,17 @@ class ConfigDialog(QtGui.QDialog): self.othersyncSettingsLayout.setAlignment(Qt.AlignLeft) self.othersyncSettingsLayout.addWidget(self.fastforwardCheckbox, 3, 0,1,2, Qt.AlignLeft) + self.playerLatencyGroup = QtGui.QGroupBox(getMessage("playercommanddelay-title")) + self.playerLatencyLayout = QtGui.QHBoxLayout() + self.playerLatencyGroup.setLayout(self.playerLatencyLayout) + self.playerLatencyLayout.addWidget(self.commandDelaySpinbox) + self.playerLatencyLayout.addWidget(QLabel(getMessage("playercommanddelay-label"))) + self.othersyncSettingsGroup.setLayout(self.othersyncSettingsLayout) self.othersyncSettingsGroup.setMaximumHeight(self.othersyncSettingsGroup.minimumSizeHint().height()) self.syncSettingsLayout.addWidget(self.othersyncSettingsGroup) self.syncSettingsLayout.addWidget(self.desyncSettingsGroup) + self.syncSettingsLayout.addWidget(self.playerLatencyGroup) self.syncSettingsFrame.setLayout(self.syncSettingsLayout) self.desyncSettingsGroup.setMaximumHeight(self.desyncSettingsGroup.minimumSizeHint().height()) self.syncSettingsLayout.setAlignment(Qt.AlignTop)