diff --git a/syncplay/client.py b/syncplay/client.py index dd610ed..d9833fd 100644 --- a/syncplay/client.py +++ b/syncplay/client.py @@ -190,6 +190,13 @@ class SyncplayClient(object): madeChangeOnPlayer = True return madeChangeOnPlayer + def _fastforwardPlayerDueToTimeDifference(self, position, setBy): + hideFromOSD = not constants.SHOW_SAME_ROOM_OSD + self.setPosition(position + constants.FASTFORWARD_EXTRA_TIME) + self.ui.showMessage(getMessage("fastforward-notification").format(setBy), hideFromOSD) + madeChangeOnPlayer = True + return madeChangeOnPlayer + def _serverUnpaused(self, setBy): hideFromOSD = not constants.SHOW_SAME_ROOM_OSD self._player.setPaused(False) @@ -247,6 +254,9 @@ class SyncplayClient(object): madeChangeOnPlayer = self._serverSeeked(position, setBy) if diff > self._config['rewindThreshold'] and not doSeek and not self._config['rewindOnDesync'] == False: madeChangeOnPlayer = self._rewindPlayerDueToTimeDifference(position, setBy) + if diff < (self._config['fastforwardThreshold'] * -1) and not doSeek and not self._config['fastforwardOnDesync'] == False: + if utils.RoomPasswordProvider.isControlledRoom(self.getRoom()) and not self.userlist.currentUser.isController(): + madeChangeOnPlayer = self._fastforwardPlayerDueToTimeDifference(position, setBy) if self._player.speedSupported and not doSeek and not paused and not self._config['slowOnDesync'] == False: madeChangeOnPlayer = self._slowDownToCoverTimeDifference(diff, setBy) if paused == False and pauseChanged: diff --git a/syncplay/constants.py b/syncplay/constants.py index e55afd3..491fbdd 100644 --- a/syncplay/constants.py +++ b/syncplay/constants.py @@ -28,6 +28,9 @@ DEBUG_MODE = False #Changing these might be ok DEFAULT_REWIND_THRESHOLD = 4 MINIMUM_REWIND_THRESHOLD = 3 +DEFAULT_FASTFORWARD_THRESHOLD = 5 +MINIMUM_FASTFORWARD_THRESHOLD = 2 +FASTFORWARD_EXTRA_TIME = 0.25 SEEK_THRESHOLD = 1 SLOWDOWN_RATE = 0.95 DEFAULT_SLOWDOWN_KICKIN_THRESHOLD = 1.5 diff --git a/syncplay/messages.py b/syncplay/messages.py index ae64f18..ad27fa4 100755 --- a/syncplay/messages.py +++ b/syncplay/messages.py @@ -16,6 +16,7 @@ en = { "retrying-notification" : "%s, Retrying in %d seconds...", # Seconds "rewind-notification" : "Rewinded due to time difference with <{}>", # User + "fastforward-notification" : "Fast-forwarded due to time difference with <{}>", # User "slowdown-notification" : "Slowing down due to time difference with <{}>", # User "revert-notification" : "Reverting speed back to normal", @@ -134,6 +135,7 @@ en = { "more-title" : "Show more settings", "slowdown-threshold-label" : "Slow down threshold:", "rewind-threshold-label" : "Rewind threshold:", + "fastforward-threshold-label" : "Fast-forward threshold:", "never-rewind-value" : "Never", "seconds-suffix" : " secs", "privacy-sendraw-option" : "Send raw", @@ -226,6 +228,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), "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.", @@ -235,9 +238,11 @@ en = { "dontslowdownwithme-tooltip" : "Means others do not get slowed down or rewinded if your playback is lagging.", "pauseonleave-tooltip" : "Pause playback if you get disconnected or someone leaves from your room.", "rewindondesync-label" : "Rewind on major desync (highly recommended)", + "fastforwardondesync-label" : "Fast-forward if lagging behind room controller (recommended)", "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 needed to get back in sync. Disabling this option can result in major desyncs!", "showosd-tooltip" : "Sends Syncplay messages to media player OSD.", "showosdwarnings-tooltip" : "Show warnings if playing different file, alone in room.", "showsameroomosd-tooltip" : "Show OSD notifications for events relating to room user is in.", diff --git a/syncplay/ui/ConfigurationGetter.py b/syncplay/ui/ConfigurationGetter.py index 01ff417..e85b245 100755 --- a/syncplay/ui/ConfigurationGetter.py +++ b/syncplay/ui/ConfigurationGetter.py @@ -36,8 +36,10 @@ class ConfigurationGetter(object): "playerClass": None, "slowdownThreshold": constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD, "rewindThreshold": constants.DEFAULT_REWIND_THRESHOLD, + "fastforwardThreshold": constants.DEFAULT_FASTFORWARD_THRESHOLD, "rewindOnDesync": True, "slowOnDesync": True, + "fastforwardOnDesync": True, "dontSlowDownWithMe": False, "filenamePrivacyMode": constants.PRIVACY_SENDRAW_MODE, "filesizePrivacyMode": constants.PRIVACY_SENDRAW_MODE, @@ -91,12 +93,13 @@ class ConfigurationGetter(object): self._numeric = [ "slowdownThreshold", - "rewindThreshold" + "rewindThreshold", + "fastforwardThreshold", ] self._iniStructure = { "server_data": ["host", "port", "password"], - "client_settings": ["name", "room", "playerPath", "slowdownThreshold", "rewindThreshold", "slowOnDesync", "rewindOnDesync", "dontSlowDownWithMe", "forceGuiPrompt", "filenamePrivacyMode", "filesizePrivacyMode", "pauseOnLeave"], + "client_settings": ["name", "room", "playerPath", "slowdownThreshold", "rewindThreshold", "fastforwardThreshold", "slowOnDesync", "rewindOnDesync", "fastforwardOnDesync", "dontSlowDownWithMe", "forceGuiPrompt", "filenamePrivacyMode", "filesizePrivacyMode", "pauseOnLeave"], "gui": ["showOSD", "showOSDWarnings", "showSlowdownOSD", "showDifferentRoomOSD", "showSameRoomOSD", "showContactInfo" , "showDurationNotification"], "general": ["language"] } diff --git a/syncplay/ui/GuiConfiguration.py b/syncplay/ui/GuiConfiguration.py index 6721a89..1ed195a 100644 --- a/syncplay/ui/GuiConfiguration.py +++ b/syncplay/ui/GuiConfiguration.py @@ -15,7 +15,6 @@ class GuiConfiguration: self._availablePlayerPaths = [] self.error = error - def run(self): if QCoreApplication.instance() is None: self.app = QtGui.QApplication(sys.argv) @@ -206,8 +205,11 @@ class ConfigDialog(QtGui.QDialog): self.slowdownThresholdSpinbox.value = constants.DEFAULT_SLOWDOWN_KICKIN_THRESHOLD if not self.rewindThresholdSpinbox.text: self.rewindThresholdSpinbox.value = constants.DEFAULT_REWIND_THRESHOLD + if not self.fastforwardThresholdSpinbox.text: + self.fastforwardThresholdSpinbox.value = constants.DEFAULT_FASTFORWARD_THRESHOLD self.config['slowdownThreshold'] = self.slowdownThresholdSpinbox.value() self.config['rewindThreshold'] = self.rewindThresholdSpinbox.value() + self.config['fastforwardThreshold'] = self.fastforwardThresholdSpinbox.value() self.pressedclosebutton = True self.close() @@ -415,6 +417,8 @@ class ConfigDialog(QtGui.QDialog): self.slowdownCheckbox.setObjectName("slowOnDesync") self.rewindCheckbox = QCheckBox(getMessage("rewindondesync-label")) self.rewindCheckbox.setObjectName("rewindOnDesync") + self.fastforwardCheckbox = QCheckBox(getMessage("fastforwardondesync-label")) + self.fastforwardCheckbox.setObjectName("fastforwardOnDesync") self.spaceLabel = QLabel() self.spaceLabel.setFixedHeight(5) @@ -458,6 +462,22 @@ class ConfigDialog(QtGui.QDialog): self.rewindThresholdSpinbox.setSuffix(getMessage("seconds-suffix")) self.rewindThresholdSpinbox.adjustSize() + self.fastforwardThresholdLabel = QLabel(getMessage("fastforward-threshold-label"), self) + self.fastforwardThresholdLabel.setStyleSheet(constants.STYLE_SUBLABEL.format(self.posixresourcespath + "chevrons_right.png")) + self.fastforwardThresholdSpinbox = QDoubleSpinBox() + try: + fastforwardThreshold = float(config['fastforwardThreshold']) + self.fastforwardThresholdSpinbox.setValue(fastforwardThreshold) + if fastforwardThreshold < constants.MINIMUM_FASTFORWARD_THRESHOLD: + constants.MINIMUM_FASTFORWARD_THRESHOLD = fastforwardThreshold + except ValueError: + self.fastforwardThresholdSpinbox.setValue(constants.DEFAULT_FASTFORWARD_THRESHOLD) + self.fastforwardThresholdSpinbox.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) + self.fastforwardThresholdSpinbox.setMinimum(constants.MINIMUM_FASTFORWARD_THRESHOLD) + self.fastforwardThresholdSpinbox.setSingleStep(0.1) + self.fastforwardThresholdSpinbox.setSuffix(getMessage("seconds-suffix")) + self.fastforwardThresholdSpinbox.adjustSize() + self.slowdownThresholdLabel.setObjectName("slowdown-threshold") self.slowdownThresholdSpinbox.setObjectName("slowdown-threshold") self.rewindThresholdLabel.setObjectName("rewind-threshold") @@ -484,14 +504,23 @@ class ConfigDialog(QtGui.QDialog): self.othersyncOptionsFrame = QtGui.QFrame() self.othersyncSettingsLayout = QtGui.QGridLayout() - self.dontslowwithmeCheckbox = QCheckBox(getMessage("dontslowdownwithme-label")) - self.pauseonleaveCheckbox = QCheckBox(getMessage("pauseonleave-label")) - self.othersyncSettingsLayout.addWidget(self.dontslowwithmeCheckbox) - self.othersyncSettingsLayout.addWidget(self.pauseonleaveCheckbox) self.dontslowwithmeCheckbox.setObjectName("dontSlowDownWithMe") + + self.othersyncSettingsLayout.addWidget(self.dontslowwithmeCheckbox, 1, 0, 1, 2, Qt.AlignLeft) + + self.pauseonleaveCheckbox = QCheckBox(getMessage("pauseonleave-label")) + self.othersyncSettingsLayout.addWidget(self.pauseonleaveCheckbox, 2, 0, 1, 2, Qt.AlignLeft) self.pauseonleaveCheckbox.setObjectName("pauseOnLeave") + 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.subitems['fastforwardOnDesync'] = ["fastforward-threshold"] + self.othersyncSettingsGroup.setLayout(self.othersyncSettingsLayout) self.syncSettingsLayout.addWidget(self.othersyncSettingsGroup)