Merge pull request #93 from Syncplay/sharedplaylists

Shared playlists
This commit is contained in:
Etoh 2016-07-02 23:54:34 +01:00 committed by GitHub
commit e4b033ad99
26 changed files with 2679 additions and 1290 deletions

View File

@ -127,13 +127,13 @@ NSIS_SCRIPT_TEMPLATE = r"""
Var Dialog
Var Icon_Syncplay
Var Icon_Syncplay_Handle
Var CheckBox_Associate
;Var CheckBox_Associate
Var CheckBox_VLC
Var CheckBox_AutomaticUpdates
Var CheckBox_StartMenuShortcut
Var CheckBox_DesktopShortcut
Var CheckBox_QuickLaunchShortcut
Var CheckBox_Associate_State
;Var CheckBox_Associate_State
Var CheckBox_VLC_State
Var CheckBox_AutomaticUpdates_State
Var CheckBox_StartMenuShortcut_State
@ -165,13 +165,13 @@ NSIS_SCRIPT_TEMPLATE = r"""
Var Drive
Var VLC_Directory
!macro APP_ASSOCIATE EXT FileCLASS DESCRIPTION COMMANDTEXT COMMAND
WriteRegStr HKCR ".$${EXT}" "" "$${FileCLASS}"
WriteRegStr HKCR "$${FileCLASS}" "" `$${DESCRIPTION}`
WriteRegStr HKCR "$${FileCLASS}\shell" "" "open"
WriteRegStr HKCR "$${FileCLASS}\shell\open" "" `$${COMMANDTEXT}`
WriteRegStr HKCR "$${FileCLASS}\shell\open\command" "" `$${COMMAND}`
!macroend
;!macro APP_ASSOCIATE EXT FileCLASS DESCRIPTION COMMANDTEXT COMMAND
; WriteRegStr HKCR ".$${EXT}" "" "$${FileCLASS}"
; WriteRegStr HKCR "$${FileCLASS}" "" `$${DESCRIPTION}`
; WriteRegStr HKCR "$${FileCLASS}\shell" "" "open"
; WriteRegStr HKCR "$${FileCLASS}\shell\open" "" `$${COMMANDTEXT}`
; WriteRegStr HKCR "$${FileCLASS}\shell\open\command" "" `$${COMMAND}`
;!macroend
!macro APP_UNASSOCIATE EXT FileCLASS
; Backup the previously associated File class
@ -180,10 +180,10 @@ NSIS_SCRIPT_TEMPLATE = r"""
DeleteRegKey HKCR `$${FileCLASS}`
!macroend
!macro ASSOCIATE EXT
!insertmacro APP_ASSOCIATE "$${EXT}" "Syncplay.$${EXT}" "$$INSTDIR\Syncplay.exe,%1%" \
"Open with Syncplay" "$$INSTDIR\Syncplay.exe $$\"%1$$\""
!macroend
;!macro ASSOCIATE EXT
; !insertmacro APP_ASSOCIATE "$${EXT}" "Syncplay.$${EXT}" "$$INSTDIR\Syncplay.exe,%1%" \
; "Open with Syncplay" "$$INSTDIR\Syncplay.exe $$\"%1$$\""
;!macroend
!macro UNASSOCIATE EXT
!insertmacro APP_UNASSOCIATE "$${EXT}" "Syncplay.$${EXT}"
@ -197,7 +197,7 @@ NSIS_SCRIPT_TEMPLATE = r"""
MessageBox MB_OK|MB_ICONEXCLAMATION "The installer is already running."
Abort
StrCpy $$CheckBox_Associate_State $${BST_CHECKED}
;StrCpy $$CheckBox_Associate_State $${BST_CHECKED}
StrCpy $$CheckBox_StartMenuShortcut_State $${BST_CHECKED}
Call GetVLCDir
Call UpdateVLCCheckbox
@ -257,8 +257,8 @@ NSIS_SCRIPT_TEMPLATE = r"""
$${NSD_CreateLabel} 321u 122u 132 8u "$$(^SpaceAvailable)$$AvailibleSpaceGiB.$$AvailibleSpaceGB"
Pop $$Label_Space
$${NSD_CreateCheckBox} 8u 59u 187u 10u "$$(^Associate)"
Pop $$CheckBox_Associate
;$${NSD_CreateCheckBox} 8u 59u 187u 10u "$$(^Associate)"
;Pop $$CheckBox_Associate
$${NSD_CreateBrowseButton} 185u 70u 70u 14u "$$(^BrowseVLCBtn)"
Pop $$Button_Browse_VLC
@ -283,9 +283,9 @@ NSIS_SCRIPT_TEMPLATE = r"""
$${NSD_CreateCheckbox} 158u 111u 130u 10u "$$(^QuickLaunchBar)"
Pop $$CheckBox_QuickLaunchShortcut
$${If} $$CheckBox_Associate_State == $${BST_CHECKED}
$${NSD_Check} $$CheckBox_Associate
$${EndIf}
;$${If} $$CheckBox_Associate_State == $${BST_CHECKED}
; $${NSD_Check} $$CheckBox_Associate
;$${EndIf}
$${If} $$CheckBox_VLC_State == $${BST_CHECKED}
$${NSD_Check} $$CheckBox_VLC
@ -317,7 +317,7 @@ NSIS_SCRIPT_TEMPLATE = r"""
Function DirectoryCustomLeave
$${NSD_GetText} $$Text_Directory $$INSTDIR
$${NSD_GetState} $$CheckBox_Associate $$CheckBox_Associate_State
;$${NSD_GetState} $$CheckBox_Associate $$CheckBox_Associate_State
$${NSD_GetState} $$CheckBox_VLC $$CheckBox_VLC_State
$${NSD_GetState} $$CheckBox_AutomaticUpdates $$CheckBox_AutomaticUpdates_State
$${NSD_GetState} $$CheckBox_StartMenuShortcut $$CheckBox_StartMenuShortcut_State
@ -395,10 +395,10 @@ NSIS_SCRIPT_TEMPLATE = r"""
FunctionEnd
Function InstallOptions
$${If} $$CheckBox_Associate_State == $${BST_CHECKED}
Call Associate
DetailPrint "Associated Syncplay with multimedia files"
$${EndIf}
;$${If} $$CheckBox_Associate_State == $${BST_CHECKED}
; Call Associate
; DetailPrint "Associated Syncplay with multimedia files"
;$${EndIf}
$${If} $$CheckBox_StartMenuShortcut_State == $${BST_CHECKED}
CreateDirectory $$SMPROGRAMS\Syncplay
@ -425,32 +425,32 @@ NSIS_SCRIPT_TEMPLATE = r"""
FunctionEnd
;Associates extensions with Syncplay
Function Associate
!insertmacro ASSOCIATE avi
!insertmacro ASSOCIATE mpg
!insertmacro ASSOCIATE mpeg
!insertmacro ASSOCIATE mpe
!insertmacro ASSOCIATE m1v
!insertmacro ASSOCIATE m2v
!insertmacro ASSOCIATE mpv2
!insertmacro ASSOCIATE mp2v
!insertmacro ASSOCIATE mkv
!insertmacro ASSOCIATE mp4
!insertmacro ASSOCIATE m4v
!insertmacro ASSOCIATE mp4v
!insertmacro ASSOCIATE 3gp
!insertmacro ASSOCIATE 3gpp
!insertmacro ASSOCIATE 3g2
!insertmacro ASSOCIATE 3pg2
!insertmacro ASSOCIATE flv
!insertmacro ASSOCIATE f4v
!insertmacro ASSOCIATE rm
!insertmacro ASSOCIATE wmv
!insertmacro ASSOCIATE swf
!insertmacro ASSOCIATE rmvb
!insertmacro ASSOCIATE divx
!insertmacro ASSOCIATE amv
FunctionEnd
;Function Associate
; !insertmacro ASSOCIATE avi
; !insertmacro ASSOCIATE mpg
; !insertmacro ASSOCIATE mpeg
; !insertmacro ASSOCIATE mpe
; !insertmacro ASSOCIATE m1v
; !insertmacro ASSOCIATE m2v
; !insertmacro ASSOCIATE mpv2
; !insertmacro ASSOCIATE mp2v
; !insertmacro ASSOCIATE mkv
; !insertmacro ASSOCIATE mp4
; !insertmacro ASSOCIATE m4v
; !insertmacro ASSOCIATE mp4v
; !insertmacro ASSOCIATE 3gp
; !insertmacro ASSOCIATE 3gpp
; !insertmacro ASSOCIATE 3g2
; !insertmacro ASSOCIATE 3pg2
; !insertmacro ASSOCIATE flv
; !insertmacro ASSOCIATE f4v
; !insertmacro ASSOCIATE rm
; !insertmacro ASSOCIATE wmv
; !insertmacro ASSOCIATE swf
; !insertmacro ASSOCIATE rmvb
; !insertmacro ASSOCIATE divx
; !insertmacro ASSOCIATE amv
;FunctionEnd
Function WriteRegistry
Call GetSize
@ -653,9 +653,11 @@ 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/cog.png',
'resources/film_go.png', 'resources/world_go.png',
'resources/arrow_refresh.png', 'resources/spinner.mng'
'resources/world_explore.png', 'resources/application_get.png', 'resources/cog.png', 'resources/arrow_switch.png',
'resources/film_go.png', 'resources/world_go.png', 'resources/arrow_refresh.png', 'resources/bullet_right_grey.png',
'resources/film_folder_edit.png',
'resources/shield_edit.png',
'resources/world_add.png', 'resources/film_add.png', 'resources/delete.png', 'resources/spinner.mng'
]
resources = ["resources/icon.ico", "resources/syncplay.png"]
resources.extend(guiIcons)

BIN
resources/arrow_switch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

BIN
resources/delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

BIN
resources/film_add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 B

View File

@ -5,7 +5,7 @@
Principal author: Etoh
Other contributors: DerGenaue, jb
Project: http://syncplay.pl/
Version: 0.2.8
Version: 0.2.9
Note:
* This interface module is intended to be used in conjunction with Syncplay.
@ -84,7 +84,7 @@ You may also need to re-copy the syncplay.lua file when you update VLC.
--]==========================================================================]
local connectorversion = "0.2.8"
local connectorversion = "0.2.9"
local vlcversion = vlc.misc.version()
local durationdelay = 500000 -- Pause for get_duration command etc for increased reliability (uses microseconds)
local loopsleepduration = 2500 -- Pause for every event loop (uses microseconds)
@ -463,7 +463,9 @@ function load_file (filepath)
-- [Used by load-file command]
local uri = vlc.strings.make_uri(filepath)
vlc.playlist.add({{path=uri}})
vlc.playlist.clear()
vlc.playlist.enqueue({{path=uri}})
vlc.playlist.next()
return "load-file-attempted\n"
end

BIN
resources/shield_edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 B

BIN
resources/world_add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

View File

@ -1,4 +1,4 @@
version = '1.3.4'
milestone = 'Chami'
release_number = '21'
version = '1.4.0'
milestone = 'Yoitsu'
release_number = '27'
projectURL = 'http://syncplay.pl/'

View File

@ -4,8 +4,10 @@ import time
import re
import sys
import ast
import random
import threading
from twisted.internet.protocol import ClientFactory
from twisted.internet import reactor, task
from twisted.internet import reactor, task, defer, threads
from functools import wraps
from copy import deepcopy
from syncplay.protocols import SyncClientProtocol
@ -69,6 +71,7 @@ class SyncplayClient(object):
self.lastControlPasswordAttempt = None
self.serverVersion = "0.0.0"
self.lastRewindTime = None
self.lastLeftTime = 0
self.lastPausedOnLeaveTime = None
self.lastLeftUser = u""
@ -113,7 +116,12 @@ class SyncplayClient(object):
self.autoplayTimer = task.LoopingCall(self.autoplayCountdown)
self.autoplayTimeLeft = constants.AUTOPLAY_DELAY
self.__playerReady = defer.Deferred()
self._warnings = self._WarningManager(self._player, self.userlist, self.ui, self)
self.fileSwitch = FileSwitchManager(self)
self.playlist = SyncplayPlaylist(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)
@ -121,7 +129,7 @@ class SyncplayClient(object):
if constants.DEBUG_MODE and constants.WARN_ABOUT_MISSING_STRINGS:
missingStrings = getMissingStrings()
if missingStrings is not None and missingStrings is not "":
self.ui.showDebugMessage("MISSING/UNUSED STRINGS DETECTED:\n{}".format(missingStrings))
self.ui.showDebugMessage(u"MISSING/UNUSED STRINGS DETECTED:\n{}".format(missingStrings))
def initProtocol(self, protocol):
self._protocol = protocol
@ -136,6 +144,13 @@ class SyncplayClient(object):
if not self._player.secondaryOSDSupported:
constants.OSD_WARNING_MESSAGE_DURATION = constants.NO_SECONDARY_OSD_WARNING_DURATION
self.scheduleAskPlayer()
self.__playerReady.callback(player)
def addPlayerReadyCallback(self, lambdaToCall):
self.__playerReady.addCallback(lambdaToCall)
def playerIsNotReady(self):
return self._player is None
def scheduleAskPlayer(self, when=constants.PLAYER_ASK_DELAY):
self._askPlayerTimer = task.LoopingCall(self.askPlayer)
@ -163,34 +178,34 @@ class SyncplayClient(object):
seeked = _playerDiff > constants.SEEK_THRESHOLD and _globalDiff > constants.SEEK_THRESHOLD
return pauseChange, seeked
def rewindFile(self):
self.setPosition(-1)
self.establishRewindDoubleCheck()
def establishRewindDoubleCheck(self):
reactor.callLater(0.5, self.doubleCheckRewindFile,)
reactor.callLater(1, self.doubleCheckRewindFile,)
reactor.callLater(1.5, self.doubleCheckRewindFile,)
def doubleCheckRewindFile(self):
if self.getStoredPlayerPosition() > 5:
self.setPosition(-1)
self.ui.showDebugMessage("Rewinded after double-check")
def updatePlayerStatus(self, paused, position):
position -= self.getUserOffset()
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 not self.userlist.currentUser.canControl():
self._player.setPaused(self._globalPaused)
self.toggleReady(manuallyInitiated=True)
self._playerPaused = self._globalPaused
pauseChange = False
if self.userlist.currentUser.isReady():
self.ui.showMessage(getMessage("set-as-ready-notification"))
else:
self.ui.showMessage(getMessage("set-as-not-ready-notification"))
elif not paused and not self.instaplayConditionsMet():
paused = True
self._player.setPaused(paused)
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:
self.lastPausedOnLeaveTime = None
else:
self.changeReadyState(not self.getPlayerPaused(), manuallyInitiated=False)
currentLength = self.userlist.currentUser.file["duration"] if self.userlist.currentUser.file else 0
if pauseChange and paused and currentLength > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH\
and abs(position - currentLength ) < constants.PLAYLIST_LOAD_NEXT_FILE_TIME_FROM_END_THRESHOLD:
self.playlist.advancePlaylistCheck()
elif pauseChange and utils.meetsMinVersion(self.serverVersion, constants.USER_READY_MIN_VERSION):
if currentLength == 0 or currentLength == -1 or\
not (not self.playlist.notJustChangedPlaylist() and abs(position - currentLength ) < constants.PLAYLIST_LOAD_NEXT_FILE_TIME_FROM_END_THRESHOLD):
pauseChange = self._toggleReady(pauseChange, paused)
if self._lastGlobalUpdate:
self._lastPlayerUpdate = time.time()
if (pauseChange or seeked) and self._protocol:
@ -198,6 +213,31 @@ class SyncplayClient(object):
self.playerPositionBeforeLastSeek = self.getGlobalPosition()
self._protocol.sendState(self.getPlayerPosition(), self.getPlayerPaused(), seeked, None, True)
def _toggleReady(self, pauseChange, paused):
if not self.userlist.currentUser.canControl():
self._player.setPaused(self._globalPaused)
self.toggleReady(manuallyInitiated=True)
self._playerPaused = self._globalPaused
pauseChange = False
if self.userlist.currentUser.isReady():
self.ui.showMessage(getMessage("set-as-ready-notification"))
else:
self.ui.showMessage(getMessage("set-as-not-ready-notification"))
elif not paused and not self.instaplayConditionsMet():
paused = True
self._player.setPaused(paused)
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:
self.lastPausedOnLeaveTime = None
else:
self.changeReadyState(not self.getPlayerPaused(), manuallyInitiated=False)
return pauseChange
def getLocalState(self):
paused = self.getPlayerPaused()
if self._config['dontSlowDownWithMe']:
@ -307,7 +347,8 @@ class SyncplayClient(object):
self.behindFirstDetected = time.time()
else:
durationBehind = time.time() - self.behindFirstDetected
if (durationBehind > (self._config['fastforwardThreshold']-constants.FASTFORWARD_BEHIND_THRESHOLD)) and (diff < (self._config['fastforwardThreshold'] * -1)):
if (durationBehind > (self._config['fastforwardThreshold']-constants.FASTFORWARD_BEHIND_THRESHOLD))\
and (diff < (self._config['fastforwardThreshold'] * -1)):
madeChangeOnPlayer = self._fastforwardPlayerDueToTimeDifference(position, setBy)
self.behindFirstDetected = time.time() + constants.FASTFORWARD_RESET_THRESHOLD
else:
@ -368,6 +409,9 @@ class SyncplayClient(object):
position += diff
return position
def getStoredPlayerPosition(self):
return self._playerPosition if self._playerPosition is not None else None
def getPlayerPaused(self):
if not self._lastPlayerUpdate:
if self._lastGlobalUpdate:
@ -390,6 +434,7 @@ class SyncplayClient(object):
return self._globalPaused
def updateFile(self, filename, duration, path):
newPath = u""
if utils.isURL(path):
filename = path
@ -403,9 +448,54 @@ class SyncplayClient(object):
size = os.path.getsize(path)
except:
size = 0
if not utils.isURL(path) and os.path.exists(path):
self.fileSwitch.notifyUserIfFileNotInMediaDirectory(filename, path)
filename, size = self.__executePrivacySettings(filename, size)
self.userlist.currentUser.setFile(filename, duration, size, path)
self.sendFile()
self.playlist.changeToPlaylistIndexFromFilename(filename)
def setTrustedDomains(self, newTrustedDomains):
from syncplay.ui.ConfigurationGetter import ConfigurationGetter
ConfigurationGetter().setConfigOption("trustedDomains", newTrustedDomains)
self._config['trustedDomains'] = newTrustedDomains
self.fileSwitchFoundFiles()
def isURITrusted(self, URIToTest):
for trustedProtocol in constants.TRUSTABLE_WEB_PROTOCOLS:
if URIToTest.startswith(trustedProtocol):
if self._config['onlySwitchToTrustedDomains']:
if self._config['trustedDomains']:
for trustedDomain in self._config['trustedDomains']:
trustableURI = ''.join([trustedProtocol,trustedDomain,u"/"])
if URIToTest.startswith(trustableURI):
return True
return False
else:
return True
return False
def openFile(self, filePath, resetPosition=False):
self._player.openFile(filePath, resetPosition)
if resetPosition:
self.establishRewindDoubleCheck()
self.lastRewindTime = time.time()
def fileSwitchFoundFiles(self):
self.ui.fileSwitchFoundFiles()
self.playlist.loadCurrentPlaylistIndex()
def setPlaylistIndex(self, index):
self._protocol.setPlaylistIndex(index)
def changeToPlaylistIndex(self, *args, **kwargs):
self.playlist.changeToPlaylistIndex(*args, **kwargs)
def loopSingleFiles(self):
return self._config["loopSingleFiles"]
def isPlaylistLoopingEnabled(self):
return self._config["loopAtEndOfPlaylist"]
def __executePrivacySettings(self, filename, size):
if self._config['filenamePrivacyMode'] == PRIVACY_SENDHASHED_MODE:
@ -442,8 +532,6 @@ class SyncplayClient(object):
if username and username <> "":
self.userlist.currentUser.username = username
else:
import random
random.seed()
random_number = random.randrange(1000, 9999)
self.userlist.currentUser.username = "Anonymous" + str(random_number) # Not localised as this would give away locale
@ -469,6 +557,12 @@ class SyncplayClient(object):
if storedRoomPassword:
self.identifyAsController(storedRoomPassword)
def isConnectedAndInARoom(self):
return self._protocol and self._protocol.logged and self.userlist.currentUser.room
def sharedPlaylistIsEnabled(self):
return self._config['sharedPlaylistEnabled']
def connected(self):
readyState = self._config['readyAtStart'] if self.userlist.currentUser.isReady() is None else self.userlist.currentUser.isReady()
self._protocol.setReady(readyState, manuallyInitiated=False)
@ -493,6 +587,9 @@ class SyncplayClient(object):
def setPosition(self, position):
if self._lastPlayerUpdate:
self._lastPlayerUpdate = time.time()
if self.lastRewindTime is not None and abs(time.time() - self.lastRewindTime) < 1.0 and position > 5:
self.ui.showDebugMessage("Ignored seek to {} after rewind".format(position))
return
position += self.getUserOffset()
if self._player and self.userlist.currentUser.file:
if position < 0:
@ -550,10 +647,18 @@ class SyncplayClient(object):
return wrapper
return requireMinVersionDecorator
def changePlaylistEnabledState(self, newState):
oldState = self.sharedPlaylistIsEnabled()
from syncplay.ui.ConfigurationGetter import ConfigurationGetter
ConfigurationGetter().setConfigOption("sharedPlaylistEnabled", newState)
self._config["sharedPlaylistEnabled"] = newState
if oldState == False and newState == True:
self.playlist.loadCurrentPlaylistIndex()
def changeAutoplayState(self, newState):
self.autoPlay = newState
self.autoplayCheck()
def changeAutoPlayThrehsold(self, newThreshold):
oldAutoplayConditionsMet = self.autoplayConditionsMet()
self.autoPlayThreshold = newThreshold
@ -576,13 +681,16 @@ class SyncplayClient(object):
return True
elif unpauseAction == constants.UNPAUSE_IFOTHERSREADY_MODE and self.userlist.areAllOtherUsersInRoomReady():
return True
elif unpauseAction == constants.UNPAUSE_IFMINUSERSREADY_MODE and self.userlist.areAllOtherUsersInRoomReady() and self.autoPlayThreshold and self.userlist.usersInRoomCount() >= self.autoPlayThreshold:
elif unpauseAction == constants.UNPAUSE_IFMINUSERSREADY_MODE and self.userlist.areAllOtherUsersInRoomReady()\
and self.autoPlayThreshold and self.userlist.usersInRoomCount() >= self.autoPlayThreshold:
return True
else:
return False
def autoplayConditionsMet(self):
return self._playerPaused and self.autoPlay and self.userlist.currentUser.canControl() and self.userlist.isReadinessSupported() and self.userlist.areAllUsersInRoomReady() and self.autoPlayThreshold and self.userlist.usersInRoomCount() >= self.autoPlayThreshold
return self._playerPaused and self.autoPlay and self.userlist.currentUser.canControl() and self.userlist.isReadinessSupported()\
and self.userlist.areAllUsersInRoomReady(requireSameFilenames=self._config["autoplayRequireSameFilenames"])\
and self.autoPlayThreshold and self.userlist.usersInRoomCount() >= self.autoPlayThreshold
def autoplayTimerIsRunning(self):
return self.autoplayTimer.running
@ -601,7 +709,9 @@ class SyncplayClient(object):
if not self.autoplayConditionsMet():
self.stopAutoplayCountdown()
return
countdownMessage = u"{}{}{}".format(getMessage("all-users-ready").format(self.userlist.readyUserCount()),self._player.osdMessageSeparator, getMessage("autoplaying-notification").format(int(self.autoplayTimeLeft)))
allReadyMessage = getMessage("all-users-ready").format(self.userlist.readyUserCount())
autoplayingMessage = getMessage("autoplaying-notification").format(int(self.autoplayTimeLeft))
countdownMessage = u"{}{}{}".format(allReadyMessage,self._player.osdMessageSeparator, autoplayingMessage)
self.ui.showOSDMessage(countdownMessage, 1, secondaryOSD=True)
if self.autoplayTimeLeft <= 0:
self.setPaused(False)
@ -692,9 +802,11 @@ class SyncplayClient(object):
response = json.loads(response)
publicServers = None
if response["public-servers"]:
publicServers = response["public-servers"].replace("&#8221;","'").replace(":&#8217;","'").replace("&#8217;","'").replace("&#8242;","'").replace("\n","").replace("\r","")
publicServers = response["public-servers"].\
replace("&#8221;","'").replace(":&#8217;","'").replace("&#8217;","'").replace("&#8242;","'").replace("\n","").replace("\r","")
publicServers = ast.literal_eval(publicServers)
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, publicServers
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, publicServers
except:
return "failed", getMessage("update-check-failed-notification").format(syncplay.version), constants.SYNCPLAY_DOWNLOAD_URL, None
@ -741,7 +853,7 @@ class SyncplayClient(object):
def _checkIfYouAreOnlyUserInRoomWhoSupportsReadiness(self):
self._userlist._onlyUserInRoomWhoSupportsReadiness()
def _checkIfYouReAloneInTheRoom(self, OSDOnly):
if self._userlist.areYouAloneInRoom():
self._ui.showOSDMessage(getMessage("alone-in-the-room"), constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL, secondaryOSD=True)
@ -779,9 +891,11 @@ class SyncplayClient(object):
fileDifferencesMessage = getMessage("room-file-differences").format(fileDifferencesForRoom)
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").format(self._userlist.readyUserCount()))
allReadyMessage = getMessage("all-users-ready").format(self._userlist.readyUserCount())
osdMessage = u"{}{}{}".format(fileDifferencesMessage, self._client._player.osdMessageSeparator, allReadyMessage)
else:
osdMessage = u"{}{}{}".format(fileDifferencesMessage, self._client._player.osdMessageSeparator, getMessage("not-all-ready").format(self._userlist.usersInRoomNotReady()))
notAllReadyMessage = getMessage("not-all-ready").format(self._userlist.usersInRoomNotReady())
osdMessage = u"{}{}{}".format(fileDifferencesMessage, self._client._player.osdMessageSeparator, notAllReadyMessage)
else:
osdMessage = fileDifferencesMessage
elif self._userlist.isReadinessSupported():
@ -845,9 +959,9 @@ class SyncplayUser(object):
def __repr__(self, *args, **kwargs):
if self.file:
return "{}: {} ({}, {})".format(self.username, self.file['name'], self.file['duration'], self.file['size'])
return u"{}: {} ({}, {})".format(self.username, self.file['name'], self.file['duration'], self.file['size'])
else:
return "{}".format(self.username)
return u"{}".format(self.username)
def setControllerStatus(self, isController):
self._controller = isController
@ -1011,14 +1125,20 @@ class SyncplayUserlist(object):
user = self._users[username]
user.setControllerStatus(True)
def areAllUsersInRoomReady(self):
def areAllUsersInRoomReady(self, requireSameFilenames=False):
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.isReadyWithFile() == False:
return False
if user.room == self.currentUser.room:
if user.isReadyWithFile() == False:
return False
elif requireSameFilenames and\
(self.currentUser.file is None
or user.file is None
or not utils.sameFilename(self.currentUser.file['name'], user.file['name'])):
return False
return True
def areAllOtherUsersInRoomReady(self):
@ -1155,6 +1275,15 @@ class UiManager(object):
self.lastSecondaryOSDEndTime = None
self.lastError = ""
def setPlaylist(self, newPlaylist, newIndexFilename=None):
self.__ui.setPlaylist(newPlaylist, newIndexFilename)
def setPlaylistIndexFilename(self, filename):
self.__ui.setPlaylistIndexFilename(filename)
def fileSwitchFoundFiles(self):
self.__ui.fileSwitchFoundFiles()
def showDebugMessage(self, message):
if constants.DEBUG_MODE and message.rstrip():
sys.stderr.write("{}{}\n".format(time.strftime(constants.UI_TIME_FORMAT, time.localtime()),message.rstrip()))
@ -1215,4 +1344,422 @@ class UiManager(object):
def drop(self):
self.__ui.drop()
class SyncplayPlaylist():
def __init__(self, client):
self._client = client
self._ui = self._client.ui
self._previousPlaylist = None
self._previousPlaylistRoom = None
self._playlist = []
self._playlistIndex = None
self.addedChangeListCallback = False
self._lastPlaylistIndexChange = time.time()
def needsSharedPlaylistsEnabled(f): # @NoSelf
@wraps(f)
def wrapper(self, *args, **kwds):
if not self._client.sharedPlaylistIsEnabled():
self._ui.showDebugMessage(u"Tried to use shared playlists when it was disabled!")
return
return f(self, *args, **kwds)
return wrapper
def changeToPlaylistIndexFromFilename(self, filename):
try:
index = self._playlist.index(filename)
if index <> self._playlistIndex:
self.changeToPlaylistIndex(index)
except ValueError:
pass
def changeToPlaylistIndex(self, index, username = None):
if self._playlist is None or len(self._playlist) == 0:
return
if index is None:
return
if username is None and not self._client.sharedPlaylistIsEnabled():
return
self._lastPlaylistIndexChange = time.time()
if self._client.playerIsNotReady():
if not self.addedChangeListCallback:
self.addedChangeListCallback = True
self._client.addPlayerReadyCallback(lambda x: self.changeToPlaylistIndex(index, username))
return
try:
filename = self._playlist[index]
self._ui.setPlaylistIndexFilename(filename)
if not self._client.sharedPlaylistIsEnabled():
self._playlistIndex = index
if username is not None and self._client.userlist.currentUser.file and filename == self._client.userlist.currentUser.file['name']:
return
except IndexError:
pass
self._playlistIndex = index
if username is None:
if self._client.isConnectedAndInARoom() and self._client.sharedPlaylistIsEnabled():
self._client.setPlaylistIndex(index)
else:
self._ui.showMessage(getMessage("playlist-selection-changed-notification").format(username))
self.switchToNewPlaylistIndex(index)
@needsSharedPlaylistsEnabled
def switchToNewPlaylistIndex(self, index, resetPosition=False):
self._lastPlaylistIndexChange = time.time()
if self._client.playerIsNotReady():
self._client.addPlayerReadyCallback(lambda x: self.switchToNewPlaylistIndex(index, resetPosition))
return
try:
if index is None:
self._ui.showDebugMessage(u"Cannot switch to None index in playlist")
return
filename = self._playlist[index]
# TODO: Handle isse with index being None
if utils.isURL(filename):
if self._client.isURITrusted(filename):
self._client.openFile(filename, resetPosition=resetPosition)
else:
self._ui.showErrorMessage(getMessage("cannot-add-unsafe-path-error").format(filename))
return
else:
path = self._client.fileSwitch.findFilepath(filename, highPriority=True)
if path:
self._client.openFile(path, resetPosition)
else:
self._ui.showErrorMessage(getMessage("cannot-find-file-for-playlist-switch-error").format(filename))
return
except IndexError:
self._ui.showDebugMessage("Could not change playlist index due to IndexError")
def _getValidIndexFromNewPlaylist(self, newPlaylist=None):
if self._playlistIndex is None or not newPlaylist or len(newPlaylist) <= 1:
return 0
i = self._playlistIndex
while i <= len(self._playlist):
try:
filename = self._playlist[i]
validIndex = newPlaylist.index(filename)
return validIndex
except:
i += 1
i = self._playlistIndex
while i > 0:
try:
filename = self._playlist[i]
validIndex = newPlaylist.index(filename)
return validIndex+1 if validIndex < len(newPlaylist)-1 else validIndex
except:
i -= 1
return 0
def _getFilenameFromIndexInGivenPlaylist(self, _playlist, _index):
if not _index or not _playlist:
return None
filename = _playlist[_index] if len(_playlist) > _index else None
return filename
def changePlaylist(self, files, username = None, resetIndex=False):
if self._playlist == files:
if self._playlistIndex <> 0 and resetIndex:
self.changeToPlaylistIndex(0)
return
if resetIndex:
newIndex = 0
filename = files[0] if files and len(files) > 0 else None
else:
newIndex = self._getValidIndexFromNewPlaylist(files)
filename = self._getFilenameFromIndexInGivenPlaylist(files, newIndex)
self._updateUndoPlaylistBuffer(newPlaylist=files, newRoom=self._client.userlist.currentUser.room)
self._playlist = files
if username is None:
if self._client.isConnectedAndInARoom() and self._client.sharedPlaylistIsEnabled():
self._client._protocol.setPlaylist(files)
self.changeToPlaylistIndex(newIndex)
self._ui.setPlaylist(self._playlist, filename)
self._ui.showMessage(getMessage("playlist-contents-changed-notification").format(self._client.getUsername()))
else:
self._ui.setPlaylist(self._playlist)
self._ui.showMessage(getMessage("playlist-contents-changed-notification").format(username))
@needsSharedPlaylistsEnabled
def undoPlaylistChange(self):
if self.canUndoPlaylist(self._playlist):
newPlaylist = self._getPreviousPlaylist()
self.changePlaylist(newPlaylist, username=None)
@needsSharedPlaylistsEnabled
def shufflePlaylist(self):
if self._playlist and len(self._playlist) > 0:
shuffledPlaylist = deepcopy(self._playlist)
random.shuffle(shuffledPlaylist)
self.changePlaylist(shuffledPlaylist, username=None, resetIndex=True)
def canUndoPlaylist(self, currentPlaylist):
return self._previousPlaylist is not None and currentPlaylist <> self._previousPlaylist
def loadCurrentPlaylistIndex(self):
if self._notPlayingCurrentIndex():
self.switchToNewPlaylistIndex(self._playlistIndex)
@needsSharedPlaylistsEnabled
def advancePlaylistCheck(self):
position = self._client.getStoredPlayerPosition()
currentLength = self._client.userlist.currentUser.file["duration"] if self._client.userlist.currentUser.file else 0
if currentLength > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH\
and abs(position - currentLength ) < constants.PLAYLIST_LOAD_NEXT_FILE_TIME_FROM_END_THRESHOLD\
and self.notJustChangedPlaylist():
self.loadNextFileInPlaylist()
def notJustChangedPlaylist(self):
secondsSinceLastChange = time.time() - self._lastPlaylistIndexChange
return secondsSinceLastChange > constants.PLAYLIST_LOAD_NEXT_FILE_TIME_FROM_END_THRESHOLD
@needsSharedPlaylistsEnabled
def loadNextFileInPlaylist(self):
if self._notPlayingCurrentIndex():
return
if len(self._playlist) == 1 and self._client.loopSingleFiles():
self._client.rewindFile()
self._client.setPaused(False)
reactor.callLater(0.5, self._client.setPaused, False,)
elif self._thereIsNextPlaylistIndex():
self.switchToNewPlaylistIndex(self._nextPlaylistIndex(), resetPosition=True)
def _updateUndoPlaylistBuffer(self, newPlaylist, newRoom):
if self._playlistBufferIsFromOldRoom(newRoom):
self._movePlaylistBufferToNewRoom(newRoom)
elif self._playlistBufferNeedsUpdating(newPlaylist):
self._previousPlaylist = self._playlist
def _getPreviousPlaylist(self):
return self._previousPlaylist
def _notPlayingCurrentIndex(self):
if self._playlistIndex is None or self._playlist is None or len(self._playlist) <= self._playlistIndex:
self._ui.showDebugMessage(u"Not playing current index - Index none or length issue")
return True
currentPlaylistFilename = self._playlist[self._playlistIndex]
if self._client.userlist.currentUser.file and currentPlaylistFilename == self._client.userlist.currentUser.file['name']:
return False
else:
self._ui.showDebugMessage(u"Not playing current index - Filename mismatch or no file")
return True
def _thereIsNextPlaylistIndex(self):
if self._playlistIndex is None:
return False
elif len(self._playlist) == 1 and not self._client.loopSingleFiles():
return False
elif self._playlistIsAtEnd():
return self._client.isPlaylistLoopingEnabled()
else:
return True
def _nextPlaylistIndex(self):
if self._playlistIsAtEnd():
return 0
else:
return self._playlistIndex+1
def _playlistIsAtEnd(self):
return len(self._playlist) <= self._playlistIndex+1
def _playlistBufferIsFromOldRoom(self, newRoom):
return self._previousPlaylistRoom <> newRoom
def _movePlaylistBufferToNewRoom(self, currentRoom):
self._previousPlaylist = None
self._previousPlaylistRoom = currentRoom
def _playlistBufferNeedsUpdating(self, newPlaylist):
return self._previousPlaylist <> self._playlist and self._playlist <> newPlaylist
class FileSwitchManager(object):
def __init__(self, client):
self._client = client
self.mediaFilesCache = {}
self.filenameWatchlist = []
self.currentDirectory = None
self.mediaDirectories = None
self.lock = threading.Lock()
self.folderSearchEnabled = True
self.directorySearchError = None
self.newInfo = False
self.currentlyUpdating = False
self.newWatchlist = []
self.fileSwitchTimer = task.LoopingCall(self.updateInfo)
self.fileSwitchTimer.start(constants.FOLDER_SEARCH_DOUBLE_CHECK_INTERVAL, True)
self.mediaDirectoriesNotFound = []
def setClient(self, newClient):
self.client = newClient
def setCurrentDirectory(self, curDir):
self.currentDirectory = curDir
def changeMediaDirectories(self, mediaDirs):
from syncplay.ui.ConfigurationGetter import ConfigurationGetter
ConfigurationGetter().setConfigOption("mediaSearchDirectories", mediaDirs)
self._client._config["mediaSearchDirectories"] = mediaDirs
self._client.ui.showMessage(getMessage("media-directory-list-updated-notification"))
self.mediaDirectoriesNotFound = []
self.folderSearchEnabled = True
self.setMediaDirectories(mediaDirs)
if mediaDirs == "":
self._client.ui.showErrorMessage(getMessage("no-media-directories-error"))
self.mediaFilesCache = {}
self.newInfo = True
self.checkForFileSwitchUpdate()
def setMediaDirectories(self, mediaDirs):
self.mediaDirectories = mediaDirs
self.updateInfo()
def checkForFileSwitchUpdate(self):
if self.newInfo:
self.newInfo = False
self.infoUpdated()
if self.directorySearchError:
self._client.ui.showErrorMessage(self.directorySearchError)
self.directorySearchError = None
def updateInfo(self):
if not self.currentlyUpdating and self.mediaDirectories:
threads.deferToThread(self._updateInfoThread).addCallback(lambda x: self.checkForFileSwitchUpdate())
def setFilenameWatchlist(self, unfoundFilenames):
self.filenameWatchlist = unfoundFilenames
def _updateInfoThread(self):
with self.lock:
try:
self.currentlyUpdating = True
dirsToSearch = self.mediaDirectories
if dirsToSearch:
# Spin up hard drives to prevent premature timeout
randomFilename = u"RandomFile"+unicode(random.randrange(10000, 99999))+u".txt"
for directory in dirsToSearch:
if not os.path.isdir(directory):
self.directorySearchError = getMessage("cannot-find-directory-error").format(directory)
startTime = time.time()
if os.path.isfile(os.path.join(directory, randomFilename)):
randomFilename = u"RandomFile"+unicode(random.randrange(10000, 99999))+u".txt"
if time.time() - startTime > constants.FOLDER_SEARCH_FIRST_FILE_TIMEOUT:
self.folderSearchEnabled = False
self.directorySearchError = getMessage("folder-search-first-file-timeout-error").format(directory)
return
# Actual directory search
newMediaFilesCache = {}
startTime = time.time()
for directory in dirsToSearch:
for root, dirs, files in os.walk(directory):
newMediaFilesCache[root] = files
if time.time() - startTime > constants.FOLDER_SEARCH_TIMEOUT:
self.directorySearchError = getMessage("folder-search-timeout-error").format(directory)
self.folderSearchEnabled = False
return
if self.mediaFilesCache <> newMediaFilesCache:
self.mediaFilesCache = newMediaFilesCache
self.newInfo = True
finally:
self.currentlyUpdating = False
def infoUpdated(self):
self._client.fileSwitchFoundFiles()
def findFilepath(self, filename, highPriority=False):
if filename is None:
return
if self.mediaFilesCache is not None:
for directory in self.mediaFilesCache:
files = self.mediaFilesCache[directory]
if len(files) > 0 and filename in files:
filepath = os.path.join(directory, filename)
if os.path.isfile(filepath):
return filepath
if highPriority and self.folderSearchEnabled:
directoryList = self.mediaDirectories
# Spin up hard drives to prevent premature timeout
randomFilename = u"RandomFile"+unicode(random.randrange(10000, 99999))+u".txt"
for directory in directoryList:
startTime = time.time()
if os.path.isfile(os.path.join(directory, randomFilename)):
randomFilename = u"RandomFile"+unicode(random.randrange(10000, 99999))+u".txt"
if not self.folderSearchEnabled:
return
if time.time() - startTime > constants.FOLDER_SEARCH_FIRST_FILE_TIMEOUT:
return
startTime = time.time()
if filename and directoryList:
for directory in directoryList:
for root, dirs, files in os.walk(directory):
if filename in files:
return os.path.join(root,filename)
if time.time() - startTime > constants.FOLDER_SEARCH_TIMEOUT:
self.folderSearchEnabled = False
self.directorySearchError = getMessage("folder-search-timeout-error").format(directory)
return None
return None
def areWatchedFilenamesInCache(self):
if self.filenameWatchlist is not None:
for filename in self.filenameWatchlist:
if self.isFilenameInCache(filename):
return True
def isFilenameInCache(self, filename):
if filename is not None and self.mediaFilesCache is not None:
for directory in self.mediaFilesCache:
files = self.mediaFilesCache[directory]
if filename in files:
return True
def getDirectoryOfFilenameInCache(self, filename):
if filename is not None and self.mediaFilesCache is not None:
for directory in self.mediaFilesCache:
files = self.mediaFilesCache[directory]
if filename in files:
return directory
return None
def isDirectoryInList(self, directoryToFind, folderList):
if directoryToFind and folderList:
normedDirectoryToFind = os.path.normcase(os.path.normpath(directoryToFind))
for listedFolder in folderList:
normedListedFolder = os.path.normcase(os.path.normpath(listedFolder))
if normedDirectoryToFind.startswith(normedListedFolder):
return True
return False
def notifyUserIfFileNotInMediaDirectory(self, filenameToFind, path):
directoryToFind = os.path.dirname(path)
if directoryToFind in self.mediaDirectoriesNotFound:
return
if self.mediaDirectories is not None and self.mediaFilesCache is not None:
if directoryToFind in self.mediaFilesCache:
return
for directory in self.mediaFilesCache:
files = self.mediaFilesCache[directory]
if filenameToFind in files:
return
if directoryToFind in self.mediaFilesCache:
return
if self.isDirectoryInList(directoryToFind, self.mediaDirectories):
return
self._client.ui.showErrorMessage(getMessage("added-file-not-in-media-directory-error").format(directoryToFind))
self.mediaDirectoriesNotFound.append(directoryToFind)

View File

@ -17,6 +17,8 @@ SHOW_TOOLTIPS = True
WARN_ABOUT_MISSING_STRINGS = False # (If debug mode is enabled)
FALLBACK_INITIAL_LANGUAGE = "en"
FALLBACK_PUBLIC_SYNCPLAY_SERVERS = [[u'syncplay.pl:8995 (France)', u'syncplay.pl:8995'],[u'syncplay.pl:8996 (France)', u'syncplay.pl:8996'],[u'syncplay.pl:8997 (France)', u'syncplay.pl:8997'],[u'syncplay.pl:8998 (France)', u'syncplay.pl:8998'],[u'syncplay.pl:8999 (France)', u'syncplay.pl:8999']]
PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH = 10 # Seconds
PLAYLIST_LOAD_NEXT_FILE_TIME_FROM_END_THRESHOLD = 5 # Seconds (only triggered if file is paused, e.g. due to EOF)
#Overriden by config
SHOW_OSD = True # Sends Syncplay messages to media player OSD
@ -51,8 +53,9 @@ AUTOPLAY_DELAY = 3.0
SYNC_ON_PAUSE = True # Client seek to global position - subtitles may disappear on some media players
# 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)
FOLDER_SEARCH_DOUBLE_CHECK_INTERVAL = 120.0 # Secs - Frequency of updating cache when someone is playing a file not in current cache
FOLDER_SEARCH_FIRST_FILE_TIMEOUT = 10.0 # Secs - How long to wait to find the first file in folder search (to take account of HDD spin up)
FOLDER_SEARCH_TIMEOUT = 3.0 # Secs - How long to wait until searches in folder to update cache are aborted (after first file is found)
FOLDER_SEARCH_DOUBLE_CHECK_INTERVAL = 30.0 # Secs - Frequency of updating cache when someone is playing a file not in current cache
#Usually there's no need to adjust these
LAST_PAUSED_DIFF_THRESHOLD = 2
@ -69,7 +72,7 @@ COMMANDS_AUTH = ['a','auth']
COMMANDS_TOGGLE = ['t','toggle']
MPC_MIN_VER = "1.6.4"
VLC_MIN_VERSION = "2.2.1"
VLC_INTERFACE_MIN_VERSION = "0.2.8"
VLC_INTERFACE_MIN_VERSION = "0.2.9"
VLC_LATENCY_ERROR_THRESHOLD = 2.0
MPV_UNRESPONSIVE_THRESHOLD = 60.0
CONTROLLED_ROOMS_MIN_VERSION = "1.3.0"
@ -107,6 +110,8 @@ MPV_ICONPATH = "mpv.png"
MPC_ICONPATH = "mpc-hc.png"
MPC64_ICONPATH = "mpc-hc64.png"
MPV_ERROR_MESSAGES_TO_REPEAT = ['[ytdl_hook] Your version of youtube-dl is too old', '[ytdl_hook] youtube-dl failed', 'Failed to recognize file format.']
#Changing these is usually not something you're looking for
PLAYER_ASK_DELAY = 0.1
PING_MOVING_AVERAGE_WEIGHT = 0.85
@ -116,7 +121,10 @@ MPC_RETRY_WAIT_TIME = 0.01
MPC_MAX_RETRIES = 30
MPC_PAUSE_TOGGLE_DELAY = 0.05
MPV_NEWFILE_IGNORE_TIME = 1
MPV_LOCK_WAIT_TIME = 0.2
MPV_SENDMESSAGE_COOLDOWN_TIME = 0.05
MPV_MAX_NEWFILE_COOLDOWN_TIME = 3
STREAM_ADDITIONAL_IGNORE_TIME = 10
MPV_LOCK_WAIT_TIME = 0.05
VLC_OPEN_MAX_WAIT_TIME = 15
VLC_MIN_PORT = 10000
VLC_MAX_PORT = 55000
@ -136,6 +144,7 @@ STYLE_ERRORNOTIFICATION = "color: red;"
STYLE_DIFFERENTITEM_COLOR = 'red'
STYLE_NOFILEITEM_COLOR = 'blue'
STYLE_NOTCONTROLLER_COLOR = 'grey'
STYLE_UNTRUSTEDITEM_COLOR = 'purple'
USERLIST_GUI_USERNAME_OFFSET = 21 # Pixels
USERLIST_GUI_USERNAME_COLUMN = 0
@ -149,6 +158,8 @@ MPV_NEW_VERSION = False
VLC_SLAVE_ARGS = ['--extraintf=luaintf', '--lua-intf=syncplay', '--no-quiet', '--no-input-fast-seek',
'--play-and-pause', '--start-time=0']
VLC_SLAVE_NONOSX_ARGS = ['--no-one-instance', '--no-one-instance-when-started-from-file']
MPV_SUPERSEDE_IF_DUPLICATE_COMMANDS = ["no-osd set time-pos ", "loadfile "]
MPV_REMOVE_BOTH_IF_DUPLICATE_COMMANDS = ["cycle pause"]
MPLAYER_ANSWER_REGEX = "^ANS_([a-zA-Z_-]+)=(.+)$|^(Exiting)\.\.\. \((.+)\)$"
VLC_ANSWER_REGEX = r"(?:^(?P<command>[a-zA-Z_]+)(?:\: )?(?P<argument>.*))"
UI_COMMAND_REGEX = r"^(?P<command>[^\ ]+)(?:\ (?P<parameter>.+))?"
@ -176,9 +187,13 @@ FILEITEM_SWITCH_ROLE = 1
FILEITEM_SWITCH_NO_SWITCH = 0
FILEITEM_SWITCH_FILE_SWITCH = 1
FILEITEM_SWITCH_STREAM_SWITCH = 2
PLAYLISTITEM_CURRENTLYPLAYING_ROLE = 3
SYNCPLAY_UPDATE_URL = u"http://syncplay.pl/checkforupdate?{}" # Params
SYNCPLAY_DOWNLOAD_URL = "http://syncplay.pl/download/"
SYNCPLAY_PUBLIC_SERVER_LIST_URL = u"http://syncplay.pl/listpublicservers?{}" # Params
PRIVATE_FILE_FIELDS = ["path"]
DEFAULT_TRUSTED_DOMAINS = [u"youtube.com",u"youtu.be"]
TRUSTABLE_WEB_PROTOCOLS = [u"http://www.",u"https://www.",u"http://",u"https://"]
PRIVATE_FILE_FIELDS = ["path"]

View File

@ -1,5 +1,6 @@
# coding:utf8
from syncplay import constants
import messages_en
import messages_ru
import messages_de

View File

@ -3,370 +3,408 @@
"""Deutsch dictionary"""
de = {
"LANGUAGE" : u"Deutsch", # (German)
"LANGUAGE" : u"Deutsch", # (German)
# Client notifications
"config-cleared-notification" : u"Einstellungen gelöscht. Änderungen werden gespeichert, wenn du eine gültige Konfiguration speicherst.",
# Client notifications
"config-cleared-notification" : u"Einstellungen gelöscht. Änderungen werden gespeichert, wenn du eine gültige Konfiguration speicherst.",
"relative-config-notification" : u"Relative Konfigurationsdatei(en) geladen: {}",
"relative-config-notification" : u"Relative Konfigurationsdatei(en) geladen: {}",
"connection-attempt-notification" : u"Verbinde mit {}:{}", # Port, IP
"reconnection-attempt-notification" : u"Verbindung zum Server verloren, versuche erneut",
"disconnection-notification" : u"Verbindung zum Server beendet",
"connection-failed-notification" : u"Verbindung zum Server fehlgeschlagen",
"connected-successful-notification" : u"Erfolgreich mit Server verbunden",
"retrying-notification" : u"%s, versuche erneut in %d Sekunden...", # Seconds
"connection-attempt-notification" : u"Verbinde mit {}:{}", # Port, IP
"reconnection-attempt-notification" : u"Verbindung zum Server verloren, versuche erneut",
"disconnection-notification" : u"Verbindung zum Server beendet",
"connection-failed-notification" : u"Verbindung zum Server fehlgeschlagen",
"connected-successful-notification" : u"Erfolgreich mit Server verbunden",
"retrying-notification" : u"%s, versuche erneut in %d Sekunden...", # Seconds
"rewind-notification" : u"Zurückgespult wegen Zeitdifferenz mit <{}>", # User
"fastforward-notification" : u"Vorgespult wegen Zeitdifferenz mit <{}>", # User
"slowdown-notification" : u"Verlangsamt wegen Zeitdifferenz mit <{}>", # User
"revert-notification" : u"Normalgeschwindigkeit",
"rewind-notification" : u"Zurückgespult wegen Zeitdifferenz mit <{}>", # User
"fastforward-notification" : u"Vorgespult wegen Zeitdifferenz mit <{}>", # User
"slowdown-notification" : u"Verlangsamt wegen Zeitdifferenz mit <{}>", # User
"revert-notification" : u"Normalgeschwindigkeit",
"pause-notification" : u"<{}> pausierte", # User
"unpause-notification" : u"<{}> startete", # User
"seek-notification" : u"<{}> sprang von {} nach {}", # User, from time, to time
"pause-notification" : u"<{}> pausierte", # User
"unpause-notification" : u"<{}> startete", # User
"seek-notification" : u"<{}> sprang von {} nach {}", # User, from time, to time
"current-offset-notification" : u"Aktueller Offset: {} Sekunden", # Offset
"current-offset-notification" : u"Aktueller Offset: {} Sekunden", # Offset
"room-join-notification" : u"<{}> hat den Raum '{}' betreten", # User
"left-notification" : u"<{}> ist gegangen", # User
"left-paused-notification" : u"<{}> ist gegangen, <{}> pausierte", # User who left, User who paused
"playing-notification" : u"<{}> spielt '{}' ({})", # User, file, duration
"playing-notification/room-addendum" : u" in Raum: '{}'", # Room
"media-directory-list-updated-notification" : u"Syncplay media directories have been updated.", # TODO: Translate
"not-all-ready" : u"Noch nicht bereit: {}", # Usernames
"all-users-ready" : u"Alle sind bereit ({} Nutzer)", #Number of ready users
"ready-to-unpause-notification" : u"Du bist bereit - noch einmal fortsetzen klicken zum abspielen",
"set-as-ready-notification" : u"Du bist bereit",
"set-as-not-ready-notification" : u"Du bist nicht bereit",
"autoplaying-notification" : u"Starte in {}...", # Number of seconds until playback will start
"room-join-notification" : u"<{}> hat den Raum '{}' betreten", # User
"left-notification" : u"<{}> ist gegangen", # User
"left-paused-notification" : u"<{}> ist gegangen, <{}> pausierte", # User who left, User who paused
"playing-notification" : u"<{}> spielt '{}' ({})", # User, file, duration
"playing-notification/room-addendum" : u" in Raum: '{}'", # Room
"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"Gesteuerten Raum '{}' mit Passwort '{}' erstellt. Bitte diese Informationen für die Zukunft aufheben!", # RoomName, operatorPassword
"not-all-ready" : u"Noch nicht bereit: {}", # Usernames
"all-users-ready" : u"Alle sind bereit ({} Nutzer)", #Number of ready users
"ready-to-unpause-notification" : u"Du bist bereit - noch einmal fortsetzen klicken zum abspielen",
"set-as-ready-notification" : u"Du bist bereit",
"set-as-not-ready-notification" : u"Du bist nicht bereit",
"autoplaying-notification" : u"Starte in {}...", # Number of seconds until playback will start
"file-different-notification" : u"Deine Datei scheint sich von <{}>s zu unterscheiden", # User
"file-differences-notification" : u"Deine Datei unterscheidet sich auf folgende Art: {}",
"room-file-differences" : u"Unterschiedlich in: {}", # File differences (filename, size, and/or duration)
"file-difference-filename" : u"Name",
"file-difference-filesize" : u"Größe",
"file-difference-duration" : u"Dauer",
"alone-in-the-room": u"Du bist alleine im Raum",
"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"Gesteuerten Raum '{}' mit Passwort '{}' erstellt. Bitte diese Informationen für die Zukunft aufheben!", # RoomName, operatorPassword
"different-filesize-notification" : u" (ihre Dateigröße ist anders als deine!)",
"userlist-playing-notification" : u"{} spielt:", #Username
"file-played-by-notification" : u"Datei: {} wird gespielt von:", # File
"no-file-played-notification" : u"{} spielt keine Datei ab", # Username
"notplaying-notification" : u"Personen im Raum, die keine Dateien spielen:",
"userlist-room-notification" : u"In Raum '{}':", # Room
"userlist-file-notification" : u"Datei",
"controller-userlist-userflag" : u"Raumleiter",
"ready-userlist-userflag" : u"Bereit",
"file-different-notification" : u"Deine Datei scheint sich von <{}>s zu unterscheiden", # User
"file-differences-notification" : u"Deine Datei unterscheidet sich auf folgende Art: {}",
"room-file-differences" : u"Unterschiedlich in: {}", # File differences (filename, size, and/or duration)
"file-difference-filename" : u"Name",
"file-difference-filesize" : u"Größe",
"file-difference-duration" : u"Dauer",
"alone-in-the-room": u"Du bist alleine im Raum",
"update-check-failed-notification" : u"Konnte nicht automatisch prüfen, ob Syncplay {} aktuell ist. Soll http://syncplay.pl/ geöffnet werden, um manuell nach Updates zu suchen?", #Syncplay version
"syncplay-uptodate-notification" : u"Syncplay ist aktuell",
"syncplay-updateavailable-notification" : u"Eine neuere Version von Syncplay ist verfügbar. Soll die Download-Seite geöffnet werden?",
"different-filesize-notification" : u" (ihre Dateigröße ist anders als deine!)",
"userlist-playing-notification" : u"{} spielt:", #Username
"file-played-by-notification" : u"Datei: {} wird gespielt von:", # File
"no-file-played-notification" : u"{} spielt keine Datei ab", # Username
"notplaying-notification" : u"Personen im Raum, die keine Dateien spielen:",
"userlist-room-notification" : u"In Raum '{}':", # Room
"userlist-file-notification" : u"Datei",
"controller-userlist-userflag" : u"Raumleiter",
"ready-userlist-userflag" : u"Bereit",
"mplayer-file-required-notification" : u"Syncplay für mplayer benötigt eine Dateiangabe beim Start",
"mplayer-file-required-notification/example" : u"Anwendungsbeispiel: syncplay [optionen] [url|pfad/]Dateiname",
"mplayer2-required" : u"Syncplay ist inkompatibel zu MPlayer 1.x, bitte nutze MPlayer2 oder mpv",
"update-check-failed-notification" : u"Konnte nicht automatisch prüfen, ob Syncplay {} aktuell ist. Soll http://syncplay.pl/ geöffnet werden, um manuell nach Updates zu suchen?", #Syncplay version
"syncplay-uptodate-notification" : u"Syncplay ist aktuell",
"syncplay-updateavailable-notification" : u"Eine neuere Version von Syncplay ist verfügbar. Soll die Download-Seite geöffnet werden?",
"unrecognized-command-notification" : u"Unbekannter Befehl",
"commandlist-notification" : u"Verfügbare Befehle:",
"commandlist-notification/room" : u"\tr [Name] - Raum ändern",
"commandlist-notification/list" : u"\tl - Nutzerliste anzeigen",
"commandlist-notification/undo" : u"\tu - Letzter Zeitsprung rückgängig",
"commandlist-notification/pause" : u"\tp - Pausieren / weiter",
"commandlist-notification/seek" : u"\t[s][+-]Zeit - zu einer bestimmten Zeit spulen, ohne + oder - wird als absolute Zeit gewertet; Angabe in Sekunden oder Minuten:Sekunden",
"commandlist-notification/help" : u"\th - Diese Hilfe",
"commandlist-notification/toggle" : u"\tt - Bereitschaftsanzeige umschalten",
"commandlist-notification/create" : u"\tc [name] - erstelle zentral gesteuerten Raum mit dem aktuellen Raumnamen",
"commandlist-notification/auth" : u"\ta [password] - authentifiziere als Raumleiter mit Passwort",
"syncplay-version-notification" : u"Syncplay Version: {}", # syncplay.version
"more-info-notification" : u"Weitere Informationen auf: {}", # projectURL
"mplayer-file-required-notification" : u"Syncplay für mplayer benötigt eine Dateiangabe beim Start",
"mplayer-file-required-notification/example" : u"Anwendungsbeispiel: syncplay [optionen] [url|pfad/]Dateiname",
"mplayer2-required" : u"Syncplay ist inkompatibel zu MPlayer 1.x, bitte nutze MPlayer2 oder mpv",
"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"Soll Syncplay regelmäßig nach Updates suchen?",
"unrecognized-command-notification" : u"Unbekannter Befehl",
"commandlist-notification" : u"Verfügbare Befehle:",
"commandlist-notification/room" : u"\tr [Name] - Raum ändern",
"commandlist-notification/list" : u"\tl - Nutzerliste anzeigen",
"commandlist-notification/undo" : u"\tu - Letzter Zeitsprung rückgängig",
"commandlist-notification/pause" : u"\tp - Pausieren / weiter",
"commandlist-notification/seek" : u"\t[s][+-]Zeit - zu einer bestimmten Zeit spulen, ohne + oder - wird als absolute Zeit gewertet; Angabe in Sekunden oder Minuten:Sekunden",
"commandlist-notification/help" : u"\th - Diese Hilfe",
"commandlist-notification/toggle" : u"\tt - Bereitschaftsanzeige umschalten",
"commandlist-notification/create" : u"\tc [name] - erstelle zentral gesteuerten Raum mit dem aktuellen Raumnamen",
"commandlist-notification/auth" : u"\ta [password] - authentifiziere als Raumleiter mit Passwort",
"syncplay-version-notification" : u"Syncplay Version: {}", # syncplay.version
"more-info-notification" : u"Weitere Informationen auf: {}", # projectURL
"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
"vlc-interface-oldversion-warning": u"Warnung: Es ist eine alte Version des Syncplay Interface-Moduls für VLC im VLC-Verzeichnis installiert. In der Syncplay-Anleitung unter http://syncplay.pl/guide/ [Englisch] findest du Details zur Installation des syncplay.lua-Skripts.",
"vlc-interface-not-installed": u"Warnung: Es wurde kein Syncplay Interface-Modul für VLC im VLC-Verzeichnis gefunden. Daher wird, wenn du VLC 2.0 nutzt, die syncplay.lua die mit Syncplay mitgeliefert wurde, verwendet. Dies bedeutet allerdings, dass keine anderen Interface-Skripts und Erweiterungen geladen werden. In der Syncplay-Anleitung unter http://syncplay.pl/guide/ [Englisch] findest du Details zur Installation des syncplay.lua-Skripts.",
"media-player-latency-warning": u"Warnung: Der Mediaplayer brauchte {} Sekunden zum Antworten. Wenn Probleme bei der Synchronisation auftreten, schließe bitte andere Anwendungen, um Ressourcen freizugeben. Sollte das nicht funktionieren, versuche es mit einem anderen Media-Player.", # Seconds to respond
"mpv-unresponsive-error": u"MPV hat für {} Sekunden nicht geantwortet und scheint abgestürzt zu sein. Bitte starte Syncplay neu.", # Seconds to respond
"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"Soll Syncplay regelmäßig nach Updates suchen?",
# Client prompts
"enter-to-exit-prompt" : u"Enter drücken zum Beenden\n",
"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
"vlc-interface-oldversion-warning": u"Warnung: Es ist eine alte Version des Syncplay Interface-Moduls für VLC im VLC-Verzeichnis installiert. In der Syncplay-Anleitung unter http://syncplay.pl/guide/ [Englisch] findest du Details zur Installation des syncplay.lua-Skripts.",
"vlc-interface-not-installed": u"Warnung: Es wurde kein Syncplay Interface-Modul für VLC im VLC-Verzeichnis gefunden. Daher wird, wenn du VLC 2.0 nutzt, die syncplay.lua die mit Syncplay mitgeliefert wurde, verwendet. Dies bedeutet allerdings, dass keine anderen Interface-Skripts und Erweiterungen geladen werden. In der Syncplay-Anleitung unter http://syncplay.pl/guide/ [Englisch] findest du Details zur Installation des syncplay.lua-Skripts.",
"media-player-latency-warning": u"Warnung: Der Mediaplayer brauchte {} Sekunden zum Antworten. Wenn Probleme bei der Synchronisation auftreten, schließe bitte andere Anwendungen, um Ressourcen freizugeben. Sollte das nicht funktionieren, versuche es mit einem anderen Media-Player.", # Seconds to respond
"mpv-unresponsive-error": u"MPV hat für {} Sekunden nicht geantwortet und scheint abgestürzt zu sein. Bitte starte Syncplay neu.", # Seconds to respond
# Client errors
"missing-arguments-error" : u"Notwendige Argumente fehlen, siehe --help",
"server-timeout-error" : u"Timeout: Verbindung zum Server fehlgeschlagen",
"mpc-slave-error" : u"Kann MPC nicht im Slave-Modus starten!",
"mpc-version-insufficient-error" : u"MPC-Version nicht ausreichend, bitte nutze `mpc-hc` >= `{}`",
"mpv-version-error" : u"Syncplay ist nicht kompatibel mit dieser Version von mpv. Bitte benutze eine andere Version (z.B. Git HEAD).",
"player-file-open-error" : u"Fehler beim Öffnen der Datei durch den Player",
"player-path-error" : u"Ungültiger Player-Pfad",
"hostname-empty-error" : u"Hostname darf nicht leer sein",
"empty-error" : u"{} darf nicht leer sein", # Configuration
"media-player-error": u"Player-Fehler: \"{}\"", # Error line
"unable-import-gui-error": u"Konnte die GUI-Bibliotheken nicht importieren. PySide muss installiert sein, damit die grafische Oberfläche funktioniert.",
# Client prompts
"enter-to-exit-prompt" : u"Enter drücken zum Beenden\n",
"arguments-missing-error" : u"Notwendige Argumente fehlen, siehe --help",
# Client errors
"missing-arguments-error" : u"Notwendige Argumente fehlen, siehe --help",
"server-timeout-error" : u"Timeout: Verbindung zum Server fehlgeschlagen",
"mpc-slave-error" : u"Kann MPC nicht im Slave-Modus starten!",
"mpc-version-insufficient-error" : u"MPC-Version nicht ausreichend, bitte nutze `mpc-hc` >= `{}`",
"mpv-version-error" : u"Syncplay ist nicht kompatibel mit dieser Version von mpv. Bitte benutze eine andere Version (z.B. Git HEAD).",
"player-file-open-error" : u"Fehler beim Öffnen der Datei durch den Player",
"player-path-error" : u"Ungültiger Player-Pfad",
"hostname-empty-error" : u"Hostname darf nicht leer sein",
"empty-error" : u"{} darf nicht leer sein", # Configuration
"media-player-error": u"Player-Fehler: \"{}\"", # Error line
"unable-import-gui-error": u"Konnte die GUI-Bibliotheken nicht importieren. PySide muss installiert sein, damit die grafische Oberfläche funktioniert.",
"unable-to-start-client-error" : u"Client kann nicht gestartet werden",
"arguments-missing-error" : u"Notwendige Argumente fehlen, siehe --help",
"player-path-config-error": u"Player-Pfad ist nicht ordnungsgemäß gesetzt.",
"no-file-path-config-error": u"Es muss eine Datei ausgewählt werden, bevor der Player gestartet wird.",
"no-hostname-config-error": u"Hostname darf nicht leer sein",
"invalid-port-config-error" : u"Port muss gültig sein",
"empty-value-config-error" : u"{} darf nicht leer sein", # Config option
"unable-to-start-client-error" : u"Client kann nicht gestartet werden",
"not-json-error" : u"Kein JSON-String\n",
"hello-arguments-error" : u"Zu wenige Hello-Argumente\n",
"version-mismatch-error" : u"Verschiedene Versionen auf Client und Server\n",
"vlc-failed-connection": u"Kann nicht zu VLC verbinden. Wenn du syncplay.lua nicht installiert hast, findest du auf http://syncplay.pl/LUA/ [Englisch] eine Anleitung.",
"vlc-failed-noscript": u"Laut VLC ist das syncplay.lua Interface-Skript nicht installiert. Auf http://syncplay.pl/LUA/ [Englisch] findest du eine Anleitung.",
"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
"player-path-config-error": u"Player-Pfad ist nicht ordnungsgemäß gesetzt.",
"no-file-path-config-error": u"Es muss eine Datei ausgewählt werden, bevor der Player gestartet wird.",
"no-hostname-config-error": u"Hostname darf nicht leer sein",
"invalid-port-config-error" : u"Port muss gültig sein",
"empty-value-config-error" : u"{} darf nicht leer sein", # Config option
"not-supported-by-server-error" : u"Dieses Feature wird vom Server nicht unterstützt. Es wird ein Server mit Syncplay Version {}+ benötigt, aktuell verwendet wird jedoch Version {}.", #minVersion, serverVersion
"not-json-error" : u"Kein JSON-String\n",
"hello-arguments-error" : u"Zu wenige Hello-Argumente\n",
"version-mismatch-error" : u"Verschiedene Versionen auf Client und Server\n",
"vlc-failed-connection": u"Kann nicht zu VLC verbinden. Wenn du syncplay.lua nicht installiert hast, findest du auf http://syncplay.pl/LUA/ [Englisch] eine Anleitung.",
"vlc-failed-noscript": u"Laut VLC ist das syncplay.lua Interface-Skript nicht installiert. Auf http://syncplay.pl/LUA/ [Englisch] findest du eine Anleitung.",
"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"Ungültige Zeitangabe",
"invalid-offset-value" : u"Ungültiger Offset-Wert",
"not-supported-by-server-error" : u"Dieses Feature wird vom Server nicht unterstützt. Es wird ein Server mit Syncplay Version {}+ benötigt, aktuell verwendet wird jedoch Version {}.", #minVersion, serverVersion
"switch-file-not-found-error" : u"Konnte nicht zur Datei '{0}' wechseln. Syncplay sucht im Ordner der aktuellen Datei und angegebenen Medien-Verzeichnissen.", # File not found, folder it was not found in
"folder-search-timeout-error" : u"Die Suche nach Mediendateien in '{}' wurde abgebrochen weil sie zu lange gedauert hat. Dies tritt auf, wenn ein zu durchsuchender Medienordner zu viele Unterordner hat. Syncplay wird bis zum Neustart nur noch das Verzeichnis der aktuellen Datei durchsuchen.", #Folder
"invalid-seek-value" : u"Ungültige Zeitangabe",
"invalid-offset-value" : u"Ungültiger Offset-Wert",
"failed-to-load-server-list-error" : u"Konnte die Liste der öffentlichen Server nicht laden. Bitte besuche http://www.syncplay.pl/ [Englisch] mit deinem Browser.",
"switch-file-not-found-error" : u"Konnte nicht zur Datei '{0}' wechseln. Syncplay looks in the specified media directories.", # File not found, folder it was not found in # TODO: Re-translate "Syncplay sucht im Ordner der aktuellen Datei und angegebenen Medien-Verzeichnissen." to reference to checking in "current media directory"
"folder-search-timeout-error" : u"The search for media in media directories was aborted as it took too long to search through '{}'. This will occur if you select a folder with too many sub-folders in your list of media folders to search through. For automatic file switching to work again please select File->Set Media Directories in the menu bar and remove this directory or replace it with an appropriate sub-folder.", #Folder # TODO: Translate
"folder-search-first-file-timeout-error" : u"The search for media in '{}' was aborted as it took too long to access the directory. This could happen if it is a network drive or if you configure your drive to spin down after a period of inactivity. For automatic file switching to work again please go to File->Set Media Directories and either remove the directory or resolve the issue (e.g. by changing power saving settings).", #Folder # TODO: Translate
"added-file-not-in-media-directory-error" : u"You loaded a file in '{}' which is not a known media directory. You can add this as a media directory by selecting File->Set Media Directories in the menu bar.", #Folder # TODO: Translate
"no-media-directories-error" : u"No media directories have been set. For shared playlist and file switching features to work properly please select File->Set Media Directories and specify where Syncplay should look to find media files.", # TODO: Translate
"cannot-find-directory-error" : u"Could not find media directory '{}'. To update your list of media directories please select File->Set Media Directories from the menu bar and specify where Syncplay should look to find media files.", # TODO: Translate
# Client arguments
"argument-description" : u'Syncplay ist eine 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',
"nogui-argument" : u'Keine GUI anzeigen',
"host-argument" : u'Server-Adresse',
"name-argument" : u'Gewünschter Nutzername',
"debug-argument" : u'Debug-Modus',
"force-gui-prompt-argument" : u'Einstellungsfenster anzeigen',
"no-store-argument" : u'keine Werte in .syncplay speichern',
"room-argument" : u'Standard-Raum',
"password-argument" : u'Server-Passwort',
"player-path-argument" : u'Pfad zum Player',
"file-argument" : u'Abzuspielende Datei',
"args-argument" : u'Player-Einstellungen; Wenn du Einstellungen, die mit - beginnen, nutzen willst, stelle ein einzelnes \'--\'-Argument davor',
"clear-gui-data-argument" : u'Setzt die Pfad- und GUI-Fenster-Daten die in den QSettings gespeichert sind zurück',
"language-argument" : u'Sprache für Syncplay-Nachrichten (de/en/ru)',
"failed-to-load-server-list-error" : u"Konnte die Liste der öffentlichen Server nicht laden. Bitte besuche http://www.syncplay.pl/ [Englisch] mit deinem Browser.",
"version-argument" : u'gibt die aktuelle Version aus',
"version-message" : u"Du verwendest Syncplay v. {} ({})",
# Client arguments
"argument-description" : u'Syncplay ist eine 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',
"nogui-argument" : u'Keine GUI anzeigen',
"host-argument" : u'Server-Adresse',
"name-argument" : u'Gewünschter Nutzername',
"debug-argument" : u'Debug-Modus',
"force-gui-prompt-argument" : u'Einstellungsfenster anzeigen',
"no-store-argument" : u'keine Werte in .syncplay speichern',
"room-argument" : u'Standard-Raum',
"password-argument" : u'Server-Passwort',
"player-path-argument" : u'Pfad zum Player',
"file-argument" : u'Abzuspielende Datei',
"args-argument" : u'Player-Einstellungen; Wenn du Einstellungen, die mit - beginnen, nutzen willst, stelle ein einzelnes \'--\'-Argument davor',
"clear-gui-data-argument" : u'Setzt die Pfad- und GUI-Fenster-Daten die in den QSettings gespeichert sind zurück',
"language-argument" : u'Sprache für Syncplay-Nachrichten (de/en/ru)',
# Client labels
"config-window-title" : u"Syncplay Konfiguration",
"version-argument" : u'gibt die aktuelle Version aus',
"version-message" : u"Du verwendest Syncplay v. {} ({})",
"connection-group-title" : u"Verbindungseinstellungen",
"host-label" : u"Server-Adresse:",
"name-label" : u"Benutzername (optional):",
"password-label" : u"Server-Passwort (falls nötig):",
"room-label" : u"Standard-Raum:",
# Client labels
"config-window-title" : u"Syncplay Konfiguration",
"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" : u"Playerparameter:",
"browse-label" : u"Durchsuchen",
"update-server-list-label" : u"Liste aktualisieren",
"connection-group-title" : u"Verbindungseinstellungen",
"host-label" : u"Server-Adresse:",
"name-label" : u"Benutzername (optional):",
"password-label" : u"Server-Passwort (falls nötig):",
"room-label" : u"Standard-Raum:",
"more-title" : u"Mehr Einstellungen zeigen",
"never-rewind-value" : u"Niemals",
"seconds-suffix" : u" sek",
"privacy-sendraw-option" : u"Klartext senden",
"privacy-sendhashed-option" : u"Hash senden",
"privacy-dontsend-option" : u"Nicht senden",
"filename-privacy-label" : u"Dateiname:",
"filesize-privacy-label" : u"Dateigröße:",
"checkforupdatesautomatically-label" : u"Automatisch nach Updates suchen",
"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",
"readyatstart-label" : u"Standardmäßig auf \'Bereit\' stellen",
"forceguiprompt-label" : u"Diesen Dialog nicht mehr anzeigen",
"nostore-label" : u"Diese Konfiguration nicht speichern",
"showosd-label" : u"OSD-Nachrichten anzeigen",
"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" : u"Playerparameter:",
"browse-label" : u"Durchsuchen",
"update-server-list-label" : u"Liste aktualisieren",
"showosdwarnings-label" : u"Zeige Warnungen (z.B. wenn Dateien verschieden)",
"showsameroomosd-label" : u"Zeige Ereignisse in deinem Raum",
"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",
"language-label" : u"Sprache:",
"automatic-language" : u"Automatisch ({})", # Default language
"showdurationnotification-label" : u"Zeige Warnung wegen unterschiedlicher Dauer",
"basics-label" : u"Grundlagen",
"readiness-label" : u"Play/Pause",
"misc-label" : u"Diverse",
"core-behaviour-title" : u"Verhalten des Raumes",
"syncplay-internals-title" : u"Syncplay intern",
"syncplay-mediasearchdirectories-title" : u"In diesen Verzeichnissen nach Medien suchen (ein Pfad pro Zeile)",
"sync-label" : u"Synchronisation",
"sync-otherslagging-title" : u"Wenn andere laggen...",
"sync-youlaggging-title" : u"Wenn du laggst...",
"messages-label" : u"Nachrichten",
"messages-osd-title" : u"OSD-(OnScreenDisplay)-Einstellungen",
"messages-other-title" : u"Weitere Display-Einstellungen",
"privacy-label" : u"Privatsphäre",
"privacy-title" : u"Privatsphäreneinstellungen",
"unpause-title" : u"Wenn du Play drückst, auf Bereit setzen und:",
"unpause-ifalreadyready-option" : u"Wiedergeben wenn bereits als Bereit gesetzt",
"unpause-ifothersready-option" : u"Wiedergeben wenn bereits als Bereit gesetzt oder alle anderen bereit sind (Standard)",
"unpause-ifminusersready-option" : u"Wiedergeben wenn bereits als Bereit gesetzt oder die minimale Anzahl anderer Nutzer bereit ist",
"unpause-always" : u"Immer wiedergeben",
"more-title" : u"Mehr Einstellungen zeigen",
"never-rewind-value" : u"Niemals",
"seconds-suffix" : u" sek",
"privacy-sendraw-option" : u"Klartext senden",
"privacy-sendhashed-option" : u"Hash senden",
"privacy-dontsend-option" : u"Nicht senden",
"filename-privacy-label" : u"Dateiname:",
"filesize-privacy-label" : u"Dateigröße:",
"checkforupdatesautomatically-label" : u"Automatisch nach Updates suchen",
"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",
"readyatstart-label" : u"Standardmäßig auf \'Bereit\' stellen",
"forceguiprompt-label" : u"Diesen Dialog nicht mehr anzeigen",
"showosd-label" : u"OSD-Nachrichten anzeigen",
"help-label" : u"Hilfe",
"reset-label" : u"Standardwerte zurücksetzen",
"run-label" : u"Syncplay starten",
"storeandrun-label" : u"Konfiguration speichern und Syncplay starten",
"showosdwarnings-label" : u"Zeige Warnungen (z.B. wenn Dateien verschieden)",
"showsameroomosd-label" : u"Zeige Ereignisse in deinem Raum",
"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",
"language-label" : u"Sprache:",
"automatic-language" : u"Automatisch ({})", # Default language
"showdurationnotification-label" : u"Zeige Warnung wegen unterschiedlicher Dauer",
"basics-label" : u"Grundlagen",
"readiness-label" : u"Play/Pause",
"misc-label" : u"Diverse",
"core-behaviour-title" : u"Verhalten des Raumes",
"syncplay-internals-title" : u"Syncplay intern",
"syncplay-mediasearchdirectories-title" : u"In diesen Verzeichnissen nach Medien suchen (ein Pfad pro Zeile)",
"sync-label" : u"Synchronisation",
"sync-otherslagging-title" : u"Wenn andere laggen...",
"sync-youlaggging-title" : u"Wenn du laggst...",
"messages-label" : u"Nachrichten",
"messages-osd-title" : u"OSD-(OnScreenDisplay)-Einstellungen",
"messages-other-title" : u"Weitere Display-Einstellungen",
"privacy-label" : u"Privatsphäre",
"privacy-title" : u"Privatsphäreneinstellungen",
"unpause-title" : u"Wenn du Play drückst, auf Bereit setzen und:",
"unpause-ifalreadyready-option" : u"Wiedergeben wenn bereits als Bereit gesetzt",
"unpause-ifothersready-option" : u"Wiedergeben wenn bereits als Bereit gesetzt oder alle anderen bereit sind (Standard)",
"unpause-ifminusersready-option" : u"Wiedergeben wenn bereits als Bereit gesetzt oder die minimale Anzahl anderer Nutzer bereit ist",
"unpause-always" : u"Immer wiedergeben",
"syncplay-trusteddomains-title": u"Trusted domains (for streaming services and hosted content)", # TODO: Translate into German
"contact-label" : u"Du hast eine Idee, einen Bug gefunden oder möchtest Feedback geben? Sende eine E-Mail an <a href=\"mailto:dev@syncplay.pl\">dev@syncplay.pl</a>, chatte auf dem <a href=\"https://webchat.freenode.net/?channels=#syncplay\">#Syncplay IRC-Kanal</a> auf irc.freenode.net oder <a href=\"https://github.com/Uriziel/syncplay/issues\">öffne eine Fehlermeldung auf GitHub</a>. Außerdem findest du auf <a href=\"http://syncplay.pl/\">http://syncplay.pl/</a> weitere Informationen, Hilfestellungen und Updates.",
"help-label" : u"Hilfe",
"reset-label" : u"Standardwerte zurücksetzen",
"run-label" : u"Syncplay starten",
"storeandrun-label" : u"Konfiguration speichern und Syncplay starten",
"joinroom-menu-label" : u"Raum beitreten",
"seektime-menu-label" : u"Spule zu Zeit",
"undoseek-menu-label" : u"Rückgängig",
"play-menu-label" : u"Wiedergabe",
"pause-menu-label" : u"Pause",
"playbackbuttons-menu-label" : u"Wiedergabesteuerung anzeigen",
"autoplay-menu-label" : u"Auto-Play-Knopf anzeigen",
"autoplay-guipushbuttonlabel" : u"Automatisch abspielen wenn alle bereit sind",
"autoplay-minimum-label" : u"Minimum an Nutzern:",
"contact-label" : u"Du hast eine Idee, einen Bug gefunden oder möchtest Feedback geben? Sende eine E-Mail an <a href=\"mailto:dev@syncplay.pl\">dev@syncplay.pl</a>, chatte auf dem <a href=\"https://webchat.freenode.net/?channels=#syncplay\">#Syncplay IRC-Kanal</a> auf irc.freenode.net oder <a href=\"https://github.com/Uriziel/syncplay/issues\">öffne eine Fehlermeldung auf GitHub</a>. Außerdem findest du auf <a href=\"http://syncplay.pl/\">http://syncplay.pl/</a> weitere Informationen, Hilfestellungen und Updates.",
"ready-guipushbuttonlabel" : u"Ich bin bereit den Film anzuschauen!",
"joinroom-label" : u"Raum beitreten",
"joinroom-menu-label" : u"Raum beitreten {}", #TODO: Might want to fix this
"seektime-menu-label" : u"Spule zu Zeit",
"undoseek-menu-label" : u"Rückgängig",
"play-menu-label" : u"Wiedergabe",
"pause-menu-label" : u"Pause",
"playbackbuttons-menu-label" : u"Wiedergabesteuerung anzeigen",
"autoplay-menu-label" : u"Auto-Play-Knopf anzeigen",
"autoplay-guipushbuttonlabel" : u"Automatisch abspielen wenn alle bereit sind",
"autoplay-minimum-label" : u"Minimum an Nutzern:",
"roomuser-heading-label" : u"Raum / Benutzer",
"size-heading-label" : u"Größe",
"duration-heading-label" : u"Länge",
"filename-heading-label" : u"Dateiname",
"notifications-heading-label" : u"Benachrichtigungen",
"userlist-heading-label" : u"Liste der gespielten Dateien",
"ready-guipushbuttonlabel" : u"Ich bin bereit den Film anzuschauen!",
"browseformedia-label" : u"Nach Mediendateien durchsuchen",
"roomuser-heading-label" : u"Raum / Benutzer",
"size-heading-label" : u"Größe",
"duration-heading-label" : u"Länge",
"filename-heading-label" : u"Dateiname",
"notifications-heading-label" : u"Benachrichtigungen",
"userlist-heading-label" : u"Liste der gespielten Dateien",
"file-menu-label" : u"&Datei", # & precedes shortcut key
"openmedia-menu-label" : u"&Mediendatei öffnen...",
"openstreamurl-menu-label" : u"&Stream URL öffnen",
"exit-menu-label" : u"&Beenden",
"advanced-menu-label" : u"&Erweitert",
"window-menu-label" : u"&Fenster",
"setoffset-menu-label" : u"&Offset einstellen",
"createcontrolledroom-menu-label" : u"&Zentral gesteuerten Raum erstellen",
"identifyascontroller-menu-label" : u"Als Raumleiter &identifizieren",
"browseformedia-label" : u"Nach Mediendateien durchsuchen",
"playback-menu-label" : u"&Wiedergabe",
"file-menu-label" : u"&Datei", # & precedes shortcut key
"openmedia-menu-label" : u"&Mediendatei öffnen...",
"openstreamurl-menu-label" : u"&Stream URL öffnen",
"setmediadirectories-menu-label" : u"Set media &directories", # TODO: Translate
"exit-menu-label" : u"&Beenden",
"advanced-menu-label" : u"&Erweitert",
"window-menu-label" : u"&Fenster",
"setoffset-menu-label" : u"&Offset einstellen",
"createcontrolledroom-menu-label" : u"&Zentral gesteuerten Raum erstellen",
"identifyascontroller-menu-label" : u"Als Raumleiter &identifizieren",
"settrusteddomains-menu-label" : u"Set &trusted domains", # TODO: Translate
"help-menu-label" : u"&Hilfe",
"userguide-menu-label" : u"&Benutzerhandbuch öffnen",
"update-menu-label" : u"auf &Aktualisierung prüfen",
"playback-menu-label" : u"&Wiedergabe",
"setoffset-msgbox-label" : u"Offset einstellen",
"offsetinfo-msgbox-label" : u"Offset (siehe http://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
"help-menu-label" : u"&Hilfe",
"userguide-menu-label" : u"&Benutzerhandbuch öffnen",
"update-menu-label" : u"auf &Aktualisierung prüfen",
"promptforstreamurl-msgbox-label" : u"Stream URL öffnen",
"promptforstreamurlinfo-msgbox-label" : u"Stream URL",
"setoffset-msgbox-label" : u"Offset einstellen",
"offsetinfo-msgbox-label" : u"Offset (siehe http://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
"createcontrolledroom-msgbox-label" : u"Zentral gesteuerten Raum erstellen",
"controlledroominfo-msgbox-label" : u"Namen des zentral gesteuerten Raums eingeben\r\n(siehe http://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
"promptforstreamurl-msgbox-label" : u"Stream URL öffnen",
"promptforstreamurlinfo-msgbox-label" : u"Stream URL",
"identifyascontroller-msgbox-label" : u"Als Raumleiter identifizieren",
"identifyinfo-msgbox-label" : u"Passwort des zentral gesteuerten Raums eingeben\r\n(siehe http://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
"addfolder-label" : u"Add folder", # TODO: Translate
"public-server-msgbox-label" : u"Einen öffentlichen Server für diese Sitzung auswählen",
"adduris-msgbox-label" : u"Add URLs to playlist (one per line)", # TODO: Translate
"trusteddomains-msgbox-label" : u"Domains it is okay to automatically switch to (one per line)", # TODO: Translate
"megabyte-suffix" : u" MB",
"createcontrolledroom-msgbox-label" : u"Zentral gesteuerten Raum erstellen",
"controlledroominfo-msgbox-label" : u"Namen des zentral gesteuerten Raums eingeben\r\n(siehe http://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
# Tooltips
"identifyascontroller-msgbox-label" : u"Als Raumleiter identifizieren",
"identifyinfo-msgbox-label" : u"Passwort des zentral gesteuerten Raums eingeben\r\n(siehe http://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
"host-tooltip" : u"Hostname oder IP zu der verbunden werden soll. Optional mit Port (z.B.. syncplay.pl:8999). Synchronisation findet nur mit Personen auf dem selben Server und Port statt.",
"name-tooltip" : u"Dein Benutzername. Keine Registrierung, kann einfach geändert werden. Bei fehlender Angabe wird ein zufälliger Name generiert.",
"password-tooltip" : u"Passwörter sind nur bei Verbindung zu privaten Servern nötig.",
"room-tooltip" : u"Der Raum, der betreten werden soll, kann ein x-beliebiger sein. Allerdings werden nur Clients im selben Raum synchronisiert.",
"public-server-msgbox-label" : u"Einen öffentlichen Server für diese Sitzung auswählen",
"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" : u"Zusätzliche Kommandozeilenparameter / -schalter für diesen Mediaplayer.",
"mediasearcdirectories-arguments-tooltip" : u"Verzeichnisse, in denen Syncplay nach Mediendateien suchen soll, z.B. wenn du das Click-to-switch-Feature verwendest. Syncplay wird rekursiv Unterordner durchsuchen.", # TODO: Translate Click-to-switch? (or use as name for feature)
"megabyte-suffix" : u" MB",
"more-tooltip" : u"Weitere Einstellungen anzeigen.",
"filename-privacy-tooltip" : u"Privatheitsmodus beim Senden des Namens der aktuellen Datei zum Server.",
"filesize-privacy-tooltip" : u"Privatheitsmodus beim Senden der Größe der aktuellen Datei zum Server.",
"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"Regelmäßig auf der Syncplay-Website nach Updates suchen.",
"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 laggt (empfohlen)",
"dontslowdownwithme-tooltip" : u"Lässt andere nicht langsamer werden oder zurückspringen, wenn deine Wiedergabe hängt.",
"pauseonleave-tooltip" : u"Wiedergabe anhalten, wenn deine Verbindung verloren geht oder jemand den Raum verlässt.",
"readyatstart-tooltip" : u"Zu Beginn auf 'Bereit' setzen (sonst bist du als 'Nicht Bereit' gesetzt, bis du den Status änderst)",
"forceguiprompt-tooltip" : u"Der Konfigurationsdialog wird nicht angezeigt, wenn eine Datei mit Syncplay geöffnet wird.",
"nostore-tooltip" : u"Syncplay mit den angegebenen Einstellungen starten, diese aber nicht dauerhaft speichern.",
"rewindondesync-tooltip" : u"Zum Wiederherstellen der Synchronität in der Zeit zurückspringen (empfohlen)",
"fastforwardondesync-tooltip" : u"Nach vorne springen, wenn asynchron zum Raumleiter (oder deine vorgetäuschte Position, falls 'Niemals verlangsamen oder andere zurückspulen' aktiviert ist).",
"showosd-tooltip" : u"Syncplay-Nachrichten auf dem OSD (= OnScreenDisplay, ein eingeblendetes Textfeld) des Players anzeigen.",
"showosdwarnings-tooltip" : u"Warnungen bei Unterschiedlichen Dateien oder Alleinsein im Raum anzeigen.",
"showsameroomosd-tooltip" : u"OSD-Meldungen über Ereignisse im selben Raum anzeigen.",
"shownoncontrollerosd-tooltip" : u"OSD-Meldungen bei Ereignissen verursacht durch nicht-Raumleiter in zentral gesteuerten Räumen anzeigen.",
"showdifferentroomosd-tooltip" : u"OSD-Meldungen zu anderen Räumen als dem aktuell betretenen anzeigen.",
"showslowdownosd-tooltip" : u"Meldungen bei Geschwindigkeitsänderung anzeigen.",
"showdurationnotification-tooltip" : u"Nützlich, wenn z.B. ein Teil eines mehrteiligen Videos fehlt, kann jedoch auch fehlerhaft anschlagen.",
"language-tooltip" : u"Die verwendete Sprache von Syncplay",
"unpause-always-tooltip" : u"Wiedergabe startet immer (anstatt nur den Bereitschaftsstatus zu ändern)",
"unpause-ifalreadyready-tooltip" : u"Wenn du nicht bereit bist und Play drückst wirst du als bereit gesetzt - zum Starten der Wiedergabe nochmal drücken.",
"unpause-ifothersready-tooltip" : u"Wenn du Play drückst und nicht bereit bist, wird nur gestartet, wenn alle anderen bereit sind.",
"unpause-ifminusersready-tooltip" : u"Wenn du Play drückst und nicht bereit bist, wird nur gestartet, wenn die minimale Anzahl anderer Benutzer bereit ist.",
# Tooltips
"help-tooltip" : u"Öffnet Hilfe auf syncplay.pl [Englisch]",
"reset-tooltip" : u"Alle Einstellungen auf Standardwerte zurücksetzen.",
"update-server-list-tooltip" : u"Mit syncplay.pl verbinden um die Liste öffentlicher Server zu aktualisieren.",
"host-tooltip" : u"Hostname oder IP zu der verbunden werden soll. Optional mit Port (z.B.. syncplay.pl:8999). Synchronisation findet nur mit Personen auf dem selben Server und Port statt.",
"name-tooltip" : u"Dein Benutzername. Keine Registrierung, kann einfach geändert werden. Bei fehlender Angabe wird ein zufälliger Name generiert.",
"password-tooltip" : u"Passwörter sind nur bei Verbindung zu privaten Servern nötig.",
"room-tooltip" : u"Der Raum, der betreten werden soll, kann ein x-beliebiger sein. Allerdings werden nur Clients im selben Raum synchronisiert.",
"joinroom-tooltip" : u"Den aktuellen Raum verlassen und stattdessen den angegebenen betreten.",
"seektime-msgbox-label" : u"Springe zur angegebenen Zeit (in Sekunden oder min:sek). Verwende +/- zum relativen Springen.",
"ready-tooltip" : u"Zeigt an, ob du bereit zum anschauen bist",
"autoplay-tooltip" : u"Automatisch abspielen, wenn alle Nutzer bereit sind oder die minimale Nutzerzahl erreicht ist.",
"switch-to-file-tooltip" : u"Doppelklicken um zu {} zu wechseln", # Filename
"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" : u"Zusätzliche Kommandozeilenparameter / -schalter für diesen Mediaplayer.",
"mediasearcdirectories-arguments-tooltip" : u"Verzeichnisse, in denen Syncplay nach Mediendateien suchen soll, z.B. wenn du das Click-to-switch-Feature verwendest. Syncplay wird rekursiv Unterordner durchsuchen.", # TODO: Translate Click-to-switch? (or use as name for feature)
# In-userlist notes (GUI)
"differentsize-note" : u"Verschiedene Größe!",
"differentsizeandduration-note" : u"Verschiedene Größe und Dauer!",
"differentduration-note" : u"Verschiedene Dauer!",
"nofile-note" : u"(keine Datei wird abgespielt)",
"more-tooltip" : u"Weitere Einstellungen anzeigen.",
"filename-privacy-tooltip" : u"Privatheitsmodus beim Senden des Namens der aktuellen Datei zum Server.",
"filesize-privacy-tooltip" : u"Privatheitsmodus beim Senden der Größe der aktuellen Datei zum Server.",
"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"Regelmäßig auf der Syncplay-Website nach Updates suchen.",
"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 laggt (empfohlen)",
"dontslowdownwithme-tooltip" : u"Lässt andere nicht langsamer werden oder zurückspringen, wenn deine Wiedergabe hängt.",
"pauseonleave-tooltip" : u"Wiedergabe anhalten, wenn deine Verbindung verloren geht oder jemand den Raum verlässt.",
"readyatstart-tooltip" : u"Zu Beginn auf 'Bereit' setzen (sonst bist du als 'Nicht Bereit' gesetzt, bis du den Status änderst)",
"forceguiprompt-tooltip" : u"Der Konfigurationsdialog wird nicht angezeigt, wenn eine Datei mit Syncplay geöffnet wird.",
"nostore-tooltip" : u"Syncplay mit den angegebenen Einstellungen starten, diese aber nicht dauerhaft speichern.",
"rewindondesync-tooltip" : u"Zum Wiederherstellen der Synchronität in der Zeit zurückspringen (empfohlen)",
"fastforwardondesync-tooltip" : u"Nach vorne springen, wenn asynchron zum Raumleiter (oder deine vorgetäuschte Position, falls 'Niemals verlangsamen oder andere zurückspulen' aktiviert ist).",
"showosd-tooltip" : u"Syncplay-Nachrichten auf dem OSD (= OnScreenDisplay, ein eingeblendetes Textfeld) des Players anzeigen.",
"showosdwarnings-tooltip" : u"Warnungen bei Unterschiedlichen Dateien oder Alleinsein im Raum anzeigen.",
"showsameroomosd-tooltip" : u"OSD-Meldungen über Ereignisse im selben Raum anzeigen.",
"shownoncontrollerosd-tooltip" : u"OSD-Meldungen bei Ereignissen verursacht durch nicht-Raumleiter in zentral gesteuerten Räumen anzeigen.",
"showdifferentroomosd-tooltip" : u"OSD-Meldungen zu anderen Räumen als dem aktuell betretenen anzeigen.",
"showslowdownosd-tooltip" : u"Meldungen bei Geschwindigkeitsänderung anzeigen.",
"showdurationnotification-tooltip" : u"Nützlich, wenn z.B. ein Teil eines mehrteiligen Videos fehlt, kann jedoch auch fehlerhaft anschlagen.",
"language-tooltip" : u"Die verwendete Sprache von Syncplay",
"unpause-always-tooltip" : u"Wiedergabe startet immer (anstatt nur den Bereitschaftsstatus zu ändern)",
"unpause-ifalreadyready-tooltip" : u"Wenn du nicht bereit bist und Play drückst wirst du als bereit gesetzt - zum Starten der Wiedergabe nochmal drücken.",
"unpause-ifothersready-tooltip" : u"Wenn du Play drückst und nicht bereit bist, wird nur gestartet, wenn alle anderen bereit sind.",
"unpause-ifminusersready-tooltip" : u"Wenn du Play drückst und nicht bereit bist, wird nur gestartet, wenn die minimale Anzahl anderer Benutzer bereit ist.",
"trusteddomains-arguments-tooltip" : u"Domains that it is okay for Syncplay to automatically switch to when shared playlists is enabled.", # TODO: Translate into German
# Server messages to client
"new-syncplay-available-motd-message" : u"<NOTICE> Du nutzt Syncplay Version {}, aber es gibt eine neuere Version auf http://syncplay.pl</NOTICE>", # ClientVersion
"help-tooltip" : u"Öffnet Hilfe auf syncplay.pl [Englisch]",
"reset-tooltip" : u"Alle Einstellungen auf Standardwerte zurücksetzen.",
"update-server-list-tooltip" : u"Mit syncplay.pl verbinden um die Liste öffentlicher Server zu aktualisieren.",
# Server notifications
"welcome-server-notification" : u"Willkommen zum Syncplay-Server, v. {0}", # version
"client-connected-room-server-notification" : u"{0}({2}) hat den Raum '{1}' betreten", # username, host, room
"client-left-server-notification" : u"{0} hat den Server verlassen", # name
"no-salt-notification" : u"WICHTIGER HINWEIS: Damit von dem Server generierte Passwörter für geführte Räume auch nach einem Serverneustart funktionieren, starte den Server mit dem folgenden Parameter: --salt {}", #Salt
"joinroom-tooltip" : u"Den aktuellen Raum verlassen und stattdessen den angegebenen betreten.",
"seektime-msgbox-label" : u"Springe zur angegebenen Zeit (in Sekunden oder min:sek). Verwende +/- zum relativen Springen.",
"ready-tooltip" : u"Zeigt an, ob du bereit zum anschauen bist",
"autoplay-tooltip" : u"Automatisch abspielen, wenn alle Nutzer bereit sind oder die minimale Nutzerzahl erreicht ist.",
"switch-to-file-tooltip" : u"Doppelklicken um zu {} zu wechseln", # Filename
# Server arguments
"server-argument-description" : u'Anwendung, um mehrere MPlayer, MPC-HC und VLC-Instanzen über das Internet zu synchronisieren. Server',
"server-argument-epilog" : u'Wenn keine Optionen angegeben sind, werden die _config-Werte verwendet',
"server-port-argument" : u'Server TCP-Port',
"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"Bereitschaftsfeature deaktivieren",
"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 {}.",
# In-userlist notes (GUI)
"differentsize-note" : u"Verschiedene Größe!",
"differentsizeandduration-note" : u"Verschiedene Größe und Dauer!",
"differentduration-note" : u"Verschiedene Dauer!",
"nofile-note" : u"(keine Datei wird abgespielt)",
# Server errors
"unknown-command-server-error" : u"Unbekannter Befehl {}", # message
"not-json-server-error" : u"Kein JSON-String {}", # message
"not-known-server-error" : u"Der Server muss dich kennen, bevor du diesen Befehl nutzen kannst",
"client-drop-server-error" : u"Client verloren: {} -- {}", # host, error
"password-required-server-error" : u"Passwort nötig",
"wrong-password-server-error" : u"Ungültiges Passwort",
"hello-server-error" : u"Zu wenige Hello-Argumente"
}
# Server messages to client
"new-syncplay-available-motd-message" : u"<NOTICE> Du nutzt Syncplay Version {}, aber es gibt eine neuere Version auf http://syncplay.pl</NOTICE>", # ClientVersion
# Server notifications
"welcome-server-notification" : u"Willkommen zum Syncplay-Server, v. {0}", # version
"client-connected-room-server-notification" : u"{0}({2}) hat den Raum '{1}' betreten", # username, host, room
"client-left-server-notification" : u"{0} hat den Server verlassen", # name
"no-salt-notification" : u"WICHTIGER HINWEIS: Damit von dem Server generierte Passwörter für geführte Räume auch nach einem Serverneustart funktionieren, starte den Server mit dem folgenden Parameter: --salt {}", #Salt
# Server arguments
"server-argument-description" : u'Anwendung, um mehrere MPlayer, MPC-HC und VLC-Instanzen über das Internet zu synchronisieren. Server',
"server-argument-epilog" : u'Wenn keine Optionen angegeben sind, werden die _config-Werte verwendet',
"server-port-argument" : u'Server TCP-Port',
"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"Bereitschaftsfeature deaktivieren",
"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 {}.",
# Server errors
"unknown-command-server-error" : u"Unbekannter Befehl {}", # message
"not-json-server-error" : u"Kein JSON-String {}", # message
"not-known-server-error" : u"Der Server muss dich kennen, bevor du diesen Befehl nutzen kannst",
"client-drop-server-error" : u"Client verloren: {} -- {}", # host, error
"password-required-server-error" : u"Passwort nötig",
"wrong-password-server-error" : u"Ungültiges Passwort",
"hello-server-error" : u"Zu wenige Hello-Argumente",
# Playlists TODO: Translate all this to German
"playlist-selection-changed-notification" : u"{} changed the playlist selection", # Username
"playlist-contents-changed-notification" : u"{} updated the playlist", # Username
"cannot-find-file-for-playlist-switch-error" : u"Could not find file {} in media directories for playlist switch!", # Filename
"cannot-add-duplicate-error" : u"Could not add second entry for '{}' to the playlist as no duplicates are allowed.", #Filename
"cannot-add-unsafe-path-error" : u"Could not automatically load {} because it is not on a trusted domain. You can switch to the URL manually by double clicking it in the playlist, and add trusted domains via File->Advanced->Set Trusted Domains.", # Filename
"sharedplaylistenabled-label" : u"Enable shared playlists",
"removefromplaylist-menu-label" : u"Remove from playlist",
"shuffleplaylist-menuu-label" : u"Shuffle playlist",
"undoplaylist-menu-label" : u"Undo last change to playlist",
"addfilestoplaylist-menu-label" : u"Add file(s) to bottom of playlist",
"addurlstoplaylist-menu-label" : u"Add URL(s) to bottom of playlist",
"addusersfiletoplaylist-menu-label" : u"Add {} file to playlist", # item owner indicator
"addusersstreamstoplaylist-menu-label" : u"Add {} stream to playlist", # item owner indicator
"openusersstream-menu-label" : u"Open {} stream", # [username]'s
"openusersfile-menu-label" : u"Open {} file", # [username]'s
"item-is-yours-indicator" : u"your", # Goes with addusersfiletoplaylist/addusersstreamstoplaylist
"item-is-others-indicator" : u"{}'s", # username - goes with addusersfiletoplaylist/addusersstreamstoplaylist
"playlist-instruction-item-message" : u"Drag file here to add it to the shared playlist.",
"sharedplaylistenabled-tooltip" : u"Room operators can add files to a synced playlist to make it easy for everyone to watching the same thing. Configure media directories under 'Misc'.",
}

View File

@ -3,371 +3,409 @@
"""English dictionary"""
en = {
"LANGUAGE" : "English",
"LANGUAGE" : "English",
# Client notifications
"config-cleared-notification" : "Settings cleared. Changes will be saved when you store a valid configuration.",
# Client notifications
"config-cleared-notification" : "Settings cleared. Changes will be saved when you store a valid configuration.",
"relative-config-notification" : u"Loaded relative configuration file(s): {}",
"relative-config-notification" : u"Loaded relative configuration file(s): {}",
"connection-attempt-notification" : "Attempting to connect to {}:{}", # Port, IP
"reconnection-attempt-notification" : "Connection with server lost, attempting to reconnect",
"disconnection-notification" : "Disconnected from server",
"connection-failed-notification" : "Connection with server failed",
"connected-successful-notification" : "Successfully connected to server",
"retrying-notification" : "%s, Retrying in %d seconds...", # Seconds
"connection-attempt-notification" : "Attempting to connect to {}:{}", # Port, IP
"reconnection-attempt-notification" : "Connection with server lost, attempting to reconnect",
"disconnection-notification" : "Disconnected from server",
"connection-failed-notification" : "Connection with server failed",
"connected-successful-notification" : "Successfully connected to server",
"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",
"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",
"pause-notification" : u"<{}> paused", # User
"unpause-notification" : u"<{}> unpaused", # User
"seek-notification" : u"<{}> jumped from {} to {}", # User, from time, to time
"pause-notification" : u"<{}> paused", # User
"unpause-notification" : u"<{}> unpaused", # User
"seek-notification" : u"<{}> jumped from {} to {}", # User, from time, to time
"current-offset-notification" : "Current offset: {} seconds", # Offset
"current-offset-notification" : "Current offset: {} seconds", # Offset
"room-join-notification" : u"<{}> has joined the room: '{}'", # User
"left-notification" : u"<{}> has left", # User
"left-paused-notification" : u"<{}> left, <{}> paused", # User who left, User who paused
"playing-notification" : u"<{}> is playing '{}' ({})", # User, file, duration
"playing-notification/room-addendum" : u" in room: '{}'", # Room
"media-directory-list-updated-notification" : u"Syncplay media directories have been updated.",
"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",
"set-as-ready-notification" : u"You are now set as ready",
"set-as-not-ready-notification" : u"You are now set as not ready",
"autoplaying-notification" : u"Auto-playing in {}...", # Number of seconds until playback will start
"room-join-notification" : u"<{}> has joined the room: '{}'", # User
"left-notification" : u"<{}> has left", # User
"left-paused-notification" : u"<{}> left, <{}> paused", # User who left, User who paused
"playing-notification" : u"<{}> is playing '{}' ({})", # User, file, duration
"playing-notification/room-addendum" : u" in room: '{}'", # Room
"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, operatorPassword
"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",
"set-as-ready-notification" : u"You are now set as ready",
"set-as-not-ready-notification" : u"You are now set as not ready",
"autoplaying-notification" : u"Auto-playing in {}...", # Number of seconds until playback will start
"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
"room-file-differences" : u"File differences: {}", # File differences (filename, size, and/or duration)
"file-difference-filename" : u"name",
"file-difference-filesize" : u"size",
"file-difference-duration" : u"duration",
"alone-in-the-room": u"You're alone in the room",
"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, operatorPassword
"different-filesize-notification" : u" (their file size is different from yours!)",
"userlist-playing-notification" : u"{} is playing:", #Username
"file-played-by-notification" : u"File: {} is being played by:", # File
"no-file-played-notification" : u"{} is not playing a file", # Username
"notplaying-notification" : "People who are not playing any file:",
"userlist-room-notification" : u"In room '{}':", # Room
"userlist-file-notification" : "File",
"controller-userlist-userflag" : "Operator",
"ready-userlist-userflag" : "Ready",
"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
"room-file-differences" : u"File differences: {}", # File differences (filename, size, and/or duration)
"file-difference-filename" : u"name",
"file-difference-filesize" : u"size",
"file-difference-duration" : u"duration",
"alone-in-the-room": u"You're alone in the room",
"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 visit the release page?",
"different-filesize-notification" : u" (their file size is different from yours!)",
"userlist-playing-notification" : u"{} is playing:", #Username
"file-played-by-notification" : u"File: {} is being played by:", # File
"no-file-played-notification" : u"{} is not playing a file", # Username
"notplaying-notification" : "People who are not playing any file:",
"userlist-room-notification" : u"In room '{}':", # Room
"userlist-file-notification" : "File",
"controller-userlist-userflag" : "Operator",
"ready-userlist-userflag" : "Ready",
"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",
"mplayer2-required" : "Syncplay is incompatible with MPlayer 1.x, please use mplayer2 or mpv",
"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 visit the release page?",
"unrecognized-command-notification" : "Unrecognized command",
"commandlist-notification" : "Available commands:",
"commandlist-notification/room" : "\tr [name] - change room",
"commandlist-notification/list" : "\tl - show user list",
"commandlist-notification/undo" : "\tu - undo last seek",
"commandlist-notification/pause" : "\tp - toggle pause",
"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 managed room using name of current room",
"commandlist-notification/auth" : "\ta [password] - authenticate as room operator with operator password",
"syncplay-version-notification" : "Syncplay version: {}", # syncplay.version
"more-info-notification" : "More info available at: {}", # projectURL
"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",
"mplayer2-required" : "Syncplay is incompatible with MPlayer 1.x, please use mplayer2 or mpv",
"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?",
"unrecognized-command-notification" : "Unrecognized command",
"commandlist-notification" : "Available commands:",
"commandlist-notification/room" : "\tr [name] - change room",
"commandlist-notification/list" : "\tl - show user list",
"commandlist-notification/undo" : "\tu - undo last seek",
"commandlist-notification/pause" : "\tp - toggle pause",
"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 managed room using name of current room",
"commandlist-notification/auth" : "\ta [password] - authenticate as room operator with operator password",
"syncplay-version-notification" : "Syncplay version: {}", # syncplay.version
"more-info-notification" : "More info available at: {}", # projectURL
"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
"vlc-interface-oldversion-warning": "Warning: Syncplay detected that an old version version of the Syncplay interface module for VLC was installed in the VLC directory. Please refer to the Syncplay User Guide at http://syncplay.pl/guide/ for instructions on how to install syncplay.lua.",
"vlc-interface-not-installed": "Warning: The Syncplay interface module for VLC was not found in the VLC directory. As such, if you are running VLC 2.0 then VLC will use the syncplay.lua module contained within the Syncplay directory, but this will mean that other custom interface scripts and extensions will not work. Please refer to the Syncplay User Guide at http://syncplay.pl/guide/ for instructions on how to install syncplay.lua.",
"media-player-latency-warning": u"Warning: The media player took {} seconds to respond. If you experience syncing issues then close applications to free up system resources, and if that doesn't work then try a different media player.", # Seconds to respond
"mpv-unresponsive-error": u"mpv has not responded for {} seconds so appears to have malfunctioned. Please restart Syncplay.", # Seconds to respond
"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?",
# Client prompts
"enter-to-exit-prompt" : "Press enter to exit\n",
"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
"vlc-interface-oldversion-warning": "Warning: Syncplay detected that an old version version of the Syncplay interface module for VLC was installed in the VLC directory. Please refer to the Syncplay User Guide at http://syncplay.pl/guide/ for instructions on how to install syncplay.lua.",
"vlc-interface-not-installed": "Warning: The Syncplay interface module for VLC was not found in the VLC directory. As such, if you are running VLC 2.0 then VLC will use the syncplay.lua module contained within the Syncplay directory, but this will mean that other custom interface scripts and extensions will not work. Please refer to the Syncplay User Guide at http://syncplay.pl/guide/ for instructions on how to install syncplay.lua.",
"media-player-latency-warning": u"Warning: The media player took {} seconds to respond. If you experience syncing issues then close applications to free up system resources, and if that doesn't work then try a different media player.", # Seconds to respond
"mpv-unresponsive-error": u"mpv has not responded for {} seconds so appears to have malfunctioned. Please restart Syncplay.", # Seconds to respond
# Client errors
"missing-arguments-error" : "Some necessary arguments are missing, refer to --help",
"server-timeout-error" : "Connection with server timed out",
"mpc-slave-error" : "Unable to start MPC in slave mode!",
"mpc-version-insufficient-error" : "MPC version not sufficient, please use `mpc-hc` >= `{}`",
"mpv-version-error" : "Syncplay is not compatible with this version of mpv. Please use a different version of mpv (e.g. Git HEAD).",
"player-file-open-error" : "Player failed opening file",
"player-path-error" : "Player path is not set properly",
"hostname-empty-error" : "Hostname can't be empty",
"empty-error" : "{} can't be empty", # Configuration
"media-player-error": "Media player error: \"{}\"", # Error line
"unable-import-gui-error": "Could not import GUI libraries. If you do not have PySide installed then you will need to install it for the GUI to work.",
# Client prompts
"enter-to-exit-prompt" : "Press enter to exit\n",
"arguments-missing-error" : "Some necessary arguments are missing, refer to --help",
# Client errors
"missing-arguments-error" : "Some necessary arguments are missing, refer to --help",
"server-timeout-error" : "Connection with server timed out",
"mpc-slave-error" : "Unable to start MPC in slave mode!",
"mpc-version-insufficient-error" : "MPC version not sufficient, please use `mpc-hc` >= `{}`",
"mpv-version-error" : "Syncplay is not compatible with this version of mpv. Please use a different version of mpv (e.g. Git HEAD).",
"player-file-open-error" : "Player failed opening file",
"player-path-error" : "Player path is not set properly",
"hostname-empty-error" : "Hostname can't be empty",
"empty-error" : "{} can't be empty", # Configuration
"media-player-error": "Media player error: \"{}\"", # Error line
"unable-import-gui-error": "Could not import GUI libraries. If you do not have PySide installed then you will need to install it for the GUI to work.",
"unable-to-start-client-error" : "Unable to start client",
"arguments-missing-error" : "Some necessary arguments are missing, refer to --help",
"player-path-config-error": "Player path is not set properly",
"no-file-path-config-error" :"File must be selected before starting your player",
"no-hostname-config-error": "Hostname can't be empty",
"invalid-port-config-error" : "Port must be valid",
"empty-value-config-error" : "{} can't be empty", # Config option
"unable-to-start-client-error" : "Unable to start client",
"not-json-error" : "Not a json encoded string\n",
"hello-arguments-error" : "Not enough Hello arguments\n",
"version-mismatch-error" : "Mismatch between versions of client and server\n",
"vlc-failed-connection": "Failed to connect to VLC. If you have not installed syncplay.lua then please refer to http://syncplay.pl/LUA/ for instructions.",
"vlc-failed-noscript": "VLC has reported that the syncplay.lua interface script has not been installed. Please refer to http://syncplay.pl/LUA/ for instructions.",
"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
"player-path-config-error": "Player path is not set properly",
"no-file-path-config-error" :"File must be selected before starting your player",
"no-hostname-config-error": "Hostname can't be empty",
"invalid-port-config-error" : "Port must be valid",
"empty-value-config-error" : "{} can't be empty", # Config option
"not-supported-by-server-error" : "This feature is not supported by the server. The feature requires a server running Syncplay {}+, but the server is running Syncplay {}.", #minVersion, serverVersion
"not-json-error" : "Not a json encoded string\n",
"hello-arguments-error" : "Not enough Hello arguments\n",
"version-mismatch-error" : "Mismatch between versions of client and server\n",
"vlc-failed-connection": "Failed to connect to VLC. If you have not installed syncplay.lua then please refer to http://syncplay.pl/LUA/ for instructions.",
"vlc-failed-noscript": "VLC has reported that the syncplay.lua interface script has not been installed. Please refer to http://syncplay.pl/LUA/ for instructions.",
"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",
"not-supported-by-server-error" : "This feature is not supported by the server. The feature requires a server running Syncplay {}+, but the server is running Syncplay {}.", #minVersion, serverVersion
"switch-file-not-found-error" : u"Could not switch to file '{0}'. Syncplay looks in the folder of the currently playing file and specified media directories.", # File not found
"folder-search-timeout-error" : u"The search for media in '{}' was aborted as it took too long. This will occur if you select a folder with too many sub-folders in your list of media folders to search through. Until Syncplay is restarted only the directory of the currently open file will be checked.", #Folder
"invalid-seek-value" : u"Invalid seek value",
"invalid-offset-value" : u"Invalid offset value",
"failed-to-load-server-list-error" : u"Failed to load public server list. Please visit http://www.syncplay.pl/ in your browser.",
"switch-file-not-found-error" : u"Could not switch to file '{0}'. Syncplay looks in specified media directories.", # File not found
"folder-search-timeout-error" : u"The search for media in media directories was aborted as it took too long to search through '{}'. This will occur if you select a folder with too many sub-folders in your list of media folders to search through. For automatic file switching to work again please select File->Set Media Directories in the menu bar and remove this directory or replace it with an appropriate sub-folder.", #Folder
"folder-search-first-file-timeout-error" : u"The search for media in '{}' was aborted as it took too long to access the directory. This could happen if it is a network drive or if you configure your drive to spin down after a period of inactivity. For automatic file switching to work again please go to File->Set Media Directories and either remove the directory or resolve the issue (e.g. by changing power saving settings).", #Folder
"added-file-not-in-media-directory-error" : u"You loaded a file in '{}' which is not a known media directory. You can add this as a media directory by selecting File->Set Media Directories in the menu bar.", #Folder
"no-media-directories-error" : u"No media directories have been set. For shared playlist and file switching features to work properly please select File->Set Media Directories and specify where Syncplay should look to find media files.",
"cannot-find-directory-error" : u"Could not find media directory '{}'. To update your list of media directories please select File->Set Media Directories from the menu bar and specify where Syncplay should look to find media files.",
# 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',
"nogui-argument" : 'show no GUI',
"host-argument" : 'server\'s address',
"name-argument" : 'desired username',
"debug-argument" : 'debug mode',
"force-gui-prompt-argument" : 'make configuration prompt appear',
"no-store-argument" : 'don\'t store values in .syncplay',
"room-argument" : 'default room',
"password-argument" : 'server password',
"player-path-argument" : 'path to your player executable',
"file-argument" : 'file to play',
"args-argument" : 'player options, if you need to pass options starting with - prepend them with single \'--\' argument',
"clear-gui-data-argument" : 'resets path and window state GUI data stored as QSettings',
"language-argument" :'language for Syncplay messages (de/en/ru)',
"failed-to-load-server-list-error" : u"Failed to load public server list. Please visit http://www.syncplay.pl/ in your browser.",
"version-argument" : 'prints your version',
"version-message" : "You're using Syncplay version {} ({})",
# 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',
"nogui-argument" : 'show no GUI',
"host-argument" : 'server\'s address',
"name-argument" : 'desired username',
"debug-argument" : 'debug mode',
"force-gui-prompt-argument" : 'make configuration prompt appear',
"no-store-argument" : 'don\'t store values in .syncplay',
"room-argument" : 'default room',
"password-argument" : 'server password',
"player-path-argument" : 'path to your player executable',
"file-argument" : 'file to play',
"args-argument" : 'player options, if you need to pass options starting with - prepend them with single \'--\' argument',
"clear-gui-data-argument" : 'resets path and window state GUI data stored as QSettings',
"language-argument" :'language for Syncplay messages (de/en/ru)',
# Client labels
"config-window-title" : "Syncplay configuration",
"version-argument" : 'prints your version',
"version-message" : "You're using Syncplay version {} ({})",
"connection-group-title" : "Connection settings",
"host-label" : "Server address: ",
"name-label" : "Username (optional):",
"password-label" : "Server password (if any):",
"room-label" : "Default room: ",
# Client labels
"config-window-title" : "Syncplay configuration",
"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",
"update-server-list-label" : u"Update list",
"connection-group-title" : "Connection settings",
"host-label" : "Server address: ",
"name-label" : "Username (optional):",
"password-label" : "Server password (if any):",
"room-label" : "Default room: ",
"more-title" : "Show more settings",
"never-rewind-value" : "Never",
"seconds-suffix" : " secs",
"privacy-sendraw-option" : "Send raw",
"privacy-sendhashed-option" : "Send hashed",
"privacy-dontsend-option" : "Don't send",
"filename-privacy-label" : "Filename information:",
"filesize-privacy-label" : "File size information:",
"checkforupdatesautomatically-label" : "Check for Syncplay updates automatically",
"slowondesync-label" : "Slow down on minor desync (not supported on MPC-HC)",
"rewindondesync-label" : "Rewind on major desync (recommended)",
"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 the Syncplay configuration window", # (Inverted)
"nostore-label" : "Don't store this configuration", # (Inverted)
"showosd-label" : "Enable OSD Messages",
"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",
"update-server-list-label" : u"Update list",
"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-operators in managed rooms",
"showdifferentroomosd-label" : "Include events in other rooms",
"showslowdownosd-label" :"Include slowing down / reverting notifications",
"language-label" : "Language:",
"automatic-language" : "Default ({})", # Default language
"showdurationnotification-label" : "Warn about media duration mismatches",
"basics-label" : "Basics",
"readiness-label" : u"Play/Pause",
"misc-label" : u"Misc",
"core-behaviour-title" : "Core room behaviour",
"syncplay-internals-title" : u"Syncplay internals",
"syncplay-mediasearchdirectories-title" : u"Directories to search for media (one path per line)",
"sync-label" : "Sync",
"sync-otherslagging-title" : "If others are lagging behind...",
"sync-youlaggging-title" : "If you are lagging behind...",
"messages-label" : "Messages",
"messages-osd-title" : "On-screen Display settings",
"messages-other-title" : "Other display settings",
"privacy-label" : "Privacy", # Currently unused, but will be brought back if more space is needed in Misc tab
"privacy-title" : "Privacy settings",
"unpause-title" : u"If you press play, set as ready and:",
"unpause-ifalreadyready-option" : u"Unpause if already set as ready",
"unpause-ifothersready-option" : u"Unpause if already ready or others in room are ready (default)",
"unpause-ifminusersready-option" : u"Unpause if already ready or if all others ready and min users ready",
"unpause-always" : u"Always unpause",
"more-title" : "Show more settings",
"never-rewind-value" : "Never",
"seconds-suffix" : " secs",
"privacy-sendraw-option" : "Send raw",
"privacy-sendhashed-option" : "Send hashed",
"privacy-dontsend-option" : "Don't send",
"filename-privacy-label" : "Filename information:",
"filesize-privacy-label" : "File size information:",
"checkforupdatesautomatically-label" : "Check for Syncplay updates automatically",
"slowondesync-label" : "Slow down on minor desync (not supported on MPC-HC)",
"rewindondesync-label" : "Rewind on major desync (recommended)",
"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 the Syncplay configuration window", # (Inverted)
"showosd-label" : "Enable OSD Messages",
"help-label" : "Help",
"reset-label" : "Restore defaults",
"run-label" : "Run Syncplay",
"storeandrun-label" : "Store configuration and run Syncplay",
"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-operators in managed rooms",
"showdifferentroomosd-label" : "Include events in other rooms",
"showslowdownosd-label" :"Include slowing down / reverting notifications",
"language-label" : "Language:",
"automatic-language" : u"Default ({})", # Default language
"showdurationnotification-label" : "Warn about media duration mismatches",
"basics-label" : "Basics",
"readiness-label" : u"Play/Pause",
"misc-label" : u"Misc",
"core-behaviour-title" : "Core room behaviour",
"syncplay-internals-title" : u"Syncplay internals",
"syncplay-mediasearchdirectories-title" : u"Directories to search for media (one path per line)",
"sync-label" : "Sync",
"sync-otherslagging-title" : "If others are lagging behind...",
"sync-youlaggging-title" : "If you are lagging behind...",
"messages-label" : "Messages",
"messages-osd-title" : "On-screen Display settings",
"messages-other-title" : "Other display settings",
"privacy-label" : "Privacy", # Currently unused, but will be brought back if more space is needed in Misc tab
"privacy-title" : "Privacy settings",
"unpause-title" : u"If you press play, set as ready and:",
"unpause-ifalreadyready-option" : u"Unpause if already set as ready",
"unpause-ifothersready-option" : u"Unpause if already ready or others in room are ready (default)",
"unpause-ifminusersready-option" : u"Unpause if already ready or if all others ready and min users ready",
"unpause-always" : u"Always unpause",
"syncplay-trusteddomains-title": u"Trusted domains (for streaming services and hosted content)",
"contact-label" : "Feel free to e-mail <a href=\"mailto:dev@syncplay.pl\"><nobr>dev@syncplay.pl</nobr></a>, chat via the <a href=\"https://webchat.freenode.net/?channels=#syncplay\"><nobr>#Syncplay IRC channel</nobr></a> on irc.freenode.net, <a href=\"https://github.com/Uriziel/syncplay/issues\"><nobr>raise an issue</nobr></a> via GitHub, <a href=\"https://www.facebook.com/SyncplaySoftware\"><nobr>like us on Facebook</nobr></a>, <a href=\"https://twitter.com/Syncplay/\"><nobr>follow us on Twitter</nobr></a>, or visit <a href=\"http://syncplay.pl/\"><nobr>http://syncplay.pl/</nobr></a>",
"help-label" : "Help",
"reset-label" : "Restore defaults",
"run-label" : "Run Syncplay",
"storeandrun-label" : "Store configuration and run Syncplay",
"joinroom-menu-label" : "Join room",
"seektime-menu-label" : "Seek to time",
"undoseek-menu-label" : "Undo seek",
"play-menu-label" : "Play",
"pause-menu-label" : "Pause",
"playbackbuttons-menu-label" : u"Show playback buttons",
"autoplay-menu-label" : u"Show auto-play button",
"autoplay-guipushbuttonlabel" : u"Play when all ready",
"autoplay-minimum-label" : u"Min users:",
"contact-label" : "Feel free to e-mail <a href=\"mailto:dev@syncplay.pl\"><nobr>dev@syncplay.pl</nobr></a>, chat via the <a href=\"https://webchat.freenode.net/?channels=#syncplay\"><nobr>#Syncplay IRC channel</nobr></a> on irc.freenode.net, <a href=\"https://github.com/Uriziel/syncplay/issues\"><nobr>raise an issue</nobr></a> via GitHub, <a href=\"https://www.facebook.com/SyncplaySoftware\"><nobr>like us on Facebook</nobr></a>, <a href=\"https://twitter.com/Syncplay/\"><nobr>follow us on Twitter</nobr></a>, or visit <a href=\"http://syncplay.pl/\"><nobr>http://syncplay.pl/</nobr></a>",
"ready-guipushbuttonlabel" : u"I'm ready to watch!",
"joinroom-label" : "Join room",
"joinroom-menu-label" : u"Join room {}",
"seektime-menu-label" : "Seek to time",
"undoseek-menu-label" : "Undo seek",
"play-menu-label" : "Play",
"pause-menu-label" : "Pause",
"playbackbuttons-menu-label" : u"Show playback buttons",
"autoplay-menu-label" : u"Show auto-play button",
"autoplay-guipushbuttonlabel" : u"Play when all ready",
"autoplay-minimum-label" : u"Min users:",
"roomuser-heading-label" : "Room / User",
"size-heading-label" : "Size",
"duration-heading-label" : "Length",
"filename-heading-label" : "Filename",
"notifications-heading-label" : "Notifications",
"userlist-heading-label" : "List of who is playing what",
"ready-guipushbuttonlabel" : u"I'm ready to watch!",
"browseformedia-label" : "Browse for media files",
"roomuser-heading-label" : "Room / User",
"size-heading-label" : "Size",
"duration-heading-label" : "Length",
"filename-heading-label" : "Filename",
"notifications-heading-label" : "Notifications",
"userlist-heading-label" : "List of who is playing what",
"file-menu-label" : "&File", # & precedes shortcut key
"openmedia-menu-label" : "&Open media file",
"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 managed room",
"identifyascontroller-menu-label" : "&Identify as room operator",
"browseformedia-label" : "Browse for media files",
"playback-menu-label" : u"&Playback",
"file-menu-label" : "&File", # & precedes shortcut key
"openmedia-menu-label" : "&Open media file",
"openstreamurl-menu-label" : "Open &media stream URL",
"setmediadirectories-menu-label" : u"Set media &directories",
"exit-menu-label" : "E&xit",
"advanced-menu-label" : "&Advanced",
"window-menu-label" : "&Window",
"setoffset-menu-label" : "Set &offset",
"createcontrolledroom-menu-label" : "&Create managed room",
"identifyascontroller-menu-label" : "&Identify as room operator",
"settrusteddomains-menu-label" : u"Set &trusted domains",
"help-menu-label" : "&Help",
"userguide-menu-label" : "Open user &guide",
"update-menu-label" : "Check for &update",
"playback-menu-label" : u"&Playback",
"setoffset-msgbox-label" : "Set offset",
"offsetinfo-msgbox-label" : "Offset (see http://syncplay.pl/guide/ for usage instructions):",
"help-menu-label" : "&Help",
"userguide-menu-label" : "Open user &guide",
"update-menu-label" : "Check for &update",
"promptforstreamurl-msgbox-label" : "Open media stream URL",
"promptforstreamurlinfo-msgbox-label" : "Stream URL",
"setoffset-msgbox-label" : "Set offset",
"offsetinfo-msgbox-label" : "Offset (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):",
"promptforstreamurl-msgbox-label" : "Open media stream URL",
"promptforstreamurlinfo-msgbox-label" : "Stream URL",
"identifyascontroller-msgbox-label" : "Identify as room operator",
"identifyinfo-msgbox-label" : "Enter operator password for this room\r\n(see http://syncplay.pl/guide/ for usage instructions):",
"addfolder-label" : u"Add folder",
"public-server-msgbox-label" : u"Select the public server for this viewing session",
"adduris-msgbox-label" : u"Add URLs to playlist (one per line)",
"trusteddomains-msgbox-label" : u"Domains it is okay to automatically switch to (one per line)",
"megabyte-suffix" : " MB",
"createcontrolledroom-msgbox-label" : "Create managed room",
"controlledroominfo-msgbox-label" : "Enter name of managed room\r\n(see http://syncplay.pl/guide/ for usage instructions):",
# Tooltips
"identifyascontroller-msgbox-label" : "Identify as room operator",
"identifyinfo-msgbox-label" : "Enter operator password for this room\r\n(see http://syncplay.pl/guide/ for usage instructions):",
"host-tooltip" : "Hostname or IP to connect to, optionally including port (e.g. syncplay.pl:8999). Only synchronised with people on same server/port.",
"name-tooltip" : "Nickname you will be known by. No registration, so can easily change later. Random name generated if none specified.",
"password-tooltip" : "Passwords are only needed for connecting to private servers.",
"room-tooltip" : "Room to join upon connection can be almost anything, but you will only be synchronised with people in the same room.",
"public-server-msgbox-label" : u"Select the public server for this viewing session",
"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.",
"mediasearcdirectories-arguments-tooltip" : u"Directories where Syncplay will search for media files, e.g. when you are using the click to switch feature. Syncplay will look recursively through sub-folders.",
"megabyte-suffix" : " MB",
"more-tooltip" : "Display less frequently used settings.",
"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.",
"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 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 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-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.",
"language-tooltip" : u"Language to be used by Syncplay.",
"unpause-always-tooltip" : u"If you press unpause it always sets you as ready and unpause, rather than just setting you as ready.",
"unpause-ifalreadyready-tooltip" : u"If you press unpause when not ready it will set you as ready - press unpause again to unpause.",
"unpause-ifothersready-tooltip" : u"If you press unpause when not ready, it will only upause if others are ready.",
"unpause-ifminusersready-tooltip" : u"If you press unpause when not ready, it will only upause if others are ready and minimum users threshold is met.",
# Tooltips
"help-tooltip" : "Opens the Syncplay.pl user guide.",
"reset-tooltip" : "Reset all settings to the default configuration.",
"update-server-list-tooltip" : u"Connect to syncplay.pl to update list of public servers.",
"host-tooltip" : "Hostname or IP to connect to, optionally including port (e.g. syncplay.pl:8999). Only synchronised with people on same server/port.",
"name-tooltip" : "Nickname you will be known by. No registration, so can easily change later. Random name generated if none specified.",
"password-tooltip" : "Passwords are only needed for connecting to private servers.",
"room-tooltip" : "Room to join upon connection can be almost anything, but you will only be synchronised with people in the same room.",
"joinroom-tooltip" : "Leave current room and joins specified room.",
"seektime-msgbox-label" : "Jump to specified time (in seconds / min:sec). Use +/- for relative seek.",
"ready-tooltip" : "Indicates whether you are ready to watch.",
"autoplay-tooltip" : "Auto-play when all users who have readiness indicator are ready and minimum user threshold met.",
"switch-to-file-tooltip" : "Double click to switch to {}", # Filename
"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.",
"mediasearcdirectories-arguments-tooltip" : u"Directories where Syncplay will search for media files, e.g. when you are using the click to switch feature. Syncplay will look recursively through sub-folders.",
# In-userlist notes (GUI)
"differentsize-note" : "Different size!",
"differentsizeandduration-note" : "Different size and duration!",
"differentduration-note" : "Different duration!",
"nofile-note" : "(No file being played)",
"more-tooltip" : "Display less frequently used settings.",
"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.",
"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 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 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-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.",
"language-tooltip" : u"Language to be used by Syncplay.",
"unpause-always-tooltip" : u"If you press unpause it always sets you as ready and unpause, rather than just setting you as ready.",
"unpause-ifalreadyready-tooltip" : u"If you press unpause when not ready it will set you as ready - press unpause again to unpause.",
"unpause-ifothersready-tooltip" : u"If you press unpause when not ready, it will only upause if others are ready.",
"unpause-ifminusersready-tooltip" : u"If you press unpause when not ready, it will only upause if others are ready and minimum users threshold is met.",
"trusteddomains-arguments-tooltip" : u"Domains that it is okay for Syncplay to automatically switch to when shared playlists is enabled.",
# Server messages to client
"new-syncplay-available-motd-message" : "<NOTICE> You are using Syncplay {} but a newer version is available from http://syncplay.pl </NOTICE>", # ClientVersion
"help-tooltip" : "Opens the Syncplay.pl user guide.",
"reset-tooltip" : "Reset all settings to the default configuration.",
"update-server-list-tooltip" : u"Connect to syncplay.pl to update list of public servers.",
# Server notifications
"welcome-server-notification" : "Welcome to Syncplay server, ver. {0}", # version
"client-connected-room-server-notification" : "{0}({2}) connected to room '{1}'", # username, host, room
"client-left-server-notification" : "{0} left server", # name
"no-salt-notification" : "PLEASE NOTE: To allow room operator passwords generated by this server instance to still work when the server is restarted, please add the following command line argument when running the Syncplay server in the future: --salt {}", #Salt
"joinroom-tooltip" : "Leave current room and joins specified room.",
"seektime-msgbox-label" : "Jump to specified time (in seconds / min:sec). Use +/- for relative seek.",
"ready-tooltip" : "Indicates whether you are ready to watch.",
"autoplay-tooltip" : "Auto-play when all users who have readiness indicator are ready and minimum user threshold met.",
"switch-to-file-tooltip" : u"Double click to switch to {}", # Filename
# In-userlist notes (GUI)
"differentsize-note" : "Different size!",
"differentsizeandduration-note" : "Different size and duration!",
"differentduration-note" : "Different duration!",
"nofile-note" : "(No file being played)",
# Server messages to client
"new-syncplay-available-motd-message" : "<NOTICE> You are using Syncplay {} but a newer version is available from http://syncplay.pl </NOTICE>", # ClientVersion
# Server notifications
"welcome-server-notification" : "Welcome to Syncplay server, ver. {0}", # version
"client-connected-room-server-notification" : u"{0}({2}) connected to room '{1}'", # username, host, room
"client-left-server-notification" : u"{0} left server", # name
"no-salt-notification" : "PLEASE NOTE: To allow room operator passwords generated by this server instance to still work when the server is restarted, please add the following command line argument when running the Syncplay server in the future: --salt {}", #Salt
# Server arguments
"server-argument-description" : 'Solution to synchronize playback of multiple MPlayer and MPC-HC instances over the network. Server instance',
"server-argument-epilog" : 'If no options supplied _config values will be used',
"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 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 ($$).",
"server-messed-up-motd-too-long": "Message of the Day is too long - maximum of {} chars, {} given.",
# Server arguments
"server-argument-description" : 'Solution to synchronize playback of multiple MPlayer and MPC-HC instances over the network. Server instance',
"server-argument-epilog" : 'If no options supplied _config values will be used',
"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 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 ($$).",
"server-messed-up-motd-too-long": u"Message of the Day is too long - maximum of {} chars, {} given.",
# Server errors
"unknown-command-server-error" : "Unknown command {}", # message
"not-json-server-error" : "Not a json encoded string {}", # message
"not-known-server-error" : "You must be known to server before sending this command",
"client-drop-server-error" : "Client drop: {} -- {}", # host, error
"password-required-server-error" : "Password required",
"wrong-password-server-error" : "Wrong password supplied",
"hello-server-error" : "Not enough Hello arguments",
}
# Server errors
"unknown-command-server-error" : u"Unknown command {}", # message
"not-json-server-error" : "Not a json encoded string {}", # message
"not-known-server-error" : "You must be known to server before sending this command",
"client-drop-server-error" : u"Client drop: {} -- {}", # host, error
"password-required-server-error" : "Password required",
"wrong-password-server-error" : "Wrong password supplied",
"hello-server-error" : "Not enough Hello arguments",
# Playlists
"playlist-selection-changed-notification" : u"{} changed the playlist selection", # Username
"playlist-contents-changed-notification" : u"{} updated the playlist", # Username
"cannot-find-file-for-playlist-switch-error" : u"Could not find file {} in media directories for playlist switch!", # Filename
"cannot-add-duplicate-error" : u"Could not add second entry for '{}' to the playlist as no duplicates are allowed.", #Filename
"cannot-add-unsafe-path-error" : u"Could not automatically load {} because it is not on a trusted domain. You can switch to the URL manually by double clicking it in the playlist, and add trusted domains via File->Advanced->Set Trusted Domains.", # Filename
"sharedplaylistenabled-label" : u"Enable shared playlists",
"removefromplaylist-menu-label" : u"Remove from playlist",
"shuffleplaylist-menuu-label" : u"Shuffle playlist",
"undoplaylist-menu-label" : u"Undo last change to playlist",
"addfilestoplaylist-menu-label" : u"Add file(s) to bottom of playlist",
"addurlstoplaylist-menu-label" : u"Add URL(s) to bottom of playlist",
"addusersfiletoplaylist-menu-label" : u"Add {} file to playlist", # item owner indicator
"addusersstreamstoplaylist-menu-label" : u"Add {} stream to playlist", # item owner indicator
"openusersstream-menu-label" : u"Open {} stream", # [username]'s
"openusersfile-menu-label" : u"Open {} file", # [username]'s
"item-is-yours-indicator" : u"your", # Goes with addusersfiletoplaylist/addusersstreamstoplaylist
"item-is-others-indicator" : u"{}'s", # username - goes with addusersfiletoplaylist/addusersstreamstoplaylist
"playlist-instruction-item-message" : u"Drag file here to add it to the shared playlist.",
"sharedplaylistenabled-tooltip" : u"Room operators can add files to a synced playlist to make it easy for everyone to watching the same thing. Configure media directories under 'Misc'.",
}

View File

@ -3,371 +3,408 @@
"""Russian dictionary"""
ru = {
"LANGUAGE" : u"Русский", # (Russian)
"LANGUAGE" : u"Русский", # (Russian)
# Client notifications
"config-cleared-notification" : u"Настройки сброшены. Изменения вступят в силу при сохранении корректной конфигурации.",
# Client notifications
"config-cleared-notification" : u"Настройки сброшены. Изменения вступят в силу при сохранении корректной конфигурации.",
"relative-config-notification" : u"Загружен(ы) файл(ы) относительной конфигурации: {}",
"relative-config-notification" : u"Загружен(ы) файл(ы) относительной конфигурации: {}",
"connection-attempt-notification" : u"Подключение к {}:{}", # Port, IP
"reconnection-attempt-notification" : u"Соединение с сервером потеряно, переподключение",
"disconnection-notification" : u"Отключились от сервера",
"connection-failed-notification" : u"Не удалось подключиться к серверу",
"connected-successful-notification" : u"Соединение с сервером установлено",
"retrying-notification" : u"%s, следующая попытка через %d секунд(ы)...", # Seconds
"connection-attempt-notification" : u"Подключение к {}:{}", # Port, IP
"reconnection-attempt-notification" : u"Соединение с сервером потеряно, переподключение",
"disconnection-notification" : u"Отключились от сервера",
"connection-failed-notification" : u"Не удалось подключиться к серверу",
"connected-successful-notification" : u"Соединение с сервером установлено",
"retrying-notification" : u"%s, следующая попытка через %d секунд(ы)...", # Seconds
"rewind-notification" : u"Перемотано из-за разницы во времени с <{}>", # User
"fastforward-notification" : u"Ускорено из-за разницы во времени с <{}>", # User
"slowdown-notification" : u"Воспроизведение замедлено из-за разницы во времени с <{}>", # User
"revert-notification" : u"Возвращаемся к нормальной скорости воспроизведения",
"rewind-notification" : u"Перемотано из-за разницы во времени с <{}>", # User
"fastforward-notification" : u"Ускорено из-за разницы во времени с <{}>", # User
"slowdown-notification" : u"Воспроизведение замедлено из-за разницы во времени с <{}>", # User
"revert-notification" : u"Возвращаемся к нормальной скорости воспроизведения",
"pause-notification" : u"<{}> приостановил(а) воспроизведение", # User
"unpause-notification" : u"<{}> возобновил(а) воспроизведение", # User
"seek-notification" : u"<{}> перемотал с {} на {}", # User, from time, to time
"pause-notification" : u"<{}> приостановил(а) воспроизведение", # User
"unpause-notification" : u"<{}> возобновил(а) воспроизведение", # User
"seek-notification" : u"<{}> перемотал с {} на {}", # User, from time, to time
"current-offset-notification" : u"Текущее смещение: {} секунд(ы)", # Offset
"current-offset-notification" : u"Текущее смещение: {} секунд(ы)", # Offset
"room-join-notification" : u"<{}> зашел(зашла) в комнату: '{}'", # User
"left-notification" : u"<{}> покинул(а) комнату", # User
"left-paused-notification" : u"<{}> покинул(а) комнату, <{}> приостановил(а) воспроизведение", # User who left, User who paused
"playing-notification" : u"<{}> включил '{}' ({})", # User, file, duration
"playing-notification/room-addendum" : u" в комнате: '{}'", # Room
"media-directory-list-updated-notification" : u"Syncplay media directories have been updated.", # TODO: Translate
"not-all-ready" : u"Не готовы: {}", # Usernames
"all-users-ready" : u"Все пользователи готовы ({} чел.)", #Number of ready users
"ready-to-unpause-notification" : u"Вы помечены как готовый - нажмите еще раз, чтобы продолжить воспроизведение",
"set-as-ready-notification" : u"Вы помечены как готовый",
"set-as-not-ready-notification" : u"Вы помечены как неготовый",
"autoplaying-notification" : u"Автовоспроизведение через {}...", # Number of seconds until playback will start
"room-join-notification" : u"<{}> зашел(зашла) в комнату: '{}'", # User
"left-notification" : u"<{}> покинул(а) комнату", # User
"left-paused-notification" : u"<{}> покинул(а) комнату, <{}> приостановил(а) воспроизведение", # User who left, User who paused
"playing-notification" : u"<{}> включил '{}' ({})", # User, file, duration
"playing-notification/room-addendum" : u" в комнате: '{}'", # Room
"identifying-as-controller-notification" : u"Идентификация как оператора комнаты с паролем '{}'...",
"failed-to-identify-as-controller-notification" : u"<{}> не прошел идентификацию в качестве оператора комнаты.",
"authenticated-as-controller-notification" : u"<{}> вошел как оператор комнаты.",
"created-controlled-room-notification" : u"Создана управляемая комната '{}' с паролем '{}'. Сохраните эти данные!", # RoomName, operatorPassword
"not-all-ready" : u"Не готовы: {}", # Usernames
"all-users-ready" : u"Все пользователи готовы ({} чел.)", #Number of ready users
"ready-to-unpause-notification" : u"Вы помечены как готовый - нажмите еще раз, чтобы продолжить воспроизведение",
"set-as-ready-notification" : u"Вы помечены как готовый",
"set-as-not-ready-notification" : u"Вы помечены как неготовый",
"autoplaying-notification" : u"Автовоспроизведение через {}...", # Number of seconds until playback will start
"file-different-notification" : u"Вероятно, файл, который Вы смотрите, отличается от того, который смотрит <{}>.", # User
"file-differences-notification" : u"Ваш файл отличается: {}", # Differences
"room-file-differences" : u"Несовпадения файла: {}", # File differences (filename, size, and/or duration)
"file-difference-filename" : u"имя",
"file-difference-filesize" : u"размер",
"file-difference-duration" : u"длительность",
"alone-in-the-room" : u"В этой комнате кроме Вас никого нет.",
"identifying-as-controller-notification" : u"Идентификация как оператора комнаты с паролем '{}'...",
"failed-to-identify-as-controller-notification" : u"<{}> не прошел идентификацию в качестве оператора комнаты.",
"authenticated-as-controller-notification" : u"<{}> вошел как оператор комнаты.",
"created-controlled-room-notification" : u"Создана управляемая комната '{}' с паролем '{}'. Сохраните эти данные!", # RoomName, operatorPassword
"different-filesize-notification" : u" (размер Вашего файла не совпадает с размером их файла!)",
"userlist-playing-notification" : u"{} смотрит:", #Username
"file-played-by-notification" : u"Файл: {} просматривают:", # File
"no-file-played-notification" : u"{} не смотрит ничего", # Username
"notplaying-notification" : u"Люди, которые не смотрят ничего:",
"userlist-room-notification" : u"В комнате '{}':", # Room
"userlist-file-notification" : u"Файл",
"controller-userlist-userflag" : u"Оператор",
"ready-userlist-userflag" : u"Готов",
"file-different-notification" : u"Вероятно, файл, который Вы смотрите, отличается от того, который смотрит <{}>.", # User
"file-differences-notification" : u"Ваш файл отличается: {}", # Differences
"room-file-differences" : u"Несовпадения файла: {}", # File differences (filename, size, and/or duration)
"file-difference-filename" : u"имя",
"file-difference-filesize" : u"размер",
"file-difference-duration" : u"длительность",
"alone-in-the-room" : u"В этой комнате кроме Вас никого нет.",
"update-check-failed-notification" : u"Невозможно автоматически проверить, что версия Syncplay {} все еще актуальна. Хотите зайти на http://syncplay.pl/ и вручную проверить наличие обновлений?",
"syncplay-uptodate-notification" : u"Syncplay обновлен",
"syncplay-updateavailable-notification" : u"Доступна новая версия Syncplay. Хотите открыть страницу релиза?",
"different-filesize-notification" : u" (размер Вашего файла не совпадает с размером их файла!)",
"userlist-playing-notification" : u"{} смотрит:", #Username
"file-played-by-notification" : u"Файл: {} просматривают:", # File
"no-file-played-notification" : u"{} не смотрит ничего", # Username
"notplaying-notification" : u"Люди, которые не смотрят ничего:",
"userlist-room-notification" : u"В комнате '{}':", # Room
"userlist-file-notification" : u"Файл",
"controller-userlist-userflag" : u"Оператор",
"ready-userlist-userflag" : u"Готов",
"mplayer-file-required-notification" : u"Для использования Syncplay с mplayer необходимо передать файл в качестве параметра",
"mplayer-file-required-notification/example" : u"Пример использования: syncplay [options] [url|path/]filename",
"mplayer2-required" : u"Syncplay не совместим с MPlayer 1.x, пожалуйста, используйте mplayer2 или mpv",
"update-check-failed-notification" : u"Невозможно автоматически проверить, что версия Syncplay {} все еще актуальна. Хотите зайти на http://syncplay.pl/ и вручную проверить наличие обновлений?",
"syncplay-uptodate-notification" : u"Syncplay обновлен",
"syncplay-updateavailable-notification" : u"Доступна новая версия Syncplay. Хотите открыть страницу релиза?",
"unrecognized-command-notification" : u"Неизвестная команда.",
"commandlist-notification" : u"Доступные команды:",
"commandlist-notification/room" : u"\tr [name] - сменить комнату",
"commandlist-notification/list" : u"\tl - показать список пользователей",
"commandlist-notification/undo" : u"\tu - отменить последнюю перемотку",
"commandlist-notification/pause" : u"\tp - вкл./выкл. паузу",
"commandlist-notification/seek" : u"\t[s][+-]time - перемотать к заданному моменту времени, если не указан + или -, то время считается абсолютным (от начала файла) в секундах или мин:сек",
"commandlist-notification/help" : u"\th - помощь",
"commandlist-notification/toggle" : u"\tt - переключить статус готов/неготов к просмотру",
"commandlist-notification/create" : u"\tc [name] - создать управляемую комнату с таким же именем, как у текущей",
"commandlist-notification/auth" : u"\ta [password] - авторизоваться как оператор комнаты с помощью пароля",
"syncplay-version-notification" : u"Версия Syncplay: {}", # syncplay.version
"more-info-notification" : u"Больше информации на {}", # projectURL
"mplayer-file-required-notification" : u"Для использования Syncplay с mplayer необходимо передать файл в качестве параметра",
"mplayer-file-required-notification/example" : u"Пример использования: syncplay [options] [url|path/]filename",
"mplayer2-required" : u"Syncplay не совместим с MPlayer 1.x, пожалуйста, используйте mplayer2 или mpv",
"gui-data-cleared-notification" : u"Syncplay очистил путь и информацию о состоянии окна, использованного GUI.",
"language-changed-msgbox-label" : u"Язык переключится при следующем запуске SYncplay.",
"promptforupdate-label" : u"Вы не против, если Syncplay будет автоматически изредка проверять наличие обновлений?",
"unrecognized-command-notification" : u"Неизвестная команда.",
"commandlist-notification" : u"Доступные команды:",
"commandlist-notification/room" : u"\tr [name] - сменить комнату",
"commandlist-notification/list" : u"\tl - показать список пользователей",
"commandlist-notification/undo" : u"\tu - отменить последнюю перемотку",
"commandlist-notification/pause" : u"\tp - вкл./выкл. паузу",
"commandlist-notification/seek" : u"\t[s][+-]time - перемотать к заданному моменту времени, если не указан + или -, то время считается абсолютным (от начала файла) в секундах или мин:сек",
"commandlist-notification/help" : u"\th - помощь",
"commandlist-notification/toggle" : u"\tt - переключить статус готов/неготов к просмотру",
"commandlist-notification/create" : u"\tc [name] - создать управляемую комнату с таким же именем, как у текущей",
"commandlist-notification/auth" : u"\ta [password] - авторизоваться как оператор комнаты с помощью пароля",
"syncplay-version-notification" : u"Версия Syncplay: {}", # syncplay.version
"more-info-notification" : u"Больше информации на {}", # projectURL
"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
"vlc-interface-oldversion-warning" : u"Внимание: Syncplay обнаружил, что старая версия модуля интерфейса Syncplay для VLC уже установлена в директорию VLC. Пожалуйста, обратитесь к Руководству Пользователя Syncplay (http://syncplay.pl/guide/) за инструкциями о том, как установить syncplay.lua.",
"vlc-interface-not-installed" : u"Внимание: Модуль интерфейса Syncplay для VLC не обнаружен в директории VLC. По существу, если Вы используете VLC 2.0, то VLC будет использовать модуль syncplay.lua из директории Syncplay, но в таком случае другие пользовательские скрипты и расширения интерфейса не будут работать. Пожалуйста, обратитесь к Руководству Пользователя Syncplay (http://syncplay.pl/guide/) за инструкциями о том, как установить syncplay.lua.",
"media-player-latency-warning": u"Внимание: У Вашего проигрывателя слишком большой отклик ({} секунд). Если Вы замечаете проблемы с синхронизацией, то закройте ресурсоемкие приложения, а если это не помогло - попробуйте другой проигрыватель.", # Seconds to respond
"mpv-unresponsive-error": u"mpv has not responded for {} seconds so appears to have malfunctioned. Please restart Syncplay.", # Seconds to respond # TODO: Translate to Russian
"gui-data-cleared-notification" : u"Syncplay очистил путь и информацию о состоянии окна, использованного GUI.",
"language-changed-msgbox-label" : u"Язык переключится при следующем запуске SYncplay.",
"promptforupdate-label" : u"Вы не против, если Syncplay будет автоматически изредка проверять наличие обновлений?",
# Client prompts
"enter-to-exit-prompt" : u"Для выхода нажмите Enter\n",
"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
"vlc-interface-oldversion-warning" : u"Внимание: Syncplay обнаружил, что старая версия модуля интерфейса Syncplay для VLC уже установлена в директорию VLC. Пожалуйста, обратитесь к Руководству Пользователя Syncplay (http://syncplay.pl/guide/) за инструкциями о том, как установить syncplay.lua.",
"vlc-interface-not-installed" : u"Внимание: Модуль интерфейса Syncplay для VLC не обнаружен в директории VLC. По существу, если Вы используете VLC 2.0, то VLC будет использовать модуль syncplay.lua из директории Syncplay, но в таком случае другие пользовательские скрипты и расширения интерфейса не будут работать. Пожалуйста, обратитесь к Руководству Пользователя Syncplay (http://syncplay.pl/guide/) за инструкциями о том, как установить syncplay.lua.",
"media-player-latency-warning": u"Внимание: У Вашего проигрывателя слишком большой отклик ({} секунд). Если Вы замечаете проблемы с синхронизацией, то закройте ресурсоемкие приложения, а если это не помогло - попробуйте другой проигрыватель.", # Seconds to respond
"mpv-unresponsive-error": u"mpv has not responded for {} seconds so appears to have malfunctioned. Please restart Syncplay.", # Seconds to respond # TODO: Translate to Russian
# Client errors
"missing-arguments-error" : u"Некоторые необходимые аргументы отсутствуют, обратитесь к --help",
"server-timeout-error" : u"Подключение к серверу превысило лимит времени",
"mpc-slave-error" : u"Невозможно запустить MPC в slave режиме!",
"mpc-version-insufficient-error" : u"Версия MPC слишком старая, пожалуйста, используйте `mpc-hc` >= `{}`",
"mpv-version-error" : u"Syncplay не совместим с данной версией mpv. Пожалуйста, используйте другую версию mpv (лучше свежайшую).",
"player-file-open-error" : u"Проигрыватель не может открыть файл.",
"player-path-error" : u"Путь к проигрывателю задан неверно.",
"hostname-empty-error" : u"Имя пользователя не может быть пустым.",
"empty-error" : u"{} не может быть пустым.", # Configuration
"media-player-error" : u"Ошибка проигрывателя: \"{}\"", # Error line
"unable-import-gui-error" : u"Невозможно импортировать библиотеки GUI (графического интерфейса). Необходимо установить PySide, иначе графический интерфейс не будет работать.",
# Client prompts
"enter-to-exit-prompt" : u"Для выхода нажмите Enter\n",
"arguments-missing-error" : u"Некоторые необходимые аргументы отсутствуют, обратитесь к --help",
# Client errors
"missing-arguments-error" : u"Некоторые необходимые аргументы отсутствуют, обратитесь к --help",
"server-timeout-error" : u"Подключение к серверу превысило лимит времени",
"mpc-slave-error" : u"Невозможно запустить MPC в slave режиме!",
"mpc-version-insufficient-error" : u"Версия MPC слишком старая, пожалуйста, используйте `mpc-hc` >= `{}`",
"mpv-version-error" : u"Syncplay не совместим с данной версией mpv. Пожалуйста, используйте другую версию mpv (лучше свежайшую).",
"player-file-open-error" : u"Проигрыватель не может открыть файл.",
"player-path-error" : u"Путь к проигрывателю задан неверно.",
"hostname-empty-error" : u"Имя пользователя не может быть пустым.",
"empty-error" : u"{} не может быть пустым.", # Configuration
"media-player-error" : u"Ошибка проигрывателя: \"{}\"", # Error line
"unable-import-gui-error" : u"Невозможно импортировать библиотеки GUI (графического интерфейса). Необходимо установить PySide, иначе графический интерфейс не будет работать.",
"unable-to-start-client-error" : u"Невозможно запустить клиент",
"arguments-missing-error" : u"Некоторые необходимые аргументы отсутствуют, обратитесь к --help",
"player-path-config-error": u"Путь к проигрывателю установлен неверно",
"no-file-path-config-error" : u"Файл должен быть указан до включения проигрывателя",
"no-hostname-config-error": u"Имя сервера не может быть пустым",
"invalid-port-config-error" : u"Неверный номер порта",
"empty-value-config-error" : u"Поле '{}' не может быть пустым", # Config option
"unable-to-start-client-error" : u"Невозможно запустить клиент",
"not-json-error" : u"Не является закодированной json-строкой\n",
"hello-arguments-error" : u"Не хватает аргументов Hello\n",
"version-mismatch-error" : u"Конфликт версий между клиентом и сервером\n",
"vlc-failed-connection" : u"Ошибка подключения к VLC. Если у Вас не установлен syncplay.lua, то обратитесь к http://syncplay.pl/LUA/ за инструкциями.",
"vlc-failed-noscript" : u"VLC сообщает, что скрипт интерфейса syncplay.lua не установлен. Пожалуйста, обратитесь к http://syncplay.pl/LUA/ за инструкциями.",
"vlc-failed-versioncheck" : u"Данная версия VLC не поддерживается Syncplay. Пожалуйста, используйте VLC версии 2 или выше.",
"vlc-failed-other" : u"Во время загрузки скрипта интерфейса syncplay.lua в VLC произошла следующая ошибка: {}", # Syncplay Error
"player-path-config-error": u"Путь к проигрывателю установлен неверно",
"no-file-path-config-error" : u"Файл должен быть указан до включения проигрывателя",
"no-hostname-config-error": u"Имя сервера не может быть пустым",
"invalid-port-config-error" : u"Неверный номер порта",
"empty-value-config-error" : u"Поле '{}' не может быть пустым", # Config option
"not-supported-by-server-error" : u"Эта возможность не поддерживается сервером. The feature requires a server running Syncplay {}+, but the server is running Syncplay {}.", #minVersion, serverVersion #TODO: Translate into Russian
"not-json-error" : u"Не является закодированной json-строкой\n",
"hello-arguments-error" : u"Не хватает аргументов Hello\n",
"version-mismatch-error" : u"Конфликт версий между клиентом и сервером\n",
"vlc-failed-connection" : u"Ошибка подключения к VLC. Если у Вас не установлен syncplay.lua, то обратитесь к http://syncplay.pl/LUA/ за инструкциями.",
"vlc-failed-noscript" : u"VLC сообщает, что скрипт интерфейса syncplay.lua не установлен. Пожалуйста, обратитесь к http://syncplay.pl/LUA/ за инструкциями.",
"vlc-failed-versioncheck" : u"Данная версия VLC не поддерживается Syncplay. Пожалуйста, используйте VLC версии 2 или выше.",
"vlc-failed-other" : u"Во время загрузки скрипта интерфейса syncplay.lua в VLC произошла следующая ошибка: {}", # Syncplay Error
"invalid-seek-value" : u"Некорректное значение для перемотки",
"invalid-offset-value" : u"Некорректное смещение",
"not-supported-by-server-error" : u"Эта возможность не поддерживается сервером. The feature requires a server running Syncplay {}+, but the server is running Syncplay {}.", #minVersion, serverVersion #TODO: Translate into Russian
"switch-file-not-found-error" : u"Невозможно переключиться на файл '{0}'. Syncplay looks in the folder of the currently playing file and specified media directories.", # File not found # TODO: Translate last part into Russian
"folder-search-timeout-error" : u"The search for media in '{}' was aborted as it took too long. This will occur if you select a folder with too many sub-folders in your list of media folders to search through. Until Syncplay is restarted only the directory of the currently open file will be checked.", #Folder # TODO: Translate into Russian
"invalid-seek-value" : u"Некорректное значение для перемотки",
"invalid-offset-value" : u"Некорректное смещение",
"failed-to-load-server-list-error" : u"Failed to load public server list. Please visit http://www.syncplay.pl/ in your browser.", # TODO: Translate into Russian
"switch-file-not-found-error" : u"Невозможно переключиться на файл '{0}'. Syncplay looks in the folder specified media directories.", # File not found # TODO: Translate last part into Russian
"folder-search-timeout-error" : u"The search for media in media directories was aborted as it took too long to search through '{}'. This will occur if you select a folder with too many sub-folders in your list of media folders to search through. For automatic file switching to work again please select File->Set Media Directories in the menu bar and remove this directory or replace it with an appropriate sub-folder.", #Folder # TODO: Translate
"folder-search-first-file-timeout-error" : u"The search for media in '{}' was aborted as it took too long to access the directory. This could happen if it is a network drive or if you configure your drive to spin down after a period of inactivity. For automatic file switching to work again please go to File->Set Media Directories and either remove the directory or resolve the issue (e.g. by changing power saving settings).", #Folder # TODO: Translate
"added-file-not-in-media-directory-error" : u"You loaded a file in '{}' which is not a known media directory. You can add this as a media directory by selecting File->Set Media Directories in the menu bar.", #Folder #TODO: Translate
"no-media-directories-error" : u"No media directories have been set. For shared playlist and file switching features to work properly please select File->Set Media Directories and specify where Syncplay should look to find media files.", # TODO: Translate
"cannot-find-directory-error" : u"Could not find media directory '{}'. To update your list of media directories please select File->Set Media Directories from the menu bar and specify where Syncplay should look to find media files.", # TODO: Translate
# Client arguments
"argument-description" : u'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC через Интернет.',
"argument-epilog" : u'Если параметр не будет передан, то будет использоваться значение, указанное в _config.',
"nogui-argument" : u'не использовать GUI',
"host-argument" : u'адрес сервера',
"name-argument" : u'желательное имя пользователя',
"debug-argument" : u'режим отладки',
"force-gui-prompt-argument" : u'показать окно настройки',
"no-store-argument" : u'не сохранять данные в .syncplay',
"room-argument" : u'начальная комната',
"password-argument" : u'пароль для доступа к серверу',
"player-path-argument" : u'путь к исполняемому файлу Вашего проигрывателя',
"file-argument" : u'воспроизводимый файл',
"args-argument" : u'параметры проигрывателя; если нужно передать параметры, начинающиеся с - , то сначала пишите \'--\'',
"clear-gui-data-argument" : u'сбрасывает путь и данные о состоянии окна GUI, хранимые как QSettings',
"language-argument" : u'язык сообщений Syncplay (de/en/ru)',
"failed-to-load-server-list-error" : u"Failed to load public server list. Please visit http://www.syncplay.pl/ in your browser.", # TODO: Translate into Russian
"version-argument" : u'выводит номер версии',
"version-message" : u"Вы используете Syncplay версии {} ({})",
# Client arguments
"argument-description" : u'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC через Интернет.',
"argument-epilog" : u'Если параметр не будет передан, то будет использоваться значение, указанное в _config.',
"nogui-argument" : u'не использовать GUI',
"host-argument" : u'адрес сервера',
"name-argument" : u'желательное имя пользователя',
"debug-argument" : u'режим отладки',
"force-gui-prompt-argument" : u'показать окно настройки',
"no-store-argument" : u'не сохранять данные в .syncplay',
"room-argument" : u'начальная комната',
"password-argument" : u'пароль для доступа к серверу',
"player-path-argument" : u'путь к исполняемому файлу Вашего проигрывателя',
"file-argument" : u'воспроизводимый файл',
"args-argument" : u'параметры проигрывателя; если нужно передать параметры, начинающиеся с - , то сначала пишите \'--\'',
"clear-gui-data-argument" : u'сбрасывает путь и данные о состоянии окна GUI, хранимые как QSettings',
"language-argument" : u'язык сообщений Syncplay (de/en/ru)',
# Client labels
"config-window-title" : u"Настройка Syncplay",
"version-argument" : u'выводит номер версии',
"version-message" : u"Вы используете Syncplay версии {} ({})",
"connection-group-title" : u"Параметры подключения",
"host-label" : u"Адрес сервера: ",
"name-label" : u"Имя пользователя (не обязательно):",
"password-label" : u"Пароль к серверу (если требуется):",
"room-label" : u"Начальная комната: ",
# Client labels
"config-window-title" : u"Настройка Syncplay",
"media-setting-title" : u"Параметры проигрывателя",
"executable-path-label" : u"Путь к проигрывателю:",
"media-path-label" : u"Путь к видеофайлу:",
"player-arguments-label" : u"Аргументы для запуска проигрывателя:",
"browse-label" : u"Выбрать",
"update-server-list-label" : u"Update list", # TODO: Translate into Russian
"connection-group-title" : u"Параметры подключения",
"host-label" : u"Адрес сервера: ",
"name-label" : u"Имя пользователя (не обязательно):",
"password-label" : u"Пароль к серверу (если требуется):",
"room-label" : u"Начальная комната: ",
"more-title" : u"Больше настроек",
"never-rewind-value" : u"Никогда",
"seconds-suffix" : u" секунд(ы)",
"privacy-sendraw-option" : u"отпр. как есть",
"privacy-sendhashed-option" : u"отпр. хэш",
"privacy-dontsend-option" : u"не отпр.",
"filename-privacy-label" : u"Имя файла:",
"filesize-privacy-label" : u"Размер файла:",
"checkforupdatesautomatically-label" : u"Проверять обновления автоматически",
"slowondesync-label" : u"Замедлять при небольших рассинхронизациях (не поддерживаетя в MPC-HC)",
"rewindondesync-label" : u"Перемотка при больших рассинхронизациях (настоятельно рекомендуется)",
"dontslowdownwithme-label" : u"Никогда не замедлять и не перематывать видео другим (функция тестируется)",
"pauseonleave-label" : u"Приостанавливать, когда кто-то уходит (например, отключился)",
"readyatstart-label" : u"Выставить статус 'готово к просмотру' по умолчанию",
"fastforwardondesync-label" : u"Ускорять видео при отставании (рекомендуется)",
"forceguiprompt-label" : u"Не показывать больше этот диалог", # (Inverted)
"nostore-label" : u"Не сохранять текущую конфигурацию", # (Inverted)
"showosd-label" : u"Включить экранные сообщения (поверх видео)",
"media-setting-title" : u"Параметры проигрывателя",
"executable-path-label" : u"Путь к проигрывателю:",
"media-path-label" : u"Путь к видеофайлу:",
"player-arguments-label" : u"Аргументы для запуска проигрывателя:",
"browse-label" : u"Выбрать",
"update-server-list-label" : u"Update list", # TODO: Translate into Russian
"showosdwarnings-label" : u"Показывать предупреждения (напр., когда файлы не совпадают)",
"showsameroomosd-label" : u"Показывать события Вашей комнаты",
"shownoncontrollerosd-label" : u"Включить события, связанные с не-операторами в управляемой комнате.",
"showdifferentroomosd-label" : u"Показывать события других комнат",
"showslowdownosd-label" : u"Показывать уведомления о замедлении/перемотке",
"language-label" : u"Язык:",
"automatic-language" : u"По умолчанию ({})", # Automatic language
"showdurationnotification-label" : u"Предупреждать о несовпадении продолжительности видео",
"basics-label" : u"Основное",
"readiness-label" : u"Воспроизведение/Пауза", # TODO: Confirm translation of play/pause
"misc-label" : u"Прочее",
"core-behaviour-title" : u"Core room behaviour", # TODO: Translate into Russian
"syncplay-internals-title" : u"Syncplay internals", # TODO: Translate into Russian
"syncplay-mediasearchdirectories-title" : u"Directories to search for media (one path per line)", # TODO: Translate into Russian
"sync-label" : u"Синхронизация",
"sync-otherslagging-title" : u"При отставании других зрителей...",
"sync-youlaggging-title" : u"Когда я отстаю ...",
"messages-label" : u"Сообщения",
"messages-osd-title" : u"Настройки OSD",
"messages-other-title" : u"Другие настройки отображения",
"privacy-label" : u"Приватность",
"privacy-title" : u"Настройки приватности",
"unpause-title" : u"If you press play, set as ready and:", # TODO: Translate into Russian
"unpause-ifalreadyready-option" : u"Unpause if already set as ready", # TODO: Translate into Russian
"unpause-ifothersready-option" : u"Unpause if already ready or others in room are ready (default)", # TODO: Translate into Russian
"unpause-ifminusersready-option" : u"Unpause if already ready or if all others ready and min users ready", # TODO: Translate into Russian
"unpause-always" : u"Always unpause", # TODO: Translate into Russian
"more-title" : u"Больше настроек",
"never-rewind-value" : u"Никогда",
"seconds-suffix" : u" секунд(ы)",
"privacy-sendraw-option" : u"отпр. как есть",
"privacy-sendhashed-option" : u"отпр. хэш",
"privacy-dontsend-option" : u"не отпр.",
"filename-privacy-label" : u"Имя файла:",
"filesize-privacy-label" : u"Размер файла:",
"checkforupdatesautomatically-label" : u"Проверять обновления автоматически",
"slowondesync-label" : u"Замедлять при небольших рассинхронизациях (не поддерживаетя в MPC-HC)",
"rewindondesync-label" : u"Перемотка при больших рассинхронизациях (настоятельно рекомендуется)",
"dontslowdownwithme-label" : u"Никогда не замедлять и не перематывать видео другим (функция тестируется)",
"pauseonleave-label" : u"Приостанавливать, когда кто-то уходит (например, отключился)",
"readyatstart-label" : u"Выставить статус 'готово к просмотру' по умолчанию",
"fastforwardondesync-label" : u"Ускорять видео при отставании (рекомендуется)",
"forceguiprompt-label" : u"Не показывать больше этот диалог", # (Inverted)
"showosd-label" : u"Включить экранные сообщения (поверх видео)",
"help-label" : u"Помощь",
"reset-label" : u"Сброс настроек",
"run-label" : u"Запустить Syncplay",
"storeandrun-label" : u"Сохранить настройки и зап. Syncplay",
"showosdwarnings-label" : u"Показывать предупреждения (напр., когда файлы не совпадают)",
"showsameroomosd-label" : u"Показывать события Вашей комнаты",
"shownoncontrollerosd-label" : u"Включить события, связанные с не-операторами в управляемой комнате.",
"showdifferentroomosd-label" : u"Показывать события других комнат",
"showslowdownosd-label" : u"Показывать уведомления о замедлении/перемотке",
"language-label" : u"Язык:",
"automatic-language" : u"По умолчанию ({})", # Automatic language
"showdurationnotification-label" : u"Предупреждать о несовпадении продолжительности видео",
"basics-label" : u"Основное",
"readiness-label" : u"Воспроизведение/Пауза", # TODO: Confirm translation of play/pause
"misc-label" : u"Прочее",
"core-behaviour-title" : u"Core room behaviour", # TODO: Translate into Russian
"syncplay-internals-title" : u"Syncplay internals", # TODO: Translate into Russian
"syncplay-mediasearchdirectories-title" : u"Directories to search for media (one path per line)", # TODO: Translate into Russian
"sync-label" : u"Синхронизация",
"sync-otherslagging-title" : u"При отставании других зрителей...",
"sync-youlaggging-title" : u"Когда я отстаю ...",
"messages-label" : u"Сообщения",
"messages-osd-title" : u"Настройки OSD",
"messages-other-title" : u"Другие настройки отображения",
"privacy-label" : u"Приватность",
"privacy-title" : u"Настройки приватности",
"unpause-title" : u"If you press play, set as ready and:", # TODO: Translate into Russian
"unpause-ifalreadyready-option" : u"Unpause if already set as ready", # TODO: Translate into Russian
"unpause-ifothersready-option" : u"Unpause if already ready or others in room are ready (default)", # TODO: Translate into Russian
"unpause-ifminusersready-option" : u"Unpause if already ready or if all others ready and min users ready", # TODO: Translate into Russian
"unpause-always" : u"Always unpause", # TODO: Translate into Russian
"syncplay-trusteddomains-title": u"Trusted domains (for streaming services and hosted content)", # TODO: Translate into Russian
"contact-label" : u"Есть идея, нашли ошибку или хотите оставить отзыв? Пишите на <a href=\"mailto:dev@syncplay.pl\">dev@syncplay.pl</a>, в <a href=\"https://webchat.freenode.net/?channels=#syncplay\">IRC канал #Syncplay</a> на irc.freenode.net или <a href=\"https://github.com/Uriziel/syncplay/issues\">задавайте вопросы через GitHub</a>. Кроме того, заходите на <a href=\"http://syncplay.pl/\">http://syncplay.pl/</a> за инорфмацией, помощью и обновлениями!",
"help-label" : u"Помощь",
"reset-label" : u"Сброс настроек",
"run-label" : u"Запустить Syncplay",
"storeandrun-label" : u"Сохранить настройки и зап. Syncplay",
"joinroom-menu-label" : u"Зайти в комнату",
"seektime-menu-label" : u"Перемотать",
"undoseek-menu-label" : u"Отменить перемотку",
"play-menu-label" : u"Play",
"pause-menu-label" : u"Пауза",
"playbackbuttons-menu-label" : u"Показывать кнопки воспроизведения",
"autoplay-menu-label" : u"Показывать кнопку автовоспроизведения",
"autoplay-guipushbuttonlabel" : u"Воспроизвести автоматически, когда все будут готовы",
"autoplay-minimum-label" : u"Минимум пользователей:",
"contact-label" : u"Есть идея, нашли ошибку или хотите оставить отзыв? Пишите на <a href=\"mailto:dev@syncplay.pl\">dev@syncplay.pl</a>, в <a href=\"https://webchat.freenode.net/?channels=#syncplay\">IRC канал #Syncplay</a> на irc.freenode.net или <a href=\"https://github.com/Uriziel/syncplay/issues\">задавайте вопросы через GitHub</a>. Кроме того, заходите на <a href=\"http://syncplay.pl/\">http://syncplay.pl/</a> за инорфмацией, помощью и обновлениями!",
"ready-guipushbuttonlabel" : u"Я готов к просмотру!",
"joinroom-label" : u"Зайти в комнату",
"joinroom-menu-label" : u"Зайти в комнату {}", #TODO: Might want to fix this
"seektime-menu-label" : u"Перемотать",
"undoseek-menu-label" : u"Отменить перемотку",
"play-menu-label" : u"Play",
"pause-menu-label" : u"Пауза",
"playbackbuttons-menu-label" : u"Показывать кнопки воспроизведения",
"autoplay-menu-label" : u"Показывать кнопку автовоспроизведения",
"autoplay-guipushbuttonlabel" : u"Воспроизвести автоматически, когда все будут готовы",
"autoplay-minimum-label" : u"Минимум пользователей:",
"roomuser-heading-label" : u"Комната / Пользователь",
"size-heading-label" : u"Размер",
"duration-heading-label" : u"Длительность",
"filename-heading-label" : u"Имя файла",
"notifications-heading-label" : u"Уведомления",
"userlist-heading-label" : u"Кто что смотрит",
"ready-guipushbuttonlabel" : u"Я готов к просмотру!",
"browseformedia-label" : u"Выбрать видеофайл",
"roomuser-heading-label" : u"Комната / Пользователь",
"size-heading-label" : u"Размер",
"duration-heading-label" : u"Длительность",
"filename-heading-label" : u"Имя файла",
"notifications-heading-label" : u"Уведомления",
"userlist-heading-label" : u"Кто что смотрит",
"file-menu-label" : u"&Файл", # & precedes shortcut key
"openmedia-menu-label" : u"&Открыть видеофайл",
"openstreamurl-menu-label" : u"Открыть URL &потокового вещания",
"exit-menu-label" : u"&Выход",
"advanced-menu-label" : u"&Дополнительно",
"window-menu-label" : u"&Окна",
"setoffset-menu-label" : u"Установить &смещение",
"createcontrolledroom-menu-label" : u"&Создать управляемую комнату",
"identifyascontroller-menu-label" : u"&Войти как оператор комнаты",
"browseformedia-label" : u"Выбрать видеофайл",
"playback-menu-label" : u"&Воспроизведение",
"file-menu-label" : u"&Файл", # & precedes shortcut key
"openmedia-menu-label" : u"&Открыть видеофайл",
"openstreamurl-menu-label" : u"Открыть URL &потокового вещания",
"setmediadirectories-menu-label" : u"Set media &directories", # TODO: Translate
"exit-menu-label" : u"&Выход",
"advanced-menu-label" : u"&Дополнительно",
"window-menu-label" : u"&Окна",
"setoffset-menu-label" : u"Установить &смещение",
"createcontrolledroom-menu-label" : u"&Создать управляемую комнату",
"identifyascontroller-menu-label" : u"&Войти как оператор комнаты",
"settrusteddomains-menu-label" : u"Set &trusted domains", # TODO: Translate
"help-menu-label" : u"&Помощь",
"userguide-menu-label" : u"&Руководство Пользователя",
"update-menu-label" : u"Проверить &обновления",
"playback-menu-label" : u"&Воспроизведение",
"setoffset-msgbox-label" : u"Установить смещение",
"offsetinfo-msgbox-label" : u"Смещение (см. инструкцию на странице http://syncplay.pl/guide/):",
"help-menu-label" : u"&Помощь",
"userguide-menu-label" : u"&Руководство Пользователя",
"update-menu-label" : u"Проверить &обновления",
"promptforstreamurl-msgbox-label" : u"Открыть URL потокового вещания",
"promptforstreamurlinfo-msgbox-label" : u"URL потока",
"setoffset-msgbox-label" : u"Установить смещение",
"offsetinfo-msgbox-label" : u"Смещение (см. инструкцию на странице http://syncplay.pl/guide/):",
"createcontrolledroom-msgbox-label" : u"Создать управляемую комнату",
"controlledroominfo-msgbox-label" : u"Введите имя управляемой комнаты\r\n(см. инструкцию на странице http://syncplay.pl/guide/):",
"promptforstreamurl-msgbox-label" : u"Открыть URL потокового вещания",
"promptforstreamurlinfo-msgbox-label" : u"URL потока",
"identifyascontroller-msgbox-label" : u"Войти как оператор комнаты",
"identifyinfo-msgbox-label" : u"Введите пароль оператора комнаты\r\n(см. инструкцию на странице http://syncplay.pl/guide/):",
"addfolder-label" : u"Add folder", # TODO: Translate
"public-server-msgbox-label" : u"Select the public server for this viewing session", # TODO: Translate into Russian
"adduris-msgbox-label" : u"Add URLs to playlist (one per line)", # TODO: Translate
"trusteddomains-msgbox-label" : u"Domains it is okay to automatically switch to (one per line)", # TODO: Translate
"megabyte-suffix" : u" МБ", # Technically it is a mebibyte
"createcontrolledroom-msgbox-label" : u"Создать управляемую комнату",
"controlledroominfo-msgbox-label" : u"Введите имя управляемой комнаты\r\n(см. инструкцию на странице http://syncplay.pl/guide/):",
# Tooltips
"identifyascontroller-msgbox-label" : u"Войти как оператор комнаты",
"identifyinfo-msgbox-label" : u"Введите пароль оператора комнаты\r\n(см. инструкцию на странице http://syncplay.pl/guide/):",
"host-tooltip" : u"Имя или IP-адрес, к которому будет произведено подключение, может содержать номер порта (напр., syncplay.pl:8999). Синхронизация возможна только в рамках одного сервера/порта.",
"name-tooltip" : u"Имя, под которым Вы будете известны. Регистриция не требуется, так что имя пользователя можно легко сменить в любой момент. Будет сгенерировано случайным образом, если не указать.",
"password-tooltip" : u"Пароли нужны для подключения к приватным серверам.",
"room-tooltip" : u"Комната, в которую Вы попадете сразу после подключения. Можно не указывать. Синхронизация возможна только между людьми в одной и той же комнате.",
"public-server-msgbox-label" : u"Select the public server for this viewing session", # TODO: Translate into Russian
"executable-path-tooltip" : u"Расположение Вашего видеопроигрывателя (MPC-HC, VLC, mplayer2 или mpv).",
"media-path-tooltip" : u"Расположение видеофайла или потока для просмотра. Обязательно для mpv и mplayer2.",
"player-arguments-tooltip" : u"Передавать дополнительные аргументы командной строки этому проигрывателю.",
"mediasearcdirectories-arguments-tooltip" : u"Directories where Syncplay will search for media files, e.g. when you are using the click to switch feature. Syncplay will look recursively through sub-folders.", # TODO: Translate into Russian
"megabyte-suffix" : u" МБ", # Technically it is a mebibyte
"more-tooltip" : u"Показать дополнительные настройки.",
"filename-privacy-tooltip" : u"Режим приватности для передачи имени воспроизводимого файла на сервер.",
"filesize-privacy-tooltip" : u"Режим приватности для передачи размера воспроизводимого файла на сервер.",
"privacy-sendraw-tooltip" : u"Отправляет эту информацию без шифрования. Рекомендуемая опция с наибольшей функциональностью.",
"privacy-sendhashed-tooltip" : u"Отправляет хэш-сумму этой информации, делая ее невидимой для других пользователей.",
"privacy-dontsend-tooltip" : u"Не отправлять эту информацию на сервер. Предоставляет наибольшую приватность.",
"checkforupdatesautomatically-tooltip" : u"Syncplay будет регулярно заходить на сайт и проверять наличие новых версий.",
"slowondesync-tooltip" : u"Временно уменьшить скорость воспроизведения в целях синхронизации с другими зрителями. Не поддерживается в MPC-HC.",
"dontslowdownwithme-tooltip" : u"Ваши лаги не будут влиять на других зрителей.",
"pauseonleave-tooltip" : u"Приостановить воспроизведение, если Вы покинули комнату или кто-то из зрителей отключился от сервера.",
"readyatstart-tooltip" : u"Отметить Вас готовым к просмотру сразу же (по умолчанию Вы отмечены не готовым)",
"forceguiprompt-tooltip" : u"Окно настройки не будет отображаться при открытии файла в Syncplay.", # (Inverted)
"nostore-tooltip" : u"Запустить Syncplay с данной конфигурацией, но не сохранять изменения навсегда.", # (Inverted)
"rewindondesync-tooltip" : u"Перематывать назад, когда это необходимо для синхронизации. Отключение этой опции может привести к большим рассинхронизациям!",
"fastforwardondesync-tooltip" : u"Перематывать вперед при рассинхронизации с оператором комнаты (или если включена опция 'Никогда не замедлять и не перематывать видео другим').",
"showosd-tooltip" : u"Отправлять сообщения Syncplay в видеопроигрыватель и отображать их поверх видео (OSD - On Screen Display).",
"showosdwarnings-tooltip" : u"Показывать OSC-предупреждения, если проигрываются разные файлы или если Вы в комнате больше никого нет.",
"showsameroomosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к комнате, в которой Вы находитесь.",
"shownoncontrollerosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к не-операторам в управляемой комнате.",
"showdifferentroomosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к любым другим комнатам.",
"showslowdownosd-tooltip" : u"Показывать уведомления о замедлении или перемотке в целях синхронизации.",
"showdurationnotification-tooltip" : u"Полезно, когда сегмент составного файла отсутствует. Возможны ложные срабатывания.",
"language-tooltip" : u"Язык, используемый Syncplay.",
"unpause-always-tooltip" : u"If you press unpause it always sets you as ready and unpause, rather than just setting you as ready.", # TODO: Translate into Russian
"unpause-ifalreadyready-tooltip" : u"If you press unpause when not ready it will set you as ready - press unpause again to unpause.", # TODO: Translate into Russian
"unpause-ifothersready-tooltip" : u"If you press unpause when not ready, it will only upause if others are ready.", # TODO: Translate into Russian
"unpause-ifminusersready-tooltip" : u"If you press unpause when not ready, it will only upause if others are ready and minimum users threshold is met.", # TODO: Translate into Russian
# Tooltips
"help-tooltip" : u"Открыть Руководство Пользователя на Syncplay.pl.",
"reset-tooltip" : u"Сбрасывает все настройки Syncplay в начальное состояние.",
"update-server-list-tooltip" : u"Connect to syncplay.pl to update list of public servers.", # TODO: Translate to Russian
"host-tooltip" : u"Имя или IP-адрес, к которому будет произведено подключение, может содержать номер порта (напр., syncplay.pl:8999). Синхронизация возможна только в рамках одного сервера/порта.",
"name-tooltip" : u"Имя, под которым Вы будете известны. Регистриция не требуется, так что имя пользователя можно легко сменить в любой момент. Будет сгенерировано случайным образом, если не указать.",
"password-tooltip" : u"Пароли нужны для подключения к приватным серверам.",
"room-tooltip" : u"Комната, в которую Вы попадете сразу после подключения. Можно не указывать. Синхронизация возможна только между людьми в одной и той же комнате.",
"joinroom-tooltip" : u"Покинуть комнату и зайти в другую, указанную комнату.",
"seektime-msgbox-label" : u"Перемотать к определенному моменту времени (указывать в секундах или мин:сек). Используйте +/-, чтобы перемотать вперед/назад относительно настоящего момента.",
"ready-tooltip" : u"Показывает, готовы ли Вы к просмотру или нет.",
"autoplay-tooltip" : u"Автоматическое воспроизведение, когда все пользователи с индикаторами готовности будут готовы и присутствует достаточное число пользователей.",
"switch-to-file-tooltip" : u"Double click to switch to {}", # Filename # TODO: Translate to Russian
"executable-path-tooltip" : u"Расположение Вашего видеопроигрывателя (MPC-HC, VLC, mplayer2 или mpv).",
"media-path-tooltip" : u"Расположение видеофайла или потока для просмотра. Обязательно для mpv и mplayer2.",
"player-arguments-tooltip" : u"Передавать дополнительные аргументы командной строки этому проигрывателю.",
"mediasearcdirectories-arguments-tooltip" : u"Directories where Syncplay will search for media files, e.g. when you are using the click to switch feature. Syncplay will look recursively through sub-folders.", # TODO: Translate into Russian
# In-userlist notes (GUI)
"differentsize-note" : u"Размер файла не совпадает!",
"differentsizeandduration-note" : u"Размер и продолжительность файла не совпадают!",
"differentduration-note" : u"Продолжительность файла не совпадает!",
"nofile-note" : u"(Ничего не воспроизводим)",
"more-tooltip" : u"Показать дополнительные настройки.",
"filename-privacy-tooltip" : u"Режим приватности для передачи имени воспроизводимого файла на сервер.",
"filesize-privacy-tooltip" : u"Режим приватности для передачи размера воспроизводимого файла на сервер.",
"privacy-sendraw-tooltip" : u"Отправляет эту информацию без шифрования. Рекомендуемая опция с наибольшей функциональностью.",
"privacy-sendhashed-tooltip" : u"Отправляет хэш-сумму этой информации, делая ее невидимой для других пользователей.",
"privacy-dontsend-tooltip" : u"Не отправлять эту информацию на сервер. Предоставляет наибольшую приватность.",
"checkforupdatesautomatically-tooltip" : u"Syncplay будет регулярно заходить на сайт и проверять наличие новых версий.",
"slowondesync-tooltip" : u"Временно уменьшить скорость воспроизведения в целях синхронизации с другими зрителями. Не поддерживается в MPC-HC.",
"dontslowdownwithme-tooltip" : u"Ваши лаги не будут влиять на других зрителей.",
"pauseonleave-tooltip" : u"Приостановить воспроизведение, если Вы покинули комнату или кто-то из зрителей отключился от сервера.",
"readyatstart-tooltip" : u"Отметить Вас готовым к просмотру сразу же (по умолчанию Вы отмечены не готовым)",
"forceguiprompt-tooltip" : u"Окно настройки не будет отображаться при открытии файла в Syncplay.", # (Inverted)
"nostore-tooltip" : u"Запустить Syncplay с данной конфигурацией, но не сохранять изменения навсегда.",
"rewindondesync-tooltip" : u"Перематывать назад, когда это необходимо для синхронизации. Отключение этой опции может привести к большим рассинхронизациям!",
"fastforwardondesync-tooltip" : u"Перематывать вперед при рассинхронизации с оператором комнаты (или если включена опция 'Никогда не замедлять и не перематывать видео другим').",
"showosd-tooltip" : u"Отправлять сообщения Syncplay в видеопроигрыватель и отображать их поверх видео (OSD - On Screen Display).",
"showosdwarnings-tooltip" : u"Показывать OSC-предупреждения, если проигрываются разные файлы или если Вы в комнате больше никого нет.",
"showsameroomosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к комнате, в которой Вы находитесь.",
"shownoncontrollerosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к не-операторам в управляемой комнате.",
"showdifferentroomosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к любым другим комнатам.",
"showslowdownosd-tooltip" : u"Показывать уведомления о замедлении или перемотке в целях синхронизации.",
"showdurationnotification-tooltip" : u"Полезно, когда сегмент составного файла отсутствует. Возможны ложные срабатывания.",
"language-tooltip" : u"Язык, используемый Syncplay.",
"unpause-always-tooltip" : u"If you press unpause it always sets you as ready and unpause, rather than just setting you as ready.", # TODO: Translate into Russian
"unpause-ifalreadyready-tooltip" : u"If you press unpause when not ready it will set you as ready - press unpause again to unpause.", # TODO: Translate into Russian
"unpause-ifothersready-tooltip" : u"If you press unpause when not ready, it will only upause if others are ready.", # TODO: Translate into Russian
"unpause-ifminusersready-tooltip" : u"If you press unpause when not ready, it will only upause if others are ready and minimum users threshold is met.", # TODO: Translate into Russian
"trusteddomains-arguments-tooltip" : u"Domains that it is okay for Syncplay to automatically switch to when shared playlists is enabled.", # TODO: Translate into Russian
# Server messages to client
"new-syncplay-available-motd-message" : u"<NOTICE> Вы используете Syncplay версии {}. Доступна более новая версия на http://syncplay.pl/ . </NOTICE>", # ClientVersion
"help-tooltip" : u"Открыть Руководство Пользователя на Syncplay.pl.",
"reset-tooltip" : u"Сбрасывает все настройки Syncplay в начальное состояние.",
"update-server-list-tooltip" : u"Connect to syncplay.pl to update list of public servers.", # TODO: Translate to Russian
# Server notifications
"welcome-server-notification" : u"Добро пожаловать на сервер Syncplay версии {0}", # version
"client-connected-room-server-notification" : u"{0}({2}) подключился(-лась) к комнате '{1}'", # username, host, room
"client-left-server-notification" : u"{0} покинул(а) сервер", # name
"no-salt-notification" : u"ВНИМАНИЕ: Чтобы сгенерированные сервером пароли операторов комнат работали после перезагрузки сервера, необходимо указать следующий аргумент командной строки при запуске сервера Syncplay: --salt {}", #Salt
"joinroom-tooltip" : u"Покинуть комнату и зайти в другую, указанную комнату.",
"seektime-msgbox-label" : u"Перемотать к определенному моменту времени (указывать в секундах или мин:сек). Используйте +/-, чтобы перемотать вперед/назад относительно настоящего момента.",
"ready-tooltip" : u"Показывает, готовы ли Вы к просмотру или нет.",
"autoplay-tooltip" : u"Автоматическое воспроизведение, когда все пользователи с индикаторами готовности будут готовы и присутствует достаточное число пользователей.",
"switch-to-file-tooltip" : u"Double click to switch to {}", # Filename # TODO: Translate to Russian
# Server arguments
"server-argument-description" : u'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC через Интернет. Серверная часть',
"server-argument-epilog" : u'Если параметр не будет передан, то будет использоваться значение, указанное в _config.',
"server-port-argument" : u'номер TCP порта сервера',
"server-password-argument" : u'пароль к серверу',
"server-isolate-room-argument" : u'должны ли комнаты быть изолированными?',
"server-salt-argument" : u"генерировать пароли к управляемым комнатам на основании указанной строки (соли)",
"server-disable-ready-argument" : u"отключить статусы готов/не готов",
"server-motd-argument" : u"путь к файлу, из которого будет извлекаться MOTD-сообщение",
"server-messed-up-motd-unescaped-placeholders" : u"MOTD-сообщение содержит неэкранированные спец.символы. Все знаки $ должны быть продублированы ($$).",
"server-messed-up-motd-too-long" : u"MOTD-сообщение слишком длинное: максимальная длина - {} символ(ов), текущая длина - {} символ(ов).",
# In-userlist notes (GUI)
"differentsize-note" : u"Размер файла не совпадает!",
"differentsizeandduration-note" : u"Размер и продолжительность файла не совпадают!",
"differentduration-note" : u"Продолжительность файла не совпадает!",
"nofile-note" : u"(Ничего не воспроизводим)",
# Server errors
"unknown-command-server-error" : u"Неизвестная команда: {}", # message
"not-json-server-error" : u"Не является закодированной json-строкой: {}", # message
"not-known-server-error" : u"Данную команду могут выполнять только авторизованные пользователи.",
"client-drop-server-error" : u"Клиент отключен с ошибкой: {} -- {}", # host, error
"password-required-server-error" : u"Необходимо указать пароль.",
"wrong-password-server-error" : u"Указан неверный пароль.",
"hello-server-error" : u"Не хватает аргументов Hello.",
# Server messages to client
"new-syncplay-available-motd-message" : u"<NOTICE> Вы используете Syncplay версии {}. Доступна более новая версия на http://syncplay.pl/ . </NOTICE>", # ClientVersion
}
# Server notifications
"welcome-server-notification" : u"Добро пожаловать на сервер Syncplay версии {0}", # version
"client-connected-room-server-notification" : u"{0}({2}) подключился(-лась) к комнате '{1}'", # username, host, room
"client-left-server-notification" : u"{0} покинул(а) сервер", # name
"no-salt-notification" : u"ВНИМАНИЕ: Чтобы сгенерированные сервером пароли операторов комнат работали после перезагрузки сервера, необходимо указать следующий аргумент командной строки при запуске сервера Syncplay: --salt {}", #Salt
# Server arguments
"server-argument-description" : u'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC через Интернет. Серверная часть',
"server-argument-epilog" : u'Если параметр не будет передан, то будет использоваться значение, указанное в _config.',
"server-port-argument" : u'номер TCP порта сервера',
"server-password-argument" : u'пароль к серверу',
"server-isolate-room-argument" : u'должны ли комнаты быть изолированными?',
"server-salt-argument" : u"генерировать пароли к управляемым комнатам на основании указанной строки (соли)",
"server-disable-ready-argument" : u"отключить статусы готов/не готов",
"server-motd-argument" : u"путь к файлу, из которого будет извлекаться MOTD-сообщение",
"server-messed-up-motd-unescaped-placeholders" : u"MOTD-сообщение содержит неэкранированные спец.символы. Все знаки $ должны быть продублированы ($$).",
"server-messed-up-motd-too-long" : u"MOTD-сообщение слишком длинное: максимальная длина - {} символ(ов), текущая длина - {} символ(ов).",
# Server errors
"unknown-command-server-error" : u"Неизвестная команда: {}", # message
"not-json-server-error" : u"Не является закодированной json-строкой: {}", # message
"not-known-server-error" : u"Данную команду могут выполнять только авторизованные пользователи.",
"client-drop-server-error" : u"Клиент отключен с ошибкой: {} -- {}", # host, error
"password-required-server-error" : u"Необходимо указать пароль.",
"wrong-password-server-error" : u"Указан неверный пароль.",
"hello-server-error" : u"Не хватает аргументов Hello.",
# Playlists TODO: Translate all this to Russian
"playlist-selection-changed-notification" : u"{} changed the playlist selection", # Username
"playlist-contents-changed-notification" : u"{} updated the playlist", # Username
"cannot-find-file-for-playlist-switch-error" : u"Could not find file {} in media directories for playlist switch!", # Filename
"cannot-add-duplicate-error" : u"Could not add second entry for '{}' to the playlist as no duplicates are allowed.", #Filename
"cannot-add-unsafe-path-error" : u"Could not automatically load {} because it is not on a trusted domain. You can switch to the URL manually by double clicking it in the playlist, and add trusted domains via File->Advanced->Set Trusted Domains.", # Filename # TODO: Translate
"sharedplaylistenabled-label" : u"Enable shared playlists",
"removefromplaylist-menu-label" : u"Remove from playlist",
"shuffleplaylist-menuu-label" : u"Shuffle playlist",
"undoplaylist-menu-label" : u"Undo last change to playlist",
"addfilestoplaylist-menu-label" : u"Add file(s) to bottom of playlist",
"addurlstoplaylist-menu-label" : u"Add URL(s) to bottom of playlist",
"addusersfiletoplaylist-menu-label" : u"Add {} file to playlist", # item owner indicator
"addusersstreamstoplaylist-menu-label" : u"Add {} stream to playlist", # item owner indicator
"openusersstream-menu-label" : u"Open {} stream", # [username]'s
"openusersfile-menu-label" : u"Open {} file", # [username]'s
"item-is-yours-indicator" : u"your", # Goes with addusersfiletoplaylist/addusersstreamstoplaylist
"item-is-others-indicator" : u"{}'s", # username - goes with addusersfiletoplaylist/addusersstreamstoplaylist
"playlist-instruction-item-message" : u"Drag file here to add it to the shared playlist.",
"sharedplaylistenabled-tooltip" : u"Room operators can add files to a synced playlist to make it easy for everyone to watching the same thing. Configure media directories under 'Misc'.",
}

View File

@ -103,7 +103,7 @@ class MpcHcApi:
elif cmd == self.CMD_STATE:
self.loadState = int(value)
fileNotReady = self.loadState == self.__MPC_LOADSTATE.MLS_CLOSING or self.loadState == self.__MPC_LOADSTATE.MLS_LOADING
fileNotReady = self.loadState == self.__MPC_LOADSTATE.MLS_CLOSING or self.loadState == self.__MPC_LOADSTATE.MLS_LOADING or self.loadState == self.__MPC_LOADSTATE.MLS_CLOSED
if fileNotReady:
self.playState = None
self.__locks.fileReady.clear()
@ -418,20 +418,22 @@ class MPCHCAPIPlayer(BasePlayer):
self._mpcApi.askForCurrentPosition()
self.__positionUpdate.wait(constants.MPC_LOCK_WAIT_TIME)
return self._mpcApi.lastFilePosition
@retry(MpcHcApi.PlayerNotReadyException, constants.MPC_MAX_RETRIES, constants.MPC_RETRY_WAIT_TIME, 1)
def askForStatus(self):
if self._mpcApi.filePlaying and self.__preventAsking.wait(0) and self.__fileUpdate.acquire(0):
self.__fileUpdate.release()
position = self.__getPosition()
paused = self._mpcApi.isPaused()
position = float(position)
if self.__preventAsking.wait(0) and self.__fileUpdate.acquire(0):
self.__client.updatePlayerStatus(paused, position)
try:
if self._mpcApi.filePlaying and self.__preventAsking.wait(0) and self.__fileUpdate.acquire(0):
self.__fileUpdate.release()
return
self.__echoGlobalStatus()
position = self.__getPosition()
paused = self._mpcApi.isPaused()
position = float(position)
if self.__preventAsking.wait(0) and self.__fileUpdate.acquire(0):
self.__client.updatePlayerStatus(paused, position)
self.__fileUpdate.release()
else:
self.__echoGlobalStatus()
except MpcHcApi.PlayerNotReadyException:
self.__echoGlobalStatus()
def __echoGlobalStatus(self):
self.__client.updatePlayerStatus(self.__client.getGlobalPaused(), self.__client.getGlobalPosition())

View File

@ -88,7 +88,7 @@ class MplayerPlayer(BasePlayer):
self._listener.sendLine("get_property {}".format(property_))
def displayMessage(self, message, duration=(constants.OSD_DURATION * 1000), secondaryOSD=False):
self._listener.sendLine(u'{} "{!s}" {} {}'.format(self.OSD_QUERY, message, duration, constants.MPLAYER_OSD_LEVEL).encode('utf-8'))
self._listener.sendLine(u'{} "{!s}" {} {}'.format(self.OSD_QUERY, self._stripNewlines(message), duration, constants.MPLAYER_OSD_LEVEL).encode('utf-8'))
def setSpeed(self, value):
self._setProperty('speed', "{:.2f}".format(value))
@ -105,7 +105,7 @@ class MplayerPlayer(BasePlayer):
self.setPosition(self._client.getGlobalPosition())
def setPosition(self, value):
self._position = value
self._position = max(value,0)
self._setProperty(self.POSITION_QUERY, "{}".format(value))
time.sleep(0.03)
@ -129,10 +129,17 @@ class MplayerPlayer(BasePlayer):
def _getPosition(self):
self._getProperty(self.POSITION_QUERY)
def _stripNewlines(self, text):
text = text.replace("\r", "")
text = text.replace("\n", "")
return text
def _quoteArg(self, arg):
arg = arg.replace('\\', '\\\\')
arg = arg.replace("'", "\\'")
arg = arg.replace('"', '\\"')
arg = arg.replace("\r", "")
arg = arg.replace("\n", "")
return u'"{}"'.format(arg)
def _fileIsLoaded(self):
@ -142,7 +149,7 @@ class MplayerPlayer(BasePlayer):
pass
def _storePosition(self, value):
self._position = value
self._position = max(value,0)
def _storePauseState(self, value):
self._paused = value
@ -216,7 +223,7 @@ class MplayerPlayer(BasePlayer):
@staticmethod
def isValidPlayerPath(path):
if "mplayer" in path and MplayerPlayer.getExpandedPath(path):
if "mplayer" in path and MplayerPlayer.getExpandedPath(path) and not "mplayerc.exe" in path: # "mplayerc.exe" is Media Player Classic (not Home Cinema):
return True
return False
@ -259,6 +266,10 @@ class MplayerPlayer(BasePlayer):
class __Listener(threading.Thread):
def __init__(self, playerController, playerPath, filePath, args):
self.sendQueue = []
self.readyToSend = True
self.lastSendTime = None
self.lastNotReadyTime = None
self.__playerController = playerController
if self.__playerController.getPlayerPathErrors(playerPath,filePath):
raise ValueError()
@ -315,7 +326,70 @@ class MplayerPlayer(BasePlayer):
self.__playerController.lineReceived(line)
self.__playerController.drop()
def sendLine(self, line):
def isReadyForSend(self):
self.checkForReadinessOverride()
return self.readyToSend
def setReadyToSend(self, newReadyState):
oldState = self.readyToSend
self.readyToSend = newReadyState
self.lastNotReadyTime = time.time() if newReadyState == False else None
if self.readyToSend == True:
self.__playerController._client.ui.showDebugMessage("<mpv> Ready to send: True")
else:
self.__playerController._client.ui.showDebugMessage("<mpv> Ready to send: False")
if self.readyToSend == True and oldState == False:
self.processSendQueue()
def checkForReadinessOverride(self):
if self.lastNotReadyTime and time.time() - self.lastNotReadyTime > constants.MPV_MAX_NEWFILE_COOLDOWN_TIME:
self.setReadyToSend(True)
def sendLine(self, line, notReadyAfterThis=None):
self.checkForReadinessOverride()
if self.readyToSend == False and "print_text ANS_pause" in line:
self.__playerController._client.ui.showDebugMessage("<mpv> Not ready to get status update, so skipping")
return
try:
if self.sendQueue:
if constants.MPV_SUPERSEDE_IF_DUPLICATE_COMMANDS:
for command in constants.MPV_SUPERSEDE_IF_DUPLICATE_COMMANDS:
if line.startswith(command):
for itemID, deletionCandidate in enumerate(self.sendQueue):
if deletionCandidate.startswith(command):
self.__playerController._client.ui.showDebugMessage(u"<mpv> Remove duplicate (supersede): {}".format(self.sendQueue[itemID]))
self.sendQueue.remove(self.sendQueue[itemID])
break
break
if constants.MPV_REMOVE_BOTH_IF_DUPLICATE_COMMANDS:
for command in constants.MPV_REMOVE_BOTH_IF_DUPLICATE_COMMANDS:
if line == command:
for itemID, deletionCandidate in enumerate(self.sendQueue):
if deletionCandidate == command:
self.__playerController._client.ui.showDebugMessage(u"<mpv> Remove duplicate (delete both): {}".format(self.sendQueue[itemID]))
self.__playerController._client.ui.showDebugMessage(self.sendQueue[itemID])
return
except:
self.__playerController._client.ui.showDebugMessage("<mpv> Problem removing duplicates, etc")
self.sendQueue.append(line)
self.processSendQueue()
if notReadyAfterThis:
self.setReadyToSend(False)
def processSendQueue(self):
while self.sendQueue and self.readyToSend:
if self.lastSendTime and time.time() - self.lastSendTime < constants.MPV_SENDMESSAGE_COOLDOWN_TIME:
self.__playerController._client.ui.showDebugMessage("<mpv> Throttling message send, so sleeping for {}".format(constants.MPV_SENDMESSAGE_COOLDOWN_TIME))
time.sleep(constants.MPV_SENDMESSAGE_COOLDOWN_TIME)
try:
lineToSend = self.sendQueue.pop()
if lineToSend:
self.lastSendTime = time.time()
self.actuallySendLine(lineToSend)
except IndexError:
pass
def actuallySendLine(self, line):
try:
if not isinstance(line, unicode):
line = line.decode('utf8')

View File

@ -3,6 +3,7 @@ import subprocess
from syncplay.players.mplayer import MplayerPlayer
from syncplay.messages import getMessage
from syncplay import constants
from syncplay.utils import isURL
import os, sys, time
class MpvPlayer(MplayerPlayer):
@ -75,14 +76,14 @@ class OldMpvPlayer(MpvPlayer):
OSD_QUERY = 'show_text'
def _setProperty(self, property_, value):
self._listener.sendLine("no-osd set {} {}".format(property_, value))
self._listener.sendLine(u"no-osd set {} {}".format(property_, value))
def setPaused(self, value):
if self._paused <> value:
self._paused = not self._paused
self._listener.sendLine('cycle pause')
def mpvVersionErrorCheck(self, line):
def mpvErrorCheck(self, line):
if "Error parsing option" in line or "Error parsing commandline option" in line:
self.quitReason = getMessage("mpv-version-error")
@ -90,11 +91,11 @@ class OldMpvPlayer(MpvPlayer):
self.reactor.callFromThread(self._client.ui.showErrorMessage, getMessage("mpv-version-error"), True)
self.drop()
elif "[ytdl_hook] Your version of youtube-dl is too old" in line:
if constants and any(errormsg in line for errormsg in constants.MPV_ERROR_MESSAGES_TO_REPEAT):
self._client.ui.showErrorMessage(line)
def _handleUnknownLine(self, line):
self.mpvVersionErrorCheck(line)
self.mpvErrorCheck(line)
if "Playing: " in line:
newpath = line[9:]
oldpath = self._filepath
@ -129,7 +130,12 @@ class NewMpvPlayer(OldMpvPlayer):
if self.lastMPVPositionUpdate is None:
return self._client.getGlobalPosition()
if self._recentlyReset:
return self._position
diff = time.time() - self.lastMPVPositionUpdate
if diff > constants.MPV_UNRESPONSIVE_THRESHOLD:
self.reactor.callFromThread(self._client.ui.showErrorMessage, getMessage("mpv-unresponsive-error").format(int(diff)), True)
self.drop()
@ -144,7 +150,7 @@ class NewMpvPlayer(OldMpvPlayer):
if self._recentlyReset():
self._position = 0
elif self._fileIsLoaded():
self._position = value
self._position = max(value,0)
else:
self._position = self._client.getGlobalPosition()
@ -157,12 +163,18 @@ class NewMpvPlayer(OldMpvPlayer):
def askForStatus(self):
self._positionAsk.clear()
self._pausedAsk.clear()
self._getPaused()
self._getPosition()
if not self._listener.isReadyForSend:
self._client.ui.showDebugMessage("mpv not ready for update")
return
self._getPausedAndPosition()
self._positionAsk.wait(constants.MPV_LOCK_WAIT_TIME)
self._pausedAsk.wait(constants.MPV_LOCK_WAIT_TIME)
self._client.updatePlayerStatus(self._paused if self.fileLoaded else self._client.getGlobalPaused(), self.getCalculatedPosition())
def _getPausedAndPosition(self):
self._listener.sendLine(u"print_text ANS_pause=${pause}\r\nprint_text ANS_time-pos=${=time-pos}")
def _preparePlayer(self):
if self.delayedFilePath:
self.openFile(self.delayedFilePath)
@ -175,7 +187,7 @@ class NewMpvPlayer(OldMpvPlayer):
def _loadFile(self, filePath):
self._clearFileLoaded()
self._listener.sendLine(u'loadfile {}'.format(self._quoteArg(filePath)))
self._listener.sendLine(u'loadfile {}'.format(self._quoteArg(filePath)), notReadyAfterThis=True)
def setPosition(self, value):
super(self.__class__, self).setPosition(value)
@ -184,19 +196,29 @@ class NewMpvPlayer(OldMpvPlayer):
def openFile(self, filePath, resetPosition=False):
if resetPosition:
self.lastResetTime = time.time()
if isURL(filePath):
self.lastResetTime += constants.STREAM_ADDITIONAL_IGNORE_TIME
self._loadFile(filePath)
if self._paused != self._client.getGlobalPaused():
self.setPaused(self._client.getGlobalPaused())
self.setPosition(self._client.getGlobalPosition())
if resetPosition == False:
self.setPosition(self._client.getGlobalPosition())
else:
self._storePosition(0)
def _handleUnknownLine(self, line):
self.mpvVersionErrorCheck(line)
self.mpvErrorCheck(line)
if line == "<SyncplayUpdateFile>" or "Playing:" in line:
self._listener.setReadyToSend(False)
self._clearFileLoaded()
elif line == "</SyncplayUpdateFile>":
self._onFileUpdate()
self._listener.setReadyToSend(True)
elif "Failed" in line or "failed" in line or "No video or audio streams selected" in line or "error" in line:
self._listener.setReadyToSend(True)
def _recentlyReset(self):
if not self.lastResetTime:

View File

@ -22,7 +22,6 @@ class VlcPlayer(BasePlayer):
SLAVE_ARGS = constants.VLC_SLAVE_ARGS
if not sys.platform.startswith('darwin'):
SLAVE_ARGS.extend(constants.VLC_SLAVE_NONOSX_ARGS)
random.seed()
vlcport = random.randrange(constants.VLC_MIN_PORT, constants.VLC_MAX_PORT) if (constants.VLC_MIN_PORT < constants.VLC_MAX_PORT) else constants.VLC_MIN_PORT
def __init__(self, client, playerPath, filePath, args):
@ -141,6 +140,10 @@ class VlcPlayer(BasePlayer):
return fileURL
def openFile(self, filePath, resetPosition=False):
if not utils.isURL(filePath):
normedPath = os.path.normpath(filePath)
if os.path.isfile(normedPath):
filePath = normedPath
if utils.isASCII(filePath):
self._listener.sendLine('load-file: {}'.format(filePath.encode('ascii', 'ignore')))
else:

View File

@ -140,6 +140,10 @@ class SyncClientProtocol(JSONCommandProtocol):
user, isReady = values["username"], values["isReady"]
manuallyInitiated = values["manuallyInitiated"] if values.has_key("manuallyInitiated") else True
self._client.setReady(user, isReady, manuallyInitiated)
elif command == "playlistIndex":
self._client.playlist.changeToPlaylistIndex(values['index'], values['user'])
elif command == "playlistChange":
self._client.playlist.changePlaylist(values['files'], values['user'])
def sendSet(self, setting):
self.sendMessage({"Set": setting})
@ -247,6 +251,21 @@ class SyncClientProtocol(JSONCommandProtocol):
}
})
def setPlaylist(self, files):
self.sendSet({
"playlistChange": {
"files": files
}
})
def setPlaylistIndex(self, index):
self.sendSet({
"playlistIndex": {
"index": index
}
})
def handleError(self, error):
self.dropWithError(error["message"])
@ -358,6 +377,10 @@ class SyncServerProtocol(JSONCommandProtocol):
elif command == "ready":
manuallyInitiated = set_[1]['manuallyInitiated'] if set_[1].has_key("manuallyInitiated") else False
self._factory.setReady(self._watcher, set_[1]['isReady'], manuallyInitiated=manuallyInitiated)
elif command == "playlistChange":
self._factory.setPlaylist(self._watcher, set_[1]['files'])
elif command == "playlistIndex":
self._factory.setPlaylistIndex(self._watcher, set_[1]['index'])
def sendSet(self, setting):
self.sendMessage({"Set": setting})
@ -389,6 +412,22 @@ class SyncServerProtocol(JSONCommandProtocol):
}
})
def setPlaylist(self, username, files):
self.sendSet({
"playlistChange": {
"user": username,
"files": files
}
})
def setPlaylistIndex(self, username, index):
self.sendSet({
"playlistIndex": {
"user": username,
"index": index
}
})
def sendUserSetting(self, username, room, file_, event):
room = {"name": room.getName()}
user = {username: {}}

View File

@ -72,8 +72,13 @@ class SyncFactory(Factory):
self.sendJoinMessage(watcher)
else:
self.sendRoomSwitchMessage(watcher)
room = watcher.getRoom()
roomSetByName = room.getSetBy().getName() if room.getSetBy() else None
watcher.setPlaylist(roomSetByName, room.getPlaylist())
watcher.setPlaylistIndex(roomSetByName, room.getPlaylistIndex())
if RoomPasswordProvider.isControlledRoom(roomName):
for controller in watcher.getRoom().getControllers():
for controller in room.getControllers():
watcher.sendControlledRoomAuthStatus(True, controller, roomName)
def sendRoomSwitchMessage(self, watcher):
@ -132,6 +137,24 @@ class SyncFactory(Factory):
watcher.setReady(isReady)
self._roomManager.broadcastRoom(watcher, lambda w: w.sendSetReady(watcher.getName(), watcher.isReady(), manuallyInitiated))
def setPlaylist(self, watcher, files):
room = watcher.getRoom()
if room.canControl(watcher):
watcher.getRoom().setPlaylist(files, watcher)
self._roomManager.broadcastRoom(watcher, lambda w: w.setPlaylist(watcher.getName(), files))
else:
watcher.setPlaylist(room.getName(), room.getPlaylist())
watcher.setPlaylistIndex(room.getName(), room.getPlaylistIndex())
def setPlaylistIndex(self, watcher, index):
room = watcher.getRoom()
if room.canControl(watcher):
watcher.getRoom().setPlaylistIndex(index, watcher)
self._roomManager.broadcastRoom(watcher, lambda w: w.setPlaylistIndex(watcher.getName(), index))
else:
watcher.setPlaylistIndex(room.getName(), room.getPlaylistIndex())
class RoomManager(object):
def __init__(self):
self._rooms = {}
@ -214,6 +237,10 @@ class Room(object):
self._watchers = {}
self._playState = self.STATE_PAUSED
self._setBy = None
self._playlist = []
self._playlistIndex = None
self.__lastUpdate = time.time()
self.__position = 0
def __str__(self, *args, **kwargs):
return self.getName()
@ -222,10 +249,15 @@ class Room(object):
return self._name
def getPosition(self):
if self._watchers:
age = time.time() - self.__lastUpdate
if self._watchers and age > 1:
watcher = min(self._watchers.values())
self._setBy = watcher
return watcher.getPosition()
self.__position = watcher.getPosition()
self.__lastUpdate = time.time()
return self.__position
elif self.__position is not None:
return self.__position + (age if self._playState == self.STATE_PLAYING else 0)
else:
return 0
@ -234,6 +266,7 @@ class Room(object):
self._setBy = setBy
def setPosition(self, position, setBy=None):
self.__position = position
for watcher in self._watchers.itervalues():
watcher.setPosition(position)
self._setBy = setBy
@ -258,6 +291,8 @@ class Room(object):
return
del self._watchers[watcher.getName()]
watcher.setRoom(None)
if not self._watchers:
self.__position = 0
def isEmpty(self):
return not bool(self._watchers)
@ -268,16 +303,33 @@ class Room(object):
def canControl(self, watcher):
return True
def setPlaylist(self, files, setBy=None):
self._playlist = files
def setPlaylistIndex(self, index, setBy=None):
self._playlistIndex = index
def getPlaylist(self):
return self._playlist
def getPlaylistIndex(self):
return self._playlistIndex
class ControlledRoom(Room):
def __init__(self, name):
Room.__init__(self, name)
self._controllers = {}
def getPosition(self):
if self._controllers:
age = time.time() - self.__lastUpdate
if self._controllers and age > 1:
watcher = min(self._controllers.values())
self._setBy = watcher
return watcher.getPosition()
self.__position = watcher.getPosition()
self.__lastUpdate = time.time()
return self.__position
elif self.__position is not None:
return self.__position + (age if self._playState == self.STATE_PLAYING else 0)
else:
return 0
@ -297,6 +349,14 @@ class ControlledRoom(Room):
if self.canControl(setBy):
Room.setPosition(self, position, setBy)
def setPlaylist(self, files, setBy=None):
if self.canControl(setBy):
self._playlist = files
def setPlaylistIndex(self, index, setBy=None):
if self.canControl(setBy):
self._playlistIndex = index
def canControl(self, watcher):
return watcher.getName() in self._controllers
@ -370,6 +430,12 @@ class Watcher(object):
def sendSetReady(self, username, isReady, manuallyInitiated=True):
self._connector.sendSetReady(username, isReady, manuallyInitiated)
def setPlaylistIndex(self, username, index):
self._connector.setPlaylistIndex(username, index)
def setPlaylist(self, username, files):
self._connector.setPlaylist(username, files)
def __lt__(self, b):
if self.getPosition() is None or self._file is None:
return False
@ -442,4 +508,4 @@ class ConfigurationGetter(object):
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"))
self._argparser.add_argument('--motd-file', metavar='file', type=str, nargs='?', help=getMessage("server-motd-argument"))

View File

@ -34,6 +34,11 @@ class ConfigurationGetter(object):
"playerPath": None,
"perPlayerArguments": None,
"mediaSearchDirectories": None,
"sharedPlaylistEnabled": True,
"loopAtEndOfPlaylist": False,
"loopSingleFiles" : False,
"onlySwitchToTrustedDomains": True,
"trustedDomains": constants.DEFAULT_TRUSTED_DOMAINS,
"file": None,
"playerArgs": [],
"playerClass": None,
@ -51,6 +56,7 @@ class ConfigurationGetter(object):
"unpauseAction": constants.UNPAUSE_IFOTHERSREADY_MODE,
"autoplayInitialState" : None,
"autoplayMinUsers" : -1,
"autoplayRequireSameFilenames": True,
"clearGUIData": False,
"language" : "",
"checkForUpdatesAutomatically" : None,
@ -87,6 +93,7 @@ class ConfigurationGetter(object):
"dontSlowDownWithMe",
"pauseOnLeave",
"readyAtStart",
"autoplayRequireSameFilenames",
"clearGUIData",
"rewindOnDesync",
"slowOnDesync",
@ -100,7 +107,11 @@ class ConfigurationGetter(object):
"showDifferentRoomOSD",
"showSameRoomOSD",
"showNonControllerOSD",
"showDurationNotification"
"showDurationNotification",
"sharedPlaylistEnabled",
"loopAtEndOfPlaylist",
"loopSingleFiles",
"onlySwitchToTrustedDomains"
]
self._tristate = [
"checkForUpdatesAutomatically",
@ -110,6 +121,7 @@ class ConfigurationGetter(object):
self._serialised = [
"perPlayerArguments",
"mediaSearchDirectories",
"trustedDomains",
]
self._numeric = [
@ -121,9 +133,23 @@ class ConfigurationGetter(object):
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"],
"gui": ["showOSD", "showOSDWarnings", "showSlowdownOSD", "showDifferentRoomOSD", "showSameRoomOSD", "showNonControllerOSD", "showDurationNotification"],
"general": ["language", "checkForUpdatesAutomatically", "lastCheckedForUpdates"]
"client_settings": ["name", "room", "playerPath",
"perPlayerArguments", "slowdownThreshold",
"rewindThreshold", "fastforwardThreshold",
"slowOnDesync", "rewindOnDesync",
"fastforwardOnDesync", "dontSlowDownWithMe",
"forceGuiPrompt", "filenamePrivacyMode",
"filesizePrivacyMode", "unpauseAction",
"pauseOnLeave", "readyAtStart", "autoplayMinUsers",
"autoplayInitialState", "mediaSearchDirectories",
"sharedPlaylistEnabled", "loopAtEndOfPlaylist",
"loopSingleFiles",
"onlySwitchToTrustedDomains", "trustedDomains"],
"gui": ["showOSD", "showOSDWarnings", "showSlowdownOSD",
"showDifferentRoomOSD", "showSameRoomOSD",
"showNonControllerOSD", "showDurationNotification"],
"general": ["language", "checkForUpdatesAutomatically",
"lastCheckedForUpdates"]
}
self._playerFactory = PlayerFactory()
@ -352,7 +378,7 @@ class ConfigurationGetter(object):
for name in constants.CONFIG_NAMES:
path = location + os.path.sep + name
if os.path.isfile(path) and (os.name == 'nt' or path != os.path.join(os.getenv('HOME', '.'), constants.DEFAULT_CONFIG_NAME_LINUX)):
loadedPaths.append("'" + os.path.normpath(path) + "'")
loadedPaths.append(u"'{}'".format(os.path.normpath(path)))
self._parseConfigFile(path, createConfig=False)
self._checkConfig()
return loadedPaths
@ -409,6 +435,15 @@ class ConfigurationGetter(object):
qt4reactor.install()
return self._config
def setConfigOption(self, option, value):
path = self._getConfigurationFilePath()
backup = self._config.copy()
self._parseConfigFile(path)
self._config[option] = value
backup[option] = value
self._saveConfig(path)
self._config = backup
class SafeConfigParserUnicode(SafeConfigParser):
def write(self, fp):
"""Write an .ini-format representation of the configuration state."""
@ -425,4 +460,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")
fp.write("\n")

View File

@ -71,7 +71,7 @@ class ConfigDialog(QtGui.QDialog):
moreToggling = False
def automaticUpdatePromptCheck(self):
if self.automaticupdatesCheckbox.checkState() == Qt.PartiallyChecked and not self.nostoreCheckbox.isChecked():
if self.automaticupdatesCheckbox.checkState() == Qt.PartiallyChecked:
reply = QtGui.QMessageBox.question(self, "Syncplay",
getMessage("promptforupdate-label"), QtGui.QMessageBox.StandardButton.Yes | QtGui.QMessageBox.StandardButton.No)
if reply == QtGui.QMessageBox.Yes:
@ -87,9 +87,9 @@ class ConfigDialog(QtGui.QDialog):
if self.showmoreCheckbox.isChecked():
self.tabListFrame.show()
self.resetButton.show()
self.nostoreCheckbox.show()
self.playerargsTextbox.show()
self.playerargsLabel.show()
self.runButton.show()
self.saveMoreState(True)
self.tabListWidget.setCurrentRow(0)
self.ensureTabListIsVisible()
@ -97,9 +97,9 @@ class ConfigDialog(QtGui.QDialog):
else:
self.tabListFrame.hide()
self.resetButton.hide()
self.nostoreCheckbox.hide()
self.playerargsTextbox.hide()
self.playerargsLabel.hide()
self.runButton.hide()
self.saveMoreState(False)
self.stackedLayout.setCurrentIndex(0)
newHeight = self.connectionSettingsGroup.minimumSizeHint().height()+self.mediaplayerSettingsGroup.minimumSizeHint().height()+self.bottomButtonFrame.minimumSizeHint().height()+3
@ -112,12 +112,6 @@ class ConfigDialog(QtGui.QDialog):
self.setFixedWidth(self.minimumSizeHint().width())
self.executablepathCombobox.setFixedWidth(self.mediapathTextbox.width())
def runButtonTextUpdate(self):
if self.nostoreCheckbox.isChecked():
self.runButton.setText(getMessage("run-label"))
else:
self.runButton.setText(getMessage("storeandrun-label"))
def openHelp(self):
self.QtGui.QDesktopServices.openUrl(QUrl("http://syncplay.pl/guide/client/"))
@ -364,17 +358,24 @@ class ConfigDialog(QtGui.QDialog):
self.mediapathTextbox.setText(os.path.normpath(fileName))
self.mediadirectory = os.path.dirname(fileName)
self.saveMediaBrowseSettings()
def _saveDataAndLeave(self):
self.automaticUpdatePromptCheck()
def _runWithoutStoringConfig(self):
self._saveDataAndLeave(storeConfiguration=False)
def _saveDataAndLeave(self, storeConfiguration=True):
self.config['noStore'] = storeConfiguration
if storeConfiguration:
self.automaticUpdatePromptCheck()
self.loadLastUpdateCheckDate()
self.config["perPlayerArguments"] = self.perPlayerArgs
self.config["mediaSearchDirectories"] = utils.convertMultilineStringToList(self.mediasearchTextEdit.toPlainText())
self.config["trustedDomains"] = utils.convertMultilineStringToList(self.trusteddomainsTextEdit.toPlainText())
self.processWidget(self, lambda w: self.saveValues(w))
if self.hostCombobox.currentText():
self.config['host'] = self.hostCombobox.currentText() if ":" in self.hostCombobox.currentText() else self.hostCombobox.currentText() + ":" + unicode(constants.DEFAULT_PORT)
self.config['host'] = self.config['host'].replace(" ","").replace("\t", "").replace("\n","").replace("\r","")
else:
self.config['host'] = None
self.config['playerPath'] = unicode(self.safenormcaseandpath(self.executablepathCombobox.currentText()))
@ -504,6 +505,7 @@ class ConfigDialog(QtGui.QDialog):
self.perPlayerArgs = self.config["perPlayerArguments"]
self.mediaSearchDirectories = self.config["mediaSearchDirectories"]
self.trustedDomains = self.config["trustedDomains"]
self.connectionSettingsGroup = QtGui.QGroupBox(getMessage("connection-group-title"))
self.loadSavedPublicServerList()
@ -794,10 +796,24 @@ class ConfigDialog(QtGui.QDialog):
self.othersyncSettingsLayout.setAlignment(Qt.AlignLeft)
self.othersyncSettingsLayout.addWidget(self.fastforwardCheckbox, 3, 0,1,2, Qt.AlignLeft)
## Trusted domains
self.trusteddomainsSettingsGroup = QtGui.QGroupBox(getMessage("syncplay-trusteddomains-title"))
self.trusteddomainsSettingsLayout = QtGui.QVBoxLayout()
self.trusteddomainsSettingsGroup.setLayout(self.trusteddomainsSettingsLayout)
self.trusteddomainsTextEdit = QPlainTextEdit(utils.getListAsMultilineString(self.trustedDomains))
self.trusteddomainsTextEdit.setObjectName(constants.LOAD_SAVE_MANUALLY_MARKER + "trusteddomains-arguments")
self.trusteddomainsTextEdit.setLineWrapMode(QtGui.QPlainTextEdit.NoWrap)
self.trusteddomainsSettingsLayout.addWidget(self.trusteddomainsTextEdit)
self.trusteddomainsSettingsGroup.setMaximumHeight(self.trusteddomainsSettingsGroup.minimumSizeHint().height())
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.trusteddomainsSettingsGroup)
self.syncSettingsFrame.setLayout(self.syncSettingsLayout)
self.desyncSettingsGroup.setMaximumHeight(self.desyncSettingsGroup.minimumSizeHint().height())
self.syncSettingsLayout.setAlignment(Qt.AlignTop)
@ -819,27 +835,27 @@ class ConfigDialog(QtGui.QDialog):
self.showSameRoomOSDCheckbox = QCheckBox(getMessage("showsameroomosd-label"))
self.showSameRoomOSDCheckbox.setObjectName("showSameRoomOSD")
self.showSameRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png"))
self.showSameRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png"))
self.osdSettingsLayout.addWidget(self.showSameRoomOSDCheckbox)
self.showNonControllerOSDCheckbox = QCheckBox(getMessage("shownoncontrollerosd-label"))
self.showNonControllerOSDCheckbox.setObjectName("showNonControllerOSD")
self.showNonControllerOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png"))
self.showNonControllerOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png"))
self.osdSettingsLayout.addWidget(self.showNonControllerOSDCheckbox)
self.showDifferentRoomOSDCheckbox = QCheckBox(getMessage("showdifferentroomosd-label"))
self.showDifferentRoomOSDCheckbox.setObjectName("showDifferentRoomOSD")
self.showDifferentRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png"))
self.showDifferentRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png"))
self.osdSettingsLayout.addWidget(self.showDifferentRoomOSDCheckbox)
self.slowdownOSDCheckbox = QCheckBox(getMessage("showslowdownosd-label"))
self.slowdownOSDCheckbox.setObjectName("showSlowdownOSD")
self.slowdownOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png"))
self.slowdownOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png"))
self.osdSettingsLayout.addWidget(self.slowdownOSDCheckbox)
self.showOSDWarningsCheckbox = QCheckBox(getMessage("showosdwarnings-label"))
self.showOSDWarningsCheckbox.setObjectName("showOSDWarnings")
self.showOSDWarningsCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png"))
self.showOSDWarningsCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png"))
self.osdSettingsLayout.addWidget(self.showOSDWarningsCheckbox)
self.subitems['showOSD'] = ["showSameRoomOSD", "showDifferentRoomOSD", "showSlowdownOSD", "showOSDWarnings", "showNonControllerOSD"]
@ -899,24 +915,26 @@ class ConfigDialog(QtGui.QDialog):
self.bottomButtonFrame = QtGui.QFrame()
self.bottomButtonLayout = QtGui.QHBoxLayout()
self.helpButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + 'help.png'), getMessage("help-label"))
self.helpButton = QtGui.QPushButton(QtGui.QIcon(self.resourcespath + u'help.png'), getMessage("help-label"))
self.helpButton.setObjectName("help")
self.helpButton.setMaximumSize(self.helpButton.sizeHint())
self.helpButton.pressed.connect(self.openHelp)
self.resetButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'cog_delete.png'),getMessage("reset-label"))
self.resetButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + u'cog_delete.png'),getMessage("reset-label"))
self.resetButton.setMaximumSize(self.resetButton.sizeHint())
self.resetButton.setObjectName("reset")
self.resetButton.pressed.connect(self.resetSettings)
self.runButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + 'accept.png'), getMessage("storeandrun-label"))
self.runButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + u'accept.png'), getMessage("run-label"))
self.runButton.pressed.connect(self._saveDataAndLeave)
self.runButton.setToolTip(getMessage("nostore-tooltip"))
self.storeAndRunButton = QtGui.QPushButton(QtGui.QIcon(resourcespath + u'accept.png'), getMessage("storeandrun-label"))
self.storeAndRunButton.pressed.connect(self._runWithoutStoringConfig)
self.bottomButtonLayout.addWidget(self.helpButton)
self.bottomButtonLayout.addWidget(self.resetButton)
self.bottomButtonLayout.addWidget(self.runButton)
self.bottomButtonLayout.addWidget(self.storeAndRunButton)
self.bottomButtonFrame.setLayout(self.bottomButtonLayout)
if config['noStore'] == True:
self.runButton.setText(getMessage("run-label"))
self.bottomButtonLayout.setContentsMargins(5,0,5,0)
self.mainLayout.addWidget(self.bottomButtonFrame, 1, 0, 1, 2)
@ -925,12 +943,11 @@ class ConfigDialog(QtGui.QDialog):
self.bottomCheckboxLayout = QtGui.QGridLayout()
self.alwaysshowCheckbox = QCheckBox(getMessage("forceguiprompt-label"))
self.nostoreCheckbox = QCheckBox(getMessage("nostore-label"))
self.enableplaylistsCheckbox = QCheckBox(getMessage("sharedplaylistenabled-label"))
self.bottomCheckboxLayout.addWidget(self.showmoreCheckbox)
self.bottomCheckboxLayout.addWidget(self.nostoreCheckbox, 0, 2, Qt.AlignRight)
self.bottomCheckboxLayout.addWidget(self.enableplaylistsCheckbox, 0, 2, Qt.AlignRight)
self.alwaysshowCheckbox.setObjectName(constants.INVERTED_STATE_MARKER + "forceGuiPrompt")
self.nostoreCheckbox.setObjectName("noStore")
self.nostoreCheckbox.toggled.connect(self.runButtonTextUpdate)
self.enableplaylistsCheckbox.setObjectName("sharedPlaylistEnabled")
self.bottomCheckboxFrame.setLayout(self.bottomCheckboxLayout)
self.mainLayout.addWidget(self.bottomCheckboxFrame, 2, 0, 1, 2)
@ -939,11 +956,11 @@ class ConfigDialog(QtGui.QDialog):
self.tabListLayout = QtGui.QHBoxLayout()
self.tabListFrame = QtGui.QFrame()
self.tabListWidget = QtGui.QListWidget()
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "house.png"),getMessage("basics-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "control_pause_blue.png"),getMessage("readiness-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "film_link.png"),getMessage("sync-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "comments.png"),getMessage("messages-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + "cog.png"),getMessage("misc-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"house.png"),getMessage("basics-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"control_pause_blue.png"),getMessage("readiness-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"film_link.png"),getMessage("sync-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"comments.png"),getMessage("messages-label")))
self.tabListWidget.addItem(QtGui.QListWidgetItem(QtGui.QIcon(self.resourcespath + u"cog.png"),getMessage("misc-label")))
self.tabListLayout.addWidget(self.tabListWidget)
self.tabListFrame.setLayout(self.tabListLayout)
self.tabListFrame.setFixedWidth(self.tabListFrame.minimumSizeHint().width())
@ -1029,15 +1046,15 @@ class ConfigDialog(QtGui.QDialog):
if sys.platform.startswith('win'):
resourcespath = utils.findWorkingDir() + "\\resources\\"
else:
resourcespath = utils.findWorkingDir() + "/resources/"
self.posixresourcespath = utils.findWorkingDir().replace("\\","/") + "/resources/"
resourcespath = utils.findWorkingDir() + u"/resources/"
self.posixresourcespath = utils.findWorkingDir().replace(u"\\","/") + u"/resources/"
self.resourcespath = resourcespath
super(ConfigDialog, self).__init__()
self.setWindowTitle(getMessage("config-window-title"))
self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint)
self.setWindowIcon(QtGui.QIcon(resourcespath + "syncplay.png"))
self.setWindowIcon(QtGui.QIcon(resourcespath + u"syncplay.png"))
self.stackedLayout = QtGui.QStackedLayout()
self.stackedFrame = QtGui.QFrame()
@ -1059,10 +1076,10 @@ class ConfigDialog(QtGui.QDialog):
if self.getMoreState() == False:
self.tabListFrame.hide()
self.nostoreCheckbox.hide()
self.resetButton.hide()
self.playerargsTextbox.hide()
self.playerargsLabel.hide()
self.runButton.hide()
newHeight = self.connectionSettingsGroup.minimumSizeHint().height()+self.mediaplayerSettingsGroup.minimumSizeHint().height()+self.bottomButtonFrame.minimumSizeHint().height()+3
if self.error:
newHeight +=self.errorLabel.height()+3

View File

@ -22,6 +22,12 @@ class ConsoleUI(threading.Thread):
def drop(self):
pass
def setPlaylist(self, newPlaylist, newIndexFilename=None):
pass
def setPlaylistIndexFilename(self, filename):
pass
def run(self):
try:
@ -77,6 +83,9 @@ class ConsoleUI(threading.Thread):
def userListChange(self):
pass
def fileSwitchFoundFiles(self):
pass
def showMessage(self, message, noTimestamp=False):
message = message.encode(sys.stdout.encoding, 'replace')
if noTimestamp:

File diff suppressed because it is too large Load Diff