Merge pull request #191 from albertosottile/master
Transition to Python 3.x
This commit is contained in:
commit
9ecb7c3b3b
@ -1,25 +1,31 @@
|
|||||||
environment:
|
environment:
|
||||||
MINICONDA: "C:\\Miniconda"
|
MINICONDA: "C:\\Miniconda"
|
||||||
|
PYTHON: "C:\\Python34"
|
||||||
|
PYTHON_VERSION: 3.4
|
||||||
|
PYTHON_ARCH: 32
|
||||||
|
|
||||||
platform: x86
|
platform: x86
|
||||||
|
|
||||||
configuration: Release
|
configuration: Release
|
||||||
|
|
||||||
init:
|
init:
|
||||||
- set PATH=C:\Miniconda;C:\Miniconda\Scripts;C:\Program Files (x86)\NSIS;%PATH%
|
- set PYTHONPATH=%PYTHON%
|
||||||
- conda create -n syncplay -y
|
- set PYTHONHOME=%PYTHON%
|
||||||
- activate syncplay
|
- set PATH=%PYTHON%\Scripts;%PYTHON%;C:\Program Files (x86)\NSIS;%PATH%
|
||||||
- conda install python pywin32 pyside -y
|
- python --version
|
||||||
- pip install twisted py2exe_py2 zope.interface
|
- python -m pip install -U pip setuptools wheel
|
||||||
- type nul > C:\Miniconda\envs\syncplay\lib\site-packages\zope\__init__.py
|
- pip install -U pypiwin32==219
|
||||||
|
- pip install pyside
|
||||||
|
- pip install twisted
|
||||||
|
- pip install py2exe
|
||||||
|
- pip install zope.interface
|
||||||
|
- type nul > C:\Python34\lib\site-packages\zope\__init__.py
|
||||||
- pip freeze
|
- pip freeze
|
||||||
- conda list
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- cd %APPVEYOR_BUILD_FOLDER%
|
- cd %APPVEYOR_BUILD_FOLDER%
|
||||||
- for /F "tokens=2 delims='" %%a in ('findstr version syncplay\__init__.py') do @set ver=%%a
|
- for /F "tokens=2 delims='" %%a in ('findstr version syncplay\__init__.py') do @set ver=%%a
|
||||||
- python buildPy2exe.py
|
- python buildPy2exe.py
|
||||||
- del syncplay_v%ver%\lib\MPR.dll
|
|
||||||
- type nul > syncplay_v%ver%\syncplay.ini
|
- type nul > syncplay_v%ver%\syncplay.ini
|
||||||
- copy resources\win_lua_note.txt syncplay_v%ver%\"VLC LUA Script installation.txt"
|
- copy resources\win_lua_note.txt syncplay_v%ver%\"VLC LUA Script installation.txt"
|
||||||
|
|
||||||
@ -29,15 +35,14 @@ build: off
|
|||||||
artifacts:
|
artifacts:
|
||||||
- path: 'syncplay_v$(ver)'
|
- path: 'syncplay_v$(ver)'
|
||||||
type: zip
|
type: zip
|
||||||
name: Syncplay_v$(ver)_Portable
|
name: Syncplay_$(ver)_Portable
|
||||||
|
|
||||||
- path: Syncplay-$(ver)-Setup.exe
|
- path: Syncplay-$(ver)-Setup.exe
|
||||||
name: Syncplay-$(ver)-win-setup
|
name: Syncplay-$(ver)-Setup
|
||||||
|
|
||||||
# Push artefact to S3 bucket and list all
|
# Push artefact to S3 bucket and list all
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- dir
|
- dir
|
||||||
- dir syncplay_v%ver%
|
|
||||||
#- python -c "from PySide2 import QtCore; print QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.PluginsPath)"
|
#- python -c "from PySide2 import QtCore; print QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.PluginsPath)"
|
||||||
|
|
||||||
|
|
||||||
@ -52,4 +57,4 @@ deploy:
|
|||||||
subject: syncplay
|
subject: syncplay
|
||||||
version: v$(ver)
|
version: v$(ver)
|
||||||
publish: true
|
publish: true
|
||||||
override: true
|
override: true
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,3 +13,4 @@ dist.7z
|
|||||||
.*
|
.*
|
||||||
!.travis.yml
|
!.travis.yml
|
||||||
!.appveyor.yml
|
!.appveyor.yml
|
||||||
|
__pycache__
|
||||||
42
.travis.yml
42
.travis.yml
@ -6,35 +6,37 @@ branches:
|
|||||||
- master
|
- master
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- python buildPy2app.py py2app
|
- python3 buildPy2app.py py2app
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- brew update
|
|
||||||
- brew install qt
|
|
||||||
- which python
|
|
||||||
- which pip
|
|
||||||
- curl -L https://bintray.com/alby128/Syncplay/download_file?file_path=PySide2-5.11.0-5.11.0-cp27-cp27m-macosx_10_11_x86_64.whl -o PySide2-5.11.0-5.11.0-cp27-cp27m-macosx_10_11_x86_64.whl
|
|
||||||
- pip install PySide2-5.11.0-5.11.0-cp27-cp27m-macosx_10_11_x86_64.whl
|
|
||||||
- ln -s /usr/local/lib/python2.7/site-packages/PySide2/libshiboken2-python2.7v.5.11.dylib /usr/local/lib/
|
|
||||||
- ln -s /usr/local/lib/python2.7/site-packages/PySide2/libpyside2-python2.7v.5.11.dylib /usr/local/lib/
|
|
||||||
#- python -c "from PySide2 import QtCore"
|
|
||||||
- python -c "from PySide2.QtCore import __version__; print __version__"
|
|
||||||
- hg clone https://alby128@bitbucket.org/alby128/py2app
|
- hg clone https://alby128@bitbucket.org/alby128/py2app
|
||||||
|
- brew uninstall python
|
||||||
|
- brew update
|
||||||
|
- curl -O https://raw.githubusercontent.com/Homebrew/homebrew-core/f2a764ef944b1080be64bd88dca9a1d80130c558/Formula/python.rb
|
||||||
|
- brew install ./python.rb
|
||||||
|
- which python3
|
||||||
|
- python3 --version
|
||||||
|
- which pip3
|
||||||
|
- pip3 --version
|
||||||
|
- brew install qt
|
||||||
|
- curl -L https://bintray.com/alby128/Syncplay/download_file?file_path=PySide2-5.11.0-5.11.0-cp36-cp36m-macosx_10_11_x86_64.whl -o PySide2-5.11.0-5.11.0-cp36-cp36m-macosx_10_11_x86_64.whl
|
||||||
|
- pip3 install PySide2-5.11.0-5.11.0-cp36-cp36m-macosx_10_11_x86_64.whl
|
||||||
|
- ln -s /usr/local/lib/python3.6/site-packages/PySide2/libpyside2.cpython-36m-darwin.5.11.dylib /usr/local/lib/
|
||||||
|
- ln -s /usr/local/lib/python3.6/site-packages/PySide2/libshiboken2.cpython-36m-darwin.5.11.dylib /usr/local/lib/
|
||||||
|
- python3 -c "from PySide2 import __version__; print(__version__)"
|
||||||
|
- python3 -c "from PySide2.QtCore import __version__; print(__version__)"
|
||||||
- cd py2app
|
- cd py2app
|
||||||
- python setup.py install
|
- python3 setup.py install
|
||||||
- cd ..
|
- cd ..
|
||||||
- python -c "from py2app.recipes import pyside2"
|
- python3 -c "from py2app.recipes import pyside2"
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip install twisted appnope
|
- pip3 install twisted appnope
|
||||||
- pip install -U https://github.com/requests/requests/zipball/master
|
- pip3 install -U https://github.com/requests/requests/zipball/master
|
||||||
#- git clone -b qtpy-pyside2 https://github.com/alby128/syncplay.git syncplay-qtpy-PySide2
|
|
||||||
#- cd syncplay-qtpy-PySide2
|
|
||||||
#- git checkout qtpy-pyside2
|
|
||||||
|
|
||||||
before_deploy:
|
before_deploy:
|
||||||
#- travis/cache-homebrew
|
- pip3 install dmgbuild
|
||||||
- pip install dmgbuild
|
|
||||||
- mkdir dist_dmg
|
- mkdir dist_dmg
|
||||||
- mv resources/macos_vlc_install.command resources/.macos_vlc_install.command
|
- mv resources/macos_vlc_install.command resources/.macos_vlc_install.command
|
||||||
- mv resources/lua/intf/syncplay.lua resources/lua/intf/.syncplay.lua
|
- mv resources/lua/intf/syncplay.lua resources/lua/intf/.syncplay.lua
|
||||||
|
|||||||
2
appdmg.py
Normal file → Executable file
2
appdmg.py
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
import biplist
|
import biplist
|
||||||
import os.path
|
import os.path
|
||||||
|
|||||||
705
buildInstaller.py
Normal file
705
buildInstaller.py
Normal file
@ -0,0 +1,705 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#coding:utf8
|
||||||
|
|
||||||
|
|
||||||
|
#*** TROUBLESHOOTING ***
|
||||||
|
#1) If you get the error "ImportError: No module named zope.interface" then add an empty __init__.py file to the PYTHONDIR/Lib/site-packages/zope directory
|
||||||
|
#2) It is expected that you will have NSIS 3 NSIS from http://nsis.sourceforge.net installed.
|
||||||
|
|
||||||
|
import sys, codecs
|
||||||
|
# try:
|
||||||
|
# if (sys.version_info.major != 2) or (sys.version_info.minor < 7):
|
||||||
|
# raise Exception("You must build Syncplay with Python 2.7!")
|
||||||
|
# except AttributeError:
|
||||||
|
# import warnings
|
||||||
|
# warnings.warn("You must build Syncplay with Python 2.7!")
|
||||||
|
|
||||||
|
from string import Template
|
||||||
|
|
||||||
|
import syncplay
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from syncplay.messages import getMissingStrings
|
||||||
|
missingStrings = getMissingStrings()
|
||||||
|
if missingStrings is not None and missingStrings is not "":
|
||||||
|
import warnings
|
||||||
|
warnings.warn("MISSING/UNUSED STRINGS DETECTED:\n{}".format(missingStrings))
|
||||||
|
|
||||||
|
def get_nsis_path():
|
||||||
|
bin_name = "makensis.exe"
|
||||||
|
from winreg import HKEY_LOCAL_MACHINE as HKLM
|
||||||
|
from winreg import KEY_READ, KEY_WOW64_32KEY, OpenKey, QueryValueEx
|
||||||
|
|
||||||
|
try:
|
||||||
|
nsisreg = OpenKey(HKLM, "Software\\NSIS", 0, KEY_READ | KEY_WOW64_32KEY)
|
||||||
|
if QueryValueEx(nsisreg, "VersionMajor")[0] >= 3:
|
||||||
|
return "{}\\{}".format(QueryValueEx(nsisreg, "")[0], bin_name)
|
||||||
|
else:
|
||||||
|
raise Exception("You must install NSIS 3 or later.")
|
||||||
|
except WindowsError:
|
||||||
|
return bin_name
|
||||||
|
NSIS_COMPILE = get_nsis_path()
|
||||||
|
|
||||||
|
OUT_DIR = "dist\Syncplay"
|
||||||
|
SETUP_SCRIPT_PATH = "syncplay_setup.nsi"
|
||||||
|
NSIS_SCRIPT_TEMPLATE = r"""
|
||||||
|
!include LogicLib.nsh
|
||||||
|
!include nsDialogs.nsh
|
||||||
|
!include FileFunc.nsh
|
||||||
|
|
||||||
|
LoadLanguageFile "$${NSISDIR}\Contrib\Language files\English.nlf"
|
||||||
|
LoadLanguageFile "$${NSISDIR}\Contrib\Language files\Polish.nlf"
|
||||||
|
LoadLanguageFile "$${NSISDIR}\Contrib\Language files\Russian.nlf"
|
||||||
|
LoadLanguageFile "$${NSISDIR}\Contrib\Language files\German.nlf"
|
||||||
|
LoadLanguageFile "$${NSISDIR}\Contrib\Language files\Italian.nlf"
|
||||||
|
|
||||||
|
Unicode true
|
||||||
|
|
||||||
|
Name "Syncplay $version"
|
||||||
|
OutFile "Syncplay-$version-Setup.exe"
|
||||||
|
InstallDir $$PROGRAMFILES\Syncplay
|
||||||
|
RequestExecutionLevel admin
|
||||||
|
XPStyle on
|
||||||
|
Icon resources\icon.ico ;Change DIR
|
||||||
|
SetCompressor /SOLID lzma
|
||||||
|
|
||||||
|
VIProductVersion "$version.0"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_ENGLISH} "ProductName" "Syncplay"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_ENGLISH} "FileVersion" "$version.0"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_ENGLISH} "LegalCopyright" "Syncplay"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_ENGLISH} "FileDescription" "Syncplay"
|
||||||
|
|
||||||
|
VIAddVersionKey /LANG=$${LANG_POLISH} "ProductName" "Syncplay"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_POLISH} "FileVersion" "$version.0"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_POLISH} "LegalCopyright" "Syncplay"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_POLISH} "FileDescription" "Syncplay"
|
||||||
|
|
||||||
|
VIAddVersionKey /LANG=$${LANG_RUSSIAN} "ProductName" "Syncplay"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_RUSSIAN} "FileVersion" "$version.0"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_RUSSIAN} "LegalCopyright" "Syncplay"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_RUSSIAN} "FileDescription" "Syncplay"
|
||||||
|
|
||||||
|
VIAddVersionKey /LANG=$${LANG_ITALIAN} "ProductName" "Syncplay"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_ITALIAN} "FileVersion" "$version.0"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_ITALIAN} "LegalCopyright" "Syncplay"
|
||||||
|
VIAddVersionKey /LANG=$${LANG_ITALIAN} "FileDescription" "Syncplay"
|
||||||
|
|
||||||
|
LangString ^SyncplayLanguage $${LANG_ENGLISH} "en"
|
||||||
|
LangString ^Associate $${LANG_ENGLISH} "Associate Syncplay with multimedia files."
|
||||||
|
LangString ^VLC $${LANG_ENGLISH} "Install Syncplay interface for VLC 2 and above"
|
||||||
|
LangString ^BrowseVLCBtn $${LANG_ENGLISH} "Select VLC folder"
|
||||||
|
LangString ^Shortcut $${LANG_ENGLISH} "Create Shortcuts in following locations:"
|
||||||
|
LangString ^StartMenu $${LANG_ENGLISH} "Start Menu"
|
||||||
|
LangString ^Desktop $${LANG_ENGLISH} "Desktop"
|
||||||
|
LangString ^QuickLaunchBar $${LANG_ENGLISH} "Quick Launch Bar"
|
||||||
|
LangString ^AutomaticUpdates $${LANG_ENGLISH} "Check for updates automatically"
|
||||||
|
LangString ^UninstConfig $${LANG_ENGLISH} "Delete configuration file."
|
||||||
|
|
||||||
|
LangString ^SyncplayLanguage $${LANG_POLISH} "pl"
|
||||||
|
LangString ^Associate $${LANG_POLISH} "Skojarz Syncplaya z multimediami"
|
||||||
|
LangString ^VLC $${LANG_POLISH} "Zainstaluj interface Syncplaya dla VLC 2+"
|
||||||
|
LangString ^BrowseVLCBtn $${LANG_POLISH} "Określ folder VLC"
|
||||||
|
LangString ^Shortcut $${LANG_POLISH} "Utworz skroty w nastepujacych miejscach:"
|
||||||
|
LangString ^StartMenu $${LANG_POLISH} "Menu Start"
|
||||||
|
LangString ^Desktop $${LANG_POLISH} "Pulpit"
|
||||||
|
LangString ^QuickLaunchBar $${LANG_POLISH} "Pasek szybkiego uruchamiania"
|
||||||
|
LangString ^UninstConfig $${LANG_POLISH} "Usun plik konfiguracyjny."
|
||||||
|
|
||||||
|
LangString ^SyncplayLanguage $${LANG_RUSSIAN} "ru"
|
||||||
|
LangString ^Associate $${LANG_RUSSIAN} "Ассоциировать Syncplay с видеофайлами"
|
||||||
|
LangString ^VLC $${LANG_RUSSIAN} "Установить интерфейс Syncplay для VLC 2+"
|
||||||
|
LangString ^BrowseVLCBtn $${LANG_RUSSIAN} "Укажите папку VLC"
|
||||||
|
LangString ^Shortcut $${LANG_RUSSIAN} "Создать ярлыки:"
|
||||||
|
LangString ^StartMenu $${LANG_RUSSIAN} "в меню Пуск"
|
||||||
|
LangString ^Desktop $${LANG_RUSSIAN} "на рабочем столе"
|
||||||
|
LangString ^QuickLaunchBar $${LANG_RUSSIAN} "в меню быстрого запуска"
|
||||||
|
LangString ^AutomaticUpdates $${LANG_RUSSIAN} "Проверять обновления автоматически"; TODO: Confirm Russian translation ("Check for updates automatically")
|
||||||
|
LangString ^UninstConfig $${LANG_RUSSIAN} "Удалить файл настроек."
|
||||||
|
|
||||||
|
LangString ^SyncplayLanguage $${LANG_GERMAN} "de"
|
||||||
|
LangString ^Associate $${LANG_GERMAN} "Syncplay als Standardprogramm für Multimedia-Dateien verwenden."
|
||||||
|
LangString ^VLC $${LANG_GERMAN} "Syncplay-Interface für VLC installieren (ab VLC 2+)"
|
||||||
|
LangString ^Shortcut $${LANG_GERMAN} "Erstelle Verknüpfungen an folgenden Orten:"
|
||||||
|
LangString ^BrowseVLCBtn $${LANG_GERMAN} "VLC-Ordner wählen"
|
||||||
|
LangString ^StartMenu $${LANG_GERMAN} "Startmenü"
|
||||||
|
LangString ^Desktop $${LANG_GERMAN} "Desktop"
|
||||||
|
LangString ^QuickLaunchBar $${LANG_GERMAN} "Schnellstartleiste"
|
||||||
|
LangString ^AutomaticUpdates $${LANG_GERMAN} "Automatisch nach Updates suchen";
|
||||||
|
LangString ^UninstConfig $${LANG_GERMAN} "Konfigurationsdatei löschen."
|
||||||
|
|
||||||
|
LangString ^SyncplayLanguage $${LANG_ITALIAN} "it"
|
||||||
|
LangString ^Associate $${LANG_ITALIAN} "Associa Syncplay con i file multimediali."
|
||||||
|
LangString ^VLC $${LANG_ITALIAN} "Installa l'interfaccia di Syncplay per VLC 2+"
|
||||||
|
LangString ^BrowseVLCBtn $${LANG_ITALIAN} "Cartella di VLC"
|
||||||
|
LangString ^Shortcut $${LANG_ITALIAN} "Crea i collegamenti nei percorsi seguenti:"
|
||||||
|
LangString ^StartMenu $${LANG_ITALIAN} "Menu Start"
|
||||||
|
LangString ^Desktop $${LANG_ITALIAN} "Desktop"
|
||||||
|
LangString ^QuickLaunchBar $${LANG_ITALIAN} "Barra di avvio rapido"
|
||||||
|
LangString ^AutomaticUpdates $${LANG_ITALIAN} "Controllo automatico degli aggiornamenti"
|
||||||
|
LangString ^UninstConfig $${LANG_ITALIAN} "Cancella i file di configurazione."
|
||||||
|
|
||||||
|
; Remove text to save space
|
||||||
|
LangString ^ClickInstall $${LANG_GERMAN} " "
|
||||||
|
|
||||||
|
PageEx license
|
||||||
|
LicenseData resources\license.rtf
|
||||||
|
PageExEnd
|
||||||
|
Page custom DirectoryCustom DirectoryCustomLeave
|
||||||
|
Page instFiles
|
||||||
|
|
||||||
|
UninstPage custom un.installConfirm un.installConfirmLeave
|
||||||
|
UninstPage instFiles
|
||||||
|
|
||||||
|
Var Dialog
|
||||||
|
Var Icon_Syncplay
|
||||||
|
Var Icon_Syncplay_Handle
|
||||||
|
;Var CheckBox_Associate
|
||||||
|
Var CheckBox_VLC
|
||||||
|
Var CheckBox_AutomaticUpdates
|
||||||
|
Var CheckBox_StartMenuShortcut
|
||||||
|
Var CheckBox_DesktopShortcut
|
||||||
|
Var CheckBox_QuickLaunchShortcut
|
||||||
|
;Var CheckBox_Associate_State
|
||||||
|
Var CheckBox_VLC_State
|
||||||
|
Var CheckBox_AutomaticUpdates_State
|
||||||
|
Var CheckBox_StartMenuShortcut_State
|
||||||
|
Var CheckBox_DesktopShortcut_State
|
||||||
|
Var CheckBox_QuickLaunchShortcut_State
|
||||||
|
Var Button_Browse
|
||||||
|
Var Button_Browse_VLC
|
||||||
|
Var Directory
|
||||||
|
Var GroupBox_DirSub
|
||||||
|
Var Label_Text
|
||||||
|
Var Label_Shortcut
|
||||||
|
Var Label_Size
|
||||||
|
Var Label_Space
|
||||||
|
Var Text_Directory
|
||||||
|
|
||||||
|
Var Uninst_Dialog
|
||||||
|
Var Uninst_Icon
|
||||||
|
Var Uninst_Icon_Handle
|
||||||
|
Var Uninst_Label_Directory
|
||||||
|
Var Uninst_Label_Text
|
||||||
|
Var Uninst_Text_Directory
|
||||||
|
Var Uninst_CheckBox_Config
|
||||||
|
Var Uninst_CheckBox_Config_State
|
||||||
|
|
||||||
|
Var Size
|
||||||
|
Var SizeHex
|
||||||
|
Var AvailibleSpace
|
||||||
|
Var AvailibleSpaceGiB
|
||||||
|
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_UNASSOCIATE EXT FileCLASS
|
||||||
|
; Backup the previously associated File class
|
||||||
|
ReadRegStr $$R0 HKCR ".$${EXT}" `$${FileCLASS}_backup`
|
||||||
|
WriteRegStr HKCR ".$${EXT}" "" "$$R0"
|
||||||
|
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 UNASSOCIATE EXT
|
||||||
|
!insertmacro APP_UNASSOCIATE "$${EXT}" "Syncplay.$${EXT}"
|
||||||
|
!macroend
|
||||||
|
|
||||||
|
;Prevents from running more than one instance of installer and sets default state of checkboxes
|
||||||
|
Function .onInit
|
||||||
|
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "SyncplayMutex") i .r1 ?e'
|
||||||
|
Pop $$R0
|
||||||
|
StrCmp $$R0 0 +3
|
||||||
|
MessageBox MB_OK|MB_ICONEXCLAMATION "The installer is already running."
|
||||||
|
Abort
|
||||||
|
|
||||||
|
;StrCpy $$CheckBox_Associate_State $${BST_CHECKED}
|
||||||
|
StrCpy $$CheckBox_StartMenuShortcut_State $${BST_CHECKED}
|
||||||
|
Call GetVLCDir
|
||||||
|
Call UpdateVLCCheckbox
|
||||||
|
|
||||||
|
Call GetSize
|
||||||
|
Call DriveSpace
|
||||||
|
Call Language
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
;Language selection dialog
|
||||||
|
Function Language
|
||||||
|
Push ""
|
||||||
|
Push $${LANG_ENGLISH}
|
||||||
|
Push English
|
||||||
|
Push $${LANG_POLISH}
|
||||||
|
Push Polski
|
||||||
|
Push $${LANG_RUSSIAN}
|
||||||
|
Push Русский
|
||||||
|
Push $${LANG_GERMAN}
|
||||||
|
Push Deutsch
|
||||||
|
Push $${LANG_ITALIAN}
|
||||||
|
Push Italiano
|
||||||
|
Push A ; A means auto count languages
|
||||||
|
LangDLL::LangDialog "Language Selection" "Please select the language of Syncplay and the installer"
|
||||||
|
Pop $$LANGUAGE
|
||||||
|
StrCmp $$LANGUAGE "cancel" 0 +2
|
||||||
|
Abort
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function DirectoryCustom
|
||||||
|
|
||||||
|
nsDialogs::Create 1018
|
||||||
|
Pop $$Dialog
|
||||||
|
|
||||||
|
GetFunctionAddress $$R8 DirectoryCustomLeave
|
||||||
|
nsDialogs::OnBack $$R8
|
||||||
|
|
||||||
|
$${NSD_CreateIcon} 0u 0u 22u 20u ""
|
||||||
|
Pop $$Icon_Syncplay
|
||||||
|
$${NSD_SetIconFromInstaller} $$Icon_Syncplay $$Icon_Syncplay_Handle
|
||||||
|
|
||||||
|
$${NSD_CreateLabel} 25u 0u 241u 34u "$$(^DirText)"
|
||||||
|
Pop $$Label_Text
|
||||||
|
|
||||||
|
$${NSD_CreateText} 8u 38u 187u 12u "$$INSTDIR"
|
||||||
|
Pop $$Text_Directory
|
||||||
|
$${NSD_SetFocus} $$Text_Directory
|
||||||
|
|
||||||
|
$${NSD_CreateBrowseButton} 202u 37u 55u 14u "$$(^BrowseBtn)"
|
||||||
|
Pop $$Button_Browse
|
||||||
|
$${NSD_OnClick} $$Button_Browse DirectoryBrowseDialog
|
||||||
|
|
||||||
|
$${NSD_CreateGroupBox} 1u 27u 264u 30u "$$(^DirSubText)"
|
||||||
|
Pop $$GroupBox_DirSub
|
||||||
|
|
||||||
|
$${NSD_CreateLabel} 0u 122u 132 8u "$$(^SpaceRequired)$$SizeMB"
|
||||||
|
Pop $$Label_Size
|
||||||
|
|
||||||
|
$${NSD_CreateLabel} 321u 122u 132 8u "$$(^SpaceAvailable)$$AvailibleSpaceGiB.$$AvailibleSpaceGB"
|
||||||
|
Pop $$Label_Space
|
||||||
|
|
||||||
|
;$${NSD_CreateCheckBox} 8u 59u 187u 10u "$$(^Associate)"
|
||||||
|
;Pop $$CheckBox_Associate
|
||||||
|
|
||||||
|
$${NSD_CreateBrowseButton} 185u 70u 70u 14u "$$(^BrowseVLCBtn)"
|
||||||
|
Pop $$Button_Browse_VLC
|
||||||
|
$${NSD_OnClick} $$Button_Browse_VLC DirectoryBrowseDialogVLC
|
||||||
|
|
||||||
|
$${NSD_CreateCheckBox} 8u 72u 250u 10u "$$(^VLC)"
|
||||||
|
Pop $$CheckBox_VLC
|
||||||
|
|
||||||
|
$${NSD_CreateCheckBox} 8u 85u 250u 10u "$$(^AutomaticUpdates)"
|
||||||
|
Pop $$CheckBox_AutomaticUpdates
|
||||||
|
$${NSD_Check} $$CheckBox_AutomaticUpdates
|
||||||
|
|
||||||
|
$${NSD_CreateLabel} 8u 98u 187u 10u "$$(^Shortcut)"
|
||||||
|
Pop $$Label_Shortcut
|
||||||
|
|
||||||
|
$${NSD_CreateCheckbox} 8u 111u 60u 10u "$$(^StartMenu)"
|
||||||
|
Pop $$CheckBox_StartMenuShortcut
|
||||||
|
|
||||||
|
$${NSD_CreateCheckbox} 78u 111u 70u 10u "$$(^Desktop)"
|
||||||
|
Pop $$CheckBox_DesktopShortcut
|
||||||
|
|
||||||
|
$${NSD_CreateCheckbox} 158u 111u 130u 10u "$$(^QuickLaunchBar)"
|
||||||
|
Pop $$CheckBox_QuickLaunchShortcut
|
||||||
|
|
||||||
|
;$${If} $$CheckBox_Associate_State == $${BST_CHECKED}
|
||||||
|
; $${NSD_Check} $$CheckBox_Associate
|
||||||
|
;$${EndIf}
|
||||||
|
|
||||||
|
$${If} $$CheckBox_VLC_State == $${BST_CHECKED}
|
||||||
|
$${NSD_Check} $$CheckBox_VLC
|
||||||
|
$${EndIf}
|
||||||
|
|
||||||
|
Call UpdateVLCCheckbox
|
||||||
|
|
||||||
|
$${If} $$CheckBox_StartMenuShortcut_State == $${BST_CHECKED}
|
||||||
|
$${NSD_Check} $$CheckBox_StartMenuShortcut
|
||||||
|
$${EndIf}
|
||||||
|
|
||||||
|
$${If} $$CheckBox_DesktopShortcut_State == $${BST_CHECKED}
|
||||||
|
$${NSD_Check} $$CheckBox_DesktopShortcut
|
||||||
|
$${EndIf}
|
||||||
|
|
||||||
|
$${If} $$CheckBox_QuickLaunchShortcut_State == $${BST_CHECKED}
|
||||||
|
$${NSD_Check} $$CheckBox_QuickLaunchShortcut
|
||||||
|
$${EndIf}
|
||||||
|
|
||||||
|
$${If} $$CheckBox_AutomaticUpdates_State == $${BST_CHECKED}
|
||||||
|
$${NSD_Check} $$CheckBox_AutomaticUpdates
|
||||||
|
$${EndIf}
|
||||||
|
|
||||||
|
nsDialogs::Show
|
||||||
|
|
||||||
|
$${NSD_FreeIcon} $$Icon_Syncplay_Handle
|
||||||
|
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function DirectoryCustomLeave
|
||||||
|
$${NSD_GetText} $$Text_Directory $$INSTDIR
|
||||||
|
;$${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
|
||||||
|
$${NSD_GetState} $$CheckBox_DesktopShortcut $$CheckBox_DesktopShortcut_State
|
||||||
|
$${NSD_GetState} $$CheckBox_QuickLaunchShortcut $$CheckBox_QuickLaunchShortcut_State
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function DirectoryBrowseDialog
|
||||||
|
nsDialogs::SelectFolderDialog $$(^DirBrowseText)
|
||||||
|
Pop $$Directory
|
||||||
|
$${If} $$Directory != error
|
||||||
|
StrCpy $$INSTDIR $$Directory
|
||||||
|
$${NSD_SetText} $$Text_Directory $$INSTDIR
|
||||||
|
Call DriveSpace
|
||||||
|
$${NSD_SetText} $$Label_Space "$$(^SpaceAvailable)$$AvailibleSpaceGiB.$$AvailibleSpaceGB"
|
||||||
|
$${EndIf}
|
||||||
|
Abort
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function GetVLCDir
|
||||||
|
IfFileExists "$$VLC_Directory\vlc.exe" VLCFound 0
|
||||||
|
ReadRegStr $$VLC_Directory HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "VLCInstallLocation"
|
||||||
|
IfFileExists "$$VLC_Directory\vlc.exe" VLCFound 0
|
||||||
|
ReadRegStr $$VLC_Directory HKLM "Software\VideoLAN\VLC" "InstallDir"
|
||||||
|
IfFileExists "$$VLC_Directory\vlc.exe" VLCFound 0
|
||||||
|
StrCpy $$VLC_Directory "c:\program files (x86)\videolan\vlc"
|
||||||
|
IfFileExists "$$VLC_Directory\vlc.exe" VLCFound 0
|
||||||
|
StrCpy $$VLC_Directory "c:\program files\videolan\vlc"
|
||||||
|
IfFileExists "$$VLC_Directory\vlc.exe" VLCFound 0
|
||||||
|
StrCpy $$VLC_Directory ""
|
||||||
|
VLCFound:
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function UpdateVLCCheckbox
|
||||||
|
IfFileExists "$$VLC_Directory\vlc.exe" VLC_Enabled VLC_Disabled
|
||||||
|
|
||||||
|
VLC_Enabled:
|
||||||
|
EnableWindow $$CheckBox_VLC 1
|
||||||
|
StrCpy $$CheckBox_VLC_State $${BST_CHECKED}
|
||||||
|
$${NSD_SetState} $$CheckBox_VLC $$CheckBox_VLC_State
|
||||||
|
goto CheckboxUpdated
|
||||||
|
|
||||||
|
VLC_Disabled:
|
||||||
|
EnableWindow $$CheckBox_VLC 0
|
||||||
|
StrCpy $$CheckBox_VLC_State $${BST_UNCHECKED}
|
||||||
|
$${NSD_SetState} $$CheckBox_VLC $$CheckBox_VLC_State
|
||||||
|
|
||||||
|
CheckboxUpdated:
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function DirectoryBrowseDialogVLC
|
||||||
|
nsDialogs::SelectFolderDialog $$(^BrowseVLCBtn) $$VLC_Directory
|
||||||
|
Pop $$Directory
|
||||||
|
$${If} $$Directory != error
|
||||||
|
StrCpy $$VLC_Directory $$Directory
|
||||||
|
Call UpdateVLCCheckbox
|
||||||
|
$${EndIf}
|
||||||
|
Abort
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function GetSize
|
||||||
|
StrCpy $$Size "$totalSize"
|
||||||
|
IntOp $$Size $$Size / 1024
|
||||||
|
IntFmt $$SizeHex "0x%08X" $$Size
|
||||||
|
IntOp $$Size $$Size / 1024
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
;Calculates Free Space on HDD
|
||||||
|
Function DriveSpace
|
||||||
|
StrCpy $$Drive $$INSTDIR 1
|
||||||
|
$${DriveSpace} "$$Drive:\" "/D=F /S=M" $$AvailibleSpace
|
||||||
|
IntOp $$AvailibleSpaceGiB $$AvailibleSpace / 1024
|
||||||
|
IntOp $$AvailibleSpace $$AvailibleSpace % 1024
|
||||||
|
IntOp $$AvailibleSpace $$AvailibleSpace / 102
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function InstallOptions
|
||||||
|
;$${If} $$CheckBox_Associate_State == $${BST_CHECKED}
|
||||||
|
; Call Associate
|
||||||
|
; DetailPrint "Associated Syncplay with multimedia files"
|
||||||
|
;$${EndIf}
|
||||||
|
|
||||||
|
$${If} $$CheckBox_StartMenuShortcut_State == $${BST_CHECKED}
|
||||||
|
CreateDirectory $$SMPROGRAMS\Syncplay
|
||||||
|
CreateShortCut "$$SMPROGRAMS\Syncplay\Syncplay.lnk" "$$INSTDIR\Syncplay.exe" ""
|
||||||
|
CreateShortCut "$$SMPROGRAMS\Syncplay\Syncplay Server.lnk" "$$INSTDIR\syncplayServer.exe" ""
|
||||||
|
CreateShortCut "$$SMPROGRAMS\Syncplay\Uninstall.lnk" "$$INSTDIR\Uninstall.exe" ""
|
||||||
|
WriteINIStr "$$SMPROGRAMS\Syncplay\SyncplayWebsite.url" "InternetShortcut" "URL" "http://syncplay.pl"
|
||||||
|
$${EndIf}
|
||||||
|
|
||||||
|
$${If} $$CheckBox_DesktopShortcut_State == $${BST_CHECKED}
|
||||||
|
CreateShortCut "$$DESKTOP\Syncplay.lnk" "$$INSTDIR\Syncplay.exe" ""
|
||||||
|
$${EndIf}
|
||||||
|
|
||||||
|
$${If} $$CheckBox_QuickLaunchShortcut_State == $${BST_CHECKED}
|
||||||
|
CreateShortCut "$$QUICKLAUNCH\Syncplay.lnk" "$$INSTDIR\Syncplay.exe" ""
|
||||||
|
$${EndIf}
|
||||||
|
|
||||||
|
$${If} $$CheckBox_VLC_State == $${BST_CHECKED}
|
||||||
|
IfFileExists "$$VLC_Directory\vlc.exe" 0 EndOfVLC
|
||||||
|
SetOutPath $$VLC_Directory\lua\intf
|
||||||
|
File resources\lua\intf\syncplay.lua
|
||||||
|
EndOfVLC:
|
||||||
|
$${EndIf}
|
||||||
|
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 WriteRegistry
|
||||||
|
Call GetSize
|
||||||
|
WriteRegStr HKLM SOFTWARE\Syncplay "Install_Dir" "$$INSTDIR"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "DisplayName" "Syncplay"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "InstallLocation" "$$INSTDIR"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "VLCInstallLocation" "$$VLC_Directory"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "UninstallString" '"$$INSTDIR\uninstall.exe"'
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "DisplayIcon" "$$INSTDIR\resources\icon.ico"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "Publisher" "Syncplay"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "DisplayVersion" "$version"
|
||||||
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "URLInfoAbout" "http://syncplay.pl/"
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "NoModify" 1
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "NoRepair" 1
|
||||||
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "EstimatedSize" "$$SizeHex"
|
||||||
|
WriteINIStr $$APPDATA\syncplay.ini general language $$(^SyncplayLanguage)
|
||||||
|
$${If} $$CheckBox_AutomaticUpdates_State == $${BST_CHECKED}
|
||||||
|
WriteINIStr $$APPDATA\syncplay.ini general CheckForUpdatesAutomatically "True"
|
||||||
|
$${Else}
|
||||||
|
WriteINIStr $$APPDATA\syncplay.ini general CheckForUpdatesAutomatically "False"
|
||||||
|
$${EndIf}
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function un.installConfirm
|
||||||
|
nsDialogs::Create 1018
|
||||||
|
Pop $$Uninst_Dialog
|
||||||
|
|
||||||
|
$${NSD_CreateIcon} 0u 1u 22u 20u ""
|
||||||
|
Pop $$Uninst_Icon
|
||||||
|
$${NSD_SetIconFromInstaller} $$Uninst_Icon $$Uninst_Icon_Handle
|
||||||
|
|
||||||
|
$${NSD_CreateLabel} 0u 45u 55u 8u "$$(^UninstallingSubText)"
|
||||||
|
Pop $$Uninst_Label_Directory
|
||||||
|
|
||||||
|
$${NSD_CreateLabel} 25u 0u 241u 34u "$$(^UninstallingText)"
|
||||||
|
Pop $$Uninst_Label_Text
|
||||||
|
|
||||||
|
ReadRegStr $$INSTDIR HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "InstallLocation"
|
||||||
|
$${NSD_CreateText} 56u 43u 209u 12u "$$INSTDIR"
|
||||||
|
Pop $$Uninst_Text_Directory
|
||||||
|
EnableWindow $$Uninst_Text_Directory 0
|
||||||
|
|
||||||
|
$${NSD_CreateCheckBox} 0u 60u 250u 10u "$$(^UninstConfig)"
|
||||||
|
Pop $$Uninst_CheckBox_Config
|
||||||
|
|
||||||
|
|
||||||
|
nsDialogs::Show
|
||||||
|
$${NSD_FreeIcon} $$Uninst_Icon_Handle
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function un.installConfirmLeave
|
||||||
|
$${NSD_GetState} $$Uninst_CheckBox_Config $$Uninst_CheckBox_Config_State
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function un.AssociateDel
|
||||||
|
!insertmacro UNASSOCIATE avi
|
||||||
|
!insertmacro UNASSOCIATE mpg
|
||||||
|
!insertmacro UNASSOCIATE mpeg
|
||||||
|
!insertmacro UNASSOCIATE mpe
|
||||||
|
!insertmacro UNASSOCIATE m1v
|
||||||
|
!insertmacro UNASSOCIATE m2v
|
||||||
|
!insertmacro UNASSOCIATE mpv2
|
||||||
|
!insertmacro UNASSOCIATE mp2v
|
||||||
|
!insertmacro UNASSOCIATE mkv
|
||||||
|
!insertmacro UNASSOCIATE mp4
|
||||||
|
!insertmacro UNASSOCIATE m4v
|
||||||
|
!insertmacro UNASSOCIATE mp4v
|
||||||
|
!insertmacro UNASSOCIATE 3gp
|
||||||
|
!insertmacro UNASSOCIATE 3gpp
|
||||||
|
!insertmacro UNASSOCIATE 3g2
|
||||||
|
!insertmacro UNASSOCIATE 3pg2
|
||||||
|
!insertmacro UNASSOCIATE flv
|
||||||
|
!insertmacro UNASSOCIATE f4v
|
||||||
|
!insertmacro UNASSOCIATE rm
|
||||||
|
!insertmacro UNASSOCIATE wmv
|
||||||
|
!insertmacro UNASSOCIATE swf
|
||||||
|
!insertmacro UNASSOCIATE rmvb
|
||||||
|
!insertmacro UNASSOCIATE divx
|
||||||
|
!insertmacro UNASSOCIATE amv
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function un.InstallOptions
|
||||||
|
Delete $$SMPROGRAMS\Syncplay\Syncplay.lnk
|
||||||
|
Delete "$$SMPROGRAMS\Syncplay\Syncplay Server.lnk"
|
||||||
|
Delete $$SMPROGRAMS\Syncplay\Uninstall.lnk
|
||||||
|
Delete $$SMPROGRAMS\Syncplay\SyncplayWebsite.url
|
||||||
|
RMDir $$SMPROGRAMS\Syncplay
|
||||||
|
Delete $$DESKTOP\Syncplay.lnk
|
||||||
|
Delete $$QUICKLAUNCH\Syncplay.lnk
|
||||||
|
ReadRegStr $$VLC_Directory HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay" "VLCInstallLocation"
|
||||||
|
IfFileExists "$$VLC_Directory\lua\intf\syncplay.lua" 0 +2
|
||||||
|
Delete $$VLC_Directory\lua\intf\syncplay.lua
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Section "Install"
|
||||||
|
SetOverwrite on
|
||||||
|
SetOutPath $$INSTDIR
|
||||||
|
WriteUninstaller uninstall.exe
|
||||||
|
|
||||||
|
$installFiles
|
||||||
|
|
||||||
|
Call InstallOptions
|
||||||
|
Call WriteRegistry
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Uninstall"
|
||||||
|
Call un.AssociateDel
|
||||||
|
Call un.InstallOptions
|
||||||
|
$uninstallFiles
|
||||||
|
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Syncplay"
|
||||||
|
DeleteRegKey HKLM SOFTWARE\Syncplay
|
||||||
|
Delete $$INSTDIR\uninstall.exe
|
||||||
|
RMDir $$INSTDIR\Syncplay\\resources\lua\intf
|
||||||
|
RMDir $$INSTDIR\Syncplay\\resources\lua
|
||||||
|
RMDir $$INSTDIR\Syncplay\\resources
|
||||||
|
RMDir $$INSTDIR\resources
|
||||||
|
RMDir $$INSTDIR\lib
|
||||||
|
RMDir $$INSTDIR
|
||||||
|
|
||||||
|
$${If} $$Uninst_CheckBox_Config_State == $${BST_CHECKED}
|
||||||
|
IfFileExists "$$APPDATA\.syncplay" 0 +2
|
||||||
|
Delete $$APPDATA\.syncplay
|
||||||
|
IfFileExists "$$APPDATA\syncplay.ini" 0 +2
|
||||||
|
Delete $$APPDATA\syncplay.ini
|
||||||
|
$${EndIf}
|
||||||
|
SectionEnd
|
||||||
|
"""
|
||||||
|
|
||||||
|
class NSISScript(object):
|
||||||
|
def create(self):
|
||||||
|
fileList, totalSize = self.getBuildDirContents(OUT_DIR)
|
||||||
|
print("Total size eq: {}".format(totalSize))
|
||||||
|
installFiles = self.prepareInstallListTemplate(fileList)
|
||||||
|
uninstallFiles = self.prepareDeleteListTemplate(fileList)
|
||||||
|
|
||||||
|
if os.path.isfile(SETUP_SCRIPT_PATH):
|
||||||
|
raise RuntimeError("Cannot create setup script, file exists at {}".format(SETUP_SCRIPT_PATH))
|
||||||
|
contents = Template(NSIS_SCRIPT_TEMPLATE).substitute(
|
||||||
|
version = syncplay.version,
|
||||||
|
uninstallFiles = uninstallFiles,
|
||||||
|
installFiles = installFiles,
|
||||||
|
totalSize = totalSize,
|
||||||
|
)
|
||||||
|
with codecs.open(SETUP_SCRIPT_PATH, "w", "utf-8-sig") as outfile:
|
||||||
|
outfile.write(contents)
|
||||||
|
|
||||||
|
def compile(self):
|
||||||
|
if not os.path.isfile(NSIS_COMPILE):
|
||||||
|
return "makensis.exe not found, won't create the installer"
|
||||||
|
subproc = subprocess.Popen([NSIS_COMPILE, SETUP_SCRIPT_PATH], env=os.environ)
|
||||||
|
subproc.communicate()
|
||||||
|
retcode = subproc.returncode
|
||||||
|
os.remove(SETUP_SCRIPT_PATH)
|
||||||
|
if retcode:
|
||||||
|
raise RuntimeError("NSIS compilation return code: %d" % retcode)
|
||||||
|
|
||||||
|
def getBuildDirContents(self, path):
|
||||||
|
fileList = {}
|
||||||
|
totalSize = 0
|
||||||
|
for root, _, files in os.walk(path):
|
||||||
|
totalSize += sum(os.path.getsize(os.path.join(root, file_)) for file_ in files)
|
||||||
|
for file_ in files:
|
||||||
|
new_root = root.replace(OUT_DIR, "").strip("\\")
|
||||||
|
if new_root not in fileList:
|
||||||
|
fileList[new_root] = []
|
||||||
|
fileList[new_root].append(file_)
|
||||||
|
return fileList, totalSize
|
||||||
|
|
||||||
|
def prepareInstallListTemplate(self, fileList):
|
||||||
|
create = []
|
||||||
|
for dir_ in fileList.keys():
|
||||||
|
create.append('SetOutPath "$INSTDIR\\{}"'.format(dir_))
|
||||||
|
for file_ in fileList[dir_]:
|
||||||
|
create.append('FILE "{}\\{}\\{}"'.format(OUT_DIR, dir_, file_))
|
||||||
|
return "\n".join(create)
|
||||||
|
|
||||||
|
def prepareDeleteListTemplate(self, fileList):
|
||||||
|
delete = []
|
||||||
|
for dir_ in fileList.keys():
|
||||||
|
for file_ in fileList[dir_]:
|
||||||
|
delete.append('DELETE "$INSTDIR\\{}\\{}"'.format(dir_, file_))
|
||||||
|
delete.append('RMdir "$INSTDIR\\{}"'.format(file_))
|
||||||
|
return "\n".join(delete)
|
||||||
|
|
||||||
|
guiIcons = ['resources/accept.png', 'resources/arrow_undo.png', 'resources/clock_go.png',
|
||||||
|
'resources/control_pause_blue.png', 'resources/cross.png', 'resources/door_in.png',
|
||||||
|
'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png',
|
||||||
|
'resources/timeline_marker.png','resources/control_play_blue.png',
|
||||||
|
'resources/mpc-hc.png','resources/mpc-hc64.png','resources/mplayer.png',
|
||||||
|
'resources/mpc-be.png',
|
||||||
|
'resources/mpv.png','resources/vlc.png', 'resources/house.png', 'resources/film_link.png',
|
||||||
|
'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/chevrons_right.png',
|
||||||
|
'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png',
|
||||||
|
'resources/tick.png', 'resources/lock_open.png', 'resources/empty_checkbox.png', 'resources/tick_checkbox.png',
|
||||||
|
'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/user_comment.png',
|
||||||
|
'resources/error.png',
|
||||||
|
'resources/film_folder_edit.png',
|
||||||
|
'resources/film_edit.png',
|
||||||
|
'resources/folder_film.png',
|
||||||
|
'resources/shield_edit.png',
|
||||||
|
'resources/shield_add.png',
|
||||||
|
'resources/email_go.png',
|
||||||
|
'resources/world_add.png', 'resources/film_add.png', 'resources/delete.png', 'resources/spinner.mng'
|
||||||
|
]
|
||||||
|
resources = ["resources/icon.ico", "resources/syncplay.png", "resources/syncplayintf.lua", "resources/license.rtf", "resources/third-party-notices.rtf"]
|
||||||
|
resources.extend(guiIcons)
|
||||||
|
intf_resources = ["resources/lua/intf/syncplay.lua"]
|
||||||
|
|
||||||
|
common_info = dict(
|
||||||
|
name='Syncplay',
|
||||||
|
version=syncplay.version,
|
||||||
|
author='Uriziel',
|
||||||
|
author_email='dev@syncplay.pl',
|
||||||
|
description='Syncplay',
|
||||||
|
)
|
||||||
|
|
||||||
|
script = NSISScript()
|
||||||
|
script.create()
|
||||||
|
print("*** compiling the NSIS setup script***")
|
||||||
|
script.compile()
|
||||||
|
print("*** DONE ***")
|
||||||
0
buildPy2app.py
Normal file → Executable file
0
buildPy2app.py
Normal file → Executable file
@ -1,24 +1,24 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
#coding:utf8
|
#coding:utf8
|
||||||
|
|
||||||
''' *** TROUBLESHOOTING ***
|
|
||||||
|
|
||||||
) If you get the error "ImportError: No module named zope.interface" then add an empty __init__.py file to the PYTHONDIR/Lib/site-packages/zope directory
|
#*** TROUBLESHOOTING ***
|
||||||
|
#1) If you get the error "ImportError: No module named zope.interface" then add an empty __init__.py file to the PYTHONDIR/Lib/site-packages/zope directory
|
||||||
2) It is expected that you will have NSIS 3 NSIS from http://nsis.sourceforge.net installed.
|
#2) It is expected that you will have NSIS 3 NSIS from http://nsis.sourceforge.net installed.
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
import sys, codecs
|
import sys, codecs
|
||||||
try:
|
# try:
|
||||||
if (sys.version_info.major != 2) or (sys.version_info.minor < 7):
|
# if (sys.version_info.major != 2) or (sys.version_info.minor < 7):
|
||||||
raise Exception("You must build Syncplay with Python 2.7!")
|
# raise Exception("You must build Syncplay with Python 2.7!")
|
||||||
except AttributeError:
|
# except AttributeError:
|
||||||
import warnings
|
# import warnings
|
||||||
warnings.warn("You must build Syncplay with Python 2.7!")
|
# warnings.warn("You must build Syncplay with Python 2.7!")
|
||||||
|
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
from py2exe.build_exe import py2exe
|
try:
|
||||||
|
from py2exe.build_exe import py2exe
|
||||||
|
except ImportError:
|
||||||
|
from py2exe.distutils_buildexe import py2exe
|
||||||
from string import Template
|
from string import Template
|
||||||
|
|
||||||
import syncplay
|
import syncplay
|
||||||
@ -33,8 +33,8 @@ if missingStrings is not None and missingStrings is not "":
|
|||||||
|
|
||||||
def get_nsis_path():
|
def get_nsis_path():
|
||||||
bin_name = "makensis.exe"
|
bin_name = "makensis.exe"
|
||||||
from _winreg import HKEY_LOCAL_MACHINE as HKLM
|
from winreg import HKEY_LOCAL_MACHINE as HKLM
|
||||||
from _winreg import KEY_READ, KEY_WOW64_32KEY, OpenKey, QueryValueEx
|
from winreg import KEY_READ, KEY_WOW64_32KEY, OpenKey, QueryValueEx
|
||||||
|
|
||||||
try:
|
try:
|
||||||
nsisreg = OpenKey(HKLM, "Software\\NSIS", 0, KEY_READ | KEY_WOW64_32KEY)
|
nsisreg = OpenKey(HKLM, "Software\\NSIS", 0, KEY_READ | KEY_WOW64_32KEY)
|
||||||
@ -616,7 +616,7 @@ NSIS_SCRIPT_TEMPLATE = r"""
|
|||||||
class NSISScript(object):
|
class NSISScript(object):
|
||||||
def create(self):
|
def create(self):
|
||||||
fileList, totalSize = self.getBuildDirContents(OUT_DIR)
|
fileList, totalSize = self.getBuildDirContents(OUT_DIR)
|
||||||
print "Total size eq: {}".format(totalSize)
|
print("Total size eq: {}".format(totalSize))
|
||||||
installFiles = self.prepareInstallListTemplate(fileList)
|
installFiles = self.prepareInstallListTemplate(fileList)
|
||||||
uninstallFiles = self.prepareDeleteListTemplate(fileList)
|
uninstallFiles = self.prepareDeleteListTemplate(fileList)
|
||||||
|
|
||||||
@ -629,7 +629,7 @@ class NSISScript(object):
|
|||||||
totalSize = totalSize,
|
totalSize = totalSize,
|
||||||
)
|
)
|
||||||
with codecs.open(SETUP_SCRIPT_PATH, "w", "utf-8-sig") as outfile:
|
with codecs.open(SETUP_SCRIPT_PATH, "w", "utf-8-sig") as outfile:
|
||||||
outfile.write(contents.decode('utf-8'))
|
outfile.write(contents)
|
||||||
|
|
||||||
def compile(self):
|
def compile(self):
|
||||||
if not os.path.isfile(NSIS_COMPILE):
|
if not os.path.isfile(NSIS_COMPILE):
|
||||||
@ -648,14 +648,14 @@ class NSISScript(object):
|
|||||||
totalSize += sum(os.path.getsize(os.path.join(root, file_)) for file_ in files)
|
totalSize += sum(os.path.getsize(os.path.join(root, file_)) for file_ in files)
|
||||||
for file_ in files:
|
for file_ in files:
|
||||||
new_root = root.replace(OUT_DIR, "").strip("\\")
|
new_root = root.replace(OUT_DIR, "").strip("\\")
|
||||||
if not fileList.has_key(new_root):
|
if new_root not in fileList:
|
||||||
fileList[new_root] = []
|
fileList[new_root] = []
|
||||||
fileList[new_root].append(file_)
|
fileList[new_root].append(file_)
|
||||||
return fileList, totalSize
|
return fileList, totalSize
|
||||||
|
|
||||||
def prepareInstallListTemplate(self, fileList):
|
def prepareInstallListTemplate(self, fileList):
|
||||||
create = []
|
create = []
|
||||||
for dir_ in fileList.iterkeys():
|
for dir_ in fileList.keys():
|
||||||
create.append('SetOutPath "$INSTDIR\\{}"'.format(dir_))
|
create.append('SetOutPath "$INSTDIR\\{}"'.format(dir_))
|
||||||
for file_ in fileList[dir_]:
|
for file_ in fileList[dir_]:
|
||||||
create.append('FILE "{}\\{}\\{}"'.format(OUT_DIR, dir_, file_))
|
create.append('FILE "{}\\{}\\{}"'.format(OUT_DIR, dir_, file_))
|
||||||
@ -663,7 +663,7 @@ class NSISScript(object):
|
|||||||
|
|
||||||
def prepareDeleteListTemplate(self, fileList):
|
def prepareDeleteListTemplate(self, fileList):
|
||||||
delete = []
|
delete = []
|
||||||
for dir_ in fileList.iterkeys():
|
for dir_ in fileList.keys():
|
||||||
for file_ in fileList[dir_]:
|
for file_ in fileList[dir_]:
|
||||||
delete.append('DELETE "$INSTDIR\\{}\\{}"'.format(dir_, file_))
|
delete.append('DELETE "$INSTDIR\\{}\\{}"'.format(dir_, file_))
|
||||||
delete.append('RMdir "$INSTDIR\\{}"'.format(file_))
|
delete.append('RMdir "$INSTDIR\\{}"'.format(file_))
|
||||||
@ -674,9 +674,9 @@ class build_installer(py2exe):
|
|||||||
py2exe.run(self)
|
py2exe.run(self)
|
||||||
script = NSISScript()
|
script = NSISScript()
|
||||||
script.create()
|
script.create()
|
||||||
print "*** compiling the NSIS setup script***"
|
print("*** compiling the NSIS setup script***")
|
||||||
script.compile()
|
script.compile()
|
||||||
print "*** DONE ***"
|
print("*** DONE ***")
|
||||||
|
|
||||||
guiIcons = ['resources/accept.png', 'resources/arrow_undo.png', 'resources/clock_go.png',
|
guiIcons = ['resources/accept.png', 'resources/arrow_undo.png', 'resources/clock_go.png',
|
||||||
'resources/control_pause_blue.png', 'resources/cross.png', 'resources/door_in.png',
|
'resources/control_pause_blue.png', 'resources/cross.png', 'resources/door_in.png',
|
||||||
@ -721,7 +721,7 @@ info = dict(
|
|||||||
options={'py2exe': {
|
options={'py2exe': {
|
||||||
'dist_dir': OUT_DIR,
|
'dist_dir': OUT_DIR,
|
||||||
'packages': 'PySide.QtUiTools',
|
'packages': 'PySide.QtUiTools',
|
||||||
'includes': 'twisted, sys, encodings, datetime, os, time, math, PySide, liburl, ast, unicodedata',
|
'includes': 'twisted, sys, encodings, datetime, os, time, math, PySide, liburl, ast, unicodedata, _ssl',
|
||||||
'excludes': 'venv, doctest, pdb, unittest, win32clipboard, win32file, win32pdh, win32security, win32trace, win32ui, winxpgui, win32pipe, win32process, Tkinter',
|
'excludes': 'venv, doctest, pdb, unittest, win32clipboard, win32file, win32pdh, win32security, win32trace, win32ui, winxpgui, win32pipe, win32process, Tkinter',
|
||||||
'dll_excludes': 'msvcr71.dll, MSVCP90.dll, POWRPROF.dll',
|
'dll_excludes': 'msvcr71.dll, MSVCP90.dll, POWRPROF.dll',
|
||||||
'optimize': 2,
|
'optimize': 2,
|
||||||
@ -733,5 +733,5 @@ info = dict(
|
|||||||
cmdclass = {"py2exe": build_installer},
|
cmdclass = {"py2exe": build_installer},
|
||||||
)
|
)
|
||||||
|
|
||||||
sys.argv.extend(['py2exe', '-p win32com ', '-i twisted.web.resource', '-p PySide.QtGui'])
|
sys.argv.extend(['py2exe', '-p win32com ', '-i twisted.web.resource', '-i PySide.QtCore', '-i PySide.QtGui'])
|
||||||
setup(**info)
|
setup(**info)
|
||||||
|
|||||||
37
pyinstaller-client.spec
Executable file
37
pyinstaller-client.spec
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
# -*- mode: python -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
workdir = os.getcwd()
|
||||||
|
|
||||||
|
block_cipher = None
|
||||||
|
|
||||||
|
|
||||||
|
a = Analysis(['syncplayClient.py'],
|
||||||
|
pathex=[workdir],
|
||||||
|
binaries=[],
|
||||||
|
datas=[('resources/*', 'resources')],
|
||||||
|
hiddenimports=['PySide2', 'PySide2.QtCore', 'PySide2.QtWidgets'],
|
||||||
|
hookspath=[],
|
||||||
|
runtime_hooks=[],
|
||||||
|
excludes=[],
|
||||||
|
win_no_prefer_redirects=False,
|
||||||
|
win_private_assemblies=False,
|
||||||
|
cipher=block_cipher)
|
||||||
|
pyz = PYZ(a.pure, a.zipped_data,
|
||||||
|
cipher=block_cipher)
|
||||||
|
exe = EXE(pyz,
|
||||||
|
a.scripts,
|
||||||
|
exclude_binaries=True,
|
||||||
|
name='Syncplay',
|
||||||
|
debug=False,
|
||||||
|
strip=False,
|
||||||
|
upx=True,
|
||||||
|
console=False,
|
||||||
|
icon='resources/icon.ico')
|
||||||
|
coll = COLLECT(exe,
|
||||||
|
a.binaries,
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
strip=False,
|
||||||
|
upx=True,
|
||||||
|
name="Syncplay")
|
||||||
32
pyinstaller-server.spec
Executable file
32
pyinstaller-server.spec
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
# -*- mode: python -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
workdir = os.getcwd()
|
||||||
|
|
||||||
|
block_cipher = None
|
||||||
|
|
||||||
|
|
||||||
|
a = Analysis(['syncplayServer.py'],
|
||||||
|
pathex=[workdir],
|
||||||
|
binaries=[],
|
||||||
|
datas=[('resources/*', 'resources')],
|
||||||
|
hiddenimports=[],
|
||||||
|
hookspath=[],
|
||||||
|
runtime_hooks=[],
|
||||||
|
excludes=[],
|
||||||
|
win_no_prefer_redirects=False,
|
||||||
|
win_private_assemblies=False,
|
||||||
|
cipher=block_cipher)
|
||||||
|
pyz = PYZ(a.pure, a.zipped_data,
|
||||||
|
cipher=block_cipher)
|
||||||
|
exe = EXE(pyz,
|
||||||
|
a.scripts,
|
||||||
|
a.binaries,
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
name='Syncplay',
|
||||||
|
debug=False,
|
||||||
|
strip=False,
|
||||||
|
upx=False,
|
||||||
|
runtime_tmpdir=None,
|
||||||
|
console=True)
|
||||||
@ -1,11 +1,11 @@
|
|||||||
{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf400
|
{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf830
|
||||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
||||||
{\colortbl;\red255\green255\blue255;}
|
{\colortbl;\red255\green255\blue255;}
|
||||||
{\*\expandedcolortbl;;}
|
{\*\expandedcolortbl;;}
|
||||||
\paperw11900\paperh16840\margl1440\margr1440\vieww12600\viewh8400\viewkind0
|
\deftab529
|
||||||
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0
|
\pard\tx529\pardeftab529\pardirnatural\partightenfactor0
|
||||||
|
|
||||||
\f0\fs24 \cf0 Syncplay relies on the following softwares, in compliance with their licenses. \
|
\f0\fs24 \cf0 \CocoaLigature0 Syncplay relies on the following softwares, in compliance with their licenses. \
|
||||||
\
|
\
|
||||||
|
|
||||||
\b Qt.py
|
\b Qt.py
|
||||||
@ -39,11 +39,9 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of\
|
|||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\
|
||||||
Lesser General Public License for more details.\
|
Lesser General Public License for more details.\
|
||||||
\
|
\
|
||||||
\pard\pardeftab720\partightenfactor0
|
You should have received a copy of the GNU Lesser General Public License\
|
||||||
\cf0 You should have received a copy of the GNU Lesser General Public License\
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>\
|
along with this program. If not, see <http://www.gnu.org/licenses/>\
|
||||||
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0
|
\
|
||||||
\cf0 \
|
|
||||||
|
|
||||||
\b Qt for Python\
|
\b Qt for Python\
|
||||||
|
|
||||||
|
|||||||
6
syncplay/__init__.py
Normal file → Executable file
6
syncplay/__init__.py
Normal file → Executable file
@ -1,5 +1,5 @@
|
|||||||
version = '1.5.5'
|
version = '1.5.6'
|
||||||
revision = ''
|
revision = ' beta'
|
||||||
milestone = 'Yoitsu'
|
milestone = 'Yoitsu'
|
||||||
release_number = '64'
|
release_number = '65'
|
||||||
projectURL = 'https://syncplay.pl/'
|
projectURL = 'https://syncplay.pl/'
|
||||||
|
|||||||
164
syncplay/client.py
Normal file → Executable file
164
syncplay/client.py
Normal file → Executable file
@ -77,7 +77,7 @@ class SyncplayClient(object):
|
|||||||
self.lastRewindTime = None
|
self.lastRewindTime = None
|
||||||
self.lastLeftTime = 0
|
self.lastLeftTime = 0
|
||||||
self.lastPausedOnLeaveTime = None
|
self.lastPausedOnLeaveTime = None
|
||||||
self.lastLeftUser = u""
|
self.lastLeftUser = ""
|
||||||
self.protocolFactory = SyncClientFactory(self)
|
self.protocolFactory = SyncClientFactory(self)
|
||||||
self.ui = UiManager(self, ui)
|
self.ui = UiManager(self, ui)
|
||||||
self.userlist = SyncplayUserlist(self.ui, self)
|
self.userlist = SyncplayUserlist(self.ui, self)
|
||||||
@ -91,9 +91,9 @@ class SyncplayClient(object):
|
|||||||
self.setUsername(config['name'])
|
self.setUsername(config['name'])
|
||||||
self.setRoom(config['room'])
|
self.setRoom(config['room'])
|
||||||
if config['password']:
|
if config['password']:
|
||||||
config['password'] = hashlib.md5(config['password']).hexdigest()
|
config['password'] = hashlib.md5(config['password'].encode('utf-8')).hexdigest()
|
||||||
self._serverPassword = config['password']
|
self._serverPassword = config['password']
|
||||||
self._host = u"{}:{}".format(config['host'],config['port'])
|
self._host = "{}:{}".format(config['host'],config['port'])
|
||||||
self._publicServers = config["publicServers"]
|
self._publicServers = config["publicServers"]
|
||||||
if not config['file']:
|
if not config['file']:
|
||||||
self.__getUserlistOnLogon = True
|
self.__getUserlistOnLogon = True
|
||||||
@ -127,14 +127,14 @@ class SyncplayClient(object):
|
|||||||
self.fileSwitch = FileSwitchManager(self)
|
self.fileSwitch = FileSwitchManager(self)
|
||||||
self.playlist = SyncplayPlaylist(self)
|
self.playlist = SyncplayPlaylist(self)
|
||||||
|
|
||||||
if constants.LIST_RELATIVE_CONFIGS and self._config.has_key('loadedRelativePaths') and self._config['loadedRelativePaths']:
|
if constants.LIST_RELATIVE_CONFIGS and 'loadedRelativePaths' in self._config and self._config['loadedRelativePaths']:
|
||||||
paths = "; ".join(self._config['loadedRelativePaths'])
|
paths = "; ".join(self._config['loadedRelativePaths'])
|
||||||
self.ui.showMessage(getMessage("relative-config-notification").format(paths), noPlayer=True, noTimestamp=True)
|
self.ui.showMessage(getMessage("relative-config-notification").format(paths), noPlayer=True, noTimestamp=True)
|
||||||
|
|
||||||
if constants.DEBUG_MODE and constants.WARN_ABOUT_MISSING_STRINGS:
|
if constants.DEBUG_MODE and constants.WARN_ABOUT_MISSING_STRINGS:
|
||||||
missingStrings = getMissingStrings()
|
missingStrings = getMissingStrings()
|
||||||
if missingStrings is not None and missingStrings is not "":
|
if missingStrings is not None and missingStrings is not "":
|
||||||
self.ui.showDebugMessage(u"MISSING/UNUSED STRINGS DETECTED:\n{}".format(missingStrings))
|
self.ui.showDebugMessage("MISSING/UNUSED STRINGS DETECTED:\n{}".format(missingStrings))
|
||||||
|
|
||||||
def initProtocol(self, protocol):
|
def initProtocol(self, protocol):
|
||||||
self._protocol = protocol
|
self._protocol = protocol
|
||||||
@ -206,7 +206,7 @@ class SyncplayClient(object):
|
|||||||
if pauseChange and paused and currentLength > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH\
|
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:
|
and abs(position - currentLength ) < constants.PLAYLIST_LOAD_NEXT_FILE_TIME_FROM_END_THRESHOLD:
|
||||||
self.playlist.advancePlaylistCheck()
|
self.playlist.advancePlaylistCheck()
|
||||||
elif pauseChange and self.serverFeatures.has_key("readiness") and self.serverFeatures["readiness"]:
|
elif pauseChange and "readiness" in self.serverFeatures and self.serverFeatures["readiness"]:
|
||||||
if currentLength == 0 or currentLength == -1 or\
|
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):
|
not (not self.playlist.notJustChangedPlaylist() and abs(position - currentLength ) < constants.PLAYLIST_LOAD_NEXT_FILE_TIME_FROM_END_THRESHOLD):
|
||||||
pauseChange = self._toggleReady(pauseChange, paused)
|
pauseChange = self._toggleReady(pauseChange, paused)
|
||||||
@ -300,7 +300,7 @@ class SyncplayClient(object):
|
|||||||
|
|
||||||
def _serverPaused(self, setBy):
|
def _serverPaused(self, setBy):
|
||||||
hideFromOSD = not constants.SHOW_SAME_ROOM_OSD
|
hideFromOSD = not constants.SHOW_SAME_ROOM_OSD
|
||||||
if constants.SYNC_ON_PAUSE and self.getUsername() <> setBy:
|
if constants.SYNC_ON_PAUSE and self.getUsername() != setBy:
|
||||||
self.setPosition(self.getGlobalPosition())
|
self.setPosition(self.getGlobalPosition())
|
||||||
self._player.setPaused(True)
|
self._player.setPaused(True)
|
||||||
madeChangeOnPlayer = True
|
madeChangeOnPlayer = True
|
||||||
@ -312,7 +312,7 @@ class SyncplayClient(object):
|
|||||||
|
|
||||||
def _serverSeeked(self, position, setBy):
|
def _serverSeeked(self, position, setBy):
|
||||||
hideFromOSD = not constants.SHOW_SAME_ROOM_OSD
|
hideFromOSD = not constants.SHOW_SAME_ROOM_OSD
|
||||||
if self.getUsername() <> setBy:
|
if self.getUsername() != setBy:
|
||||||
self.playerPositionBeforeLastSeek = self.getPlayerPosition()
|
self.playerPositionBeforeLastSeek = self.getPlayerPosition()
|
||||||
self.setPosition(position)
|
self.setPosition(position)
|
||||||
madeChangeOnPlayer = True
|
madeChangeOnPlayer = True
|
||||||
@ -446,12 +446,9 @@ class SyncplayClient(object):
|
|||||||
return self._globalPaused
|
return self._globalPaused
|
||||||
|
|
||||||
def updateFile(self, filename, duration, path):
|
def updateFile(self, filename, duration, path):
|
||||||
newPath = u""
|
newPath = ""
|
||||||
if utils.isURL(path):
|
if utils.isURL(path):
|
||||||
try:
|
filename = path
|
||||||
filename = path.encode('utf-8')
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
filename = path
|
|
||||||
if not path:
|
if not path:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -473,7 +470,7 @@ class SyncplayClient(object):
|
|||||||
from syncplay.ui.ConfigurationGetter import ConfigurationGetter
|
from syncplay.ui.ConfigurationGetter import ConfigurationGetter
|
||||||
ConfigurationGetter().setConfigOption("trustedDomains", newTrustedDomains)
|
ConfigurationGetter().setConfigOption("trustedDomains", newTrustedDomains)
|
||||||
oldTrustedDomains = self._config['trustedDomains']
|
oldTrustedDomains = self._config['trustedDomains']
|
||||||
if oldTrustedDomains <> newTrustedDomains:
|
if oldTrustedDomains != newTrustedDomains:
|
||||||
self._config['trustedDomains'] = newTrustedDomains
|
self._config['trustedDomains'] = newTrustedDomains
|
||||||
self.fileSwitchFoundFiles()
|
self.fileSwitchFoundFiles()
|
||||||
self.ui.showMessage("Trusted domains updated")
|
self.ui.showMessage("Trusted domains updated")
|
||||||
@ -488,13 +485,13 @@ class SyncplayClient(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def isURITrusted(self, URIToTest):
|
def isURITrusted(self, URIToTest):
|
||||||
URIToTest = URIToTest+u"/"
|
URIToTest = URIToTest+"/"
|
||||||
for trustedProtocol in constants.TRUSTABLE_WEB_PROTOCOLS:
|
for trustedProtocol in constants.TRUSTABLE_WEB_PROTOCOLS:
|
||||||
if URIToTest.startswith(trustedProtocol):
|
if URIToTest.startswith(trustedProtocol):
|
||||||
if self._config['onlySwitchToTrustedDomains']:
|
if self._config['onlySwitchToTrustedDomains']:
|
||||||
if self._config['trustedDomains']:
|
if self._config['trustedDomains']:
|
||||||
for trustedDomain in self._config['trustedDomains']:
|
for trustedDomain in self._config['trustedDomains']:
|
||||||
trustableURI = ''.join([trustedProtocol,trustedDomain,u"/"])
|
trustableURI = ''.join([trustedProtocol,trustedDomain,"/"])
|
||||||
if URIToTest.startswith(trustableURI):
|
if URIToTest.startswith(trustableURI):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@ -570,9 +567,9 @@ class SyncplayClient(object):
|
|||||||
if self.serverFeatures["maxFilenameLength"] is not None:
|
if self.serverFeatures["maxFilenameLength"] is not None:
|
||||||
constants.MAX_FILENAME_LENGTH = self.serverFeatures["maxFilenameLength"]
|
constants.MAX_FILENAME_LENGTH = self.serverFeatures["maxFilenameLength"]
|
||||||
constants.MPV_SYNCPLAYINTF_CONSTANTS_TO_SEND = ["MaxChatMessageLength={}".format(constants.MAX_CHAT_MESSAGE_LENGTH),
|
constants.MPV_SYNCPLAYINTF_CONSTANTS_TO_SEND = ["MaxChatMessageLength={}".format(constants.MAX_CHAT_MESSAGE_LENGTH),
|
||||||
u"inputPromptStartCharacter={}".format(constants.MPV_INPUT_PROMPT_START_CHARACTER),
|
"inputPromptStartCharacter={}".format(constants.MPV_INPUT_PROMPT_START_CHARACTER),
|
||||||
u"inputPromptEndCharacter={}".format(constants.MPV_INPUT_PROMPT_END_CHARACTER),
|
"inputPromptEndCharacter={}".format(constants.MPV_INPUT_PROMPT_END_CHARACTER),
|
||||||
u"backslashSubstituteCharacter={}".format(
|
"backslashSubstituteCharacter={}".format(
|
||||||
constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER)]
|
constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER)]
|
||||||
self.ui.setFeatures(self.serverFeatures)
|
self.ui.setFeatures(self.serverFeatures)
|
||||||
if self._player:
|
if self._player:
|
||||||
@ -583,7 +580,7 @@ class SyncplayClient(object):
|
|||||||
file_ = deepcopy(self.userlist.currentUser.file)
|
file_ = deepcopy(self.userlist.currentUser.file)
|
||||||
if constants.PRIVATE_FILE_FIELDS:
|
if constants.PRIVATE_FILE_FIELDS:
|
||||||
for PrivateField in constants.PRIVATE_FILE_FIELDS:
|
for PrivateField in constants.PRIVATE_FILE_FIELDS:
|
||||||
if file_.has_key(PrivateField):
|
if PrivateField in file_:
|
||||||
file_.pop(PrivateField)
|
file_.pop(PrivateField)
|
||||||
return file_
|
return file_
|
||||||
else:
|
else:
|
||||||
@ -596,7 +593,7 @@ class SyncplayClient(object):
|
|||||||
self._protocol.sendFileSetting(file_)
|
self._protocol.sendFileSetting(file_)
|
||||||
|
|
||||||
def setUsername(self, username):
|
def setUsername(self, username):
|
||||||
if username and username <> "":
|
if username and username != "":
|
||||||
self.userlist.currentUser.username = username
|
self.userlist.currentUser.username = username
|
||||||
else:
|
else:
|
||||||
random_number = random.randrange(1000, 9999)
|
random_number = random.randrange(1000, 9999)
|
||||||
@ -646,7 +643,7 @@ class SyncplayClient(object):
|
|||||||
return self._protocol and self._protocol.logged and self.userlist.currentUser.room
|
return self._protocol and self._protocol.logged and self.userlist.currentUser.room
|
||||||
|
|
||||||
def sharedPlaylistIsEnabled(self):
|
def sharedPlaylistIsEnabled(self):
|
||||||
if self.serverFeatures.has_key("sharedPlaylists") and not self.serverFeatures["sharedPlaylists"]:
|
if "sharedPlaylists" in self.serverFeatures and not self.serverFeatures["sharedPlaylists"]:
|
||||||
sharedPlaylistEnabled = False
|
sharedPlaylistEnabled = False
|
||||||
else:
|
else:
|
||||||
sharedPlaylistEnabled = self._config['sharedPlaylistEnabled']
|
sharedPlaylistEnabled = self._config['sharedPlaylistEnabled']
|
||||||
@ -743,8 +740,8 @@ class SyncplayClient(object):
|
|||||||
self.ui.showDebugMessage(
|
self.ui.showDebugMessage(
|
||||||
"Tried to check server version too soon (testing support for: {})".format(featureRequired))
|
"Tried to check server version too soon (testing support for: {})".format(featureRequired))
|
||||||
return None
|
return None
|
||||||
if not self.serverFeatures.has_key(featureRequired) or not self.serverFeatures[featureRequired]:
|
if featureRequired not in self.serverFeatures or not self.serverFeatures[featureRequired]:
|
||||||
featureName = getMessage(u"feature-{}".format(featureRequired))
|
featureName = getMessage("feature-{}".format(featureRequired))
|
||||||
self.ui.showErrorMessage(getMessage("not-supported-by-server-error").format(featureName))
|
self.ui.showErrorMessage(getMessage("not-supported-by-server-error").format(featureName))
|
||||||
return
|
return
|
||||||
return f(self, *args, **kwds)
|
return f(self, *args, **kwds)
|
||||||
@ -825,7 +822,7 @@ class SyncplayClient(object):
|
|||||||
return
|
return
|
||||||
allReadyMessage = getMessage("all-users-ready").format(self.userlist.readyUserCount())
|
allReadyMessage = getMessage("all-users-ready").format(self.userlist.readyUserCount())
|
||||||
autoplayingMessage = getMessage("autoplaying-notification").format(int(self.autoplayTimeLeft))
|
autoplayingMessage = getMessage("autoplaying-notification").format(int(self.autoplayTimeLeft))
|
||||||
countdownMessage = u"{}{}{}".format(allReadyMessage,self._player.osdMessageSeparator, autoplayingMessage)
|
countdownMessage = "{}{}{}".format(allReadyMessage,self._player.osdMessageSeparator, autoplayingMessage)
|
||||||
self.ui.showOSDMessage(countdownMessage, 1, OSDType=constants.OSD_ALERT, mood=constants.MESSAGE_GOODNEWS)
|
self.ui.showOSDMessage(countdownMessage, 1, OSDType=constants.OSD_ALERT, mood=constants.MESSAGE_GOODNEWS)
|
||||||
if self.autoplayTimeLeft <= 0:
|
if self.autoplayTimeLeft <= 0:
|
||||||
self.setPaused(False)
|
self.setPaused(False)
|
||||||
@ -906,20 +903,21 @@ class SyncplayClient(object):
|
|||||||
self.controlpasswords[room] = password
|
self.controlpasswords[room] = password
|
||||||
|
|
||||||
def getControlledRoomPassword(self, room):
|
def getControlledRoomPassword(self, room):
|
||||||
if self.controlpasswords.has_key(room):
|
if room in self.controlpasswords:
|
||||||
return self.controlpasswords[room]
|
return self.controlpasswords[room]
|
||||||
|
|
||||||
def checkForUpdate(self, userInitiated):
|
def checkForUpdate(self, userInitiated):
|
||||||
try:
|
try:
|
||||||
import syncplay, sys, messages, urllib, json
|
import urllib.request, urllib.parse, urllib.error, syncplay, sys, json
|
||||||
params = urllib.urlencode({'version': syncplay.version, 'milestone': syncplay.milestone, 'release_number': syncplay.release_number, 'language': messages.messages["CURRENT"], 'platform': sys.platform, 'userInitiated': userInitiated})
|
params = urllib.parse.urlencode({'version': syncplay.version, 'milestone': syncplay.milestone, 'release_number': syncplay.release_number, 'language': syncplay.messages.messages["CURRENT"], 'platform': sys.platform, 'userInitiated': userInitiated})
|
||||||
if isMacOS():
|
if isMacOS():
|
||||||
import requests
|
import requests
|
||||||
response = requests.get(constants.SYNCPLAY_UPDATE_URL.format(params))
|
response = requests.get(constants.SYNCPLAY_UPDATE_URL.format(params))
|
||||||
response = response.text
|
response = response.text
|
||||||
else:
|
else:
|
||||||
f = urllib.urlopen(constants.SYNCPLAY_UPDATE_URL.format(params))
|
f = urllib.request.urlopen(constants.SYNCPLAY_UPDATE_URL.format(params))
|
||||||
response = f.read()
|
response = f.read()
|
||||||
|
response = response.decode('utf-8')
|
||||||
response = response.replace("<p>","").replace("</p>","").replace("<br />","").replace("“","\"").replace("”","\"") # Fix Wordpress
|
response = response.replace("<p>","").replace("</p>","").replace("<br />","").replace("“","\"").replace("”","\"") # Fix Wordpress
|
||||||
response = json.loads(response)
|
response = json.loads(response)
|
||||||
publicServers = None
|
publicServers = None
|
||||||
@ -927,10 +925,10 @@ class SyncplayClient(object):
|
|||||||
publicServers = response["public-servers"].\
|
publicServers = response["public-servers"].\
|
||||||
replace("”","'").replace(":’","'").replace("’","'").replace("′","'").replace("\n","").replace("\r","")
|
replace("”","'").replace(":’","'").replace("’","'").replace("′","'").replace("\n","").replace("\r","")
|
||||||
publicServers = ast.literal_eval(publicServers)
|
publicServers = ast.literal_eval(publicServers)
|
||||||
return response["version-status"], response["version-message"] if response.has_key("version-message")\
|
return response["version-status"], response["version-message"] if "version-message" in response\
|
||||||
else None, response["version-url"] if response.has_key("version-url") else None, publicServers
|
else None, response["version-url"] if "version-url" in response else None, publicServers
|
||||||
except:
|
except:
|
||||||
return "failed", getMessage("update-check-failed-notification").format(version), constants.SYNCPLAY_DOWNLOAD_URL, None
|
return "failed", getMessage("update-check-failed-notification").format(syncplay.version), constants.SYNCPLAY_DOWNLOAD_URL, None
|
||||||
|
|
||||||
class _WarningManager(object):
|
class _WarningManager(object):
|
||||||
def __init__(self, player, userlist, ui, client):
|
def __init__(self, player, userlist, ui, client):
|
||||||
@ -1016,10 +1014,10 @@ class SyncplayClient(object):
|
|||||||
if self._userlist.currentUser.canControl() and self._userlist.isReadinessSupported():
|
if self._userlist.currentUser.canControl() and self._userlist.isReadinessSupported():
|
||||||
if self._userlist.areAllUsersInRoomReady():
|
if self._userlist.areAllUsersInRoomReady():
|
||||||
allReadyMessage = 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)
|
osdMessage = "{}{}{}".format(fileDifferencesMessage, self._client._player.osdMessageSeparator, allReadyMessage)
|
||||||
else:
|
else:
|
||||||
notAllReadyMessage = 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)
|
osdMessage = "{}{}{}".format(fileDifferencesMessage, self._client._player.osdMessageSeparator, notAllReadyMessage)
|
||||||
else:
|
else:
|
||||||
osdMessage = fileDifferencesMessage
|
osdMessage = fileDifferencesMessage
|
||||||
elif self._userlist.isReadinessSupported():
|
elif self._userlist.isReadinessSupported():
|
||||||
@ -1071,7 +1069,7 @@ class SyncplayUser(object):
|
|||||||
|
|
||||||
def isFileSame(self, file_):
|
def isFileSame(self, file_):
|
||||||
if not self.file:
|
if not self.file:
|
||||||
return False
|
return False
|
||||||
sameName = utils.sameFilename(self.file['name'], file_['name'])
|
sameName = utils.sameFilename(self.file['name'], file_['name'])
|
||||||
sameSize = utils.sameFilesize(self.file['size'], file_['size'])
|
sameSize = utils.sameFilesize(self.file['size'], file_['size'])
|
||||||
sameDuration = utils.sameFileduration(self.file['duration'], file_['duration'])
|
sameDuration = utils.sameFileduration(self.file['duration'], file_['duration'])
|
||||||
@ -1085,9 +1083,9 @@ class SyncplayUser(object):
|
|||||||
|
|
||||||
def __repr__(self, *args, **kwargs):
|
def __repr__(self, *args, **kwargs):
|
||||||
if self.file:
|
if self.file:
|
||||||
return u"{}: {} ({}, {})".format(self.username, self.file['name'], self.file['duration'], self.file['size'])
|
return "{}: {} ({}, {})".format(self.username, self.file['name'], self.file['duration'], self.file['size'])
|
||||||
else:
|
else:
|
||||||
return u"{}".format(self.username)
|
return "{}".format(self.username)
|
||||||
|
|
||||||
def setControllerStatus(self, isController):
|
def setControllerStatus(self, isController):
|
||||||
self._controller = isController
|
self._controller = isController
|
||||||
@ -1152,7 +1150,7 @@ class SyncplayUserlist(object):
|
|||||||
else:
|
else:
|
||||||
duration = utils.formatTime(file_['duration'])
|
duration = utils.formatTime(file_['duration'])
|
||||||
message = getMessage("playing-notification").format(username, file_['name'], duration)
|
message = getMessage("playing-notification").format(username, file_['name'], duration)
|
||||||
if self.currentUser.room <> room or self.currentUser.username == username:
|
if self.currentUser.room != room or self.currentUser.username == username:
|
||||||
message += getMessage("playing-notification/room-addendum").format(room)
|
message += getMessage("playing-notification/room-addendum").format(room)
|
||||||
self.ui.showMessage(message, hideFromOSD)
|
self.ui.showMessage(message, hideFromOSD)
|
||||||
if self.currentUser.file and not self.currentUser.isFileSame(file_) and self.currentUser.room == room:
|
if self.currentUser.file and not self.currentUser.isFileSame(file_) and self.currentUser.room == room:
|
||||||
@ -1180,7 +1178,7 @@ class SyncplayUserlist(object):
|
|||||||
differentName = False
|
differentName = False
|
||||||
differentSize = False
|
differentSize = False
|
||||||
differentDuration = False
|
differentDuration = False
|
||||||
for otherUser in self._users.itervalues():
|
for otherUser in self._users.values():
|
||||||
if otherUser.room == self.currentUser.room and otherUser.file:
|
if otherUser.room == self.currentUser.room and otherUser.file:
|
||||||
if not utils.sameFilename(self.currentUser.file['name'], otherUser.file['name']):
|
if not utils.sameFilename(self.currentUser.file['name'], otherUser.file['name']):
|
||||||
differentName = True
|
differentName = True
|
||||||
@ -1211,12 +1209,12 @@ class SyncplayUserlist(object):
|
|||||||
|
|
||||||
def removeUser(self, username):
|
def removeUser(self, username):
|
||||||
hideFromOSD = not constants.SHOW_DIFFERENT_ROOM_OSD
|
hideFromOSD = not constants.SHOW_DIFFERENT_ROOM_OSD
|
||||||
if self._users.has_key(username):
|
if username in self._users:
|
||||||
user = self._users[username]
|
user = self._users[username]
|
||||||
if user.room:
|
if user.room:
|
||||||
if self.isRoomSame(user.room):
|
if self.isRoomSame(user.room):
|
||||||
hideFromOSD = not constants.SHOW_SAME_ROOM_OSD
|
hideFromOSD = not constants.SHOW_SAME_ROOM_OSD
|
||||||
if self._users.has_key(username):
|
if username in self._users:
|
||||||
self._users.pop(username)
|
self._users.pop(username)
|
||||||
message = getMessage("left-notification").format(username)
|
message = getMessage("left-notification").format(username)
|
||||||
self.ui.showMessage(message, hideFromOSD)
|
self.ui.showMessage(message, hideFromOSD)
|
||||||
@ -1231,7 +1229,7 @@ class SyncplayUserlist(object):
|
|||||||
self.__showUserChangeMessage(username, room, None, oldRoom)
|
self.__showUserChangeMessage(username, room, None, oldRoom)
|
||||||
|
|
||||||
def modUser(self, username, room, file_):
|
def modUser(self, username, room, file_):
|
||||||
if self._users.has_key(username):
|
if username in self._users:
|
||||||
user = self._users[username]
|
user = self._users[username]
|
||||||
oldRoom = user.room if user.room else None
|
oldRoom = user.room if user.room else None
|
||||||
if user.room != room:
|
if user.room != room:
|
||||||
@ -1249,7 +1247,7 @@ class SyncplayUserlist(object):
|
|||||||
def setUserAsController(self, username):
|
def setUserAsController(self, username):
|
||||||
if self.currentUser.username == username:
|
if self.currentUser.username == username:
|
||||||
self.currentUser.setControllerStatus(True)
|
self.currentUser.setControllerStatus(True)
|
||||||
elif self._users.has_key(username):
|
elif username in self._users:
|
||||||
user = self._users[username]
|
user = self._users[username]
|
||||||
user.setControllerStatus(True)
|
user.setControllerStatus(True)
|
||||||
|
|
||||||
@ -1258,7 +1256,7 @@ class SyncplayUserlist(object):
|
|||||||
return True
|
return True
|
||||||
if not self.currentUser.isReady():
|
if not self.currentUser.isReady():
|
||||||
return False
|
return False
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.room == self.currentUser.room:
|
if user.room == self.currentUser.room:
|
||||||
if user.isReadyWithFile() == False:
|
if user.isReadyWithFile() == False:
|
||||||
return False
|
return False
|
||||||
@ -1270,7 +1268,7 @@ class SyncplayUserlist(object):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def areAllOtherUsersInRoomReady(self):
|
def areAllOtherUsersInRoomReady(self):
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.room == self.currentUser.room and user.isReadyWithFile() == False:
|
if user.room == self.currentUser.room and user.isReadyWithFile() == False:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@ -1279,14 +1277,14 @@ class SyncplayUserlist(object):
|
|||||||
readyCount = 0
|
readyCount = 0
|
||||||
if self.currentUser.isReady():
|
if self.currentUser.isReady():
|
||||||
readyCount += 1
|
readyCount += 1
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.room == self.currentUser.room and user.isReadyWithFile():
|
if user.room == self.currentUser.room and user.isReadyWithFile():
|
||||||
readyCount += 1
|
readyCount += 1
|
||||||
return readyCount
|
return readyCount
|
||||||
|
|
||||||
def usersInRoomCount(self):
|
def usersInRoomCount(self):
|
||||||
userCount = 1
|
userCount = 1
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.room == self.currentUser.room and user.isReadyWithFile():
|
if user.room == self.currentUser.room and user.isReadyWithFile():
|
||||||
userCount += 1
|
userCount += 1
|
||||||
return userCount
|
return userCount
|
||||||
@ -1295,33 +1293,33 @@ class SyncplayUserlist(object):
|
|||||||
notReady = []
|
notReady = []
|
||||||
if not self.currentUser.isReady():
|
if not self.currentUser.isReady():
|
||||||
notReady.append(self.currentUser.username)
|
notReady.append(self.currentUser.username)
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.room == self.currentUser.room and user.isReadyWithFile() == False:
|
if user.room == self.currentUser.room and user.isReadyWithFile() == False:
|
||||||
notReady.append(user.username)
|
notReady.append(user.username)
|
||||||
return ", ".join(notReady)
|
return ", ".join(notReady)
|
||||||
|
|
||||||
def areAllFilesInRoomSame(self):
|
def areAllFilesInRoomSame(self):
|
||||||
if self.currentUser.file:
|
if self.currentUser.file:
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.room == self.currentUser.room and user.file and not self.currentUser.isFileSame(user.file):
|
if user.room == self.currentUser.room and user.file and not self.currentUser.isFileSame(user.file):
|
||||||
if user.canControl():
|
if user.canControl():
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def areYouAloneInRoom(self):
|
def areYouAloneInRoom(self):
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.room == self.currentUser.room:
|
if user.room == self.currentUser.room:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def onlyUserInRoomWhoSupportsReadiness(self):
|
def onlyUserInRoomWhoSupportsReadiness(self):
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.room == self.currentUser.room and user.isReadyWithFile() is not None:
|
if user.room == self.currentUser.room and user.isReadyWithFile() is not None:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isUserInYourRoom(self, username):
|
def isUserInYourRoom(self, username):
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.username == username and user.room == self.currentUser.room:
|
if user.username == username and user.room == self.currentUser.room:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@ -1330,7 +1328,7 @@ class SyncplayUserlist(object):
|
|||||||
if self.currentUser.username == username and self.currentUser.canControl():
|
if self.currentUser.username == username and self.currentUser.canControl():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.username == username and user.canControl():
|
if user.username == username and user.canControl():
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@ -1339,7 +1337,7 @@ class SyncplayUserlist(object):
|
|||||||
if self.currentUser.username == username:
|
if self.currentUser.username == username:
|
||||||
return self.currentUser.isReadyWithFile()
|
return self.currentUser.isReadyWithFile()
|
||||||
|
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.username == username:
|
if user.username == username:
|
||||||
return user.isReadyWithFile()
|
return user.isReadyWithFile()
|
||||||
return None
|
return None
|
||||||
@ -1348,7 +1346,7 @@ class SyncplayUserlist(object):
|
|||||||
if self.currentUser.username == username:
|
if self.currentUser.username == username:
|
||||||
return self.currentUser.isReady()
|
return self.currentUser.isReady()
|
||||||
|
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.username == username:
|
if user.username == username:
|
||||||
return user.isReady()
|
return user.isReady()
|
||||||
return None
|
return None
|
||||||
@ -1356,7 +1354,7 @@ class SyncplayUserlist(object):
|
|||||||
def setReady(self, username, isReady):
|
def setReady(self, username, isReady):
|
||||||
if self.currentUser.username == username:
|
if self.currentUser.username == username:
|
||||||
self.currentUser.setReady(isReady)
|
self.currentUser.setReady(isReady)
|
||||||
elif self._users.has_key(username):
|
elif username in self._users:
|
||||||
self._users[username].setReady(isReady)
|
self._users[username].setReady(isReady)
|
||||||
self._client.autoplayCheck()
|
self._client.autoplayCheck()
|
||||||
|
|
||||||
@ -1373,7 +1371,7 @@ class SyncplayUserlist(object):
|
|||||||
|
|
||||||
def showUserList(self, altUI=None):
|
def showUserList(self, altUI=None):
|
||||||
rooms = {}
|
rooms = {}
|
||||||
for user in self._users.itervalues():
|
for user in self._users.values():
|
||||||
if user.room not in rooms:
|
if user.room not in rooms:
|
||||||
rooms[user.room] = []
|
rooms[user.room] = []
|
||||||
rooms[user.room].append(user)
|
rooms[user.room].append(user)
|
||||||
@ -1393,7 +1391,7 @@ class SyncplayUserlist(object):
|
|||||||
def sortList(self, rooms):
|
def sortList(self, rooms):
|
||||||
for room in rooms:
|
for room in rooms:
|
||||||
rooms[room] = sorted(rooms[room])
|
rooms[room] = sorted(rooms[room])
|
||||||
rooms = collections.OrderedDict(sorted(rooms.items(), key=lambda s: s[0].lower()))
|
rooms = collections.OrderedDict(sorted(list(rooms.items()), key=lambda s: s[0].lower()))
|
||||||
return rooms
|
return rooms
|
||||||
|
|
||||||
class UiManager(object):
|
class UiManager(object):
|
||||||
@ -1420,10 +1418,10 @@ class UiManager(object):
|
|||||||
|
|
||||||
def showDebugMessage(self, message):
|
def showDebugMessage(self, message):
|
||||||
if constants.DEBUG_MODE and message.rstrip():
|
if constants.DEBUG_MODE and message.rstrip():
|
||||||
sys.stderr.write("{}{}\n".format(time.strftime(constants.UI_TIME_FORMAT, time.localtime()).decode('utf-8'),message.rstrip()))
|
sys.stderr.write("{}{}\n".format(time.strftime(constants.UI_TIME_FORMAT, time.localtime()),message.rstrip()))
|
||||||
|
|
||||||
def showChatMessage(self, username, userMessage):
|
def showChatMessage(self, username, userMessage):
|
||||||
messageString = u"<{}> {}".format(username, userMessage)
|
messageString = "<{}> {}".format(username, userMessage)
|
||||||
if self._client._player.chatOSDSupported and self._client._config["chatOutputEnabled"]:
|
if self._client._player.chatOSDSupported and self._client._config["chatOutputEnabled"]:
|
||||||
self._client._player.displayChatMessage(username,userMessage)
|
self._client._player.displayChatMessage(username,userMessage)
|
||||||
else:
|
else:
|
||||||
@ -1455,19 +1453,19 @@ class UiManager(object):
|
|||||||
else:
|
else:
|
||||||
self.lastAlertOSDEndTime = time.time() + constants.NO_ALERT_OSD_WARNING_DURATION
|
self.lastAlertOSDEndTime = time.time() + constants.NO_ALERT_OSD_WARNING_DURATION
|
||||||
if self.lastNotificationOSDEndTime and time.time() < self.lastNotificationOSDEndTime:
|
if self.lastNotificationOSDEndTime and time.time() < self.lastNotificationOSDEndTime:
|
||||||
message = u"{}{}{}".format(message, self._client._player.osdMessageSeparator, self.lastNotificatinOSDMessage)
|
message = "{}{}{}".format(message, self._client._player.osdMessageSeparator, self.lastNotificatinOSDMessage)
|
||||||
else:
|
else:
|
||||||
self.lastNotificatinOSDMessage = message
|
self.lastNotificatinOSDMessage = message
|
||||||
self.lastNotificationOSDEndTime = time.time() + constants.OSD_DURATION
|
self.lastNotificationOSDEndTime = time.time() + constants.OSD_DURATION
|
||||||
if self.lastAlertOSDEndTime and time.time() < self.lastAlertOSDEndTime:
|
if self.lastAlertOSDEndTime and time.time() < self.lastAlertOSDEndTime:
|
||||||
message = u"{}{}{}".format(self.lastAlertOSDMessage, self._client._player.osdMessageSeparator, message)
|
message = "{}{}{}".format(self.lastAlertOSDMessage, self._client._player.osdMessageSeparator, message)
|
||||||
self._client._player.displayMessage(message, int(duration * 1000), OSDType, mood)
|
self._client._player.displayMessage(message, int(duration * 1000), OSDType, mood)
|
||||||
|
|
||||||
def setControllerStatus(self, username, isController):
|
def setControllerStatus(self, username, isController):
|
||||||
self.__ui.setControllerStatus(username, isController)
|
self.__ui.setControllerStatus(username, isController)
|
||||||
|
|
||||||
def showErrorMessage(self, message, criticalerror=False):
|
def showErrorMessage(self, message, criticalerror=False):
|
||||||
if message <> self.lastError: # Avoid double call bug
|
if message != self.lastError: # Avoid double call bug
|
||||||
self.lastError = message
|
self.lastError = message
|
||||||
self.__ui.showErrorMessage(message, criticalerror)
|
self.__ui.showErrorMessage(message, criticalerror)
|
||||||
|
|
||||||
@ -1504,7 +1502,7 @@ class SyncplayPlaylist():
|
|||||||
@wraps(f)
|
@wraps(f)
|
||||||
def wrapper(self, *args, **kwds):
|
def wrapper(self, *args, **kwds):
|
||||||
if not self._client.sharedPlaylistIsEnabled():
|
if not self._client.sharedPlaylistIsEnabled():
|
||||||
self._ui.showDebugMessage(u"Tried to use shared playlists when it was disabled!")
|
self._ui.showDebugMessage("Tried to use shared playlists when it was disabled!")
|
||||||
return
|
return
|
||||||
return f(self, *args, **kwds)
|
return f(self, *args, **kwds)
|
||||||
return wrapper
|
return wrapper
|
||||||
@ -1515,7 +1513,7 @@ class SyncplayPlaylist():
|
|||||||
def changeToPlaylistIndexFromFilename(self, filename):
|
def changeToPlaylistIndexFromFilename(self, filename):
|
||||||
try:
|
try:
|
||||||
index = self._playlist.index(filename)
|
index = self._playlist.index(filename)
|
||||||
if index <> self._playlistIndex:
|
if index != self._playlistIndex:
|
||||||
self.changeToPlaylistIndex(index)
|
self.changeToPlaylistIndex(index)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
@ -1577,7 +1575,7 @@ class SyncplayPlaylist():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if index is None:
|
if index is None:
|
||||||
self._ui.showDebugMessage(u"Cannot switch to None index in playlist")
|
self._ui.showDebugMessage("Cannot switch to None index in playlist")
|
||||||
return
|
return
|
||||||
filename = self._playlist[index]
|
filename = self._playlist[index]
|
||||||
# TODO: Handle isse with index being None
|
# TODO: Handle isse with index being None
|
||||||
@ -1628,7 +1626,7 @@ class SyncplayPlaylist():
|
|||||||
|
|
||||||
def changePlaylist(self, files, username = None, resetIndex=False):
|
def changePlaylist(self, files, username = None, resetIndex=False):
|
||||||
if self._playlist == files:
|
if self._playlist == files:
|
||||||
if self._playlistIndex <> 0 and resetIndex:
|
if self._playlistIndex != 0 and resetIndex:
|
||||||
self.changeToPlaylistIndex(0)
|
self.changeToPlaylistIndex(0)
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -1678,7 +1676,7 @@ class SyncplayPlaylist():
|
|||||||
self.switchToNewPlaylistIndex(0, resetPosition=True)
|
self.switchToNewPlaylistIndex(0, resetPosition=True)
|
||||||
|
|
||||||
def canUndoPlaylist(self, currentPlaylist):
|
def canUndoPlaylist(self, currentPlaylist):
|
||||||
return self._previousPlaylist is not None and currentPlaylist <> self._previousPlaylist
|
return self._previousPlaylist is not None and currentPlaylist != self._previousPlaylist
|
||||||
|
|
||||||
def loadCurrentPlaylistIndex(self):
|
def loadCurrentPlaylistIndex(self):
|
||||||
if self._notPlayingCurrentIndex():
|
if self._notPlayingCurrentIndex():
|
||||||
@ -1723,13 +1721,13 @@ class SyncplayPlaylist():
|
|||||||
|
|
||||||
def _notPlayingCurrentIndex(self):
|
def _notPlayingCurrentIndex(self):
|
||||||
if self._playlistIndex is None or self._playlist is None or len(self._playlist) <= self._playlistIndex:
|
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")
|
self._ui.showDebugMessage("Not playing current index - Index none or length issue")
|
||||||
return True
|
return True
|
||||||
currentPlaylistFilename = self._playlist[self._playlistIndex]
|
currentPlaylistFilename = self._playlist[self._playlistIndex]
|
||||||
if self._client.userlist.currentUser.file and currentPlaylistFilename == self._client.userlist.currentUser.file['name']:
|
if self._client.userlist.currentUser.file and currentPlaylistFilename == self._client.userlist.currentUser.file['name']:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
self._ui.showDebugMessage(u"Not playing current index - Filename mismatch or no file")
|
self._ui.showDebugMessage("Not playing current index - Filename mismatch or no file")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _thereIsNextPlaylistIndex(self):
|
def _thereIsNextPlaylistIndex(self):
|
||||||
@ -1752,14 +1750,14 @@ class SyncplayPlaylist():
|
|||||||
return len(self._playlist) <= self._playlistIndex+1
|
return len(self._playlist) <= self._playlistIndex+1
|
||||||
|
|
||||||
def _playlistBufferIsFromOldRoom(self, newRoom):
|
def _playlistBufferIsFromOldRoom(self, newRoom):
|
||||||
return self._previousPlaylistRoom <> newRoom
|
return self._previousPlaylistRoom != newRoom
|
||||||
|
|
||||||
def _movePlaylistBufferToNewRoom(self, currentRoom):
|
def _movePlaylistBufferToNewRoom(self, currentRoom):
|
||||||
self._previousPlaylist = None
|
self._previousPlaylist = None
|
||||||
self._previousPlaylistRoom = currentRoom
|
self._previousPlaylistRoom = currentRoom
|
||||||
|
|
||||||
def _playlistBufferNeedsUpdating(self, newPlaylist):
|
def _playlistBufferNeedsUpdating(self, newPlaylist):
|
||||||
return self._previousPlaylist <> self._playlist and self._playlist <> newPlaylist
|
return self._previousPlaylist != self._playlist and self._playlist != newPlaylist
|
||||||
|
|
||||||
class FileSwitchManager(object):
|
class FileSwitchManager(object):
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
@ -1825,15 +1823,15 @@ class FileSwitchManager(object):
|
|||||||
|
|
||||||
if dirsToSearch:
|
if dirsToSearch:
|
||||||
# Spin up hard drives to prevent premature timeout
|
# Spin up hard drives to prevent premature timeout
|
||||||
randomFilename = u"RandomFile"+unicode(random.randrange(10000, 99999))+u".txt"
|
randomFilename = "RandomFile"+str(random.randrange(10000, 99999))+".txt"
|
||||||
for directory in dirsToSearch:
|
for directory in dirsToSearch:
|
||||||
if not os.path.isdir(directory):
|
if not os.path.isdir(directory):
|
||||||
self.directorySearchError = getMessage("cannot-find-directory-error").format(directory)
|
self.directorySearchError = getMessage("cannot-find-directory-error").format(directory)
|
||||||
|
|
||||||
startTime = time.time()
|
startTime = time.time()
|
||||||
if os.path.isfile(os.path.join(directory, randomFilename)):
|
if os.path.isfile(os.path.join(directory, randomFilename)):
|
||||||
randomFilename = u"RandomFile"+unicode(random.randrange(10000, 99999))+u".txt"
|
randomFilename = "RandomFile"+str(random.randrange(10000, 99999))+".txt"
|
||||||
print "Found random file (?)"
|
print("Found random file (?)")
|
||||||
if time.time() - startTime > constants.FOLDER_SEARCH_FIRST_FILE_TIMEOUT:
|
if time.time() - startTime > constants.FOLDER_SEARCH_FIRST_FILE_TIMEOUT:
|
||||||
self.folderSearchEnabled = False
|
self.folderSearchEnabled = False
|
||||||
self.directorySearchError = getMessage("folder-search-first-file-timeout-error").format(directory)
|
self.directorySearchError = getMessage("folder-search-first-file-timeout-error").format(directory)
|
||||||
@ -1850,7 +1848,7 @@ class FileSwitchManager(object):
|
|||||||
self.folderSearchEnabled = False
|
self.folderSearchEnabled = False
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.mediaFilesCache <> newMediaFilesCache:
|
if self.mediaFilesCache != newMediaFilesCache:
|
||||||
self.mediaFilesCache = newMediaFilesCache
|
self.mediaFilesCache = newMediaFilesCache
|
||||||
self.newInfo = True
|
self.newInfo = True
|
||||||
finally:
|
finally:
|
||||||
@ -1877,12 +1875,12 @@ class FileSwitchManager(object):
|
|||||||
if highPriority and self.folderSearchEnabled and self.mediaDirectories is not None:
|
if highPriority and self.folderSearchEnabled and self.mediaDirectories is not None:
|
||||||
directoryList = self.mediaDirectories
|
directoryList = self.mediaDirectories
|
||||||
# Spin up hard drives to prevent premature timeout
|
# Spin up hard drives to prevent premature timeout
|
||||||
randomFilename = u"RandomFile"+unicode(random.randrange(10000, 99999))+u".txt"
|
randomFilename = "RandomFile"+str(random.randrange(10000, 99999))+".txt"
|
||||||
for directory in directoryList:
|
for directory in directoryList:
|
||||||
startTime = time.time()
|
startTime = time.time()
|
||||||
if os.path.isfile(os.path.join(directory, randomFilename)):
|
if os.path.isfile(os.path.join(directory, randomFilename)):
|
||||||
randomFilename = u"RandomFile"+unicode(random.randrange(10000, 99999))+u".txt"
|
randomFilename = "RandomFile"+str(random.randrange(10000, 99999))+".txt"
|
||||||
print "Found random file (?)"
|
print("Found random file (?)")
|
||||||
if not self.folderSearchEnabled:
|
if not self.folderSearchEnabled:
|
||||||
return
|
return
|
||||||
if time.time() - startTime > constants.FOLDER_SEARCH_FIRST_FILE_TIMEOUT:
|
if time.time() - startTime > constants.FOLDER_SEARCH_FIRST_FILE_TIMEOUT:
|
||||||
@ -1933,10 +1931,6 @@ class FileSwitchManager(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def notifyUserIfFileNotInMediaDirectory(self, filenameToFind, path):
|
def notifyUserIfFileNotInMediaDirectory(self, filenameToFind, path):
|
||||||
try:
|
|
||||||
path = path.decode('utf-8')
|
|
||||||
except UnicodeEncodeError:
|
|
||||||
pass
|
|
||||||
directoryToFind = os.path.dirname(path)
|
directoryToFind = os.path.dirname(path)
|
||||||
if directoryToFind in self.mediaDirectoriesNotFound:
|
if directoryToFind in self.mediaDirectoriesNotFound:
|
||||||
return
|
return
|
||||||
@ -1951,6 +1945,6 @@ class FileSwitchManager(object):
|
|||||||
return
|
return
|
||||||
if self.isDirectoryInList(directoryToFind, self.mediaDirectories):
|
if self.isDirectoryInList(directoryToFind, self.mediaDirectories):
|
||||||
return
|
return
|
||||||
directoryToFind = unicode(directoryToFind)
|
directoryToFind = str(directoryToFind)
|
||||||
self._client.ui.showErrorMessage(getMessage("added-file-not-in-media-directory-error").format(directoryToFind))
|
self._client.ui.showErrorMessage(getMessage("added-file-not-in-media-directory-error").format(directoryToFind))
|
||||||
self.mediaDirectoriesNotFound.append(directoryToFind)
|
self.mediaDirectoriesNotFound.append(directoryToFind)
|
||||||
|
|||||||
0
syncplay/clientManager.py
Normal file → Executable file
0
syncplay/clientManager.py
Normal file → Executable file
30
syncplay/constants.py
Normal file → Executable file
30
syncplay/constants.py
Normal file → Executable file
@ -16,7 +16,7 @@ SHOW_CONTACT_INFO = True # Displays dev contact details below list in GUI
|
|||||||
SHOW_TOOLTIPS = True
|
SHOW_TOOLTIPS = True
|
||||||
WARN_ABOUT_MISSING_STRINGS = False # (If debug mode is enabled)
|
WARN_ABOUT_MISSING_STRINGS = False # (If debug mode is enabled)
|
||||||
FALLBACK_INITIAL_LANGUAGE = "en"
|
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']]
|
FALLBACK_PUBLIC_SYNCPLAY_SERVERS = [['syncplay.pl:8995 (France)', 'syncplay.pl:8995'],['syncplay.pl:8996 (France)', 'syncplay.pl:8996'],['syncplay.pl:8997 (France)', 'syncplay.pl:8997'],['syncplay.pl:8998 (France)', 'syncplay.pl:8998'],['syncplay.pl:8999 (France)', 'syncplay.pl:8999']]
|
||||||
PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH = 10 # Seconds
|
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)
|
PLAYLIST_LOAD_NEXT_FILE_TIME_FROM_END_THRESHOLD = 5 # Seconds (only triggered if file is paused, e.g. due to EOF)
|
||||||
|
|
||||||
@ -81,9 +81,9 @@ FOLDER_SEARCH_DOUBLE_CHECK_INTERVAL = 30.0 # Secs - Frequency of updating cache
|
|||||||
|
|
||||||
#Usually there's no need to adjust these
|
#Usually there's no need to adjust these
|
||||||
LAST_PAUSED_DIFF_THRESHOLD = 2
|
LAST_PAUSED_DIFF_THRESHOLD = 2
|
||||||
FILENAME_STRIP_REGEX = u"[-~_\.\[\](): ]"
|
FILENAME_STRIP_REGEX = "[-~_\.\[\](): ]"
|
||||||
CONTROL_PASSWORD_STRIP_REGEX = u"[^a-zA-Z0-9\-]"
|
CONTROL_PASSWORD_STRIP_REGEX = "[^a-zA-Z0-9\-]"
|
||||||
ROOM_NAME_STRIP_REGEX = u"^(\+)(?P<roomnamebase>.*)(:)(\w{12})$"
|
ROOM_NAME_STRIP_REGEX = "^(\+)(?P<roomnamebase>.*)(:)(\w{12})$"
|
||||||
COMMANDS_UNDO = ["u", "undo", "revert"]
|
COMMANDS_UNDO = ["u", "undo", "revert"]
|
||||||
COMMANDS_CHAT = ["ch","chat"]
|
COMMANDS_CHAT = ["ch","chat"]
|
||||||
COMMANDS_LIST = ["l", "list", "users"]
|
COMMANDS_LIST = ["l", "list", "users"]
|
||||||
@ -172,9 +172,9 @@ STYLE_SUCCESSLABEL = "QLabel { color : black; border-style: outset; border-width
|
|||||||
STYLE_READY_PUSHBUTTON = "QPushButton { text-align: left; padding: 10px 5px 10px 5px;}"
|
STYLE_READY_PUSHBUTTON = "QPushButton { text-align: left; padding: 10px 5px 10px 5px;}"
|
||||||
STYLE_AUTO_PLAY_PUSHBUTTON = "QPushButton { text-align: left; padding: 5px 5px 5px 5px; }"
|
STYLE_AUTO_PLAY_PUSHBUTTON = "QPushButton { text-align: left; padding: 5px 5px 5px 5px; }"
|
||||||
STYLE_NOTIFICATIONBOX = "Username { color: #367AA9; font-weight:bold; }"
|
STYLE_NOTIFICATIONBOX = "Username { color: #367AA9; font-weight:bold; }"
|
||||||
STYLE_CONTACT_INFO = u"<span style=\"color: grey\"><strong><small>{}</span><br /><br />" # Contact info message
|
STYLE_CONTACT_INFO = "<span style=\"color: grey\"><strong><small>{}</span><br /><br />" # Contact info message
|
||||||
STYLE_USER_MESSAGE = u"<span style=\"{}\"><{}></span> {}"
|
STYLE_USER_MESSAGE = "<span style=\"{}\"><{}></span> {}"
|
||||||
STYLE_USERNAME = u"color: #367AA9; font-weight:bold;"
|
STYLE_USERNAME = "color: #367AA9; font-weight:bold;"
|
||||||
STYLE_ERRORNOTIFICATION = "color: red;"
|
STYLE_ERRORNOTIFICATION = "color: red;"
|
||||||
STYLE_DIFFERENTITEM_COLOR = 'red'
|
STYLE_DIFFERENTITEM_COLOR = 'red'
|
||||||
STYLE_NOFILEITEM_COLOR = 'blue'
|
STYLE_NOFILEITEM_COLOR = 'blue'
|
||||||
@ -191,16 +191,16 @@ MPV_SLAVE_ARGS = ['--msg-level=all=error,cplayer=info,term-msg=info', '--input-t
|
|||||||
MPV_SLAVE_ARGS_NEW = ['--term-playing-msg=<SyncplayUpdateFile>\nANS_filename=${filename}\nANS_length=${=duration:${=length:0}}\nANS_path=${path}\n</SyncplayUpdateFile>', '--terminal=yes']
|
MPV_SLAVE_ARGS_NEW = ['--term-playing-msg=<SyncplayUpdateFile>\nANS_filename=${filename}\nANS_length=${=duration:${=length:0}}\nANS_path=${path}\n</SyncplayUpdateFile>', '--terminal=yes']
|
||||||
MPV_NEW_VERSION = False
|
MPV_NEW_VERSION = False
|
||||||
MPV_OSC_VISIBILITY_CHANGE_VERSION = False
|
MPV_OSC_VISIBILITY_CHANGE_VERSION = False
|
||||||
MPV_INPUT_PROMPT_START_CHARACTER = u"〉"
|
MPV_INPUT_PROMPT_START_CHARACTER = "〉"
|
||||||
MPV_INPUT_PROMPT_END_CHARACTER = u" 〈"
|
MPV_INPUT_PROMPT_END_CHARACTER = " 〈"
|
||||||
MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER = u"\"
|
MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER = "\"
|
||||||
MPV_SYNCPLAYINTF_OPTIONS_TO_SEND = ["chatInputEnabled","chatInputFontFamily", "chatInputRelativeFontSize", "chatInputFontWeight","chatInputFontUnderline",
|
MPV_SYNCPLAYINTF_OPTIONS_TO_SEND = ["chatInputEnabled","chatInputFontFamily", "chatInputRelativeFontSize", "chatInputFontWeight","chatInputFontUnderline",
|
||||||
"chatInputFontColor", "chatInputPosition","chatOutputFontFamily","chatOutputRelativeFontSize",
|
"chatInputFontColor", "chatInputPosition","chatOutputFontFamily","chatOutputRelativeFontSize",
|
||||||
"chatOutputFontWeight","chatOutputFontUnderline","chatOutputMode","chatMaxLines",
|
"chatOutputFontWeight","chatOutputFontUnderline","chatOutputMode","chatMaxLines",
|
||||||
"chatTopMargin","chatLeftMargin","chatBottomMargin","chatDirectInput",
|
"chatTopMargin","chatLeftMargin","chatBottomMargin","chatDirectInput",
|
||||||
"notificationTimeout","alertTimeout","chatTimeout","chatOutputEnabled"]
|
"notificationTimeout","alertTimeout","chatTimeout","chatOutputEnabled"]
|
||||||
|
|
||||||
MPV_SYNCPLAYINTF_CONSTANTS_TO_SEND = ["MaxChatMessageLength={}".format(MAX_CHAT_MESSAGE_LENGTH),u"inputPromptStartCharacter={}".format(MPV_INPUT_PROMPT_START_CHARACTER),u"inputPromptEndCharacter={}".format(MPV_INPUT_PROMPT_END_CHARACTER),u"backslashSubstituteCharacter={}".format(MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER)]
|
MPV_SYNCPLAYINTF_CONSTANTS_TO_SEND = ["MaxChatMessageLength={}".format(MAX_CHAT_MESSAGE_LENGTH),"inputPromptStartCharacter={}".format(MPV_INPUT_PROMPT_START_CHARACTER),"inputPromptEndCharacter={}".format(MPV_INPUT_PROMPT_END_CHARACTER),"backslashSubstituteCharacter={}".format(MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER)]
|
||||||
# Note: Constants updated in client.py->checkForFeatureSupport
|
# Note: Constants updated in client.py->checkForFeatureSupport
|
||||||
MPV_SYNCPLAYINTF_LANGUAGE_TO_SEND = ["mpv-key-tab-hint","mpv-key-hint", "alphakey-mode-warning-first-line", "alphakey-mode-warning-second-line"]
|
MPV_SYNCPLAYINTF_LANGUAGE_TO_SEND = ["mpv-key-tab-hint","mpv-key-hint", "alphakey-mode-warning-first-line", "alphakey-mode-warning-second-line"]
|
||||||
VLC_SLAVE_ARGS = ['--extraintf=luaintf', '--lua-intf=syncplay', '--no-quiet', '--no-input-fast-seek',
|
VLC_SLAVE_ARGS = ['--extraintf=luaintf', '--lua-intf=syncplay', '--no-quiet', '--no-input-fast-seek',
|
||||||
@ -255,12 +255,12 @@ OSD_CHAT = "chat"
|
|||||||
CHATROOM_MODE = "Chatroom"
|
CHATROOM_MODE = "Chatroom"
|
||||||
SCROLLING_MODE = "Scrolling"
|
SCROLLING_MODE = "Scrolling"
|
||||||
|
|
||||||
SYNCPLAY_UPDATE_URL = u"https://syncplay.pl/checkforupdate?{}" # Params
|
SYNCPLAY_UPDATE_URL = "https://syncplay.pl/checkforupdate?{}" # Params
|
||||||
SYNCPLAY_DOWNLOAD_URL = "https://syncplay.pl/download/"
|
SYNCPLAY_DOWNLOAD_URL = "https://syncplay.pl/download/"
|
||||||
SYNCPLAY_PUBLIC_SERVER_LIST_URL = u"https://syncplay.pl/listpublicservers?{}" # Params
|
SYNCPLAY_PUBLIC_SERVER_LIST_URL = "https://syncplay.pl/listpublicservers?{}" # Params
|
||||||
|
|
||||||
DEFAULT_TRUSTED_DOMAINS = [u"youtube.com",u"youtu.be"]
|
DEFAULT_TRUSTED_DOMAINS = ["youtube.com","youtu.be"]
|
||||||
TRUSTABLE_WEB_PROTOCOLS = [u"http://www.",u"https://www.",u"http://",u"https://"]
|
TRUSTABLE_WEB_PROTOCOLS = ["http://www.","https://www.","http://","https://"]
|
||||||
|
|
||||||
PRIVATE_FILE_FIELDS = ["path"]
|
PRIVATE_FILE_FIELDS = ["path"]
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
# coding:utf8
|
# coding:utf8
|
||||||
from syncplay import constants
|
from syncplay import constants
|
||||||
|
|
||||||
import messages_en
|
from . import messages_en
|
||||||
import messages_ru
|
from . import messages_ru
|
||||||
import messages_de
|
from . import messages_de
|
||||||
import messages_it
|
from . import messages_it
|
||||||
|
|
||||||
messages = {
|
messages = {
|
||||||
"en": messages_en.en,
|
"en": messages_en.en,
|
||||||
@ -29,10 +29,10 @@ def getMissingStrings():
|
|||||||
for lang in messages:
|
for lang in messages:
|
||||||
if lang != "en" and lang != "CURRENT":
|
if lang != "en" and lang != "CURRENT":
|
||||||
for message in messages["en"]:
|
for message in messages["en"]:
|
||||||
if not messages[lang].has_key(message):
|
if message not in messages[lang]:
|
||||||
missingStrings = missingStrings + "({}) Missing: {}\n".format(lang, message)
|
missingStrings = missingStrings + "({}) Missing: {}\n".format(lang, message)
|
||||||
for message in messages[lang]:
|
for message in messages[lang]:
|
||||||
if not messages["en"].has_key(message):
|
if message not in messages["en"]:
|
||||||
missingStrings = missingStrings + "({}) Unused: {}\n".format(lang, message)
|
missingStrings = missingStrings + "({}) Unused: {}\n".format(lang, message)
|
||||||
|
|
||||||
return missingStrings
|
return missingStrings
|
||||||
@ -41,14 +41,14 @@ def getInitialLanguage():
|
|||||||
import locale
|
import locale
|
||||||
try:
|
try:
|
||||||
initialLanguage = locale.getdefaultlocale()[0].split("_")[0]
|
initialLanguage = locale.getdefaultlocale()[0].split("_")[0]
|
||||||
if not messages.has_key(initialLanguage):
|
if initialLanguage not in messages:
|
||||||
initialLanguage = constants.FALLBACK_INITIAL_LANGUAGE
|
initialLanguage = constants.FALLBACK_INITIAL_LANGUAGE
|
||||||
except:
|
except:
|
||||||
initialLanguage = constants.FALLBACK_INITIAL_LANGUAGE
|
initialLanguage = constants.FALLBACK_INITIAL_LANGUAGE
|
||||||
return initialLanguage
|
return initialLanguage
|
||||||
|
|
||||||
def isValidLanguage(language):
|
def isValidLanguage(language):
|
||||||
return messages.has_key(language)
|
return language in messages
|
||||||
|
|
||||||
def getMessage(type_, locale=None):
|
def getMessage(type_, locale=None):
|
||||||
if constants.SHOW_TOOLTIPS == False:
|
if constants.SHOW_TOOLTIPS == False:
|
||||||
@ -59,15 +59,15 @@ def getMessage(type_, locale=None):
|
|||||||
setLanguage(getInitialLanguage())
|
setLanguage(getInitialLanguage())
|
||||||
|
|
||||||
lang = messages["CURRENT"]
|
lang = messages["CURRENT"]
|
||||||
if locale and messages.has_key(locale):
|
if locale and locale in messages:
|
||||||
if messages[locale].has_key(type_):
|
if type_ in messages[locale]:
|
||||||
return unicode(messages[locale][type_])
|
return str(messages[locale][type_])
|
||||||
if lang and messages.has_key(lang):
|
if lang and lang in messages:
|
||||||
if messages[lang].has_key(type_):
|
if type_ in messages[lang]:
|
||||||
return unicode(messages[lang][type_])
|
return str(messages[lang][type_])
|
||||||
if messages["en"].has_key(type_):
|
if type_ in messages["en"]:
|
||||||
return unicode(messages["en"][type_])
|
return str(messages["en"][type_])
|
||||||
else:
|
else:
|
||||||
print u"WARNING: Cannot find message '{}'!".format(type_)
|
print("WARNING: Cannot find message '{}'!".format(type_))
|
||||||
return "!{}".format(type_) # TODO: Remove
|
return "!{}".format(type_) # TODO: Remove
|
||||||
#raise KeyError(type_)
|
#raise KeyError(type_)
|
||||||
|
|||||||
764
syncplay/messages_de.py
Normal file → Executable file
764
syncplay/messages_de.py
Normal file → Executable file
@ -3,473 +3,473 @@
|
|||||||
"""Deutsch dictionary"""
|
"""Deutsch dictionary"""
|
||||||
|
|
||||||
de = {
|
de = {
|
||||||
"LANGUAGE" : u"Deutsch", # (German)
|
"LANGUAGE" : "Deutsch", # (German)
|
||||||
|
|
||||||
# Client notifications
|
# Client notifications
|
||||||
"config-cleared-notification" : u"Einstellungen gelöscht. Änderungen werden gespeichert, wenn du eine gültige Konfiguration speicherst.",
|
"config-cleared-notification" : "Einstellungen gelöscht. Änderungen werden gespeichert, wenn du eine gültige Konfiguration speicherst.",
|
||||||
|
|
||||||
"relative-config-notification" : u"Relative Konfigurationsdatei(en) geladen: {}",
|
"relative-config-notification" : "Relative Konfigurationsdatei(en) geladen: {}",
|
||||||
|
|
||||||
"connection-attempt-notification" : u"Verbinde mit {}:{}", # Port, IP
|
"connection-attempt-notification" : "Verbinde mit {}:{}", # Port, IP
|
||||||
"reconnection-attempt-notification" : u"Verbindung zum Server verloren, versuche erneut",
|
"reconnection-attempt-notification" : "Verbindung zum Server verloren, versuche erneut",
|
||||||
"disconnection-notification" : u"Verbindung zum Server beendet",
|
"disconnection-notification" : "Verbindung zum Server beendet",
|
||||||
"connection-failed-notification" : u"Verbindung zum Server fehlgeschlagen",
|
"connection-failed-notification" : "Verbindung zum Server fehlgeschlagen",
|
||||||
"connected-successful-notification" : u"Erfolgreich mit Server verbunden",
|
"connected-successful-notification" : "Erfolgreich mit Server verbunden",
|
||||||
"retrying-notification" : u"%s, versuche erneut in %d Sekunden...", # Seconds
|
"retrying-notification" : "%s, versuche erneut in %d Sekunden...", # Seconds
|
||||||
|
|
||||||
"rewind-notification" : u"Zurückgespult wegen Zeitdifferenz mit {}", # User
|
"rewind-notification" : "Zurückgespult wegen Zeitdifferenz mit {}", # User
|
||||||
"fastforward-notification" : u"Vorgespult wegen Zeitdifferenz mit {}", # User
|
"fastforward-notification" : "Vorgespult wegen Zeitdifferenz mit {}", # User
|
||||||
"slowdown-notification" : u"Verlangsamt wegen Zeitdifferenz mit {}", # User
|
"slowdown-notification" : "Verlangsamt wegen Zeitdifferenz mit {}", # User
|
||||||
"revert-notification" : u"Normalgeschwindigkeit",
|
"revert-notification" : "Normalgeschwindigkeit",
|
||||||
|
|
||||||
"pause-notification" : u"{} pausierte", # User
|
"pause-notification" : "{} pausierte", # User
|
||||||
"unpause-notification" : u"{} startete", # User
|
"unpause-notification" : "{} startete", # User
|
||||||
"seek-notification" : u"{} sprang von {} nach {}", # User, from time, to time
|
"seek-notification" : "{} sprang von {} nach {}", # User, from time, to time
|
||||||
|
|
||||||
"current-offset-notification" : u"Aktueller Offset: {} Sekunden", # Offset
|
"current-offset-notification" : "Aktueller Offset: {} Sekunden", # Offset
|
||||||
|
|
||||||
"media-directory-list-updated-notification" : u"Syncplay media directories have been updated.", # TODO: Translate
|
"media-directory-list-updated-notification" : "Syncplay media directories have been updated.", # TODO: Translate
|
||||||
|
|
||||||
"room-join-notification" : u"{} hat den Raum '{}' betreten", # User
|
"room-join-notification" : "{} hat den Raum '{}' betreten", # User
|
||||||
"left-notification" : u"{} ist gegangen", # User
|
"left-notification" : "{} ist gegangen", # User
|
||||||
"left-paused-notification" : u"{} ist gegangen, {} pausierte", # User who left, User who paused
|
"left-paused-notification" : "{} ist gegangen, {} pausierte", # User who left, User who paused
|
||||||
"playing-notification" : u"{} spielt '{}' ({})", # User, file, duration
|
"playing-notification" : "{} spielt '{}' ({})", # User, file, duration
|
||||||
"playing-notification/room-addendum" : u" in Raum: '{}'", # Room
|
"playing-notification/room-addendum" : " in Raum: '{}'", # Room
|
||||||
|
|
||||||
"not-all-ready" : u"Noch nicht bereit: {}", # Usernames
|
"not-all-ready" : "Noch nicht bereit: {}", # Usernames
|
||||||
"all-users-ready" : u"Alle sind bereit ({} Nutzer)", #Number of ready users
|
"all-users-ready" : "Alle sind bereit ({} Nutzer)", #Number of ready users
|
||||||
"ready-to-unpause-notification" : u"Du bist bereit - noch einmal fortsetzen klicken zum abspielen",
|
"ready-to-unpause-notification" : "Du bist bereit - noch einmal fortsetzen klicken zum abspielen",
|
||||||
"set-as-ready-notification" : u"Du bist bereit",
|
"set-as-ready-notification" : "Du bist bereit",
|
||||||
"set-as-not-ready-notification" : u"Du bist nicht bereit",
|
"set-as-not-ready-notification" : "Du bist nicht bereit",
|
||||||
"autoplaying-notification" : u"Starte in {}...", # Number of seconds until playback will start
|
"autoplaying-notification" : "Starte in {}...", # Number of seconds until playback will start
|
||||||
|
|
||||||
"identifying-as-controller-notification" : u"Identifiziere als Raumleiter mit Passwort '{}'...", # TODO: find a better translation to "room operator"
|
"identifying-as-controller-notification" : "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.",
|
"failed-to-identify-as-controller-notification" : "{} konnte sich nicht als Raumleiter identifizieren.",
|
||||||
"authenticated-as-controller-notification" : u"{} authentifizierte sich als Raumleiter",
|
"authenticated-as-controller-notification" : "{} authentifizierte sich als Raumleiter",
|
||||||
"created-controlled-room-notification" : u"Gesteuerten Raum '{}' mit Passwort '{}' erstellt. Bitte diese Informationen für die Zukunft aufheben!", # RoomName, operatorPassword
|
"created-controlled-room-notification" : "Gesteuerten Raum '{}' mit Passwort '{}' erstellt. Bitte diese Informationen für die Zukunft aufheben!", # RoomName, operatorPassword
|
||||||
|
|
||||||
"file-different-notification" : u"Deine Datei scheint sich von {}s zu unterscheiden", # User
|
"file-different-notification" : "Deine Datei scheint sich von {}s zu unterscheiden", # User
|
||||||
"file-differences-notification" : u"Deine Datei unterscheidet sich auf folgende Art: {}",
|
"file-differences-notification" : "Deine Datei unterscheidet sich auf folgende Art: {}",
|
||||||
"room-file-differences" : u"Unterschiedlich in: {}", # File differences (filename, size, and/or duration)
|
"room-file-differences" : "Unterschiedlich in: {}", # File differences (filename, size, and/or duration)
|
||||||
"file-difference-filename" : u"Name",
|
"file-difference-filename" : "Name",
|
||||||
"file-difference-filesize" : u"Größe",
|
"file-difference-filesize" : "Größe",
|
||||||
"file-difference-duration" : u"Dauer",
|
"file-difference-duration" : "Dauer",
|
||||||
"alone-in-the-room": u"Du bist alleine im Raum",
|
"alone-in-the-room": "Du bist alleine im Raum",
|
||||||
|
|
||||||
"different-filesize-notification" : u" (ihre Dateigröße ist anders als deine!)",
|
"different-filesize-notification" : " (ihre Dateigröße ist anders als deine!)",
|
||||||
"userlist-playing-notification" : u"{} spielt:", #Username
|
"userlist-playing-notification" : "{} spielt:", #Username
|
||||||
"file-played-by-notification" : u"Datei: {} wird gespielt von:", # File
|
"file-played-by-notification" : "Datei: {} wird gespielt von:", # File
|
||||||
"no-file-played-notification" : u"{} spielt keine Datei ab", # Username
|
"no-file-played-notification" : "{} spielt keine Datei ab", # Username
|
||||||
"notplaying-notification" : u"Personen im Raum, die keine Dateien spielen:",
|
"notplaying-notification" : "Personen im Raum, die keine Dateien spielen:",
|
||||||
"userlist-room-notification" : u"In Raum '{}':", # Room
|
"userlist-room-notification" : "In Raum '{}':", # Room
|
||||||
"userlist-file-notification" : u"Datei",
|
"userlist-file-notification" : "Datei",
|
||||||
"controller-userlist-userflag" : u"Raumleiter",
|
"controller-userlist-userflag" : "Raumleiter",
|
||||||
"ready-userlist-userflag" : u"Bereit",
|
"ready-userlist-userflag" : "Bereit",
|
||||||
|
|
||||||
"update-check-failed-notification" : u"Konnte nicht automatisch prüfen, ob Syncplay {} aktuell ist. Soll https://syncplay.pl/ geöffnet werden, um manuell nach Updates zu suchen?", #Syncplay version
|
"update-check-failed-notification" : "Konnte nicht automatisch prüfen, ob Syncplay {} aktuell ist. Soll https://syncplay.pl/ geöffnet werden, um manuell nach Updates zu suchen?", #Syncplay version
|
||||||
"syncplay-uptodate-notification" : u"Syncplay ist aktuell",
|
"syncplay-uptodate-notification" : "Syncplay ist aktuell",
|
||||||
"syncplay-updateavailable-notification" : u"Eine neuere Version von Syncplay ist verfügbar. Soll die Download-Seite geöffnet werden?",
|
"syncplay-updateavailable-notification" : "Eine neuere Version von Syncplay ist verfügbar. Soll die Download-Seite geöffnet werden?",
|
||||||
|
|
||||||
"mplayer-file-required-notification" : u"Syncplay für mplayer benötigt eine Dateiangabe beim Start",
|
"mplayer-file-required-notification" : "Syncplay für mplayer benötigt eine Dateiangabe beim Start",
|
||||||
"mplayer-file-required-notification/example" : u"Anwendungsbeispiel: syncplay [optionen] [url|pfad/]Dateiname",
|
"mplayer-file-required-notification/example" : "Anwendungsbeispiel: syncplay [optionen] [url|pfad/]Dateiname",
|
||||||
"mplayer2-required" : u"Syncplay ist inkompatibel zu MPlayer 1.x, bitte nutze MPlayer2 oder mpv",
|
"mplayer2-required" : "Syncplay ist inkompatibel zu MPlayer 1.x, bitte nutze MPlayer2 oder mpv",
|
||||||
|
|
||||||
"unrecognized-command-notification" : u"Unbekannter Befehl",
|
"unrecognized-command-notification" : "Unbekannter Befehl",
|
||||||
"commandlist-notification" : u"Verfügbare Befehle:",
|
"commandlist-notification" : "Verfügbare Befehle:",
|
||||||
"commandlist-notification/room" : u"\tr [Name] - Raum ändern",
|
"commandlist-notification/room" : "\tr [Name] - Raum ändern",
|
||||||
"commandlist-notification/list" : u"\tl - Nutzerliste anzeigen",
|
"commandlist-notification/list" : "\tl - Nutzerliste anzeigen",
|
||||||
"commandlist-notification/undo" : u"\tu - Letzter Zeitsprung rückgängig",
|
"commandlist-notification/undo" : "\tu - Letzter Zeitsprung rückgängig",
|
||||||
"commandlist-notification/pause" : u"\tp - Pausieren / weiter",
|
"commandlist-notification/pause" : "\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/seek" : "\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/help" : "\th - Diese Hilfe",
|
||||||
"commandlist-notification/toggle" : u"\tt - Bereitschaftsanzeige umschalten",
|
"commandlist-notification/toggle" : "\tt - Bereitschaftsanzeige umschalten",
|
||||||
"commandlist-notification/create" : u"\tc [name] - erstelle zentral gesteuerten Raum mit dem aktuellen Raumnamen",
|
"commandlist-notification/create" : "\tc [name] - erstelle zentral gesteuerten Raum mit dem aktuellen Raumnamen",
|
||||||
"commandlist-notification/auth" : u"\ta [password] - authentifiziere als Raumleiter mit Passwort",
|
"commandlist-notification/auth" : "\ta [password] - authentifiziere als Raumleiter mit Passwort",
|
||||||
"commandlist-notification/chat" : "\tch [message] - send a chat message in a room", # TODO: Translate
|
"commandlist-notification/chat" : "\tch [message] - send a chat message in a room", # TODO: Translate
|
||||||
"syncplay-version-notification" : u"Syncplay Version: {}", # syncplay.version
|
"syncplay-version-notification" : "Syncplay Version: {}", # syncplay.version
|
||||||
"more-info-notification" : u"Weitere Informationen auf: {}", # projectURL
|
"more-info-notification" : "Weitere Informationen auf: {}", # projectURL
|
||||||
|
|
||||||
"gui-data-cleared-notification" : u"Syncplay hat die Pfad und Fensterdaten der Syncplay-GUI zurückgesetzt.",
|
"gui-data-cleared-notification" : "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.",
|
"language-changed-msgbox-label" : "Die Sprache wird geändert, wenn du Syncplay neu startest.",
|
||||||
"promptforupdate-label" : u"Soll Syncplay regelmäßig nach Updates suchen?",
|
"promptforupdate-label" : "Soll Syncplay regelmäßig nach Updates suchen?",
|
||||||
|
|
||||||
"vlc-version-mismatch": u"This version of VLC does not support Syncplay. VLC {}+ supports Syncplay but VLC 3 does not. Please use an alternative media player.", # VLC min version # TODO: Translate
|
"vlc-version-mismatch": "This version of VLC does not support Syncplay. VLC {}+ supports Syncplay but VLC 3 does not. Please use an alternative media player.", # VLC min version # TODO: Translate
|
||||||
"vlc-interface-version-mismatch": u"Du nutzt Version {} des VLC-Syncplay Interface-Moduls, Syncplay benötigt aber mindestens Version {}. In der Syncplay-Anleitung unter https://syncplay.pl/guide/ [Englisch] findest du Details zur Installation des syncplay.lua-Skripts.", # VLC interface version, VLC interface min version
|
"vlc-interface-version-mismatch": "Du nutzt Version {} des VLC-Syncplay Interface-Moduls, Syncplay benötigt aber mindestens Version {}. In der Syncplay-Anleitung unter https://syncplay.pl/guide/ [Englisch] findest du Details zur Installation des syncplay.lua-Skripts.", # 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 https://syncplay.pl/guide/ [Englisch] findest du Details zur Installation des syncplay.lua-Skripts.",
|
"vlc-interface-oldversion-warning": "Warnung: Es ist eine alte Version des Syncplay Interface-Moduls für VLC im VLC-Verzeichnis installiert. In der Syncplay-Anleitung unter https://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 https://syncplay.pl/guide/ [Englisch] findest du Details zur Installation des syncplay.lua-Skripts.",
|
"vlc-interface-not-installed": "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 https://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
|
"media-player-latency-warning": "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
|
"mpv-unresponsive-error": "MPV hat für {} Sekunden nicht geantwortet und scheint abgestürzt zu sein. Bitte starte Syncplay neu.", # Seconds to respond
|
||||||
|
|
||||||
# Client prompts
|
# Client prompts
|
||||||
"enter-to-exit-prompt" : u"Enter drücken zum Beenden\n",
|
"enter-to-exit-prompt" : "Enter drücken zum Beenden\n",
|
||||||
|
|
||||||
# Client errors
|
# Client errors
|
||||||
"missing-arguments-error" : u"Notwendige Argumente fehlen, siehe --help",
|
"missing-arguments-error" : "Notwendige Argumente fehlen, siehe --help",
|
||||||
"server-timeout-error" : u"Timeout: Verbindung zum Server fehlgeschlagen",
|
"server-timeout-error" : "Timeout: Verbindung zum Server fehlgeschlagen",
|
||||||
"mpc-slave-error" : u"Kann MPC nicht im Slave-Modus starten!",
|
"mpc-slave-error" : "Kann MPC nicht im Slave-Modus starten!",
|
||||||
"mpc-version-insufficient-error" : u"MPC-Version nicht ausreichend, bitte nutze `mpc-hc` >= `{}`",
|
"mpc-version-insufficient-error" : "MPC-Version nicht ausreichend, bitte nutze `mpc-hc` >= `{}`",
|
||||||
"mpc-be-version-insufficient-error" : u"MPC-Version nicht ausreichend, bitte nutze `mpc-be` >= `{}`",
|
"mpc-be-version-insufficient-error" : "MPC-Version nicht ausreichend, bitte nutze `mpc-be` >= `{}`",
|
||||||
"mpv-version-error" : u"Syncplay ist nicht kompatibel mit dieser Version von mpv. Bitte benutze eine andere Version (z.B. Git HEAD).",
|
"mpv-version-error" : "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-file-open-error" : "Fehler beim Öffnen der Datei durch den Player",
|
||||||
"player-path-error" : u"Ungültiger Player-Pfad. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2", # To do: Translate end
|
"player-path-error" : "Ungültiger Player-Pfad. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2", # To do: Translate end
|
||||||
"hostname-empty-error" : u"Hostname darf nicht leer sein",
|
"hostname-empty-error" : "Hostname darf nicht leer sein",
|
||||||
"empty-error" : u"{} darf nicht leer sein", # Configuration
|
"empty-error" : "{} darf nicht leer sein", # Configuration
|
||||||
"media-player-error": u"Player-Fehler: \"{}\"", # Error line
|
"media-player-error": "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-import-gui-error": "Konnte die GUI-Bibliotheken nicht importieren. PySide muss installiert sein, damit die grafische Oberfläche funktioniert.",
|
||||||
|
|
||||||
"arguments-missing-error" : u"Notwendige Argumente fehlen, siehe --help",
|
"arguments-missing-error" : "Notwendige Argumente fehlen, siehe --help",
|
||||||
|
|
||||||
"unable-to-start-client-error" : u"Client kann nicht gestartet werden",
|
"unable-to-start-client-error" : "Client kann nicht gestartet werden",
|
||||||
|
|
||||||
"player-path-config-error": u"Player-Pfad ist nicht ordnungsgemäß gesetzt. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2.", # To do: Translate end
|
"player-path-config-error": "Player-Pfad ist nicht ordnungsgemäß gesetzt. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2.", # To do: Translate end
|
||||||
"no-file-path-config-error": u"Es muss eine Datei ausgewählt werden, bevor der Player gestartet wird.",
|
"no-file-path-config-error": "Es muss eine Datei ausgewählt werden, bevor der Player gestartet wird.",
|
||||||
"no-hostname-config-error": u"Hostname darf nicht leer sein",
|
"no-hostname-config-error": "Hostname darf nicht leer sein",
|
||||||
"invalid-port-config-error" : u"Port muss gültig sein",
|
"invalid-port-config-error" : "Port muss gültig sein",
|
||||||
"empty-value-config-error" : u"{} darf nicht leer sein", # Config option
|
"empty-value-config-error" : "{} darf nicht leer sein", # Config option
|
||||||
|
|
||||||
"not-json-error" : u"Kein JSON-String\n",
|
"not-json-error" : "Kein JSON-String\n",
|
||||||
"hello-arguments-error" : u"Zu wenige Hello-Argumente\n",
|
"hello-arguments-error" : "Zu wenige Hello-Argumente\n",
|
||||||
"version-mismatch-error" : u"Verschiedene Versionen auf Client und Server\n",
|
"version-mismatch-error" : "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 https://syncplay.pl/LUA/ [Englisch] eine Anleitung.",
|
"vlc-failed-connection": "Kann nicht zu VLC verbinden. Wenn du syncplay.lua nicht installiert hast, findest du auf https://syncplay.pl/LUA/ [Englisch] eine Anleitung.",
|
||||||
"vlc-failed-noscript": u"Laut VLC ist das syncplay.lua Interface-Skript nicht installiert. Auf https://syncplay.pl/LUA/ [Englisch] findest du eine Anleitung.",
|
"vlc-failed-noscript": "Laut VLC ist das syncplay.lua Interface-Skript nicht installiert. Auf https://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-versioncheck": "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
|
"vlc-failed-other" : "Beim Laden des syncplay.lua Interface-Skripts durch VLC trat folgender Fehler auf: {}", # Syncplay Error
|
||||||
|
|
||||||
"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-supported-by-server-error" : "Dieses Feature wird vom Server nicht unterstützt. Es wird ein Server mit Syncplay Version {}+ benötigt, aktuell verwendet wird jedoch Version {}.", #minVersion, serverVersion
|
||||||
"shared-playlists-not-supported-by-server-error" : "The shared playlists feature may not be supported by the server. To ensure that it works correctly requires a server running Syncplay {}+, but the server is running Syncplay {}.", #minVersion, serverVersion # TODO: Translate
|
"shared-playlists-not-supported-by-server-error" : "The shared playlists feature may not be supported by the server. To ensure that it works correctly requires a server running Syncplay {}+, but the server is running Syncplay {}.", #minVersion, serverVersion # TODO: Translate
|
||||||
"shared-playlists-disabled-by-server-error" : "The shared playlist feature has been disabled in the server configuration. To use this feature you will need to connect to a different server.", # TODO: Translate
|
"shared-playlists-disabled-by-server-error" : "The shared playlist feature has been disabled in the server configuration. To use this feature you will need to connect to a different server.", # TODO: Translate
|
||||||
|
|
||||||
"invalid-seek-value" : u"Ungültige Zeitangabe",
|
"invalid-seek-value" : "Ungültige Zeitangabe",
|
||||||
"invalid-offset-value" : u"Ungültiger Offset-Wert",
|
"invalid-offset-value" : "Ungültiger Offset-Wert",
|
||||||
|
|
||||||
"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"
|
"switch-file-not-found-error" : "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. If the folder is actually fine then you can re-enable it by selecting File->Set Media Directories and pressing 'OK'.", #Folder # TODO: Translate
|
"folder-search-timeout-error" : "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. If the folder is actually fine then you can re-enable it by selecting File->Set Media Directories and pressing 'OK'.", #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
|
"folder-search-first-file-timeout-error" : "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
|
"added-file-not-in-media-directory-error" : "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
|
"no-media-directories-error" : "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
|
"cannot-find-directory-error" : "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
|
||||||
|
|
||||||
"failed-to-load-server-list-error" : u"Konnte die Liste der öffentlichen Server nicht laden. Bitte besuche https://www.syncplay.pl/ [Englisch] mit deinem Browser.",
|
"failed-to-load-server-list-error" : "Konnte die Liste der öffentlichen Server nicht laden. Bitte besuche https://www.syncplay.pl/ [Englisch] mit deinem Browser.",
|
||||||
|
|
||||||
# Client arguments
|
# Client arguments
|
||||||
"argument-description" : u'Syncplay ist eine Anwendung um mehrere MPlayer, MPC-HC, MPC-BE und VLC-Instanzen über das Internet zu synchronisieren.',
|
"argument-description" : 'Syncplay ist eine Anwendung um mehrere MPlayer, MPC-HC, MPC-BE und VLC-Instanzen über das Internet zu synchronisieren.',
|
||||||
"argument-epilog" : u'Wenn keine Optionen angegeben sind, werden die _config-Werte verwendet',
|
"argument-epilog" : 'Wenn keine Optionen angegeben sind, werden die _config-Werte verwendet',
|
||||||
"nogui-argument" : u'Keine GUI anzeigen',
|
"nogui-argument" : 'Keine GUI anzeigen',
|
||||||
"host-argument" : u'Server-Adresse',
|
"host-argument" : 'Server-Adresse',
|
||||||
"name-argument" : u'Gewünschter Nutzername',
|
"name-argument" : 'Gewünschter Nutzername',
|
||||||
"debug-argument" : u'Debug-Modus',
|
"debug-argument" : 'Debug-Modus',
|
||||||
"force-gui-prompt-argument" : u'Einstellungsfenster anzeigen',
|
"force-gui-prompt-argument" : 'Einstellungsfenster anzeigen',
|
||||||
"no-store-argument" : u'keine Werte in .syncplay speichern',
|
"no-store-argument" : 'keine Werte in .syncplay speichern',
|
||||||
"room-argument" : u'Standard-Raum',
|
"room-argument" : 'Standard-Raum',
|
||||||
"password-argument" : u'Server-Passwort',
|
"password-argument" : 'Server-Passwort',
|
||||||
"player-path-argument" : u'Pfad zum Player',
|
"player-path-argument" : 'Pfad zum Player',
|
||||||
"file-argument" : u'Abzuspielende Datei',
|
"file-argument" : 'Abzuspielende Datei',
|
||||||
"args-argument" : u'Player-Einstellungen; Wenn du Einstellungen, die mit - beginnen, nutzen willst, stelle ein einzelnes \'--\'-Argument davor',
|
"args-argument" : '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',
|
"clear-gui-data-argument" : '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)',
|
"language-argument" : 'Sprache für Syncplay-Nachrichten (de/en/ru)',
|
||||||
|
|
||||||
"version-argument" : u'gibt die aktuelle Version aus',
|
"version-argument" : 'gibt die aktuelle Version aus',
|
||||||
"version-message" : u"Du verwendest Syncplay v. {} ({})",
|
"version-message" : "Du verwendest Syncplay v. {} ({})",
|
||||||
|
|
||||||
# Client labels
|
# Client labels
|
||||||
"config-window-title" : u"Syncplay Konfiguration",
|
"config-window-title" : "Syncplay Konfiguration",
|
||||||
|
|
||||||
"connection-group-title" : u"Verbindungseinstellungen",
|
"connection-group-title" : "Verbindungseinstellungen",
|
||||||
"host-label" : u"Server-Adresse:",
|
"host-label" : "Server-Adresse:",
|
||||||
"name-label" : u"Benutzername (optional):",
|
"name-label" : "Benutzername (optional):",
|
||||||
"password-label" : u"Server-Passwort (falls nötig):",
|
"password-label" : "Server-Passwort (falls nötig):",
|
||||||
"room-label" : u"Standard-Raum:",
|
"room-label" : "Standard-Raum:",
|
||||||
|
|
||||||
"media-setting-title" : u"Media-Player Einstellungen",
|
"media-setting-title" : "Media-Player Einstellungen",
|
||||||
"executable-path-label" : u"Pfad zum Media-Player:",
|
"executable-path-label" : "Pfad zum Media-Player:",
|
||||||
"media-path-label" : u"Pfad zur Datei:", # Todo: Translate to 'Path to video (optional)'
|
"media-path-label" : "Pfad zur Datei:", # Todo: Translate to 'Path to video (optional)'
|
||||||
"player-arguments-label" : u"Playerparameter:",
|
"player-arguments-label" : "Playerparameter:",
|
||||||
"browse-label" : u"Durchsuchen",
|
"browse-label" : "Durchsuchen",
|
||||||
"update-server-list-label" : u"Liste aktualisieren",
|
"update-server-list-label" : "Liste aktualisieren",
|
||||||
|
|
||||||
"more-title" : u"Mehr Einstellungen zeigen",
|
"more-title" : "Mehr Einstellungen zeigen",
|
||||||
"never-rewind-value" : u"Niemals",
|
"never-rewind-value" : "Niemals",
|
||||||
"seconds-suffix" : u" sek",
|
"seconds-suffix" : " sek",
|
||||||
"privacy-sendraw-option" : u"Klartext senden",
|
"privacy-sendraw-option" : "Klartext senden",
|
||||||
"privacy-sendhashed-option" : u"Hash senden",
|
"privacy-sendhashed-option" : "Hash senden",
|
||||||
"privacy-dontsend-option" : u"Nicht senden",
|
"privacy-dontsend-option" : "Nicht senden",
|
||||||
"filename-privacy-label" : u"Dateiname:",
|
"filename-privacy-label" : "Dateiname:",
|
||||||
"filesize-privacy-label" : u"Dateigröße:",
|
"filesize-privacy-label" : "Dateigröße:",
|
||||||
"checkforupdatesautomatically-label" : u"Automatisch nach Updates suchen",
|
"checkforupdatesautomatically-label" : "Automatisch nach Updates suchen",
|
||||||
"slowondesync-label" : u"Verlangsamen wenn nicht synchron (nicht unterstützt mit MPC-HC/BE)",
|
"slowondesync-label" : "Verlangsamen wenn nicht synchron (nicht unterstützt mit MPC-HC/BE)",
|
||||||
"dontslowdownwithme-label" : u"Nie verlangsamen oder andere zurückspulen (Experimentell)",
|
"dontslowdownwithme-label" : "Nie verlangsamen oder andere zurückspulen (Experimentell)",
|
||||||
"pausing-title" : u"Pausing", # TODO: Translate
|
"pausing-title" : "Pausing", # TODO: Translate
|
||||||
"pauseonleave-label" : u"Pausieren wenn ein Benutzer austritt",
|
"pauseonleave-label" : "Pausieren wenn ein Benutzer austritt",
|
||||||
"readiness-title" : u"Initial readiness state", # TODO: Translate
|
"readiness-title" : "Initial readiness state", # TODO: Translate
|
||||||
"readyatstart-label" : u"Standardmäßig auf \'Bereit\' stellen",
|
"readyatstart-label" : "Standardmäßig auf \'Bereit\' stellen",
|
||||||
"forceguiprompt-label" : u"Diesen Dialog nicht mehr anzeigen",
|
"forceguiprompt-label" : "Diesen Dialog nicht mehr anzeigen",
|
||||||
"showosd-label" : u"OSD-Nachrichten anzeigen",
|
"showosd-label" : "OSD-Nachrichten anzeigen",
|
||||||
|
|
||||||
"showosdwarnings-label" : u"Zeige Warnungen (z.B. wenn Dateien verschieden)",
|
"showosdwarnings-label" : "Zeige Warnungen (z.B. wenn Dateien verschieden)",
|
||||||
"showsameroomosd-label" : u"Zeige Ereignisse in deinem Raum",
|
"showsameroomosd-label" : "Zeige Ereignisse in deinem Raum",
|
||||||
"shownoncontrollerosd-label" : u"Zeige Ereignisse von nicht geführten Räumen in geführten Räumen.",
|
"shownoncontrollerosd-label" : "Zeige Ereignisse von nicht geführten Räumen in geführten Räumen.",
|
||||||
"showdifferentroomosd-label" : u"Zeige Ereignisse in anderen Räumen",
|
"showdifferentroomosd-label" : "Zeige Ereignisse in anderen Räumen",
|
||||||
"showslowdownosd-label" : u"Zeige Verlangsamungs/Zurücksetzungs-Benachrichtigung",
|
"showslowdownosd-label" : "Zeige Verlangsamungs/Zurücksetzungs-Benachrichtigung",
|
||||||
"language-label" : u"Sprache:",
|
"language-label" : "Sprache:",
|
||||||
"automatic-language" : u"Automatisch ({})", # Default language
|
"automatic-language" : "Automatisch ({})", # Default language
|
||||||
"showdurationnotification-label" : u"Zeige Warnung wegen unterschiedlicher Dauer",
|
"showdurationnotification-label" : "Zeige Warnung wegen unterschiedlicher Dauer",
|
||||||
"basics-label" : u"Grundlagen",
|
"basics-label" : "Grundlagen",
|
||||||
"readiness-label" : u"Play/Pause",
|
"readiness-label" : "Play/Pause",
|
||||||
"misc-label" : u"Diverse",
|
"misc-label" : "Diverse",
|
||||||
"core-behaviour-title" : u"Verhalten des Raumes",
|
"core-behaviour-title" : "Verhalten des Raumes",
|
||||||
"syncplay-internals-title" : u"Syncplay intern",
|
"syncplay-internals-title" : "Syncplay intern",
|
||||||
"syncplay-mediasearchdirectories-title" : u"In diesen Verzeichnissen nach Medien suchen", #needs to be checked
|
"syncplay-mediasearchdirectories-title" : "In diesen Verzeichnissen nach Medien suchen", #needs to be checked
|
||||||
"syncplay-mediasearchdirectories-label" : u"In diesen Verzeichnissen nach Medien suchen (ein Pfad pro Zeile)",
|
"syncplay-mediasearchdirectories-label" : "In diesen Verzeichnissen nach Medien suchen (ein Pfad pro Zeile)",
|
||||||
"sync-label" : u"Synchronisation",
|
"sync-label" : "Synchronisation",
|
||||||
"sync-otherslagging-title" : u"Wenn andere laggen...",
|
"sync-otherslagging-title" : "Wenn andere laggen...",
|
||||||
"sync-youlaggging-title" : u"Wenn du laggst...",
|
"sync-youlaggging-title" : "Wenn du laggst...",
|
||||||
"messages-label" : u"Nachrichten",
|
"messages-label" : "Nachrichten",
|
||||||
"messages-osd-title" : u"OSD-(OnScreenDisplay)-Einstellungen",
|
"messages-osd-title" : "OSD-(OnScreenDisplay)-Einstellungen",
|
||||||
"messages-other-title" : u"Weitere Display-Einstellungen",
|
"messages-other-title" : "Weitere Display-Einstellungen",
|
||||||
"chat-label" : u"Chat", # TODO: Translate
|
"chat-label" : "Chat", # TODO: Translate
|
||||||
"privacy-label" : u"Privatsphäre",
|
"privacy-label" : "Privatsphäre",
|
||||||
"privacy-title" : u"Privatsphäreneinstellungen",
|
"privacy-title" : "Privatsphäreneinstellungen",
|
||||||
"unpause-title" : u"Wenn du Play drückst, auf Bereit setzen und:",
|
"unpause-title" : "Wenn du Play drückst, auf Bereit setzen und:",
|
||||||
"unpause-ifalreadyready-option" : u"Wiedergeben wenn bereits als Bereit gesetzt",
|
"unpause-ifalreadyready-option" : "Wiedergeben wenn bereits als Bereit gesetzt",
|
||||||
"unpause-ifothersready-option" : u"Wiedergeben wenn bereits als Bereit gesetzt oder alle anderen bereit sind (Standard)",
|
"unpause-ifothersready-option" : "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-ifminusersready-option" : "Wiedergeben wenn bereits als Bereit gesetzt oder die minimale Anzahl anderer Nutzer bereit ist",
|
||||||
"unpause-always" : u"Immer wiedergeben",
|
"unpause-always" : "Immer wiedergeben",
|
||||||
"syncplay-trusteddomains-title": u"Trusted domains (for streaming services and hosted content)", # TODO: Translate into German
|
"syncplay-trusteddomains-title": "Trusted domains (for streaming services and hosted content)", # TODO: Translate into German
|
||||||
|
|
||||||
"chat-title": u"Chat message input", # TODO: Translate
|
"chat-title": "Chat message input", # TODO: Translate
|
||||||
"chatinputenabled-label": u"Enable chat input via mpv (using enter key)", # TODO: Translate
|
"chatinputenabled-label": "Enable chat input via mpv (using enter key)", # TODO: Translate
|
||||||
"chatdirectinput-label" : u"Allow instant chat input (bypass having to press enter key to chat)", # TODO: Translate
|
"chatdirectinput-label" : "Allow instant chat input (bypass having to press enter key to chat)", # TODO: Translate
|
||||||
"chatinputfont-label": u"Chat input font", # TODO: Translate
|
"chatinputfont-label": "Chat input font", # TODO: Translate
|
||||||
"chatfont-label": u"Set font", # TODO: Translate
|
"chatfont-label": "Set font", # TODO: Translate
|
||||||
"chatcolour-label": u"Set colour", # TODO: Translate
|
"chatcolour-label": "Set colour", # TODO: Translate
|
||||||
"chatinputposition-label": u"Position of message input area in mpv", # TODO: Translate
|
"chatinputposition-label": "Position of message input area in mpv", # TODO: Translate
|
||||||
"chat-top-option": u"Top", # TODO: Translate
|
"chat-top-option": "Top", # TODO: Translate
|
||||||
"chat-middle-option": u"Middle", # TODO: Translate
|
"chat-middle-option": "Middle", # TODO: Translate
|
||||||
"chat-bottom-option": u"Bottom", # TODO: Translate
|
"chat-bottom-option": "Bottom", # TODO: Translate
|
||||||
"chatoutputheader-label" : u"Chat message output", # TODO: Translate
|
"chatoutputheader-label" : "Chat message output", # TODO: Translate
|
||||||
"chatoutputfont-label": u"Chat output font", # TODO: Translate
|
"chatoutputfont-label": "Chat output font", # TODO: Translate
|
||||||
"chatoutputenabled-label": u"Enable chat output in media player (mpv only for now)", # TODO: Translate
|
"chatoutputenabled-label": "Enable chat output in media player (mpv only for now)", # TODO: Translate
|
||||||
"chatoutputposition-label": u"Output mode", # TODO: Translate
|
"chatoutputposition-label": "Output mode", # TODO: Translate
|
||||||
"chat-chatroom-option": u"Chatroom style", # TODO: Translate
|
"chat-chatroom-option": "Chatroom style", # TODO: Translate
|
||||||
"chat-scrolling-option": u"Scrolling style", # TODO: Translate
|
"chat-scrolling-option": "Scrolling style", # TODO: Translate
|
||||||
|
|
||||||
"mpv-key-tab-hint": u"[TAB] to toggle access to alphabet row key shortcuts.", # TODO: Translate
|
"mpv-key-tab-hint": "[TAB] to toggle access to alphabet row key shortcuts.", # TODO: Translate
|
||||||
"mpv-key-hint": u"[ENTER] to send message. [ESC] to escape chat mode.", # TODO: Translate
|
"mpv-key-hint": "[ENTER] to send message. [ESC] to escape chat mode.", # TODO: Translate
|
||||||
"alphakey-mode-warning-first-line": u"You can temporarily use old mpv bindings with a-z keys.", # TODO: Translate
|
"alphakey-mode-warning-first-line": "You can temporarily use old mpv bindings with a-z keys.", # TODO: Translate
|
||||||
"alphakey-mode-warning-second-line": u"Press [TAB] to return to Syncplay chat mode.", # TODO: Translate
|
"alphakey-mode-warning-second-line": "Press [TAB] to return to Syncplay chat mode.", # TODO: Translate
|
||||||
|
|
||||||
"help-label" : u"Hilfe",
|
"help-label" : "Hilfe",
|
||||||
"reset-label" : u"Standardwerte zurücksetzen",
|
"reset-label" : "Standardwerte zurücksetzen",
|
||||||
"run-label" : u"Syncplay starten",
|
"run-label" : "Syncplay starten",
|
||||||
"storeandrun-label" : u"Konfiguration speichern und Syncplay starten",
|
"storeandrun-label" : "Konfiguration speichern und Syncplay starten",
|
||||||
|
|
||||||
"contact-label" : u"Du hast eine Idee, einen Bug gefunden oder möchtest Feedback geben? Sende eine E-Mail an <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=\"https://syncplay.pl/\">https://syncplay.pl/</a> weitere Informationen, Hilfestellungen und Updates. OTE: Chat messages are not encrypted so do not use Syncplay to send sensitive information.", # TODO: Translate last sentence
|
"contact-label" : "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=\"https://syncplay.pl/\">https://syncplay.pl/</a> weitere Informationen, Hilfestellungen und Updates. OTE: Chat messages are not encrypted so do not use Syncplay to send sensitive information.", # TODO: Translate last sentence
|
||||||
|
|
||||||
"joinroom-label" : u"Raum beitreten",
|
"joinroom-label" : "Raum beitreten",
|
||||||
"joinroom-menu-label" : u"Raum beitreten {}", #TODO: Might want to fix this
|
"joinroom-menu-label" : "Raum beitreten {}", #TODO: Might want to fix this
|
||||||
"seektime-menu-label" : u"Spule zu Zeit",
|
"seektime-menu-label" : "Spule zu Zeit",
|
||||||
"undoseek-menu-label" : u"Rückgängig",
|
"undoseek-menu-label" : "Rückgängig",
|
||||||
"play-menu-label" : u"Wiedergabe",
|
"play-menu-label" : "Wiedergabe",
|
||||||
"pause-menu-label" : u"Pause",
|
"pause-menu-label" : "Pause",
|
||||||
"playbackbuttons-menu-label" : u"Wiedergabesteuerung anzeigen",
|
"playbackbuttons-menu-label" : "Wiedergabesteuerung anzeigen",
|
||||||
"autoplay-menu-label" : u"Auto-Play-Knopf anzeigen",
|
"autoplay-menu-label" : "Auto-Play-Knopf anzeigen",
|
||||||
"autoplay-guipushbuttonlabel" : u"Automatisch abspielen wenn alle bereit sind",
|
"autoplay-guipushbuttonlabel" : "Automatisch abspielen wenn alle bereit sind",
|
||||||
"autoplay-minimum-label" : u"Minimum an Nutzern:",
|
"autoplay-minimum-label" : "Minimum an Nutzern:",
|
||||||
|
|
||||||
"sendmessage-label" : u"Send", # TODO: Translate
|
"sendmessage-label" : "Send", # TODO: Translate
|
||||||
|
|
||||||
"ready-guipushbuttonlabel" : u"Ich bin bereit den Film anzuschauen!",
|
"ready-guipushbuttonlabel" : "Ich bin bereit den Film anzuschauen!",
|
||||||
|
|
||||||
"roomuser-heading-label" : u"Raum / Benutzer",
|
"roomuser-heading-label" : "Raum / Benutzer",
|
||||||
"size-heading-label" : u"Größe",
|
"size-heading-label" : "Größe",
|
||||||
"duration-heading-label" : u"Länge",
|
"duration-heading-label" : "Länge",
|
||||||
"filename-heading-label" : u"Dateiname",
|
"filename-heading-label" : "Dateiname",
|
||||||
"notifications-heading-label" : u"Benachrichtigungen",
|
"notifications-heading-label" : "Benachrichtigungen",
|
||||||
"userlist-heading-label" : u"Liste der gespielten Dateien",
|
"userlist-heading-label" : "Liste der gespielten Dateien",
|
||||||
|
|
||||||
"browseformedia-label" : u"Nach Mediendateien durchsuchen",
|
"browseformedia-label" : "Nach Mediendateien durchsuchen",
|
||||||
|
|
||||||
"file-menu-label" : u"&Datei", # & precedes shortcut key
|
"file-menu-label" : "&Datei", # & precedes shortcut key
|
||||||
"openmedia-menu-label" : u"&Mediendatei öffnen...",
|
"openmedia-menu-label" : "&Mediendatei öffnen...",
|
||||||
"openstreamurl-menu-label" : u"&Stream URL öffnen",
|
"openstreamurl-menu-label" : "&Stream URL öffnen",
|
||||||
"setmediadirectories-menu-label" : u"Set media &directories", # TODO: Translate
|
"setmediadirectories-menu-label" : "Set media &directories", # TODO: Translate
|
||||||
"exit-menu-label" : u"&Beenden",
|
"exit-menu-label" : "&Beenden",
|
||||||
"advanced-menu-label" : u"&Erweitert",
|
"advanced-menu-label" : "&Erweitert",
|
||||||
"window-menu-label" : u"&Fenster",
|
"window-menu-label" : "&Fenster",
|
||||||
"setoffset-menu-label" : u"&Offset einstellen",
|
"setoffset-menu-label" : "&Offset einstellen",
|
||||||
"createcontrolledroom-menu-label" : u"&Zentral gesteuerten Raum erstellen",
|
"createcontrolledroom-menu-label" : "&Zentral gesteuerten Raum erstellen",
|
||||||
"identifyascontroller-menu-label" : u"Als Raumleiter &identifizieren",
|
"identifyascontroller-menu-label" : "Als Raumleiter &identifizieren",
|
||||||
"settrusteddomains-menu-label" : u"Set &trusted domains", # TODO: Translate
|
"settrusteddomains-menu-label" : "Set &trusted domains", # TODO: Translate
|
||||||
"addtrusteddomain-menu-label" : u"Add {} as trusted domain", # Domain # TODO: Translate
|
"addtrusteddomain-menu-label" : "Add {} as trusted domain", # Domain # TODO: Translate
|
||||||
|
|
||||||
"playback-menu-label" : u"&Wiedergabe",
|
"playback-menu-label" : "&Wiedergabe",
|
||||||
|
|
||||||
"help-menu-label" : u"&Hilfe",
|
"help-menu-label" : "&Hilfe",
|
||||||
"userguide-menu-label" : u"&Benutzerhandbuch öffnen",
|
"userguide-menu-label" : "&Benutzerhandbuch öffnen",
|
||||||
"update-menu-label" : u"auf &Aktualisierung prüfen",
|
"update-menu-label" : "auf &Aktualisierung prüfen",
|
||||||
|
|
||||||
#About dialog - TODO: Translate
|
#About dialog - TODO: Translate
|
||||||
"about-menu-label": u"&About Syncplay",
|
"about-menu-label": "&About Syncplay",
|
||||||
"about-dialog-title": u"About Syncplay",
|
"about-dialog-title": "About Syncplay",
|
||||||
"about-dialog-release": u"Version {} release {}",
|
"about-dialog-release": "Version {} release {}",
|
||||||
"about-dialog-license-text" : u"Licensed under the Apache License, Version 2.0",
|
"about-dialog-license-text" : "Licensed under the Apache License, Version 2.0",
|
||||||
"about-dialog-license-button": u"License",
|
"about-dialog-license-button": "License",
|
||||||
"about-dialog-dependencies": u"Dependencies",
|
"about-dialog-dependencies": "Dependencies",
|
||||||
|
|
||||||
"setoffset-msgbox-label" : u"Offset einstellen",
|
"setoffset-msgbox-label" : "Offset einstellen",
|
||||||
"offsetinfo-msgbox-label" : u"Offset (siehe https://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
|
"offsetinfo-msgbox-label" : "Offset (siehe https://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
|
||||||
|
|
||||||
"promptforstreamurl-msgbox-label" : u"Stream URL öffnen",
|
"promptforstreamurl-msgbox-label" : "Stream URL öffnen",
|
||||||
"promptforstreamurlinfo-msgbox-label" : u"Stream URL",
|
"promptforstreamurlinfo-msgbox-label" : "Stream URL",
|
||||||
|
|
||||||
"addfolder-label" : u"Add folder", # TODO: Translate
|
"addfolder-label" : "Add folder", # TODO: Translate
|
||||||
|
|
||||||
"adduris-msgbox-label" : u"Add URLs to playlist (one per line)", # TODO: Translate
|
"adduris-msgbox-label" : "Add URLs to playlist (one per line)", # TODO: Translate
|
||||||
"editplaylist-msgbox-label": u"Set playlist (one per line)", # TODO: Translate
|
"editplaylist-msgbox-label": "Set playlist (one per line)", # TODO: Translate
|
||||||
"trusteddomains-msgbox-label" : u"Domains it is okay to automatically switch to (one per line)", # TODO: Translate
|
"trusteddomains-msgbox-label" : "Domains it is okay to automatically switch to (one per line)", # TODO: Translate
|
||||||
|
|
||||||
"createcontrolledroom-msgbox-label" : u"Zentral gesteuerten Raum erstellen",
|
"createcontrolledroom-msgbox-label" : "Zentral gesteuerten Raum erstellen",
|
||||||
"controlledroominfo-msgbox-label" : u"Namen des zentral gesteuerten Raums eingeben\r\n(siehe https://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
|
"controlledroominfo-msgbox-label" : "Namen des zentral gesteuerten Raums eingeben\r\n(siehe https://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
|
||||||
|
|
||||||
"identifyascontroller-msgbox-label" : u"Als Raumleiter identifizieren",
|
"identifyascontroller-msgbox-label" : "Als Raumleiter identifizieren",
|
||||||
"identifyinfo-msgbox-label" : u"Passwort des zentral gesteuerten Raums eingeben\r\n(siehe https://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
|
"identifyinfo-msgbox-label" : "Passwort des zentral gesteuerten Raums eingeben\r\n(siehe https://syncplay.pl/guide/ für eine Anleitung [Englisch]):",
|
||||||
|
|
||||||
"public-server-msgbox-label" : u"Einen öffentlichen Server für diese Sitzung auswählen",
|
"public-server-msgbox-label" : "Einen öffentlichen Server für diese Sitzung auswählen",
|
||||||
|
|
||||||
"megabyte-suffix" : u" MB",
|
"megabyte-suffix" : " MB",
|
||||||
|
|
||||||
# Tooltips
|
# Tooltips
|
||||||
|
|
||||||
"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.",
|
"host-tooltip" : "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.",
|
"name-tooltip" : "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.",
|
"password-tooltip" : "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.",
|
"room-tooltip" : "Der Raum, der betreten werden soll, kann ein x-beliebiger sein. Allerdings werden nur Clients im selben Raum synchronisiert.",
|
||||||
|
|
||||||
"executable-path-tooltip" : u"Pfad zum ausgewählten, unterstützten Mediaplayer (MPC-HC, MPC-BE, VLC, mplayer2 or mpv).",
|
"executable-path-tooltip" : "Pfad zum ausgewählten, unterstützten Mediaplayer (MPC-HC, MPC-BE, VLC, mplayer2 or mpv).",
|
||||||
"media-path-tooltip" : u"Pfad zum wiederzugebenden Video oder Stream. Notwendig für mplayer2.", # TODO: Confirm translation
|
"media-path-tooltip" : "Pfad zum wiederzugebenden Video oder Stream. Notwendig für mplayer2.", # TODO: Confirm translation
|
||||||
"player-arguments-tooltip" : u"Zusätzliche Kommandozeilenparameter / -schalter für diesen Mediaplayer.",
|
"player-arguments-tooltip" : "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)
|
"mediasearcdirectories-arguments-tooltip" : "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)
|
||||||
|
|
||||||
"more-tooltip" : u"Weitere Einstellungen anzeigen.",
|
"more-tooltip" : "Weitere Einstellungen anzeigen.",
|
||||||
"filename-privacy-tooltip" : u"Privatheitsmodus beim Senden des Namens der aktuellen Datei zum Server.",
|
"filename-privacy-tooltip" : "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.",
|
"filesize-privacy-tooltip" : "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-sendraw-tooltip" : "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-sendhashed-tooltip" : "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.",
|
"privacy-dontsend-tooltip" : "Diese Information nicht übertragen. Dies garantiert den größtmöglichen Datanschutz.",
|
||||||
"checkforupdatesautomatically-tooltip" : u"Regelmäßig auf der Syncplay-Website nach Updates suchen.",
|
"checkforupdatesautomatically-tooltip" : "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.",
|
"slowondesync-tooltip" : "Reduziert die Abspielgeschwindigkeit zeitweise, um die Synchronität zu den anderen Clients wiederherzustellen.",
|
||||||
"rewindondesync-label" : u"Zurückspulen bei großer Zeitdifferenz (empfohlen)",
|
"rewindondesync-label" : "Zurückspulen bei großer Zeitdifferenz (empfohlen)",
|
||||||
"fastforwardondesync-label" : u"Vorspulen wenn das Video laggt (empfohlen)",
|
"fastforwardondesync-label" : "Vorspulen wenn das Video laggt (empfohlen)",
|
||||||
"dontslowdownwithme-tooltip" : u"Lässt andere nicht langsamer werden oder zurückspringen, wenn deine Wiedergabe hängt.",
|
"dontslowdownwithme-tooltip" : "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.",
|
"pauseonleave-tooltip" : "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)",
|
"readyatstart-tooltip" : "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.",
|
"forceguiprompt-tooltip" : "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.",
|
"nostore-tooltip" : "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)",
|
"rewindondesync-tooltip" : "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).",
|
"fastforwardondesync-tooltip" : "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.",
|
"showosd-tooltip" : "Syncplay-Nachrichten auf dem OSD (= OnScreenDisplay, ein eingeblendetes Textfeld) des Players anzeigen.",
|
||||||
"showosdwarnings-tooltip" : u"Warnungen bei Unterschiedlichen Dateien oder Alleinsein im Raum anzeigen.",
|
"showosdwarnings-tooltip" : "Warnungen bei Unterschiedlichen Dateien oder Alleinsein im Raum anzeigen.",
|
||||||
"showsameroomosd-tooltip" : u"OSD-Meldungen über Ereignisse im selben Raum anzeigen.",
|
"showsameroomosd-tooltip" : "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.",
|
"shownoncontrollerosd-tooltip" : "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.",
|
"showdifferentroomosd-tooltip" : "OSD-Meldungen zu anderen Räumen als dem aktuell betretenen anzeigen.",
|
||||||
"showslowdownosd-tooltip" : u"Meldungen bei Geschwindigkeitsänderung anzeigen.",
|
"showslowdownosd-tooltip" : "Meldungen bei Geschwindigkeitsänderung anzeigen.",
|
||||||
"showdurationnotification-tooltip" : u"Nützlich, wenn z.B. ein Teil eines mehrteiligen Videos fehlt, kann jedoch auch fehlerhaft anschlagen.",
|
"showdurationnotification-tooltip" : "Nützlich, wenn z.B. ein Teil eines mehrteiligen Videos fehlt, kann jedoch auch fehlerhaft anschlagen.",
|
||||||
"language-tooltip" : u"Die verwendete Sprache von Syncplay",
|
"language-tooltip" : "Die verwendete Sprache von Syncplay",
|
||||||
"unpause-always-tooltip" : u"Wiedergabe startet immer (anstatt nur den Bereitschaftsstatus zu ändern)",
|
"unpause-always-tooltip" : "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-ifalreadyready-tooltip" : "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-ifothersready-tooltip" : "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.",
|
"unpause-ifminusersready-tooltip" : "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
|
"trusteddomains-arguments-tooltip" : "Domains that it is okay for Syncplay to automatically switch to when shared playlists is enabled.", # TODO: Translate into German
|
||||||
|
|
||||||
"chatinputenabled-tooltip": u"Enable chat input in mpv (press enter to chat, enter to send, escape to cancel)", # TODO: Translate
|
"chatinputenabled-tooltip": "Enable chat input in mpv (press enter to chat, enter to send, escape to cancel)", # TODO: Translate
|
||||||
"chatdirectinput-tooltip" : u"Skip having to press 'enter' to go into chat input mode in mpv. Press TAB in mpv to temporarily disable this feature.", # TODO: Translate
|
"chatdirectinput-tooltip" : "Skip having to press 'enter' to go into chat input mode in mpv. Press TAB in mpv to temporarily disable this feature.", # TODO: Translate
|
||||||
"font-label-tooltip": u"Font used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.", # TODO: Translate
|
"font-label-tooltip": "Font used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.", # TODO: Translate
|
||||||
"set-input-font-tooltip": u"Font family used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.", # TODO: Translate
|
"set-input-font-tooltip": "Font family used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.", # TODO: Translate
|
||||||
"set-input-colour-tooltip": u"Font colour used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.", # TODO: Translate
|
"set-input-colour-tooltip": "Font colour used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.", # TODO: Translate
|
||||||
"chatinputposition-tooltip": u"Location in mpv where chat input text will appear when you press enter and type.", # TODO: Translate
|
"chatinputposition-tooltip": "Location in mpv where chat input text will appear when you press enter and type.", # TODO: Translate
|
||||||
"chatinputposition-top-tooltip": u"Place chat input at top of mpv window.", # TODO: Translate
|
"chatinputposition-top-tooltip": "Place chat input at top of mpv window.", # TODO: Translate
|
||||||
"chatinputposition-middle-tooltip": u"Place chat input in dead centre of mpv window.", # TODO: Translate
|
"chatinputposition-middle-tooltip": "Place chat input in dead centre of mpv window.", # TODO: Translate
|
||||||
"chatinputposition-bottom-tooltip": u"Place chat input at bottom of mpv window.", # TODO: Translate
|
"chatinputposition-bottom-tooltip": "Place chat input at bottom of mpv window.", # TODO: Translate
|
||||||
"chatoutputenabled-tooltip": u"Show chat messages in OSD (if supported by media player).", # TODO: Translate
|
"chatoutputenabled-tooltip": "Show chat messages in OSD (if supported by media player).", # TODO: Translate
|
||||||
"font-output-label-tooltip": u"Chat output font.", # TODO: Translate
|
"font-output-label-tooltip": "Chat output font.", # TODO: Translate
|
||||||
"set-output-font-tooltip": u"Font used for when displaying chat messages.", # TODO: Translate
|
"set-output-font-tooltip": "Font used for when displaying chat messages.", # TODO: Translate
|
||||||
"chatoutputmode-tooltip": u"How chat messages are displayed.", # TODO: Translate
|
"chatoutputmode-tooltip": "How chat messages are displayed.", # TODO: Translate
|
||||||
"chatoutputmode-chatroom-tooltip": u"Display new lines of chat directly below previous line.", # TODO: Translate
|
"chatoutputmode-chatroom-tooltip": "Display new lines of chat directly below previous line.", # TODO: Translate
|
||||||
"chatoutputmode-scrolling-tooltip": u"Scroll chat text from right to left.", # TODO: Translate
|
"chatoutputmode-scrolling-tooltip": "Scroll chat text from right to left.", # TODO: Translate
|
||||||
|
|
||||||
"help-tooltip" : u"Öffnet Hilfe auf syncplay.pl [Englisch]",
|
"help-tooltip" : "Öffnet Hilfe auf syncplay.pl [Englisch]",
|
||||||
"reset-tooltip" : u"Alle Einstellungen auf Standardwerte zurücksetzen.",
|
"reset-tooltip" : "Alle Einstellungen auf Standardwerte zurücksetzen.",
|
||||||
"update-server-list-tooltip" : u"Mit syncplay.pl verbinden um die Liste öffentlicher Server zu aktualisieren.",
|
"update-server-list-tooltip" : "Mit syncplay.pl verbinden um die Liste öffentlicher Server zu aktualisieren.",
|
||||||
|
|
||||||
"joinroom-tooltip" : u"Den aktuellen Raum verlassen und stattdessen den angegebenen betreten.",
|
"joinroom-tooltip" : "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.",
|
"seektime-msgbox-label" : "Springe zur angegebenen Zeit (in Sekunden oder min:sek). Verwende +/- zum relativen Springen.",
|
||||||
"ready-tooltip" : u"Zeigt an, ob du bereit zum anschauen bist",
|
"ready-tooltip" : "Zeigt an, ob du bereit zum anschauen bist",
|
||||||
"autoplay-tooltip" : u"Automatisch abspielen, wenn alle Nutzer bereit sind oder die minimale Nutzerzahl erreicht ist.",
|
"autoplay-tooltip" : "Automatisch abspielen, wenn alle Nutzer bereit sind oder die minimale Nutzerzahl erreicht ist.",
|
||||||
"switch-to-file-tooltip" : u"Doppelklicken um zu {} zu wechseln", # Filename
|
"switch-to-file-tooltip" : "Doppelklicken um zu {} zu wechseln", # Filename
|
||||||
"sendmessage-tooltip" : u"Send message to room", # TODO: Translate
|
"sendmessage-tooltip" : "Send message to room", # TODO: Translate
|
||||||
|
|
||||||
# In-userlist notes (GUI)
|
# In-userlist notes (GUI)
|
||||||
"differentsize-note" : u"Verschiedene Größe!",
|
"differentsize-note" : "Verschiedene Größe!",
|
||||||
"differentsizeandduration-note" : u"Verschiedene Größe und Dauer!",
|
"differentsizeandduration-note" : "Verschiedene Größe und Dauer!",
|
||||||
"differentduration-note" : u"Verschiedene Dauer!",
|
"differentduration-note" : "Verschiedene Dauer!",
|
||||||
"nofile-note" : u"(keine Datei wird abgespielt)",
|
"nofile-note" : "(keine Datei wird abgespielt)",
|
||||||
|
|
||||||
# Server messages to client
|
# Server messages to client
|
||||||
"new-syncplay-available-motd-message" : u"<NOTICE> Du nutzt Syncplay Version {}, aber es gibt eine neuere Version auf https://syncplay.pl</NOTICE>", # ClientVersion
|
"new-syncplay-available-motd-message" : "<NOTICE> Du nutzt Syncplay Version {}, aber es gibt eine neuere Version auf https://syncplay.pl</NOTICE>", # ClientVersion
|
||||||
|
|
||||||
# Server notifications
|
# Server notifications
|
||||||
"welcome-server-notification" : u"Willkommen zum Syncplay-Server, v. {0}", # version
|
"welcome-server-notification" : "Willkommen zum Syncplay-Server, v. {0}", # version
|
||||||
"client-connected-room-server-notification" : u"{0}({2}) hat den Raum '{1}' betreten", # username, host, room
|
"client-connected-room-server-notification" : "{0}({2}) hat den Raum '{1}' betreten", # username, host, room
|
||||||
"client-left-server-notification" : u"{0} hat den Server verlassen", # name
|
"client-left-server-notification" : "{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
|
"no-salt-notification" : "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 arguments
|
||||||
"server-argument-description" : u'Anwendung, um mehrere MPlayer, MPC-HC/BE und VLC-Instanzen über das Internet zu synchronisieren. Server',
|
"server-argument-description" : 'Anwendung, um mehrere MPlayer, MPC-HC/BE und VLC-Instanzen über das Internet zu synchronisieren. Server',
|
||||||
"server-argument-epilog" : u'Wenn keine Optionen angegeben sind, werden die _config-Werte verwendet',
|
"server-argument-epilog" : 'Wenn keine Optionen angegeben sind, werden die _config-Werte verwendet',
|
||||||
"server-port-argument" : u'Server TCP-Port',
|
"server-port-argument" : 'Server TCP-Port',
|
||||||
"server-password-argument" : u'Server Passwort',
|
"server-password-argument" : 'Server Passwort',
|
||||||
"server-isolate-room-argument" : u'Sollen die Räume isoliert sein?',
|
"server-isolate-room-argument" : 'Sollen die Räume isoliert sein?',
|
||||||
"server-salt-argument" : u"zufällige Zeichenkette, die zur Erstellung von Passwörtern verwendet wird",
|
"server-salt-argument" : "zufällige Zeichenkette, die zur Erstellung von Passwörtern verwendet wird",
|
||||||
"server-disable-ready-argument" : u"Bereitschaftsfeature deaktivieren",
|
"server-disable-ready-argument" : "Bereitschaftsfeature deaktivieren",
|
||||||
"server-motd-argument": u"Pfad zur Datei, von der die Nachricht des Tages geladen wird",
|
"server-motd-argument": "Pfad zur Datei, von der die Nachricht des Tages geladen wird",
|
||||||
"server-chat-argument" : "Should chat be disabled?", # TODO: Translate
|
"server-chat-argument" : "Should chat be disabled?", # TODO: Translate
|
||||||
"server-chat-maxchars-argument": u"Maximum number of characters in a chat message (default is {})", # TODO: Translate
|
"server-chat-maxchars-argument": "Maximum number of characters in a chat message (default is {})", # TODO: Translate
|
||||||
"server-maxusernamelength-argument" : u"Maximum number of charactrs in a username (default is {})", # TODO: Translate
|
"server-maxusernamelength-argument" : "Maximum number of charactrs in a username (default is {})", # TODO: Translate
|
||||||
"server-messed-up-motd-unescaped-placeholders": u"Die Nachricht des Tages hat unmaskierte Platzhalter. Alle $-Zeichen sollten verdoppelt werden ($$).",
|
"server-messed-up-motd-unescaped-placeholders": "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-messed-up-motd-too-long": "Die Nachricht des Tages ist zu lang - Maximal {} Zeichen, aktuell {}.",
|
||||||
|
|
||||||
# Server errors
|
# Server errors
|
||||||
"unknown-command-server-error" : u"Unbekannter Befehl {}", # message
|
"unknown-command-server-error" : "Unbekannter Befehl {}", # message
|
||||||
"not-json-server-error" : u"Kein JSON-String {}", # message
|
"not-json-server-error" : "Kein JSON-String {}", # message
|
||||||
"not-known-server-error" : u"Der Server muss dich kennen, bevor du diesen Befehl nutzen kannst",
|
"not-known-server-error" : "Der Server muss dich kennen, bevor du diesen Befehl nutzen kannst",
|
||||||
"client-drop-server-error" : u"Client verloren: {} -- {}", # host, error
|
"client-drop-server-error" : "Client verloren: {} -- {}", # host, error
|
||||||
"password-required-server-error" : u"Passwort nötig",
|
"password-required-server-error" : "Passwort nötig",
|
||||||
"wrong-password-server-error" : u"Ungültiges Passwort",
|
"wrong-password-server-error" : "Ungültiges Passwort",
|
||||||
"hello-server-error" : u"Zu wenige Hello-Argumente",
|
"hello-server-error" : "Zu wenige Hello-Argumente",
|
||||||
|
|
||||||
# Playlists TODO: Translate all this to German
|
# Playlists TODO: Translate all this to German
|
||||||
"playlist-selection-changed-notification" : u"{} changed the playlist selection", # Username
|
"playlist-selection-changed-notification" : "{} changed the playlist selection", # Username
|
||||||
"playlist-contents-changed-notification" : u"{} updated the playlist", # Username
|
"playlist-contents-changed-notification" : "{} updated the playlist", # Username
|
||||||
"cannot-find-file-for-playlist-switch-error" : u"Could not find file {} in media directories for playlist switch!", # Filename
|
"cannot-find-file-for-playlist-switch-error" : "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-duplicate-error" : "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. If you right click on a URL then you can add its domain as a trusted domain via the context menu.", # Filename
|
"cannot-add-unsafe-path-error" : "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. If you right click on a URL then you can add its domain as a trusted domain via the context menu.", # Filename
|
||||||
"sharedplaylistenabled-label" : u"Enable shared playlists",
|
"sharedplaylistenabled-label" : "Enable shared playlists",
|
||||||
"removefromplaylist-menu-label" : u"Remove from playlist",
|
"removefromplaylist-menu-label" : "Remove from playlist",
|
||||||
"shuffleremainingplaylist-menu-label" : u"Shuffle remaining playlist",
|
"shuffleremainingplaylist-menu-label" : "Shuffle remaining playlist",
|
||||||
"shuffleentireplaylist-menu-label" : u"Shuffle entire playlist",
|
"shuffleentireplaylist-menu-label" : "Shuffle entire playlist",
|
||||||
"undoplaylist-menu-label" : u"Undo last change to playlist",
|
"undoplaylist-menu-label" : "Undo last change to playlist",
|
||||||
"addfilestoplaylist-menu-label" : u"Add file(s) to bottom of playlist",
|
"addfilestoplaylist-menu-label" : "Add file(s) to bottom of playlist",
|
||||||
"addurlstoplaylist-menu-label" : u"Add URL(s) to bottom of playlist",
|
"addurlstoplaylist-menu-label" : "Add URL(s) to bottom of playlist",
|
||||||
"editplaylist-menu-label": u"Edit playlist",
|
"editplaylist-menu-label": "Edit playlist",
|
||||||
|
|
||||||
"open-containing-folder": u"Open folder containing this file",
|
"open-containing-folder": "Open folder containing this file",
|
||||||
"addusersfiletoplaylist-menu-label" : u"Add {} file to playlist", # item owner indicator
|
"addusersfiletoplaylist-menu-label" : "Add {} file to playlist", # item owner indicator
|
||||||
"addusersstreamstoplaylist-menu-label" : u"Add {} stream to playlist", # item owner indicator
|
"addusersstreamstoplaylist-menu-label" : "Add {} stream to playlist", # item owner indicator
|
||||||
"openusersstream-menu-label" : u"Open {} stream", # [username]'s
|
"openusersstream-menu-label" : "Open {} stream", # [username]'s
|
||||||
"openusersfile-menu-label" : u"Open {} file", # [username]'s
|
"openusersfile-menu-label" : "Open {} file", # [username]'s
|
||||||
"item-is-yours-indicator" : u"your", # Goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
"item-is-yours-indicator" : "your", # Goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
||||||
"item-is-others-indicator" : u"{}'s", # username - goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
"item-is-others-indicator" : "{}'s", # username - goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
||||||
|
|
||||||
"playlist-instruction-item-message" : u"Drag file here to add it to the shared playlist.",
|
"playlist-instruction-item-message" : "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'.",
|
"sharedplaylistenabled-tooltip" : "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'.",
|
||||||
}
|
}
|
||||||
|
|||||||
330
syncplay/messages_en.py
Normal file → Executable file
330
syncplay/messages_en.py
Normal file → Executable file
@ -8,7 +8,7 @@ en = {
|
|||||||
# Client notifications
|
# Client notifications
|
||||||
"config-cleared-notification" : "Settings cleared. Changes will be saved when you store a valid configuration.",
|
"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" : "Loaded relative configuration file(s): {}",
|
||||||
|
|
||||||
"connection-attempt-notification" : "Attempting to connect to {}:{}", # Port, IP
|
"connection-attempt-notification" : "Attempting to connect to {}:{}", # Port, IP
|
||||||
"reconnection-attempt-notification" : "Connection with server lost, attempting to reconnect",
|
"reconnection-attempt-notification" : "Connection with server lost, attempting to reconnect",
|
||||||
@ -22,53 +22,53 @@ en = {
|
|||||||
"slowdown-notification" : "Slowing down due to time difference with {}", # User
|
"slowdown-notification" : "Slowing down due to time difference with {}", # User
|
||||||
"revert-notification" : "Reverting speed back to normal",
|
"revert-notification" : "Reverting speed back to normal",
|
||||||
|
|
||||||
"pause-notification" : u"{} paused", # User
|
"pause-notification" : "{} paused", # User
|
||||||
"unpause-notification" : u"{} unpaused", # User
|
"unpause-notification" : "{} unpaused", # User
|
||||||
"seek-notification" : u"{} jumped from {} to {}", # User, from time, to time
|
"seek-notification" : "{} jumped from {} to {}", # User, from time, to time
|
||||||
|
|
||||||
"current-offset-notification" : "Current offset: {} seconds", # Offset
|
"current-offset-notification" : "Current offset: {} seconds", # Offset
|
||||||
|
|
||||||
"media-directory-list-updated-notification" : u"Syncplay media directories have been updated.",
|
"media-directory-list-updated-notification" : "Syncplay media directories have been updated.",
|
||||||
|
|
||||||
"room-join-notification" : u"{} has joined the room: '{}'", # User
|
"room-join-notification" : "{} has joined the room: '{}'", # User
|
||||||
"left-notification" : u"{} has left", # User
|
"left-notification" : "{} has left", # User
|
||||||
"left-paused-notification" : u"{} left, {} paused", # User who left, User who paused
|
"left-paused-notification" : "{} left, {} paused", # User who left, User who paused
|
||||||
"playing-notification" : u"{} is playing '{}' ({})", # User, file, duration
|
"playing-notification" : "{} is playing '{}' ({})", # User, file, duration
|
||||||
"playing-notification/room-addendum" : u" in room: '{}'", # Room
|
"playing-notification/room-addendum" : " in room: '{}'", # Room
|
||||||
|
|
||||||
"not-all-ready" : u"Not ready: {}", # Usernames
|
"not-all-ready" : "Not ready: {}", # Usernames
|
||||||
"all-users-ready" : u"Everyone is ready ({} users)", #Number of ready users
|
"all-users-ready" : "Everyone is ready ({} users)", #Number of ready users
|
||||||
"ready-to-unpause-notification" : u"You are now set as ready - unpause again to unpause",
|
"ready-to-unpause-notification" : "You are now set as ready - unpause again to unpause",
|
||||||
"set-as-ready-notification" : u"You are now set as ready",
|
"set-as-ready-notification" : "You are now set as ready",
|
||||||
"set-as-not-ready-notification" : u"You are now set as not ready",
|
"set-as-not-ready-notification" : "You are now set as not ready",
|
||||||
"autoplaying-notification" : u"Auto-playing in {}...", # Number of seconds until playback will start
|
"autoplaying-notification" : "Auto-playing in {}...", # Number of seconds until playback will start
|
||||||
|
|
||||||
"identifying-as-controller-notification" : u"Identifying as room operator with password '{}'...",
|
"identifying-as-controller-notification" : "Identifying as room operator with password '{}'...",
|
||||||
"failed-to-identify-as-controller-notification" : u"{} failed to identify as a room operator.",
|
"failed-to-identify-as-controller-notification" : "{} failed to identify as a room operator.",
|
||||||
"authenticated-as-controller-notification" : u"{} authenticated as a room operator",
|
"authenticated-as-controller-notification" : "{} authenticated as a room operator",
|
||||||
"created-controlled-room-notification" : u"Created managed room '{}' with password '{}'. Please save this information for future reference!", # RoomName, operatorPassword
|
"created-controlled-room-notification" : "Created managed room '{}' with password '{}'. Please save this information for future reference!", # RoomName, operatorPassword
|
||||||
|
|
||||||
"file-different-notification" : "File you are playing appears to be different from {}'s", # User
|
"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
|
"file-differences-notification" : "Your file differs in the following way(s): {}", # Differences
|
||||||
"room-file-differences" : u"File differences: {}", # File differences (filename, size, and/or duration)
|
"room-file-differences" : "File differences: {}", # File differences (filename, size, and/or duration)
|
||||||
"file-difference-filename" : u"name",
|
"file-difference-filename" : "name",
|
||||||
"file-difference-filesize" : u"size",
|
"file-difference-filesize" : "size",
|
||||||
"file-difference-duration" : u"duration",
|
"file-difference-duration" : "duration",
|
||||||
"alone-in-the-room": u"You're alone in the room",
|
"alone-in-the-room": "You're alone in the room",
|
||||||
|
|
||||||
"different-filesize-notification" : u" (their file size is different from yours!)",
|
"different-filesize-notification" : " (their file size is different from yours!)",
|
||||||
"userlist-playing-notification" : u"{} is playing:", #Username
|
"userlist-playing-notification" : "{} is playing:", #Username
|
||||||
"file-played-by-notification" : u"File: {} is being played by:", # File
|
"file-played-by-notification" : "File: {} is being played by:", # File
|
||||||
"no-file-played-notification" : u"{} is not playing a file", # Username
|
"no-file-played-notification" : "{} is not playing a file", # Username
|
||||||
"notplaying-notification" : "People who are not playing any file:",
|
"notplaying-notification" : "People who are not playing any file:",
|
||||||
"userlist-room-notification" : u"In room '{}':", # Room
|
"userlist-room-notification" : "In room '{}':", # Room
|
||||||
"userlist-file-notification" : "File",
|
"userlist-file-notification" : "File",
|
||||||
"controller-userlist-userflag" : "Operator",
|
"controller-userlist-userflag" : "Operator",
|
||||||
"ready-userlist-userflag" : "Ready",
|
"ready-userlist-userflag" : "Ready",
|
||||||
|
|
||||||
"update-check-failed-notification" : u"Could not automatically check whether Syncplay {} is up to date. Want to visit https://syncplay.pl/ to manually check for updates?", #Syncplay version
|
"update-check-failed-notification" : "Could not automatically check whether Syncplay {} is up to date. Want to visit https://syncplay.pl/ to manually check for updates?", #Syncplay version
|
||||||
"syncplay-uptodate-notification" : u"Syncplay is up to date",
|
"syncplay-uptodate-notification" : "Syncplay is up to date",
|
||||||
"syncplay-updateavailable-notification" : u"A new version of Syncplay is available. Do you want to visit the release page?",
|
"syncplay-updateavailable-notification" : "A new version of Syncplay is available. Do you want to visit the release page?",
|
||||||
|
|
||||||
"mplayer-file-required-notification" : "Syncplay using mplayer requires you to provide file when starting",
|
"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",
|
"mplayer-file-required-notification/example" : "Usage example: syncplay [options] [url|path/]filename",
|
||||||
@ -82,7 +82,7 @@ en = {
|
|||||||
"commandlist-notification/pause" : "\tp - toggle pause",
|
"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/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/help" : "\th - this help",
|
||||||
"commandlist-notification/toggle" : u"\tt - toggles whether you are ready to watch or not",
|
"commandlist-notification/toggle" : "\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/create" : "\tc [name] - create managed room using name of current room",
|
||||||
"commandlist-notification/auth" : "\ta [password] - authenticate as room operator with operator password",
|
"commandlist-notification/auth" : "\ta [password] - authenticate as room operator with operator password",
|
||||||
"commandlist-notification/chat" : "\tch [message] - send a chat message in a room",
|
"commandlist-notification/chat" : "\tch [message] - send a chat message in a room",
|
||||||
@ -91,13 +91,13 @@ en = {
|
|||||||
|
|
||||||
"gui-data-cleared-notification" : "Syncplay has cleared the path and window state data used by the GUI.",
|
"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.",
|
"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?",
|
"promptforupdate-label" : "Is it okay for Syncplay to automatically check for updates from time to time?",
|
||||||
|
|
||||||
"vlc-interface-version-mismatch": "You are running version {} of the Syncplay interface module for VLC, but Syncplay is designed to run with version {} and above. Please refer to the Syncplay User Guide at https://syncplay.pl/guide/ for instructions on how to install syncplay.lua.", # VLC interface version, VLC interface min version
|
"vlc-interface-version-mismatch": "You are running version {} of the Syncplay interface module for VLC, but Syncplay is designed to run with version {} and above. Please refer to the Syncplay User Guide at https://syncplay.pl/guide/ for instructions on how to install syncplay.lua.", # 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 https://syncplay.pl/guide/ for instructions on how to install syncplay.lua.",
|
"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 https://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 https://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 https://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
|
"media-player-latency-warning": "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
|
"mpv-unresponsive-error": "mpv has not responded for {} seconds so appears to have malfunctioned. Please restart Syncplay.", # Seconds to respond
|
||||||
|
|
||||||
# Client prompts
|
# Client prompts
|
||||||
"enter-to-exit-prompt" : "Press enter to exit\n",
|
"enter-to-exit-prompt" : "Press enter to exit\n",
|
||||||
@ -133,26 +133,26 @@ en = {
|
|||||||
"vlc-failed-noscript": "VLC has reported that the syncplay.lua interface script has not been installed. Please refer to https://syncplay.pl/LUA/ for instructions.",
|
"vlc-failed-noscript": "VLC has reported that the syncplay.lua interface script has not been installed. Please refer to https://syncplay.pl/LUA/ for instructions.",
|
||||||
"vlc-failed-versioncheck": "This version of VLC is not supported by Syncplay.",
|
"vlc-failed-versioncheck": "This version of VLC is not supported by Syncplay.",
|
||||||
|
|
||||||
"feature-sharedPlaylists" : u"shared playlists", # used for not-supported-by-server-error
|
"feature-sharedPlaylists" : "shared playlists", # used for not-supported-by-server-error
|
||||||
"feature-chat" : u"chat", # used for not-supported-by-server-error
|
"feature-chat" : "chat", # used for not-supported-by-server-error
|
||||||
"feature-readiness" : u"readiness", # used for not-supported-by-server-error
|
"feature-readiness" : "readiness", # used for not-supported-by-server-error
|
||||||
"feature-managedRooms" : u"managed rooms", # used for not-supported-by-server-error
|
"feature-managedRooms" : "managed rooms", # used for not-supported-by-server-error
|
||||||
|
|
||||||
"not-supported-by-server-error" : u"The {} feature is not supported by this server..", #feature
|
"not-supported-by-server-error" : "The {} feature is not supported by this server..", #feature
|
||||||
"shared-playlists-not-supported-by-server-error" : "The shared playlists feature may not be supported by the server. To ensure that it works correctly requires a server running Syncplay {}+, but the server is running Syncplay {}.", #minVersion, serverVersion
|
"shared-playlists-not-supported-by-server-error" : "The shared playlists feature may not be supported by the server. To ensure that it works correctly requires a server running Syncplay {}+, but the server is running Syncplay {}.", #minVersion, serverVersion
|
||||||
"shared-playlists-disabled-by-server-error" : "The shared playlist feature has been disabled in the server configuration. To use this feature you will need to connect to a different server.",
|
"shared-playlists-disabled-by-server-error" : "The shared playlist feature has been disabled in the server configuration. To use this feature you will need to connect to a different server.",
|
||||||
|
|
||||||
"invalid-seek-value" : u"Invalid seek value",
|
"invalid-seek-value" : "Invalid seek value",
|
||||||
"invalid-offset-value" : u"Invalid offset value",
|
"invalid-offset-value" : "Invalid offset value",
|
||||||
|
|
||||||
"switch-file-not-found-error" : u"Could not switch to file '{0}'. Syncplay looks in specified media directories.", # File not found
|
"switch-file-not-found-error" : "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. If the folder is actually fine then you can re-enable it by selecting File->Set Media Directories and pressing 'OK'.", #Folder
|
"folder-search-timeout-error" : "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. If the folder is actually fine then you can re-enable it by selecting File->Set Media Directories and pressing 'OK'.", #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
|
"folder-search-first-file-timeout-error" : "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
|
"added-file-not-in-media-directory-error" : "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.",
|
"no-media-directories-error" : "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.",
|
"cannot-find-directory-error" : "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.",
|
||||||
|
|
||||||
"failed-to-load-server-list-error" : u"Failed to load public server list. Please visit https://www.syncplay.pl/ in your browser.",
|
"failed-to-load-server-list-error" : "Failed to load public server list. Please visit https://www.syncplay.pl/ in your browser.",
|
||||||
|
|
||||||
# Client arguments
|
# Client arguments
|
||||||
"argument-description" : 'Solution to synchronize playback of multiple media player instances over the network.',
|
"argument-description" : 'Solution to synchronize playback of multiple media player instances over the network.',
|
||||||
@ -188,7 +188,7 @@ en = {
|
|||||||
"media-path-label" : "Path to video (optional):",
|
"media-path-label" : "Path to video (optional):",
|
||||||
"player-arguments-label" : "Player arguments (if any):",
|
"player-arguments-label" : "Player arguments (if any):",
|
||||||
"browse-label" : "Browse",
|
"browse-label" : "Browse",
|
||||||
"update-server-list-label" : u"Update list",
|
"update-server-list-label" : "Update list",
|
||||||
|
|
||||||
"more-title" : "Show more settings",
|
"more-title" : "Show more settings",
|
||||||
"never-rewind-value" : "Never",
|
"never-rewind-value" : "Never",
|
||||||
@ -203,9 +203,9 @@ en = {
|
|||||||
"rewindondesync-label" : "Rewind on major desync (recommended)",
|
"rewindondesync-label" : "Rewind on major desync (recommended)",
|
||||||
"fastforwardondesync-label" : "Fast-forward if lagging behind (recommended)",
|
"fastforwardondesync-label" : "Fast-forward if lagging behind (recommended)",
|
||||||
"dontslowdownwithme-label" : "Never slow down or rewind others (experimental)",
|
"dontslowdownwithme-label" : "Never slow down or rewind others (experimental)",
|
||||||
"pausing-title" : u"Pausing",
|
"pausing-title" : "Pausing",
|
||||||
"pauseonleave-label" : "Pause when user leaves (e.g. if they are disconnected)",
|
"pauseonleave-label" : "Pause when user leaves (e.g. if they are disconnected)",
|
||||||
"readiness-title" : u"Initial readiness state",
|
"readiness-title" : "Initial readiness state",
|
||||||
"readyatstart-label" : "Set me as 'ready to watch' by default",
|
"readyatstart-label" : "Set me as 'ready to watch' by default",
|
||||||
"forceguiprompt-label" : "Don't always show the Syncplay configuration window", # (Inverted)
|
"forceguiprompt-label" : "Don't always show the Syncplay configuration window", # (Inverted)
|
||||||
"showosd-label" : "Enable OSD Messages",
|
"showosd-label" : "Enable OSD Messages",
|
||||||
@ -216,52 +216,52 @@ en = {
|
|||||||
"showdifferentroomosd-label" : "Include events in other rooms",
|
"showdifferentroomosd-label" : "Include events in other rooms",
|
||||||
"showslowdownosd-label" :"Include slowing down / reverting notifications",
|
"showslowdownosd-label" :"Include slowing down / reverting notifications",
|
||||||
"language-label" : "Language:",
|
"language-label" : "Language:",
|
||||||
"automatic-language" : u"Default ({})", # Default language
|
"automatic-language" : "Default ({})", # Default language
|
||||||
"showdurationnotification-label" : "Warn about media duration mismatches",
|
"showdurationnotification-label" : "Warn about media duration mismatches",
|
||||||
"basics-label" : "Basics",
|
"basics-label" : "Basics",
|
||||||
"readiness-label" : u"Play/Pause",
|
"readiness-label" : "Play/Pause",
|
||||||
"misc-label" : u"Misc",
|
"misc-label" : "Misc",
|
||||||
"core-behaviour-title" : "Core room behaviour",
|
"core-behaviour-title" : "Core room behaviour",
|
||||||
"syncplay-internals-title" : u"Syncplay internals",
|
"syncplay-internals-title" : "Syncplay internals",
|
||||||
"syncplay-mediasearchdirectories-title" : u"Directories to search for media",
|
"syncplay-mediasearchdirectories-title" : "Directories to search for media",
|
||||||
"syncplay-mediasearchdirectories-label" : u"Directories to search for media (one path per line)",
|
"syncplay-mediasearchdirectories-label" : "Directories to search for media (one path per line)",
|
||||||
"sync-label" : "Sync",
|
"sync-label" : "Sync",
|
||||||
"sync-otherslagging-title" : "If others are lagging behind...",
|
"sync-otherslagging-title" : "If others are lagging behind...",
|
||||||
"sync-youlaggging-title" : "If you are lagging behind...",
|
"sync-youlaggging-title" : "If you are lagging behind...",
|
||||||
"messages-label" : "Messages",
|
"messages-label" : "Messages",
|
||||||
"messages-osd-title" : "On-screen Display settings",
|
"messages-osd-title" : "On-screen Display settings",
|
||||||
"messages-other-title" : "Other display settings",
|
"messages-other-title" : "Other display settings",
|
||||||
"chat-label" : u"Chat",
|
"chat-label" : "Chat",
|
||||||
"privacy-label" : "Privacy", # Currently unused, but will be brought back if more space is needed in Misc tab
|
"privacy-label" : "Privacy", # Currently unused, but will be brought back if more space is needed in Misc tab
|
||||||
"privacy-title" : "Privacy settings",
|
"privacy-title" : "Privacy settings",
|
||||||
"unpause-title" : u"If you press play, set as ready and:",
|
"unpause-title" : "If you press play, set as ready and:",
|
||||||
"unpause-ifalreadyready-option" : u"Unpause if already set as ready",
|
"unpause-ifalreadyready-option" : "Unpause if already set as ready",
|
||||||
"unpause-ifothersready-option" : u"Unpause if already ready or others in room are ready (default)",
|
"unpause-ifothersready-option" : "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-ifminusersready-option" : "Unpause if already ready or if all others ready and min users ready",
|
||||||
"unpause-always" : u"Always unpause",
|
"unpause-always" : "Always unpause",
|
||||||
"syncplay-trusteddomains-title": u"Trusted domains (for streaming services and hosted content)",
|
"syncplay-trusteddomains-title": "Trusted domains (for streaming services and hosted content)",
|
||||||
|
|
||||||
"chat-title" : u"Chat message input",
|
"chat-title" : "Chat message input",
|
||||||
"chatinputenabled-label" : u"Enable chat input via mpv",
|
"chatinputenabled-label" : "Enable chat input via mpv",
|
||||||
"chatdirectinput-label" : u"Allow instant chat input (bypass having to press enter key to chat)",
|
"chatdirectinput-label" : "Allow instant chat input (bypass having to press enter key to chat)",
|
||||||
"chatinputfont-label" : u"Chat input font",
|
"chatinputfont-label" : "Chat input font",
|
||||||
"chatfont-label" : u"Set font",
|
"chatfont-label" : "Set font",
|
||||||
"chatcolour-label" : u"Set colour",
|
"chatcolour-label" : "Set colour",
|
||||||
"chatinputposition-label" : u"Position of message input area in mpv",
|
"chatinputposition-label" : "Position of message input area in mpv",
|
||||||
"chat-top-option" : u"Top",
|
"chat-top-option" : "Top",
|
||||||
"chat-middle-option" : u"Middle",
|
"chat-middle-option" : "Middle",
|
||||||
"chat-bottom-option" : u"Bottom",
|
"chat-bottom-option" : "Bottom",
|
||||||
"chatoutputheader-label" : u"Chat message output",
|
"chatoutputheader-label" : "Chat message output",
|
||||||
"chatoutputfont-label": u"Chat output font",
|
"chatoutputfont-label": "Chat output font",
|
||||||
"chatoutputenabled-label": u"Enable chat output in media player (mpv only for now)",
|
"chatoutputenabled-label": "Enable chat output in media player (mpv only for now)",
|
||||||
"chatoutputposition-label": u"Output mode",
|
"chatoutputposition-label": "Output mode",
|
||||||
"chat-chatroom-option": u"Chatroom style",
|
"chat-chatroom-option": "Chatroom style",
|
||||||
"chat-scrolling-option": u"Scrolling style",
|
"chat-scrolling-option": "Scrolling style",
|
||||||
|
|
||||||
"mpv-key-tab-hint": u"[TAB] to toggle access to alphabet row key shortcuts.",
|
"mpv-key-tab-hint": "[TAB] to toggle access to alphabet row key shortcuts.",
|
||||||
"mpv-key-hint": u"[ENTER] to send message. [ESC] to escape chat mode.",
|
"mpv-key-hint": "[ENTER] to send message. [ESC] to escape chat mode.",
|
||||||
"alphakey-mode-warning-first-line": u"You can temporarily use old mpv bindings with a-z keys.",
|
"alphakey-mode-warning-first-line": "You can temporarily use old mpv bindings with a-z keys.",
|
||||||
"alphakey-mode-warning-second-line": u"Press [TAB] to return to Syncplay chat mode.",
|
"alphakey-mode-warning-second-line": "Press [TAB] to return to Syncplay chat mode.",
|
||||||
|
|
||||||
"help-label" : "Help",
|
"help-label" : "Help",
|
||||||
"reset-label" : "Restore defaults",
|
"reset-label" : "Restore defaults",
|
||||||
@ -271,19 +271,19 @@ en = {
|
|||||||
"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=\"https://syncplay.pl/\"><nobr>https://syncplay.pl/</nobr></a>. NOTE: Chat messages are not encrypted so do not use Syncplay to send sensitive information.",
|
"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=\"https://syncplay.pl/\"><nobr>https://syncplay.pl/</nobr></a>. NOTE: Chat messages are not encrypted so do not use Syncplay to send sensitive information.",
|
||||||
|
|
||||||
"joinroom-label" : "Join room",
|
"joinroom-label" : "Join room",
|
||||||
"joinroom-menu-label" : u"Join room {}",
|
"joinroom-menu-label" : "Join room {}",
|
||||||
"seektime-menu-label" : "Seek to time",
|
"seektime-menu-label" : "Seek to time",
|
||||||
"undoseek-menu-label" : "Undo seek",
|
"undoseek-menu-label" : "Undo seek",
|
||||||
"play-menu-label" : "Play",
|
"play-menu-label" : "Play",
|
||||||
"pause-menu-label" : "Pause",
|
"pause-menu-label" : "Pause",
|
||||||
"playbackbuttons-menu-label" : u"Show playback buttons",
|
"playbackbuttons-menu-label" : "Show playback buttons",
|
||||||
"autoplay-menu-label" : u"Show auto-play button",
|
"autoplay-menu-label" : "Show auto-play button",
|
||||||
"autoplay-guipushbuttonlabel" : u"Play when all ready",
|
"autoplay-guipushbuttonlabel" : "Play when all ready",
|
||||||
"autoplay-minimum-label" : u"Min users:",
|
"autoplay-minimum-label" : "Min users:",
|
||||||
|
|
||||||
"sendmessage-label" : u"Send",
|
"sendmessage-label" : "Send",
|
||||||
|
|
||||||
"ready-guipushbuttonlabel" : u"I'm ready to watch!",
|
"ready-guipushbuttonlabel" : "I'm ready to watch!",
|
||||||
|
|
||||||
"roomuser-heading-label" : "Room / User",
|
"roomuser-heading-label" : "Room / User",
|
||||||
"size-heading-label" : "Size",
|
"size-heading-label" : "Size",
|
||||||
@ -297,29 +297,29 @@ en = {
|
|||||||
"file-menu-label" : "&File", # & precedes shortcut key
|
"file-menu-label" : "&File", # & precedes shortcut key
|
||||||
"openmedia-menu-label" : "&Open media file",
|
"openmedia-menu-label" : "&Open media file",
|
||||||
"openstreamurl-menu-label" : "Open &media stream URL",
|
"openstreamurl-menu-label" : "Open &media stream URL",
|
||||||
"setmediadirectories-menu-label" : u"Set media &directories",
|
"setmediadirectories-menu-label" : "Set media &directories",
|
||||||
"exit-menu-label" : "E&xit",
|
"exit-menu-label" : "E&xit",
|
||||||
"advanced-menu-label" : "&Advanced",
|
"advanced-menu-label" : "&Advanced",
|
||||||
"window-menu-label" : "&Window",
|
"window-menu-label" : "&Window",
|
||||||
"setoffset-menu-label" : "Set &offset",
|
"setoffset-menu-label" : "Set &offset",
|
||||||
"createcontrolledroom-menu-label" : "&Create managed room",
|
"createcontrolledroom-menu-label" : "&Create managed room",
|
||||||
"identifyascontroller-menu-label" : "&Identify as room operator",
|
"identifyascontroller-menu-label" : "&Identify as room operator",
|
||||||
"settrusteddomains-menu-label" : u"Set &trusted domains",
|
"settrusteddomains-menu-label" : "Set &trusted domains",
|
||||||
"addtrusteddomain-menu-label" : u"Add {} as trusted domain", # Domain
|
"addtrusteddomain-menu-label" : "Add {} as trusted domain", # Domain
|
||||||
|
|
||||||
"playback-menu-label" : u"&Playback",
|
"playback-menu-label" : "&Playback",
|
||||||
|
|
||||||
"help-menu-label" : "&Help",
|
"help-menu-label" : "&Help",
|
||||||
"userguide-menu-label" : "Open user &guide",
|
"userguide-menu-label" : "Open user &guide",
|
||||||
"update-menu-label" : "Check for &update",
|
"update-menu-label" : "Check for &update",
|
||||||
|
|
||||||
#About dialog
|
#About dialog
|
||||||
"about-menu-label": u"&About Syncplay",
|
"about-menu-label": "&About Syncplay",
|
||||||
"about-dialog-title": u"About Syncplay",
|
"about-dialog-title": "About Syncplay",
|
||||||
"about-dialog-release": u"Version {} release {}",
|
"about-dialog-release": "Version {} release {}",
|
||||||
"about-dialog-license-text" : u"Licensed under the Apache License, Version 2.0",
|
"about-dialog-license-text" : "Licensed under the Apache License, Version 2.0",
|
||||||
"about-dialog-license-button": u"License",
|
"about-dialog-license-button": "License",
|
||||||
"about-dialog-dependencies": u"Dependencies",
|
"about-dialog-dependencies": "Dependencies",
|
||||||
|
|
||||||
"setoffset-msgbox-label" : "Set offset",
|
"setoffset-msgbox-label" : "Set offset",
|
||||||
"offsetinfo-msgbox-label" : "Offset (see https://syncplay.pl/guide/ for usage instructions):",
|
"offsetinfo-msgbox-label" : "Offset (see https://syncplay.pl/guide/ for usage instructions):",
|
||||||
@ -327,11 +327,11 @@ en = {
|
|||||||
"promptforstreamurl-msgbox-label" : "Open media stream URL",
|
"promptforstreamurl-msgbox-label" : "Open media stream URL",
|
||||||
"promptforstreamurlinfo-msgbox-label" : "Stream URL",
|
"promptforstreamurlinfo-msgbox-label" : "Stream URL",
|
||||||
|
|
||||||
"addfolder-label" : u"Add folder",
|
"addfolder-label" : "Add folder",
|
||||||
|
|
||||||
"adduris-msgbox-label" : u"Add URLs to playlist (one per line)",
|
"adduris-msgbox-label" : "Add URLs to playlist (one per line)",
|
||||||
"editplaylist-msgbox-label" : u"Set playlist (one per line)",
|
"editplaylist-msgbox-label" : "Set playlist (one per line)",
|
||||||
"trusteddomains-msgbox-label" : u"Domains it is okay to automatically switch to (one per line)",
|
"trusteddomains-msgbox-label" : "Domains it is okay to automatically switch to (one per line)",
|
||||||
|
|
||||||
"createcontrolledroom-msgbox-label" : "Create managed room",
|
"createcontrolledroom-msgbox-label" : "Create managed room",
|
||||||
"controlledroominfo-msgbox-label" : "Enter name of managed room\r\n(see https://syncplay.pl/guide/ for usage instructions):",
|
"controlledroominfo-msgbox-label" : "Enter name of managed room\r\n(see https://syncplay.pl/guide/ for usage instructions):",
|
||||||
@ -339,7 +339,7 @@ en = {
|
|||||||
"identifyascontroller-msgbox-label" : "Identify as room operator",
|
"identifyascontroller-msgbox-label" : "Identify as room operator",
|
||||||
"identifyinfo-msgbox-label" : "Enter operator password for this room\r\n(see https://syncplay.pl/guide/ for usage instructions):",
|
"identifyinfo-msgbox-label" : "Enter operator password for this room\r\n(see https://syncplay.pl/guide/ for usage instructions):",
|
||||||
|
|
||||||
"public-server-msgbox-label" : u"Select the public server for this viewing session",
|
"public-server-msgbox-label" : "Select the public server for this viewing session",
|
||||||
|
|
||||||
"megabyte-suffix" : " MB",
|
"megabyte-suffix" : " MB",
|
||||||
|
|
||||||
@ -353,7 +353,7 @@ en = {
|
|||||||
"executable-path-tooltip" : "Location of your chosen supported media player (mpv, VLC, MPC-HC/BE or mplayer2).",
|
"executable-path-tooltip" : "Location of your chosen supported media player (mpv, VLC, MPC-HC/BE or mplayer2).",
|
||||||
"media-path-tooltip" : "Location of video or stream to be opened. Necessary for mplayer2.",
|
"media-path-tooltip" : "Location of video or stream to be opened. Necessary for mplayer2.",
|
||||||
"player-arguments-tooltip" : "Additional command line arguments / switches to pass on to this media player.",
|
"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.",
|
"mediasearcdirectories-arguments-tooltip" : "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.",
|
||||||
|
|
||||||
"more-tooltip" : "Display less frequently used settings.",
|
"more-tooltip" : "Display less frequently used settings.",
|
||||||
"filename-privacy-tooltip" : "Privacy mode for sending currently playing filename to server.",
|
"filename-privacy-tooltip" : "Privacy mode for sending currently playing filename to server.",
|
||||||
@ -377,39 +377,39 @@ en = {
|
|||||||
"showdifferentroomosd-tooltip" : "Show OSD notifications for events relating to room user is not in.",
|
"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.",
|
"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.",
|
"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.",
|
"language-tooltip" : "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-always-tooltip" : "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-ifalreadyready-tooltip" : "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-ifothersready-tooltip" : "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 unpause if others are ready and minimum users threshold is met.",
|
"unpause-ifminusersready-tooltip" : "If you press unpause when not ready, it will only unpause 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.",
|
"trusteddomains-arguments-tooltip" : "Domains that it is okay for Syncplay to automatically switch to when shared playlists is enabled.",
|
||||||
|
|
||||||
"chatinputenabled-tooltip" : u"Enable chat input in mpv (press enter to chat, enter to send, escape to cancel)",
|
"chatinputenabled-tooltip" : "Enable chat input in mpv (press enter to chat, enter to send, escape to cancel)",
|
||||||
"chatdirectinput-tooltip" : u"Skip having to press 'enter' to go into chat input mode in mpv. Press TAB in mpv to temporarily disable this feature.",
|
"chatdirectinput-tooltip" : "Skip having to press 'enter' to go into chat input mode in mpv. Press TAB in mpv to temporarily disable this feature.",
|
||||||
"font-label-tooltip" : u"Font used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",
|
"font-label-tooltip" : "Font used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",
|
||||||
"set-input-font-tooltip" : u"Font family used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",
|
"set-input-font-tooltip" : "Font family used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",
|
||||||
"set-input-colour-tooltip" : u"Font colour used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",
|
"set-input-colour-tooltip" : "Font colour used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",
|
||||||
"chatinputposition-tooltip" : u"Location in mpv where chat input text will appear when you press enter and type.",
|
"chatinputposition-tooltip" : "Location in mpv where chat input text will appear when you press enter and type.",
|
||||||
"chatinputposition-top-tooltip" : u"Place chat input at top of mpv window.",
|
"chatinputposition-top-tooltip" : "Place chat input at top of mpv window.",
|
||||||
"chatinputposition-middle-tooltip" : u"Place chat input in dead centre of mpv window.",
|
"chatinputposition-middle-tooltip" : "Place chat input in dead centre of mpv window.",
|
||||||
"chatinputposition-bottom-tooltip" : u"Place chat input at bottom of mpv window.",
|
"chatinputposition-bottom-tooltip" : "Place chat input at bottom of mpv window.",
|
||||||
"chatoutputenabled-tooltip": u"Show chat messages in OSD (if supported by media player).",
|
"chatoutputenabled-tooltip": "Show chat messages in OSD (if supported by media player).",
|
||||||
"font-output-label-tooltip": u"Chat output font.",
|
"font-output-label-tooltip": "Chat output font.",
|
||||||
"set-output-font-tooltip": u"Font used for when displaying chat messages.",
|
"set-output-font-tooltip": "Font used for when displaying chat messages.",
|
||||||
"chatoutputmode-tooltip": u"How chat messages are displayed.",
|
"chatoutputmode-tooltip": "How chat messages are displayed.",
|
||||||
"chatoutputmode-chatroom-tooltip": u"Display new lines of chat directly below previous line.",
|
"chatoutputmode-chatroom-tooltip": "Display new lines of chat directly below previous line.",
|
||||||
"chatoutputmode-scrolling-tooltip": u"Scroll chat text from right to left.",
|
"chatoutputmode-scrolling-tooltip": "Scroll chat text from right to left.",
|
||||||
|
|
||||||
"help-tooltip" : "Opens the Syncplay.pl user guide.",
|
"help-tooltip" : "Opens the Syncplay.pl user guide.",
|
||||||
"reset-tooltip" : "Reset all settings to the default configuration.",
|
"reset-tooltip" : "Reset all settings to the default configuration.",
|
||||||
"update-server-list-tooltip" : u"Connect to syncplay.pl to update list of public servers.",
|
"update-server-list-tooltip" : "Connect to syncplay.pl to update list of public servers.",
|
||||||
|
|
||||||
"joinroom-tooltip" : "Leave current room and joins specified 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.",
|
"seektime-msgbox-label" : "Jump to specified time (in seconds / min:sec). Use +/- for relative seek.",
|
||||||
"ready-tooltip" : "Indicates whether you are ready to watch.",
|
"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.",
|
"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
|
"switch-to-file-tooltip" : "Double click to switch to {}", # Filename
|
||||||
"sendmessage-tooltip" : u"Send message to room",
|
"sendmessage-tooltip" : "Send message to room",
|
||||||
|
|
||||||
# In-userlist notes (GUI)
|
# In-userlist notes (GUI)
|
||||||
"differentsize-note" : "Different size!",
|
"differentsize-note" : "Different size!",
|
||||||
@ -422,8 +422,8 @@ en = {
|
|||||||
|
|
||||||
# Server notifications
|
# Server notifications
|
||||||
"welcome-server-notification" : "Welcome to Syncplay server, ver. {0}", # version
|
"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-connected-room-server-notification" : "{0}({2}) connected to room '{1}'", # username, host, room
|
||||||
"client-left-server-notification" : u"{0} left server", # name
|
"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
|
"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
|
||||||
|
|
||||||
|
|
||||||
@ -434,46 +434,46 @@ en = {
|
|||||||
"server-password-argument" : 'server password',
|
"server-password-argument" : 'server password',
|
||||||
"server-isolate-room-argument" : 'should rooms be isolated?',
|
"server-isolate-room-argument" : 'should rooms be isolated?',
|
||||||
"server-salt-argument" : "random string used to generate managed room passwords",
|
"server-salt-argument" : "random string used to generate managed room passwords",
|
||||||
"server-disable-ready-argument" : u"disable readiness feature",
|
"server-disable-ready-argument" : "disable readiness feature",
|
||||||
"server-motd-argument": "path to file from which motd will be fetched",
|
"server-motd-argument": "path to file from which motd will be fetched",
|
||||||
"server-chat-argument" : "Should chat be disabled?",
|
"server-chat-argument" : "Should chat be disabled?",
|
||||||
"server-chat-maxchars-argument" : u"Maximum number of characters in a chat message (default is {})", # Default number of characters
|
"server-chat-maxchars-argument" : "Maximum number of characters in a chat message (default is {})", # Default number of characters
|
||||||
"server-maxusernamelength-argument" : u"Maximum number of charactrs in a username (default is {})",
|
"server-maxusernamelength-argument" : "Maximum number of charactrs in a username (default is {})",
|
||||||
"server-messed-up-motd-unescaped-placeholders": "Message of the Day has unescaped placeholders. All $ signs should be doubled ($$).",
|
"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-messed-up-motd-too-long": "Message of the Day is too long - maximum of {} chars, {} given.",
|
||||||
|
|
||||||
# Server errors
|
# Server errors
|
||||||
"unknown-command-server-error" : u"Unknown command {}", # message
|
"unknown-command-server-error" : "Unknown command {}", # message
|
||||||
"not-json-server-error" : "Not a json encoded string {}", # 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",
|
"not-known-server-error" : "You must be known to server before sending this command",
|
||||||
"client-drop-server-error" : u"Client drop: {} -- {}", # host, error
|
"client-drop-server-error" : "Client drop: {} -- {}", # host, error
|
||||||
"password-required-server-error" : "Password required",
|
"password-required-server-error" : "Password required",
|
||||||
"wrong-password-server-error" : "Wrong password supplied",
|
"wrong-password-server-error" : "Wrong password supplied",
|
||||||
"hello-server-error" : "Not enough Hello arguments", #DO NOT TRANSLATE
|
"hello-server-error" : "Not enough Hello arguments", #DO NOT TRANSLATE
|
||||||
|
|
||||||
# Playlists
|
# Playlists
|
||||||
"playlist-selection-changed-notification" : u"{} changed the playlist selection", # Username
|
"playlist-selection-changed-notification" : "{} changed the playlist selection", # Username
|
||||||
"playlist-contents-changed-notification" : u"{} updated the playlist", # Username
|
"playlist-contents-changed-notification" : "{} updated the playlist", # Username
|
||||||
"cannot-find-file-for-playlist-switch-error" : u"Could not find file {} in media directories for playlist switch!", # Filename
|
"cannot-find-file-for-playlist-switch-error" : "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-duplicate-error" : "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. If you right click on a URL then you can add its domain as a trusted domain via the context menu.", # Filename
|
"cannot-add-unsafe-path-error" : "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. If you right click on a URL then you can add its domain as a trusted domain via the context menu.", # Filename
|
||||||
"sharedplaylistenabled-label" : u"Enable shared playlists",
|
"sharedplaylistenabled-label" : "Enable shared playlists",
|
||||||
"removefromplaylist-menu-label" : u"Remove from playlist",
|
"removefromplaylist-menu-label" : "Remove from playlist",
|
||||||
"shuffleremainingplaylist-menu-label" : u"Shuffle remaining playlist",
|
"shuffleremainingplaylist-menu-label" : "Shuffle remaining playlist",
|
||||||
"shuffleentireplaylist-menu-label" : u"Shuffle entire playlist",
|
"shuffleentireplaylist-menu-label" : "Shuffle entire playlist",
|
||||||
"undoplaylist-menu-label" : u"Undo last change to playlist",
|
"undoplaylist-menu-label" : "Undo last change to playlist",
|
||||||
"addfilestoplaylist-menu-label" : u"Add file(s) to bottom of playlist",
|
"addfilestoplaylist-menu-label" : "Add file(s) to bottom of playlist",
|
||||||
"addurlstoplaylist-menu-label" : u"Add URL(s) to bottom of playlist",
|
"addurlstoplaylist-menu-label" : "Add URL(s) to bottom of playlist",
|
||||||
"editplaylist-menu-label": u"Edit playlist",
|
"editplaylist-menu-label": "Edit playlist",
|
||||||
|
|
||||||
"open-containing-folder": u"Open folder containing this file",
|
"open-containing-folder": "Open folder containing this file",
|
||||||
"addusersfiletoplaylist-menu-label" : u"Add {} file to playlist", # item owner indicator
|
"addusersfiletoplaylist-menu-label" : "Add {} file to playlist", # item owner indicator
|
||||||
"addusersstreamstoplaylist-menu-label" : u"Add {} stream to playlist", # item owner indicator
|
"addusersstreamstoplaylist-menu-label" : "Add {} stream to playlist", # item owner indicator
|
||||||
"openusersstream-menu-label" : u"Open {} stream", # [username]'s
|
"openusersstream-menu-label" : "Open {} stream", # [username]'s
|
||||||
"openusersfile-menu-label" : u"Open {} file", # [username]'s
|
"openusersfile-menu-label" : "Open {} file", # [username]'s
|
||||||
"item-is-yours-indicator" : u"your", # Goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
"item-is-yours-indicator" : "your", # Goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
||||||
"item-is-others-indicator" : u"{}'s", # username - goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
"item-is-others-indicator" : "{}'s", # username - goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
||||||
|
|
||||||
"playlist-instruction-item-message" : u"Drag file here to add it to the shared playlist.",
|
"playlist-instruction-item-message" : "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'.",
|
"sharedplaylistenabled-tooltip" : "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'.",
|
||||||
}
|
}
|
||||||
|
|||||||
772
syncplay/messages_it.py
Normal file → Executable file
772
syncplay/messages_it.py
Normal file → Executable file
@ -3,477 +3,477 @@
|
|||||||
"""Italian dictionary"""
|
"""Italian dictionary"""
|
||||||
|
|
||||||
it = {
|
it = {
|
||||||
"LANGUAGE" : u"Italiano",
|
"LANGUAGE" : "Italiano",
|
||||||
|
|
||||||
# Client notifications
|
# Client notifications
|
||||||
"config-cleared-notification" : u"Impostazioni iniziali ripristinate. I cambiamenti saranno memorizzati quando salverai una configurazione valida.",
|
"config-cleared-notification" : "Impostazioni iniziali ripristinate. I cambiamenti saranno memorizzati quando salverai una configurazione valida.",
|
||||||
|
|
||||||
"relative-config-notification" : u"Caricato i file di configurazione relativi: {}",
|
"relative-config-notification" : "Caricato i file di configurazione relativi: {}",
|
||||||
|
|
||||||
"connection-attempt-notification" : u"Tentativo di connessione a {}:{}", # Port, IP
|
"connection-attempt-notification" : "Tentativo di connessione a {}:{}", # Port, IP
|
||||||
"reconnection-attempt-notification" : u"Connessione col server persa, tentativo di riconnesione in corso",
|
"reconnection-attempt-notification" : "Connessione col server persa, tentativo di riconnesione in corso",
|
||||||
"disconnection-notification" : u"Disconnesso dal server",
|
"disconnection-notification" : "Disconnesso dal server",
|
||||||
"connection-failed-notification" : u"Connessione col server fallita",
|
"connection-failed-notification" : "Connessione col server fallita",
|
||||||
"connected-successful-notification" : u"Connessione al server effettuata con successo",
|
"connected-successful-notification" : "Connessione al server effettuata con successo",
|
||||||
"retrying-notification" : u"%s, Nuovo tentativo in %d secondi...", # Seconds
|
"retrying-notification" : "%s, Nuovo tentativo in %d secondi...", # Seconds
|
||||||
|
|
||||||
"rewind-notification" : u"Riavvolgo a causa della differenza temporale con {}", # User
|
"rewind-notification" : "Riavvolgo a causa della differenza temporale con {}", # User
|
||||||
"fastforward-notification" : u"Avanzamento rapido a causa della differenza temporale con {}", # User
|
"fastforward-notification" : "Avanzamento rapido a causa della differenza temporale con {}", # User
|
||||||
"slowdown-notification" : u"Rallento a causa della differenza temporale con {}", # User
|
"slowdown-notification" : "Rallento a causa della differenza temporale con {}", # User
|
||||||
"revert-notification" : u"Ripristino la velocità di riproduzione normale",
|
"revert-notification" : "Ripristino la velocità di riproduzione normale",
|
||||||
|
|
||||||
"pause-notification" : u"{} ha messo in pausa", # User
|
"pause-notification" : "{} ha messo in pausa", # User
|
||||||
"unpause-notification" : u"{} ha ripreso la riproduzione", # User
|
"unpause-notification" : "{} ha ripreso la riproduzione", # User
|
||||||
"seek-notification" : u"{} è passato da {} a {}", # User, from time, to time
|
"seek-notification" : "{} è passato da {} a {}", # User, from time, to time
|
||||||
|
|
||||||
"current-offset-notification" : u"Offset corrente: {} secondi", # Offset
|
"current-offset-notification" : "Offset corrente: {} secondi", # Offset
|
||||||
|
|
||||||
"media-directory-list-updated-notification" : u"Le cartelle multimediali di Syncplay sono state aggiornate.",
|
"media-directory-list-updated-notification" : "Le cartelle multimediali di Syncplay sono state aggiornate.",
|
||||||
|
|
||||||
"room-join-notification" : u"{} è entranto nella stanza: '{}'", # User
|
"room-join-notification" : "{} è entranto nella stanza: '{}'", # User
|
||||||
"left-notification" : u"{} ha lasciato la stanza", # User
|
"left-notification" : "{} ha lasciato la stanza", # User
|
||||||
"left-paused-notification" : u"{} ha lasciato la stanza, {} ha messo in pausa", # User who left, User who paused
|
"left-paused-notification" : "{} ha lasciato la stanza, {} ha messo in pausa", # User who left, User who paused
|
||||||
"playing-notification" : u"{} sta riproducendo '{}' ({})", # User, file, duration
|
"playing-notification" : "{} sta riproducendo '{}' ({})", # User, file, duration
|
||||||
"playing-notification/room-addendum" : u" nella stanza: '{}'", # Room
|
"playing-notification/room-addendum" : " nella stanza: '{}'", # Room
|
||||||
|
|
||||||
"not-all-ready" : u"Non pronti: {}", # Usernames
|
"not-all-ready" : "Non pronti: {}", # Usernames
|
||||||
"all-users-ready" : u"Tutti i partecipanti sono pronti ({} utenti)", #Number of ready users
|
"all-users-ready" : "Tutti i partecipanti sono pronti ({} utenti)", #Number of ready users
|
||||||
"ready-to-unpause-notification" : u"Ora sei pronto - premi ancora una volta per riprendere la riproduzione",
|
"ready-to-unpause-notification" : "Ora sei pronto - premi ancora una volta per riprendere la riproduzione",
|
||||||
"set-as-ready-notification" : u"Ora sei pronto",
|
"set-as-ready-notification" : "Ora sei pronto",
|
||||||
"set-as-not-ready-notification" : u"Non sei pronto",
|
"set-as-not-ready-notification" : "Non sei pronto",
|
||||||
"autoplaying-notification" : u"Riproduzione automatica in {}...", # Number of seconds until playback will start
|
"autoplaying-notification" : "Riproduzione automatica in {}...", # Number of seconds until playback will start
|
||||||
|
|
||||||
"identifying-as-controller-notification" : u"Ti sei identificato come gestore della stanza con password '{}'...",
|
"identifying-as-controller-notification" : "Ti sei identificato come gestore della stanza con password '{}'...",
|
||||||
"failed-to-identify-as-controller-notification" : u"{} ha fallito l'identificazione come gestore della stanza.",
|
"failed-to-identify-as-controller-notification" : "{} ha fallito l'identificazione come gestore della stanza.",
|
||||||
"authenticated-as-controller-notification" : u"{} autenticato come gestore della stanza",
|
"authenticated-as-controller-notification" : "{} autenticato come gestore della stanza",
|
||||||
"created-controlled-room-notification" : u"Stanza gestita '{}' creata con password '{}'. Per favore salva queste informazioni per una consultazione futura!", # RoomName, operatorPassword
|
"created-controlled-room-notification" : "Stanza gestita '{}' creata con password '{}'. Per favore salva queste informazioni per una consultazione futura!", # RoomName, operatorPassword
|
||||||
|
|
||||||
"file-different-notification" : u"Il file che stai riproducendo sembra essere diverso da quello di {}", # User
|
"file-different-notification" : "Il file che stai riproducendo sembra essere diverso da quello di {}", # User
|
||||||
"file-differences-notification" : u"Il tuo file mostra le seguenti differenze: {}", # Differences
|
"file-differences-notification" : "Il tuo file mostra le seguenti differenze: {}", # Differences
|
||||||
"room-file-differences" : u"Differenze: {}", # File differences (filename, size, and/or duration)
|
"room-file-differences" : "Differenze: {}", # File differences (filename, size, and/or duration)
|
||||||
"file-difference-filename" : u"nome",
|
"file-difference-filename" : "nome",
|
||||||
"file-difference-filesize" : u"dimensione",
|
"file-difference-filesize" : "dimensione",
|
||||||
"file-difference-duration" : u"durata",
|
"file-difference-duration" : "durata",
|
||||||
"alone-in-the-room": u"Non ci sono altri utenti nella stanza",
|
"alone-in-the-room": "Non ci sono altri utenti nella stanza",
|
||||||
|
|
||||||
"different-filesize-notification" : u" (la dimensione del tuo file è diversa da quella degli altri partecipanti!)",
|
"different-filesize-notification" : " (la dimensione del tuo file è diversa da quella degli altri partecipanti!)",
|
||||||
"userlist-playing-notification" : u"{} sta riproducendo:", #Username
|
"userlist-playing-notification" : "{} sta riproducendo:", #Username
|
||||||
"file-played-by-notification" : u"File: {} è in riproduzione da:", # File
|
"file-played-by-notification" : "File: {} è in riproduzione da:", # File
|
||||||
"no-file-played-notification" : u"{} non sta riproducendo alcun file", # Username
|
"no-file-played-notification" : "{} non sta riproducendo alcun file", # Username
|
||||||
"notplaying-notification" : u"Partecipanti che non stanno riproducendo alcun file:",
|
"notplaying-notification" : "Partecipanti che non stanno riproducendo alcun file:",
|
||||||
"userlist-room-notification" : u"Nella stanza '{}':", # Room
|
"userlist-room-notification" : "Nella stanza '{}':", # Room
|
||||||
"userlist-file-notification" : u"File",
|
"userlist-file-notification" : "File",
|
||||||
"controller-userlist-userflag" : u"Gestore",
|
"controller-userlist-userflag" : "Gestore",
|
||||||
"ready-userlist-userflag" : u"Pronto",
|
"ready-userlist-userflag" : "Pronto",
|
||||||
|
|
||||||
"update-check-failed-notification" : u"Controllo automatico degli aggiornamenti di Syncplay {} fallito. Vuoi visitare https://syncplay.pl/ per verificare manualmente la presenza di aggiornamenti?", #Syncplay version
|
"update-check-failed-notification" : "Controllo automatico degli aggiornamenti di Syncplay {} fallito. Vuoi visitare https://syncplay.pl/ per verificare manualmente la presenza di aggiornamenti?", #Syncplay version
|
||||||
"syncplay-uptodate-notification" : u"Syncplay è aggiornato",
|
"syncplay-uptodate-notification" : "Syncplay è aggiornato",
|
||||||
"syncplay-updateavailable-notification" : u"Una nuova versione di Syncplay è disponibile. Vuoi visitare la pagina delle release?",
|
"syncplay-updateavailable-notification" : "Una nuova versione di Syncplay è disponibile. Vuoi visitare la pagina delle release?",
|
||||||
|
|
||||||
"mplayer-file-required-notification" : u"Utilizzare Syncplay con mplayer di selezionare il file all'avvio",
|
"mplayer-file-required-notification" : "Utilizzare Syncplay con mplayer di selezionare il file all'avvio",
|
||||||
"mplayer-file-required-notification/example" : u"Esempio di utilizzo: syncplay [opzioni] [url|percorso/]nomefile",
|
"mplayer-file-required-notification/example" : "Esempio di utilizzo: syncplay [opzioni] [url|percorso/]nomefile",
|
||||||
"mplayer2-required" : u"Syncplay non è compatibile con MPlayer 1.x, per favore utilizza mplayer2 or mpv",
|
"mplayer2-required" : "Syncplay non è compatibile con MPlayer 1.x, per favore utilizza mplayer2 or mpv",
|
||||||
|
|
||||||
"unrecognized-command-notification" : u"Comando non riconosciuto",
|
"unrecognized-command-notification" : "Comando non riconosciuto",
|
||||||
"commandlist-notification" : u"Comandi disponibili:",
|
"commandlist-notification" : "Comandi disponibili:",
|
||||||
"commandlist-notification/room" : u"\tr [nome] - cambia stanza",
|
"commandlist-notification/room" : "\tr [nome] - cambia stanza",
|
||||||
"commandlist-notification/list" : u"\tl - mostra la lista di utenti",
|
"commandlist-notification/list" : "\tl - mostra la lista di utenti",
|
||||||
"commandlist-notification/undo" : u"\tu - annulla l'ultima ricerca",
|
"commandlist-notification/undo" : "\tu - annulla l'ultima ricerca",
|
||||||
"commandlist-notification/pause" : u"\tp - attiva o disattiva la pausa",
|
"commandlist-notification/pause" : "\tp - attiva o disattiva la pausa",
|
||||||
"commandlist-notification/seek" : u"\t[s][+-]tempo - salta all'istante di tempo dato, se + o - non è specificato si considera il tempo assoluto in secondi o min:sec",
|
"commandlist-notification/seek" : "\t[s][+-]tempo - salta all'istante di tempo dato, se + o - non è specificato si considera il tempo assoluto in secondi o min:sec",
|
||||||
"commandlist-notification/help" : u"\th - mostra questo help",
|
"commandlist-notification/help" : "\th - mostra questo help",
|
||||||
"commandlist-notification/toggle" : u"\tt - attiva o disattiva la funzionalità \"pronto\"",
|
"commandlist-notification/toggle" : "\tt - attiva o disattiva la funzionalità \"pronto\"",
|
||||||
"commandlist-notification/create" : u"\tc [nome] - crea una stanza gestita usando il nome della stanza attuale",
|
"commandlist-notification/create" : "\tc [nome] - crea una stanza gestita usando il nome della stanza attuale",
|
||||||
"commandlist-notification/auth" : u"\ta [password] - autentica come gestore della stanza, utilizzando la password del gestore",
|
"commandlist-notification/auth" : "\ta [password] - autentica come gestore della stanza, utilizzando la password del gestore",
|
||||||
"commandlist-notification/chat" : u"\tch [message] - invia un messaggio nella chat della stanza",
|
"commandlist-notification/chat" : "\tch [message] - invia un messaggio nella chat della stanza",
|
||||||
"syncplay-version-notification" : u"Versione di Syncplay: {}", # syncplay.version
|
"syncplay-version-notification" : "Versione di Syncplay: {}", # syncplay.version
|
||||||
"more-info-notification" : u"Maggiori informazioni a: {}", # projectURL
|
"more-info-notification" : "Maggiori informazioni a: {}", # projectURL
|
||||||
|
|
||||||
"gui-data-cleared-notification" : u"Syncplay ha ripristinato i dati dell'interfaccia relativi ai percorsi e allo stato delle finestre.",
|
"gui-data-cleared-notification" : "Syncplay ha ripristinato i dati dell'interfaccia relativi ai percorsi e allo stato delle finestre.",
|
||||||
"language-changed-msgbox-label" : u"La lingua sarà cambiata quando avvierai Syncplay.",
|
"language-changed-msgbox-label" : "La lingua sarà cambiata quando avvierai Syncplay.",
|
||||||
"promptforupdate-label" : u"Ti piacerebbe che, di tanto in tanto, Syncplay controllasse automaticamente la presenza di aggiornamenti?",
|
"promptforupdate-label" : "Ti piacerebbe che, di tanto in tanto, Syncplay controllasse automaticamente la presenza di aggiornamenti?",
|
||||||
|
|
||||||
"vlc-interface-version-mismatch": u"Stai eseguendo la versione {} del modulo di interfaccia per VLC di Syncplay, ma Syncplay è progettato per essere utilizzato con la versione {} o superiore. Per favore, fai riferimento alla User Guide di Syncplay presso https://syncplay.pl/guide/ per istruzioni su come installare syncplay.lua.", # VLC interface version, VLC interface min version
|
"vlc-interface-version-mismatch": "Stai eseguendo la versione {} del modulo di interfaccia per VLC di Syncplay, ma Syncplay è progettato per essere utilizzato con la versione {} o superiore. Per favore, fai riferimento alla User Guide di Syncplay presso https://syncplay.pl/guide/ per istruzioni su come installare syncplay.lua.", # VLC interface version, VLC interface min version
|
||||||
"vlc-interface-oldversion-warning": u"Attenzione: Syncplay ha rilevato una vecchia versione del modulo di interfaccia per VLC di Syncplay installata nella cartella di VLC. Per favore, fai riferimento alla User Guide di Syncplay presso https://syncplay.pl/guide/ per istruzioni su come installare syncplay.lua.",
|
"vlc-interface-oldversion-warning": "Attenzione: Syncplay ha rilevato una vecchia versione del modulo di interfaccia per VLC di Syncplay installata nella cartella di VLC. Per favore, fai riferimento alla User Guide di Syncplay presso https://syncplay.pl/guide/ per istruzioni su come installare syncplay.lua.",
|
||||||
"media-player-latency-warning": u"Attenzione: il media player ha impiegato {} secondi per rispondere. Se stai avendo problemi di sincronizzazione, chiudi delle applicazioni per liberare le risorse di sistema e, se ciò non dovesse avere alcun effetto, prova un altro media player.", # Seconds to respond
|
"media-player-latency-warning": "Attenzione: il media player ha impiegato {} secondi per rispondere. Se stai avendo problemi di sincronizzazione, chiudi delle applicazioni per liberare le risorse di sistema e, se ciò non dovesse avere alcun effetto, prova un altro media player.", # Seconds to respond
|
||||||
"vlc-interface-not-installed": u"Attenzione: il modulo di interfaccia per VLC di Syncplay non è stato trovato nella cartella di VLC. Se stai utilizzando VLC 2.0, VLC userà il modulo syncplay.lua contenuto nella cartella di Syncplay, ma ciò significa che altri custom script di interfaccia ed estensioni non funzioneranno. Per favore, fai riferimento alla User Guide di Syncplay presso https://syncplay.pl/guide/ per istruzioni su come installare syncplay.lua.",
|
"vlc-interface-not-installed": "Attenzione: il modulo di interfaccia per VLC di Syncplay non è stato trovato nella cartella di VLC. Se stai utilizzando VLC 2.0, VLC userà il modulo syncplay.lua contenuto nella cartella di Syncplay, ma ciò significa che altri custom script di interfaccia ed estensioni non funzioneranno. Per favore, fai riferimento alla User Guide di Syncplay presso https://syncplay.pl/guide/ per istruzioni su come installare syncplay.lua.",
|
||||||
"mpv-unresponsive-error": u"mpv non ha risposto per {} secondi, quindi sembra non funzionare correttamente. Per favore, riavvia Syncplay.", # Seconds to respond
|
"mpv-unresponsive-error": "mpv non ha risposto per {} secondi, quindi sembra non funzionare correttamente. Per favore, riavvia Syncplay.", # Seconds to respond
|
||||||
|
|
||||||
# Client prompts
|
# Client prompts
|
||||||
"enter-to-exit-prompt" : u"Premi Invio per uscire\n",
|
"enter-to-exit-prompt" : "Premi Invio per uscire\n",
|
||||||
|
|
||||||
# Client errors
|
# Client errors
|
||||||
"missing-arguments-error" : u"Alcuni argomenti obbligatori non sono stati trovati. Fai riferimento a --help",
|
"missing-arguments-error" : "Alcuni argomenti obbligatori non sono stati trovati. Fai riferimento a --help",
|
||||||
"server-timeout-error" : u"Connessione col server scaduta",
|
"server-timeout-error" : "Connessione col server scaduta",
|
||||||
"mpc-slave-error" : u"Non è possibile avviare MPC in modalità slave!",
|
"mpc-slave-error" : "Non è possibile avviare MPC in modalità slave!",
|
||||||
"mpc-version-insufficient-error" : u"La tua versione di MPC è troppo vecchia, per favore usa `mpc-hc` >= `{}`",
|
"mpc-version-insufficient-error" : "La tua versione di MPC è troppo vecchia, per favore usa `mpc-hc` >= `{}`",
|
||||||
"mpc-be-version-insufficient-error" : u"La tua versione di MPC è troppo vecchia, per favore usa `mpc-be` >= `{}`",
|
"mpc-be-version-insufficient-error" : "La tua versione di MPC è troppo vecchia, per favore usa `mpc-be` >= `{}`",
|
||||||
"mpv-version-error" : u"Syncplay non è compatibile con questa versione di mpv. Per favore usa un'altra versione di mpv (es. Git HEAD).",
|
"mpv-version-error" : "Syncplay non è compatibile con questa versione di mpv. Per favore usa un'altra versione di mpv (es. Git HEAD).",
|
||||||
"player-file-open-error" : u"Il player non è riuscito ad aprire il file",
|
"player-file-open-error" : "Il player non è riuscito ad aprire il file",
|
||||||
"player-path-error" : u"Il path del player non è configurato correttamente. I player supportati sono: mpv, VLC, MPC-HC, MPC-BE e mplayer2",
|
"player-path-error" : "Il path del player non è configurato correttamente. I player supportati sono: mpv, VLC, MPC-HC, MPC-BE e mplayer2",
|
||||||
"hostname-empty-error" : u"Il campo hostname non può essere vuoto",
|
"hostname-empty-error" : "Il campo hostname non può essere vuoto",
|
||||||
"empty-error" : u"Il campo {} non può esssere vuoto", # Configuration
|
"empty-error" : "Il campo {} non può esssere vuoto", # Configuration
|
||||||
"media-player-error": u"Errore media player: \"{}\"", # Error line
|
"media-player-error": "Errore media player: \"{}\"", # Error line
|
||||||
"unable-import-gui-error": u"Non è possibile importare le librerie di interfaccia grafica. Hai bisogno di PySide per poter utilizzare l'interfaccia grafica.",
|
"unable-import-gui-error": "Non è possibile importare le librerie di interfaccia grafica. Hai bisogno di PySide per poter utilizzare l'interfaccia grafica.",
|
||||||
|
|
||||||
"arguments-missing-error" : u"Alcuni argomenti obbligatori non sono stati trovati. Fai riferimento a --help",
|
"arguments-missing-error" : "Alcuni argomenti obbligatori non sono stati trovati. Fai riferimento a --help",
|
||||||
|
|
||||||
"unable-to-start-client-error" : u"Impossibile avviare il client",
|
"unable-to-start-client-error" : "Impossibile avviare il client",
|
||||||
|
|
||||||
"player-path-config-error": u"Il percorso del player non è configurato correttamente. I player supportati sono: mpv, VLC, MPC-HC, MPC-BE e mplayer2.",
|
"player-path-config-error": "Il percorso del player non è configurato correttamente. I player supportati sono: mpv, VLC, MPC-HC, MPC-BE e mplayer2.",
|
||||||
"no-file-path-config-error" :u"Deve essere selezionato un file prima di avviare il player",
|
"no-file-path-config-error" :"Deve essere selezionato un file prima di avviare il player",
|
||||||
"no-hostname-config-error": u"Il campo hostname non può essere vuoto",
|
"no-hostname-config-error": "Il campo hostname non può essere vuoto",
|
||||||
"invalid-port-config-error" : u"La porta deve essere valida",
|
"invalid-port-config-error" : "La porta deve essere valida",
|
||||||
"empty-value-config-error" : u"Il campo {} non può essere vuoto", # Config option
|
"empty-value-config-error" : "Il campo {} non può essere vuoto", # Config option
|
||||||
|
|
||||||
"not-json-error" : u"Non è una stringa con codifica JSON\n",
|
"not-json-error" : "Non è una stringa con codifica JSON\n",
|
||||||
"hello-arguments-error" : "Not enough Hello arguments\n", # DO NOT TRANSLATE
|
"hello-arguments-error" : "Not enough Hello arguments\n", # DO NOT TRANSLATE
|
||||||
"version-mismatch-error" : u"La versione del client è diversa da quella del server\n",
|
"version-mismatch-error" : "La versione del client è diversa da quella del server\n",
|
||||||
"vlc-failed-connection": u"Impossibile collegarsi a VLC. Se non hai installato syncplay.lua e stai usando l'ultima versione di VLC, fai riferimento a https://syncplay.pl/LUA/ per istruzioni.",
|
"vlc-failed-connection": "Impossibile collegarsi a VLC. Se non hai installato syncplay.lua e stai usando l'ultima versione di VLC, fai riferimento a https://syncplay.pl/LUA/ per istruzioni.",
|
||||||
"vlc-failed-noscript": u"VLC ha segnalato che lo script di interfaccia syncplay.lua non è stato installato. Per favore, fai riferimento a https://syncplay.pl/LUA/ per istruzioni.",
|
"vlc-failed-noscript": "VLC ha segnalato che lo script di interfaccia syncplay.lua non è stato installato. Per favore, fai riferimento a https://syncplay.pl/LUA/ per istruzioni.",
|
||||||
"vlc-failed-versioncheck": u"Questa versione di VLC non è supportata da Syncplay.",
|
"vlc-failed-versioncheck": "Questa versione di VLC non è supportata da Syncplay.",
|
||||||
|
|
||||||
"feature-sharedPlaylists" : u"playlist condivise", # used for not-supported-by-server-error
|
"feature-sharedPlaylists" : "playlist condivise", # used for not-supported-by-server-error
|
||||||
"feature-chat" : u"chat", # used for not-supported-by-server-error
|
"feature-chat" : "chat", # used for not-supported-by-server-error
|
||||||
"feature-readiness" : u"pronto", # used for not-supported-by-server-error
|
"feature-readiness" : "pronto", # used for not-supported-by-server-error
|
||||||
"feature-managedRooms" : u"stanze gestite", # used for not-supported-by-server-error
|
"feature-managedRooms" : "stanze gestite", # used for not-supported-by-server-error
|
||||||
|
|
||||||
"not-supported-by-server-error" : u"La feature {} non è supportata da questo server..", #feature
|
"not-supported-by-server-error" : "La feature {} non è supportata da questo server..", #feature
|
||||||
"shared-playlists-not-supported-by-server-error" : u"Le playlist condivise potrebbero non essere supportata dal server. È necessario un server con Syncplay {}+ per assicurarsi che funzionino correttamente, tuttavia il server sta utilizzando Syncplay {}.", #minVersion, serverVersion
|
"shared-playlists-not-supported-by-server-error" : "Le playlist condivise potrebbero non essere supportata dal server. È necessario un server con Syncplay {}+ per assicurarsi che funzionino correttamente, tuttavia il server sta utilizzando Syncplay {}.", #minVersion, serverVersion
|
||||||
"shared-playlists-disabled-by-server-error" : u"Le playlist condivise sono state disabilitate nella configurazione del server. Per utilizzarle, dovrai collegarti a un altro server.",
|
"shared-playlists-disabled-by-server-error" : "Le playlist condivise sono state disabilitate nella configurazione del server. Per utilizzarle, dovrai collegarti a un altro server.",
|
||||||
|
|
||||||
"invalid-seek-value" : u"Valore di ricerca non valido",
|
"invalid-seek-value" : "Valore di ricerca non valido",
|
||||||
"invalid-offset-value" : u"Valore di offset non valido",
|
"invalid-offset-value" : "Valore di offset non valido",
|
||||||
|
|
||||||
"switch-file-not-found-error" : u"Impossibile selezionare il file '{0}'. Syncplay osserva solo le cartelle multimediali specificate.", # File not found
|
"switch-file-not-found-error" : "Impossibile selezionare il file '{0}'. Syncplay osserva solo le cartelle multimediali specificate.", # File not found
|
||||||
"folder-search-timeout-error" : u"La ricerca nelle cartelle multimediali è stata interrotta perché l'analisi di '{}' sta impiegando troppo tempo. Ciò accade se si aggiunge nella lista di ricerca una cartella con troppe sottocartelle. Per riabilitare la selezione automatica dei file seleziona File->Imposta cartelle multimediali nella barra dei menù e rimuovi questa cartella, o sostituiscila con una sottocartella appropriata. Se la cartella è idonea, è possibile riabilitarla selezionando File->Imposta cartelle multimediali e premendo 'OK'.", #Folder
|
"folder-search-timeout-error" : "La ricerca nelle cartelle multimediali è stata interrotta perché l'analisi di '{}' sta impiegando troppo tempo. Ciò accade se si aggiunge nella lista di ricerca una cartella con troppe sottocartelle. Per riabilitare la selezione automatica dei file seleziona File->Imposta cartelle multimediali nella barra dei menù e rimuovi questa cartella, o sostituiscila con una sottocartella appropriata. Se la cartella è idonea, è possibile riabilitarla selezionando File->Imposta cartelle multimediali e premendo 'OK'.", #Folder
|
||||||
"folder-search-first-file-timeout-error" : u"La ricerca dei media in '{}' è stata interrotta perché l'accesso alla cartella sta impiegando troppo tempo. Ciò accade se questa si trova in un disco di rete oppure se hai impostato il blocco della rotazione del disco rigido dopo un certo periodo di inattività. Per riabilitare la selezione automatica dei file seleziona File->Imposta cartelle multimediali, quindi rimuovi la cartella oppure risolvi il problema (es. cambiando le impostazioni di risparmio energetico).", #Folder
|
"folder-search-first-file-timeout-error" : "La ricerca dei media in '{}' è stata interrotta perché l'accesso alla cartella sta impiegando troppo tempo. Ciò accade se questa si trova in un disco di rete oppure se hai impostato il blocco della rotazione del disco rigido dopo un certo periodo di inattività. Per riabilitare la selezione automatica dei file seleziona File->Imposta cartelle multimediali, quindi rimuovi la cartella oppure risolvi il problema (es. cambiando le impostazioni di risparmio energetico).", #Folder
|
||||||
"added-file-not-in-media-directory-error" : u"Hai selezionato un file in '{}', che non è impostata come cartella multimediale. Puoi aggiungerla come cartella multimediale selezionando File->Imposta cartelle multimediali nella barra dei menù.", #Folder
|
"added-file-not-in-media-directory-error" : "Hai selezionato un file in '{}', che non è impostata come cartella multimediale. Puoi aggiungerla come cartella multimediale selezionando File->Imposta cartelle multimediali nella barra dei menù.", #Folder
|
||||||
"no-media-directories-error" : u"Nessuna cartella multimediale è stata configurata. Per permettere il corretto funzionamento delle playlist condivise e la selezione automatica dei file, naviga in File->Imposta cartelle multimediali e specifica dove Syncplay deve ricercare i file multimediali.",
|
"no-media-directories-error" : "Nessuna cartella multimediale è stata configurata. Per permettere il corretto funzionamento delle playlist condivise e la selezione automatica dei file, naviga in File->Imposta cartelle multimediali e specifica dove Syncplay deve ricercare i file multimediali.",
|
||||||
"cannot-find-directory-error" : u"Impossibile trovare la cartella multimediale '{}'. Per aggiornare la lista delle cartelle multimediali seleziona File->Imposta cartelle multimediali dalla barra dei menù e specifica dove Syncplay deve ricercare i file multimediali.",
|
"cannot-find-directory-error" : "Impossibile trovare la cartella multimediale '{}'. Per aggiornare la lista delle cartelle multimediali seleziona File->Imposta cartelle multimediali dalla barra dei menù e specifica dove Syncplay deve ricercare i file multimediali.",
|
||||||
|
|
||||||
"failed-to-load-server-list-error" : u"Impossibile caricare la lista dei server pubblici. Per favore, visita https://www.syncplay.pl/ con il tuo browser.",
|
"failed-to-load-server-list-error" : "Impossibile caricare la lista dei server pubblici. Per favore, visita https://www.syncplay.pl/ con il tuo browser.",
|
||||||
|
|
||||||
# Client arguments
|
# Client arguments
|
||||||
"argument-description" : u'Programma per sincronizzare la riproduzione di media player multipli attraverso la rete.',
|
"argument-description" : 'Programma per sincronizzare la riproduzione di media player multipli attraverso la rete.',
|
||||||
"argument-epilog" : u'Se non è specificata alcuna opzione saranno utilizzati i valori _config',
|
"argument-epilog" : 'Se non è specificata alcuna opzione saranno utilizzati i valori _config',
|
||||||
"nogui-argument" : u'non mostrare l\'interfaccia grafica',
|
"nogui-argument" : 'non mostrare l\'interfaccia grafica',
|
||||||
"host-argument" : u'indirizzo del server',
|
"host-argument" : 'indirizzo del server',
|
||||||
"name-argument" : u'username desiderato',
|
"name-argument" : 'username desiderato',
|
||||||
"debug-argument" : u'modalità debug',
|
"debug-argument" : 'modalità debug',
|
||||||
"force-gui-prompt-argument" : u'mostra la finestra di configurazione',
|
"force-gui-prompt-argument" : 'mostra la finestra di configurazione',
|
||||||
"no-store-argument" : u'non salvare i valori in .syncplay',
|
"no-store-argument" : 'non salvare i valori in .syncplay',
|
||||||
"room-argument" : u'stanza di default',
|
"room-argument" : 'stanza di default',
|
||||||
"password-argument" : u'password del server',
|
"password-argument" : 'password del server',
|
||||||
"player-path-argument" : u'percorso dell\'eseguibile del tuo player',
|
"player-path-argument" : 'percorso dell\'eseguibile del tuo player',
|
||||||
"file-argument" : u'file da riprodurre',
|
"file-argument" : 'file da riprodurre',
|
||||||
"args-argument" : u'opzioni del player, se hai bisogno di utilizzare opzioni che iniziano con - anteponi un singolo \'--\'',
|
"args-argument" : 'opzioni del player, se hai bisogno di utilizzare opzioni che iniziano con - anteponi un singolo \'--\'',
|
||||||
"clear-gui-data-argument" : u'ripristina il percorso e i dati impostati tramite interfaccia grafica e salvati come QSettings',
|
"clear-gui-data-argument" : 'ripristina il percorso e i dati impostati tramite interfaccia grafica e salvati come QSettings',
|
||||||
"language-argument" : u'lingua per i messaggi di Syncplay (de/en/ru/it)',
|
"language-argument" : 'lingua per i messaggi di Syncplay (de/en/ru/it)',
|
||||||
|
|
||||||
"version-argument" : u'mostra la tua versione',
|
"version-argument" : 'mostra la tua versione',
|
||||||
"version-message" : u"Stai usando la versione di Syncplay {} ({})",
|
"version-message" : "Stai usando la versione di Syncplay {} ({})",
|
||||||
|
|
||||||
# Client labels
|
# Client labels
|
||||||
"config-window-title" : u"Configurazione di Syncplay",
|
"config-window-title" : "Configurazione di Syncplay",
|
||||||
|
|
||||||
"connection-group-title" : u"Impostazioni di connessione",
|
"connection-group-title" : "Impostazioni di connessione",
|
||||||
"host-label" : u"Indirizzo del server: ",
|
"host-label" : "Indirizzo del server: ",
|
||||||
"name-label" : u"Username (opzionale):",
|
"name-label" : "Username (opzionale):",
|
||||||
"password-label" : u"Password del server (se necessaria):",
|
"password-label" : "Password del server (se necessaria):",
|
||||||
"room-label" : u"Stanza di default: ",
|
"room-label" : "Stanza di default: ",
|
||||||
|
|
||||||
"media-setting-title" : u"Impostazioni del media player",
|
"media-setting-title" : "Impostazioni del media player",
|
||||||
"executable-path-label" : u"Percorso del media player:",
|
"executable-path-label" : "Percorso del media player:",
|
||||||
"media-path-label" : u"Percorso del video (opzionale):",
|
"media-path-label" : "Percorso del video (opzionale):",
|
||||||
"player-arguments-label" : u"Opzioni del player (se necessarie):",
|
"player-arguments-label" : "Opzioni del player (se necessarie):",
|
||||||
"browse-label" : u"Sfoglia",
|
"browse-label" : "Sfoglia",
|
||||||
"update-server-list-label" : u"Aggiorna lista",
|
"update-server-list-label" : "Aggiorna lista",
|
||||||
|
|
||||||
"more-title" : u"Mostra altre impostazioni",
|
"more-title" : "Mostra altre impostazioni",
|
||||||
"never-rewind-value" : u"Mai",
|
"never-rewind-value" : "Mai",
|
||||||
"seconds-suffix" : u" sec",
|
"seconds-suffix" : " sec",
|
||||||
"privacy-sendraw-option" : u"Invio semplice",
|
"privacy-sendraw-option" : "Invio semplice",
|
||||||
"privacy-sendhashed-option" : u"Invio cifrato",
|
"privacy-sendhashed-option" : "Invio cifrato",
|
||||||
"privacy-dontsend-option" : u"Non inviare",
|
"privacy-dontsend-option" : "Non inviare",
|
||||||
"filename-privacy-label" : u"Nome del file:",
|
"filename-privacy-label" : "Nome del file:",
|
||||||
"filesize-privacy-label" : u"Dimensione del file:",
|
"filesize-privacy-label" : "Dimensione del file:",
|
||||||
"checkforupdatesautomatically-label" : u"Controlla automaticamente gli aggiornamenti di Syncplay",
|
"checkforupdatesautomatically-label" : "Controlla automaticamente gli aggiornamenti di Syncplay",
|
||||||
"slowondesync-label" : u"Rallenta in caso di sfasamento minimo (non supportato su MPC-HC/BE)",
|
"slowondesync-label" : "Rallenta in caso di sfasamento minimo (non supportato su MPC-HC/BE)",
|
||||||
"rewindondesync-label" : u"Riavvolgi in caso di grande sfasamento (consigliato)",
|
"rewindondesync-label" : "Riavvolgi in caso di grande sfasamento (consigliato)",
|
||||||
"fastforwardondesync-label" : u"Avanzamento rapido in caso di ritardo (consigliato)",
|
"fastforwardondesync-label" : "Avanzamento rapido in caso di ritardo (consigliato)",
|
||||||
"dontslowdownwithme-label" : u"Non rallentare o riavvolgere gli altri utenti (sperimentale)",
|
"dontslowdownwithme-label" : "Non rallentare o riavvolgere gli altri utenti (sperimentale)",
|
||||||
"pausing-title" : u"Pausa",
|
"pausing-title" : "Pausa",
|
||||||
"pauseonleave-label" : u"Metti in pausa quando gli altri utenti lasciano la stanza (es. disconnessione)",
|
"pauseonleave-label" : "Metti in pausa quando gli altri utenti lasciano la stanza (es. disconnessione)",
|
||||||
"readiness-title" : u"Stato iniziale di 'pronto'",
|
"readiness-title" : "Stato iniziale di 'pronto'",
|
||||||
"readyatstart-label" : u"Imposta sempre il mio stato come \"pronto\" a guardare",
|
"readyatstart-label" : "Imposta sempre il mio stato come \"pronto\" a guardare",
|
||||||
"forceguiprompt-label" : u"Non mostrare la finestra di configurazione di Syncplay a ogni avvio", # (Inverted)
|
"forceguiprompt-label" : "Non mostrare la finestra di configurazione di Syncplay a ogni avvio", # (Inverted)
|
||||||
"showosd-label" : u"Abilita i messaggi OSD",
|
"showosd-label" : "Abilita i messaggi OSD",
|
||||||
|
|
||||||
"showosdwarnings-label" : u"Mostra gli avvisi (es. file differenti, utenti non pronti)",
|
"showosdwarnings-label" : "Mostra gli avvisi (es. file differenti, utenti non pronti)",
|
||||||
"showsameroomosd-label" : u"Mostra gli eventi della tua stanza",
|
"showsameroomosd-label" : "Mostra gli eventi della tua stanza",
|
||||||
"shownoncontrollerosd-label" : u"Mostra gli eventi dei non gestori nelle stanze gestite",
|
"shownoncontrollerosd-label" : "Mostra gli eventi dei non gestori nelle stanze gestite",
|
||||||
"showdifferentroomosd-label" : u"Mostra gli eventi di altre stanze",
|
"showdifferentroomosd-label" : "Mostra gli eventi di altre stanze",
|
||||||
"showslowdownosd-label" : u"Mostra le notifiche di rallentamento / riavvolgimento",
|
"showslowdownosd-label" : "Mostra le notifiche di rallentamento / riavvolgimento",
|
||||||
"language-label" : u"Lingua:",
|
"language-label" : "Lingua:",
|
||||||
"automatic-language" : u"Predefinita ({})", # Default language
|
"automatic-language" : "Predefinita ({})", # Default language
|
||||||
"showdurationnotification-label" : u"Avvisa in caso di mancata corrispondenza della durata del file",
|
"showdurationnotification-label" : "Avvisa in caso di mancata corrispondenza della durata del file",
|
||||||
"basics-label" : u"Generali",
|
"basics-label" : "Generali",
|
||||||
"readiness-label" : u"Play/Pausa",
|
"readiness-label" : "Play/Pausa",
|
||||||
"misc-label" : u"Varie",
|
"misc-label" : "Varie",
|
||||||
"core-behaviour-title" : u"Comportamento principale della stanza",
|
"core-behaviour-title" : "Comportamento principale della stanza",
|
||||||
"syncplay-internals-title" : u"Funzionamento di Syncplay",
|
"syncplay-internals-title" : "Funzionamento di Syncplay",
|
||||||
"syncplay-mediasearchdirectories-title" : u"Cartelle contenenti i file multimediali",
|
"syncplay-mediasearchdirectories-title" : "Cartelle contenenti i file multimediali",
|
||||||
"syncplay-mediasearchdirectories-label" : u"Cartelle contenenti i file multimediali (un solo percorso per riga)",
|
"syncplay-mediasearchdirectories-label" : "Cartelle contenenti i file multimediali (un solo percorso per riga)",
|
||||||
"sync-label" : u"Sincronia", # don't have better options as the label won't fit in the panel.
|
"sync-label" : "Sincronia", # don't have better options as the label won't fit in the panel.
|
||||||
"sync-otherslagging-title" : u"Se gli altri partecipanti non sono sincronizzati...",
|
"sync-otherslagging-title" : "Se gli altri partecipanti non sono sincronizzati...",
|
||||||
"sync-youlaggging-title" : u"Se tu sei non sei sincronizzato...",
|
"sync-youlaggging-title" : "Se tu sei non sei sincronizzato...",
|
||||||
"messages-label" : u"Messaggi",
|
"messages-label" : "Messaggi",
|
||||||
"messages-osd-title" : u"Impostazioni On-Screen Display",
|
"messages-osd-title" : "Impostazioni On-Screen Display",
|
||||||
"messages-other-title" : u"Altre impostazioni dello schermo",
|
"messages-other-title" : "Altre impostazioni dello schermo",
|
||||||
"chat-label" : u"Chat",
|
"chat-label" : "Chat",
|
||||||
"privacy-label" : u"Privacy", # Currently unused, but will be brought back if more space is needed in Misc tab
|
"privacy-label" : "Privacy", # Currently unused, but will be brought back if more space is needed in Misc tab
|
||||||
"privacy-title" : u"Impostazioni privacy",
|
"privacy-title" : "Impostazioni privacy",
|
||||||
"unpause-title" : u"Premendo play, imposta il tuo stato su \"pronto\" e:",
|
"unpause-title" : "Premendo play, imposta il tuo stato su \"pronto\" e:",
|
||||||
"unpause-ifalreadyready-option" : u"Riprendi la riproduzione se eri già pronto",
|
"unpause-ifalreadyready-option" : "Riprendi la riproduzione se eri già pronto",
|
||||||
"unpause-ifothersready-option" : u"Riprendi la riproduzione se eri già pronto o se gli altri partecipanti sono pronti (default)",
|
"unpause-ifothersready-option" : "Riprendi la riproduzione se eri già pronto o se gli altri partecipanti sono pronti (default)",
|
||||||
"unpause-ifminusersready-option" : u"Riprendi la riproduzione se eri già pronto o se un numero minimo di partecipanti è pronto",
|
"unpause-ifminusersready-option" : "Riprendi la riproduzione se eri già pronto o se un numero minimo di partecipanti è pronto",
|
||||||
"unpause-always" : u"Riprendi sempre la riproduzione",
|
"unpause-always" : "Riprendi sempre la riproduzione",
|
||||||
"syncplay-trusteddomains-title": u"Domini fidati (per streaming e i contenuti in rete)",
|
"syncplay-trusteddomains-title": "Domini fidati (per streaming e i contenuti in rete)",
|
||||||
|
|
||||||
"chat-title" : u"Inserimento messaggi di chat",
|
"chat-title" : "Inserimento messaggi di chat",
|
||||||
"chatinputenabled-label" : u"Abilita la chat su mpv",
|
"chatinputenabled-label" : "Abilita la chat su mpv",
|
||||||
"chatdirectinput-label" : u"Abilita la chat istantanea (evita di dover premere Invio per chattare)",
|
"chatdirectinput-label" : "Abilita la chat istantanea (evita di dover premere Invio per chattare)",
|
||||||
"chatinputfont-label" : u"Font dell'input della chat",
|
"chatinputfont-label" : "Font dell'input della chat",
|
||||||
"chatfont-label" : u"Imposta font",
|
"chatfont-label" : "Imposta font",
|
||||||
"chatcolour-label" : u"Imposta colore",
|
"chatcolour-label" : "Imposta colore",
|
||||||
"chatinputposition-label" : u"Posizione dell'area di inserimento testo in mpv",
|
"chatinputposition-label" : "Posizione dell'area di inserimento testo in mpv",
|
||||||
"chat-top-option" : u"In alto",
|
"chat-top-option" : "In alto",
|
||||||
"chat-middle-option" : u"Al centro",
|
"chat-middle-option" : "Al centro",
|
||||||
"chat-bottom-option" : u"In basso",
|
"chat-bottom-option" : "In basso",
|
||||||
"chatoutputheader-label" : u"Output messaggi di chat",
|
"chatoutputheader-label" : "Output messaggi di chat",
|
||||||
"chatoutputfont-label": u"Font dell'output della chat",
|
"chatoutputfont-label": "Font dell'output della chat",
|
||||||
"chatoutputenabled-label": u"Abilita l'output della chat nel media player (al momento solo mpv è supportato)",
|
"chatoutputenabled-label": "Abilita l'output della chat nel media player (al momento solo mpv è supportato)",
|
||||||
"chatoutputposition-label": u"Modalità di output",
|
"chatoutputposition-label": "Modalità di output",
|
||||||
"chat-chatroom-option": u"Stile chatroom",
|
"chat-chatroom-option": "Stile chatroom",
|
||||||
"chat-scrolling-option": u"A scorrimento",
|
"chat-scrolling-option": "A scorrimento",
|
||||||
|
|
||||||
"mpv-key-tab-hint": u"[TAB] per attivare le scorciatoie da tastiera e disattivare la chat.",
|
"mpv-key-tab-hint": "[TAB] per attivare le scorciatoie da tastiera e disattivare la chat.",
|
||||||
"mpv-key-hint": u"[Invio] per inviare un messaggio. [Esc] per uscire dalla modalità chat.",
|
"mpv-key-hint": "[Invio] per inviare un messaggio. [Esc] per uscire dalla modalità chat.",
|
||||||
"alphakey-mode-warning-first-line": u"Puoi utilizzare temporaneamente i vecchi comandi di mpv con i tasti a-z.",
|
"alphakey-mode-warning-first-line": "Puoi utilizzare temporaneamente i vecchi comandi di mpv con i tasti a-z.",
|
||||||
"alphakey-mode-warning-second-line": u"Premi [TAB] per ritornare alla modalità chat di Syncplay.",
|
"alphakey-mode-warning-second-line": "Premi [TAB] per ritornare alla modalità chat di Syncplay.",
|
||||||
|
|
||||||
"help-label" : u"Aiuto",
|
"help-label" : "Aiuto",
|
||||||
"reset-label" : u"Elimina configurazione",
|
"reset-label" : "Elimina configurazione",
|
||||||
"run-label" : u"Avvia Syncplay",
|
"run-label" : "Avvia Syncplay",
|
||||||
"storeandrun-label" : u"Salva la configurazione e avvia Syncplay",
|
"storeandrun-label" : "Salva la configurazione e avvia Syncplay",
|
||||||
|
|
||||||
"contact-label" : u"Sentiti libero di inviare un'e-mail a <a href=\"mailto:dev@syncplay.pl\"><nobr>dev@syncplay.pl</nobr></a>, chattare tramite il <a href=\"https://webchat.freenode.net/?channels=#syncplay\"><nobr>canale IRC #Syncplay</nobr></a> su irc.freenode.net, <a href=\"https://github.com/Uriziel/syncplay/issues\"><nobr>segnalare un problema</nobr></a> su GitHub, <a href=\"https://www.facebook.com/SyncplaySoftware\"><nobr>lasciare un like sulla nostra pagina Facebook</nobr></a>, <a href=\"https://twitter.com/Syncplay/\"><nobr>seguirci su Twitter</nobr></a>, o visitare <a href=\"https://syncplay.pl/\"><nobr>https://syncplay.pl/</nobr></a>. NOTA: i messaggi di chat non sono cifrati, quindi non usare Syncplay per inviare dati sensibili.",
|
"contact-label" : "Sentiti libero di inviare un'e-mail a <a href=\"mailto:dev@syncplay.pl\"><nobr>dev@syncplay.pl</nobr></a>, chattare tramite il <a href=\"https://webchat.freenode.net/?channels=#syncplay\"><nobr>canale IRC #Syncplay</nobr></a> su irc.freenode.net, <a href=\"https://github.com/Uriziel/syncplay/issues\"><nobr>segnalare un problema</nobr></a> su GitHub, <a href=\"https://www.facebook.com/SyncplaySoftware\"><nobr>lasciare un like sulla nostra pagina Facebook</nobr></a>, <a href=\"https://twitter.com/Syncplay/\"><nobr>seguirci su Twitter</nobr></a>, o visitare <a href=\"https://syncplay.pl/\"><nobr>https://syncplay.pl/</nobr></a>. NOTA: i messaggi di chat non sono cifrati, quindi non usare Syncplay per inviare dati sensibili.",
|
||||||
|
|
||||||
"joinroom-label" : u"Entra nella stanza",
|
"joinroom-label" : "Entra nella stanza",
|
||||||
"joinroom-menu-label" : u"Entra nella stanza {}",
|
"joinroom-menu-label" : "Entra nella stanza {}",
|
||||||
"seektime-menu-label" : u"Vai a...",
|
"seektime-menu-label" : "Vai a...",
|
||||||
"undoseek-menu-label" : u"Annulla vai a...",
|
"undoseek-menu-label" : "Annulla vai a...",
|
||||||
"play-menu-label" : u"Play",
|
"play-menu-label" : "Play",
|
||||||
"pause-menu-label" : u"Pausa",
|
"pause-menu-label" : "Pausa",
|
||||||
"playbackbuttons-menu-label" : u"Mostra i controlli della riproduzione",
|
"playbackbuttons-menu-label" : "Mostra i controlli della riproduzione",
|
||||||
"autoplay-menu-label" : u"Mostra il tasto di riproduzione automatica",
|
"autoplay-menu-label" : "Mostra il tasto di riproduzione automatica",
|
||||||
"autoplay-guipushbuttonlabel" : u"Riproduci quando tutti sono pronti",
|
"autoplay-guipushbuttonlabel" : "Riproduci quando tutti sono pronti",
|
||||||
"autoplay-minimum-label" : u"Minimo utenti pronti:",
|
"autoplay-minimum-label" : "Minimo utenti pronti:",
|
||||||
|
|
||||||
"sendmessage-label" : u"Invia",
|
"sendmessage-label" : "Invia",
|
||||||
|
|
||||||
"ready-guipushbuttonlabel" : u"Sono pronto a guardare!",
|
"ready-guipushbuttonlabel" : "Sono pronto a guardare!",
|
||||||
|
|
||||||
"roomuser-heading-label" : u"Stanza / Utente",
|
"roomuser-heading-label" : "Stanza / Utente",
|
||||||
"size-heading-label" : u"Dimensione",
|
"size-heading-label" : "Dimensione",
|
||||||
"duration-heading-label" : u"Durata",
|
"duration-heading-label" : "Durata",
|
||||||
"filename-heading-label" : u"Nome del file",
|
"filename-heading-label" : "Nome del file",
|
||||||
"notifications-heading-label" : u"Notifiche",
|
"notifications-heading-label" : "Notifiche",
|
||||||
"userlist-heading-label" : u"Lista degli utenti nella stanza",
|
"userlist-heading-label" : "Lista degli utenti nella stanza",
|
||||||
|
|
||||||
"browseformedia-label" : u"Seleziona i file multimediali",
|
"browseformedia-label" : "Seleziona i file multimediali",
|
||||||
|
|
||||||
"file-menu-label" : u"&File", # & precedes shortcut key
|
"file-menu-label" : "&File", # & precedes shortcut key
|
||||||
"openmedia-menu-label" : u"&Apri file multimediali",
|
"openmedia-menu-label" : "&Apri file multimediali",
|
||||||
"openstreamurl-menu-label" : u"Apri indirizzo di &rete",
|
"openstreamurl-menu-label" : "Apri indirizzo di &rete",
|
||||||
"setmediadirectories-menu-label" : u"Imposta &cartelle multimediali",
|
"setmediadirectories-menu-label" : "Imposta &cartelle multimediali",
|
||||||
"exit-menu-label" : u"&Esci",
|
"exit-menu-label" : "&Esci",
|
||||||
"advanced-menu-label" : u"&Avanzate",
|
"advanced-menu-label" : "&Avanzate",
|
||||||
"window-menu-label" : u"&Finestra",
|
"window-menu-label" : "&Finestra",
|
||||||
"setoffset-menu-label" : u"Imposta &offset",
|
"setoffset-menu-label" : "Imposta &offset",
|
||||||
"createcontrolledroom-menu-label" : u"&Crea stanza gestita",
|
"createcontrolledroom-menu-label" : "&Crea stanza gestita",
|
||||||
"identifyascontroller-menu-label" : u"&Identificati come operatore della stanza",
|
"identifyascontroller-menu-label" : "&Identificati come operatore della stanza",
|
||||||
"settrusteddomains-menu-label" : u"Imposta &domini fidati",
|
"settrusteddomains-menu-label" : "Imposta &domini fidati",
|
||||||
"addtrusteddomain-menu-label" : u"Aggiungi {} come dominio fidato", # Domain
|
"addtrusteddomain-menu-label" : "Aggiungi {} come dominio fidato", # Domain
|
||||||
|
|
||||||
"playback-menu-label" : u"&Riproduzione",
|
"playback-menu-label" : "&Riproduzione",
|
||||||
|
|
||||||
"help-menu-label" : u"&Aiuto",
|
"help-menu-label" : "&Aiuto",
|
||||||
"userguide-menu-label" : u"Apri guida &utente",
|
"userguide-menu-label" : "Apri guida &utente",
|
||||||
"update-menu-label" : u"Controlla la presenza di &aggiornamenti",
|
"update-menu-label" : "Controlla la presenza di &aggiornamenti",
|
||||||
|
|
||||||
#About dialog
|
#About dialog
|
||||||
"about-menu-label": u"&Informazioni su Syncplay",
|
"about-menu-label": "&Informazioni su Syncplay",
|
||||||
"about-dialog-title": u"Informazioni su Syncplay",
|
"about-dialog-title": "Informazioni su Syncplay",
|
||||||
"about-dialog-release": u"Versione {} release {}",
|
"about-dialog-release": "Versione {} release {}",
|
||||||
"about-dialog-license-text" : u"Rilasciato sotto Apache License, Version 2.0",
|
"about-dialog-license-text" : "Rilasciato sotto Apache License, Version 2.0",
|
||||||
"about-dialog-license-button": u"Licenza",
|
"about-dialog-license-button": "Licenza",
|
||||||
"about-dialog-dependencies": u"Dipendenze",
|
"about-dialog-dependencies": "Dipendenze",
|
||||||
|
|
||||||
"setoffset-msgbox-label" : u"Imposta offset",
|
"setoffset-msgbox-label" : "Imposta offset",
|
||||||
"offsetinfo-msgbox-label" : u"Offset (vedi https://syncplay.pl/guide/ per istruzioni):",
|
"offsetinfo-msgbox-label" : "Offset (vedi https://syncplay.pl/guide/ per istruzioni):",
|
||||||
|
|
||||||
"promptforstreamurl-msgbox-label" : u"Apri URL",
|
"promptforstreamurl-msgbox-label" : "Apri URL",
|
||||||
"promptforstreamurlinfo-msgbox-label" : u"Indirizzo di rete",
|
"promptforstreamurlinfo-msgbox-label" : "Indirizzo di rete",
|
||||||
|
|
||||||
"addfolder-label" : u"Aggiungi cartella",
|
"addfolder-label" : "Aggiungi cartella",
|
||||||
|
|
||||||
"adduris-msgbox-label" : u"Aggiungi gli indirizzi alla playlist (uno per riga)",
|
"adduris-msgbox-label" : "Aggiungi gli indirizzi alla playlist (uno per riga)",
|
||||||
"editplaylist-msgbox-label" : u"Imposta playlist (una per riga)",
|
"editplaylist-msgbox-label" : "Imposta playlist (una per riga)",
|
||||||
"trusteddomains-msgbox-label" : u"Domini a cui è lecito passare automaticamente (uno per riga)",
|
"trusteddomains-msgbox-label" : "Domini a cui è lecito passare automaticamente (uno per riga)",
|
||||||
|
|
||||||
"createcontrolledroom-msgbox-label" : u"Crea stanza gestita",
|
"createcontrolledroom-msgbox-label" : "Crea stanza gestita",
|
||||||
"controlledroominfo-msgbox-label" : u"Inserisci il nome della stanza gestita\r\n(vedi https://syncplay.pl/guide/ per istruzioni):",
|
"controlledroominfo-msgbox-label" : "Inserisci il nome della stanza gestita\r\n(vedi https://syncplay.pl/guide/ per istruzioni):",
|
||||||
|
|
||||||
"identifyascontroller-msgbox-label" : u"Identificati come operatore della stanza",
|
"identifyascontroller-msgbox-label" : "Identificati come operatore della stanza",
|
||||||
"identifyinfo-msgbox-label" : u"Inserisci la password dell'operatore per questa stanza\r\n(vedi https://syncplay.pl/guide/ per istruzioni):",
|
"identifyinfo-msgbox-label" : "Inserisci la password dell'operatore per questa stanza\r\n(vedi https://syncplay.pl/guide/ per istruzioni):",
|
||||||
|
|
||||||
"public-server-msgbox-label" : u"Seleziona il server pubblico per questa sessione",
|
"public-server-msgbox-label" : "Seleziona il server pubblico per questa sessione",
|
||||||
|
|
||||||
"megabyte-suffix" : u" MB",
|
"megabyte-suffix" : " MB",
|
||||||
|
|
||||||
# Tooltips
|
# Tooltips
|
||||||
|
|
||||||
"host-tooltip" : u"Hostname o indirizzo IP a cui collegarsi e, se necessario, includere la porta (es. syncplay.pl:8999). La sincronizzazione avviene solo con gli utenti collegati allo stesso server/porta.",
|
"host-tooltip" : "Hostname o indirizzo IP a cui collegarsi e, se necessario, includere la porta (es. syncplay.pl:8999). La sincronizzazione avviene solo con gli utenti collegati allo stesso server/porta.",
|
||||||
"name-tooltip" : u"Il nome utente con cui sarai riconosciuto. Nessuna registrazione necessaria, cosi potrai sempre cambiarlo. Se lasciato vuoto, viene scelto un nome casuale.",
|
"name-tooltip" : "Il nome utente con cui sarai riconosciuto. Nessuna registrazione necessaria, cosi potrai sempre cambiarlo. Se lasciato vuoto, viene scelto un nome casuale.",
|
||||||
"password-tooltip" : u"La password è necessaria solo in caso di connessione a server privati.",
|
"password-tooltip" : "La password è necessaria solo in caso di connessione a server privati.",
|
||||||
"room-tooltip" : u"La stanza in cui entrare dopo la connessione. Può assumere qualsiasi nome, ma ricorda che sarai sincronizzato solo con gli utenti nella stessa stanza.",
|
"room-tooltip" : "La stanza in cui entrare dopo la connessione. Può assumere qualsiasi nome, ma ricorda che sarai sincronizzato solo con gli utenti nella stessa stanza.",
|
||||||
|
|
||||||
"executable-path-tooltip" : u"Percorso del media player desiderato (scegliere tra mpv, VLC, MPC-HC/BE or mplayer2).",
|
"executable-path-tooltip" : "Percorso del media player desiderato (scegliere tra mpv, VLC, MPC-HC/BE or mplayer2).",
|
||||||
"media-path-tooltip" : u"Percorso del video o stream da aprire. Necessario per mplayer2.",
|
"media-path-tooltip" : "Percorso del video o stream da aprire. Necessario per mplayer2.",
|
||||||
"player-arguments-tooltip" : u"Argomenti da linea di comando aggiuntivi da passare al media player scelto.",
|
"player-arguments-tooltip" : "Argomenti da linea di comando aggiuntivi da passare al media player scelto.",
|
||||||
"mediasearcdirectories-arguments-tooltip" : u"Cartelle dove Syncplay cercherà i file multimediali, es. quando usi la funzione click to switch. Syncplay cercherà anche nelle sottocartelle.",
|
"mediasearcdirectories-arguments-tooltip" : "Cartelle dove Syncplay cercherà i file multimediali, es. quando usi la funzione click to switch. Syncplay cercherà anche nelle sottocartelle.",
|
||||||
|
|
||||||
"more-tooltip" : u"Mostra le impostazioni usate meno frequentemente.",
|
"more-tooltip" : "Mostra le impostazioni usate meno frequentemente.",
|
||||||
"filename-privacy-tooltip" : u"Modalità di invio al server del nome del file attualmente in riproduzione.",
|
"filename-privacy-tooltip" : "Modalità di invio al server del nome del file attualmente in riproduzione.",
|
||||||
"filesize-privacy-tooltip" : u"Modalità di invio al server della dimensione del file attualmente in riproduzione.",
|
"filesize-privacy-tooltip" : "Modalità di invio al server della dimensione del file attualmente in riproduzione.",
|
||||||
"privacy-sendraw-tooltip" : u"Invia questa informazione in chiaro. Questa è l'impostazione predefinita per la maggior parte delle funzionalità.",
|
"privacy-sendraw-tooltip" : "Invia questa informazione in chiaro. Questa è l'impostazione predefinita per la maggior parte delle funzionalità.",
|
||||||
"privacy-sendhashed-tooltip" : u"Invia una versione cifrata dell'informazione, rendendola meno visibile agli altri client.",
|
"privacy-sendhashed-tooltip" : "Invia una versione cifrata dell'informazione, rendendola meno visibile agli altri client.",
|
||||||
"privacy-dontsend-tooltip" : u"Non inviare questa informazione al server. Questo garantisce massima privacy.",
|
"privacy-dontsend-tooltip" : "Non inviare questa informazione al server. Questo garantisce massima privacy.",
|
||||||
"checkforupdatesautomatically-tooltip" : u"Controlla regolarmente la presenza di nuove versioni di Syncplay.",
|
"checkforupdatesautomatically-tooltip" : "Controlla regolarmente la presenza di nuove versioni di Syncplay.",
|
||||||
"slowondesync-tooltip" : u"Riduce temporaneamente la velocità di riproduzione quando c'è bisogno di sincronizzarti con gli altri utenti. Non supportato su MPC-HC/BE.",
|
"slowondesync-tooltip" : "Riduce temporaneamente la velocità di riproduzione quando c'è bisogno di sincronizzarti con gli altri utenti. Non supportato su MPC-HC/BE.",
|
||||||
"dontslowdownwithme-tooltip" : u"Gli altri utenti non vengono rallentati se non sei sincronizzato. Utile per i gestori della stanza.",
|
"dontslowdownwithme-tooltip" : "Gli altri utenti non vengono rallentati se non sei sincronizzato. Utile per i gestori della stanza.",
|
||||||
"pauseonleave-tooltip" : u"Mette in pausa la riproduzione se vieni disconnesso o se qualcuno lascia la stanza.",
|
"pauseonleave-tooltip" : "Mette in pausa la riproduzione se vieni disconnesso o se qualcuno lascia la stanza.",
|
||||||
"readyatstart-tooltip" : u"Imposta il tuo stato su \"pronto\" all'avvio (in caso contrario, sarai su \"non pronto\" finché non cambierai il tuo stato)",
|
"readyatstart-tooltip" : "Imposta il tuo stato su \"pronto\" all'avvio (in caso contrario, sarai su \"non pronto\" finché non cambierai il tuo stato)",
|
||||||
"forceguiprompt-tooltip" : u"La finestra di configurazione non viene mostrata quando apri Syncplay.",
|
"forceguiprompt-tooltip" : "La finestra di configurazione non viene mostrata quando apri Syncplay.",
|
||||||
"nostore-tooltip" : u"Avvia Syncplay con la configurazione scelta, ma non salva le impostazioni.",
|
"nostore-tooltip" : "Avvia Syncplay con la configurazione scelta, ma non salva le impostazioni.",
|
||||||
"rewindondesync-tooltip" : u"Torna indietro quando necessario per ristabilire la sincronizzazione. Disabilitare quest'opzione può causare gravi problemi di sincronizzazione!",
|
"rewindondesync-tooltip" : "Torna indietro quando necessario per ristabilire la sincronizzazione. Disabilitare quest'opzione può causare gravi problemi di sincronizzazione!",
|
||||||
"fastforwardondesync-tooltip" : u"Avanza rapidamente quando non sei sincronizzato col gestore della stanza (usa una posizione fittizia se 'Non rallentare o riavvolgere gli altri utenti' è abilitato).",
|
"fastforwardondesync-tooltip" : "Avanza rapidamente quando non sei sincronizzato col gestore della stanza (usa una posizione fittizia se 'Non rallentare o riavvolgere gli altri utenti' è abilitato).",
|
||||||
"showosd-tooltip" : u"Invia i messaggi di Syncplay al media player tramite OSD.",
|
"showosd-tooltip" : "Invia i messaggi di Syncplay al media player tramite OSD.",
|
||||||
"showosdwarnings-tooltip" : u"Mostra gli avvisi in caso di riproduzione di un file differente, se sei l'unico utente nella stanza, se ci sono utenti non pronti, ecc.",
|
"showosdwarnings-tooltip" : "Mostra gli avvisi in caso di riproduzione di un file differente, se sei l'unico utente nella stanza, se ci sono utenti non pronti, ecc.",
|
||||||
"showsameroomosd-tooltip" : u"Mostra le notifiche OSD per gli eventi relativi alla stanza in cui si trova l'utente.",
|
"showsameroomosd-tooltip" : "Mostra le notifiche OSD per gli eventi relativi alla stanza in cui si trova l'utente.",
|
||||||
"shownoncontrollerosd-tooltip" : u"Mostra le notifiche OSD per gli eventi relativi ai non operatori presenti nelle stanze gestite.",
|
"shownoncontrollerosd-tooltip" : "Mostra le notifiche OSD per gli eventi relativi ai non operatori presenti nelle stanze gestite.",
|
||||||
"showdifferentroomosd-tooltip" : u"Mostra le notifiche OSD per gli eventi relativi alle stanze in cui l'utente non si trova.",
|
"showdifferentroomosd-tooltip" : "Mostra le notifiche OSD per gli eventi relativi alle stanze in cui l'utente non si trova.",
|
||||||
"showslowdownosd-tooltip" : u"Mostra le notifiche di rallentamento / riavvolgimento in caso di differenza temporale.",
|
"showslowdownosd-tooltip" : "Mostra le notifiche di rallentamento / riavvolgimento in caso di differenza temporale.",
|
||||||
"showdurationnotification-tooltip" : u"Utile quando manca un segmento di un file con più parti. Può causare dei falsi positivi.",
|
"showdurationnotification-tooltip" : "Utile quando manca un segmento di un file con più parti. Può causare dei falsi positivi.",
|
||||||
"language-tooltip" : u"Lingua da utilizzare in Syncplay.",
|
"language-tooltip" : "Lingua da utilizzare in Syncplay.",
|
||||||
"unpause-always-tooltip" : u"Se riprendi la riproduzione, il tuo stato cambia in \"pronto\" e la riproduzione viene avviata, piuttosto che impostarti solo su pronto.",
|
"unpause-always-tooltip" : "Se riprendi la riproduzione, il tuo stato cambia in \"pronto\" e la riproduzione viene avviata, piuttosto che impostarti solo su pronto.",
|
||||||
"unpause-ifalreadyready-tooltip" : u"Se riprendi la riproduzione quando non sei \"pronto\", verrai impostato su pronto - ripeti il comando ancora una volta per avviare la riproduzione.",
|
"unpause-ifalreadyready-tooltip" : "Se riprendi la riproduzione quando non sei \"pronto\", verrai impostato su pronto - ripeti il comando ancora una volta per avviare la riproduzione.",
|
||||||
"unpause-ifothersready-tooltip" : u"Se riprendi la riproduzione quando non sei \"pronto\" la riproduzione verrà avviata solo se gli altri sono pronti.",
|
"unpause-ifothersready-tooltip" : "Se riprendi la riproduzione quando non sei \"pronto\" la riproduzione verrà avviata solo se gli altri sono pronti.",
|
||||||
"unpause-ifminusersready-tooltip" : u"Se riprendi la riproduzione quando non sei \"pronto\", la riproduzione verrà avviata solo se un numero minimo di utenti è \"pronto\".",
|
"unpause-ifminusersready-tooltip" : "Se riprendi la riproduzione quando non sei \"pronto\", la riproduzione verrà avviata solo se un numero minimo di utenti è \"pronto\".",
|
||||||
"trusteddomains-arguments-tooltip" : u"Domini verso cui è possibile collegarsi automaticamente quando le playlist condivise sono abilitate.",
|
"trusteddomains-arguments-tooltip" : "Domini verso cui è possibile collegarsi automaticamente quando le playlist condivise sono abilitate.",
|
||||||
|
|
||||||
"chatinputenabled-tooltip" : u"Abilita l'input della chat in mpv (premi Invio per chattare, per inviare ed Esc per cancellare)",
|
"chatinputenabled-tooltip" : "Abilita l'input della chat in mpv (premi Invio per chattare, per inviare ed Esc per cancellare)",
|
||||||
"chatdirectinput-tooltip" : u"Evita di dover premere Invio per aprire l'input della chat in mpv. Premi TAB in mpv per disabilitare temporaneamente questa funzione.",
|
"chatdirectinput-tooltip" : "Evita di dover premere Invio per aprire l'input della chat in mpv. Premi TAB in mpv per disabilitare temporaneamente questa funzione.",
|
||||||
"font-label-tooltip" : u"Font usato nell'input della chat in mpv. Non influenza cosa vedono gli altri, vale solo per te.",
|
"font-label-tooltip" : "Font usato nell'input della chat in mpv. Non influenza cosa vedono gli altri, vale solo per te.",
|
||||||
"set-input-font-tooltip" : u"Font usato nell'input della chat in mpv. Non influenza cosa vedono gli altri, vale solo per te.",
|
"set-input-font-tooltip" : "Font usato nell'input della chat in mpv. Non influenza cosa vedono gli altri, vale solo per te.",
|
||||||
"set-input-colour-tooltip" : u"Colore del font usato nell'input della chat in mpv. Non influenza cosa vedono gli altri, vale solo per te.",
|
"set-input-colour-tooltip" : "Colore del font usato nell'input della chat in mpv. Non influenza cosa vedono gli altri, vale solo per te.",
|
||||||
"chatinputposition-tooltip" : u"Posizione dell'input della chat in mpv quando premi Invio.",
|
"chatinputposition-tooltip" : "Posizione dell'input della chat in mpv quando premi Invio.",
|
||||||
"chatinputposition-top-tooltip" : u"Posiziona l'input della chat in cima alla finestra di mpv.",
|
"chatinputposition-top-tooltip" : "Posiziona l'input della chat in cima alla finestra di mpv.",
|
||||||
"chatinputposition-middle-tooltip" : u"Posizione l'input della chat al centro della finestra di mpv.",
|
"chatinputposition-middle-tooltip" : "Posizione l'input della chat al centro della finestra di mpv.",
|
||||||
"chatinputposition-bottom-tooltip" : u"Posiziona l'input della chat in basso alla finestra di mpv.",
|
"chatinputposition-bottom-tooltip" : "Posiziona l'input della chat in basso alla finestra di mpv.",
|
||||||
"chatoutputenabled-tooltip": u"Mostra i messaggi di chat nell'OSD (se supportato dal media player).",
|
"chatoutputenabled-tooltip": "Mostra i messaggi di chat nell'OSD (se supportato dal media player).",
|
||||||
"font-output-label-tooltip": u"Font dell'output della chat.",
|
"font-output-label-tooltip": "Font dell'output della chat.",
|
||||||
"set-output-font-tooltip": u"Font usato per mostrare i messaggi di chat.",
|
"set-output-font-tooltip": "Font usato per mostrare i messaggi di chat.",
|
||||||
"chatoutputmode-tooltip": u"Come sono mostrati i messaggi di chat.",
|
"chatoutputmode-tooltip": "Come sono mostrati i messaggi di chat.",
|
||||||
"chatoutputmode-chatroom-tooltip": u"Mostra i nuovi messaggi di chat al di sotto di quelli precedenti.",
|
"chatoutputmode-chatroom-tooltip": "Mostra i nuovi messaggi di chat al di sotto di quelli precedenti.",
|
||||||
"chatoutputmode-scrolling-tooltip": u"Scorri il testo della chat da destra a sinistra.",
|
"chatoutputmode-scrolling-tooltip": "Scorri il testo della chat da destra a sinistra.",
|
||||||
|
|
||||||
"help-tooltip" : u"Apri la guida utente su syncplay.pl.",
|
"help-tooltip" : "Apri la guida utente su syncplay.pl.",
|
||||||
"reset-tooltip" : u"Ripristina le impostazioni iniziali di Syncplay.",
|
"reset-tooltip" : "Ripristina le impostazioni iniziali di Syncplay.",
|
||||||
"update-server-list-tooltip" : u"Scarica la lista dei server pubblici da syncplay.pl.",
|
"update-server-list-tooltip" : "Scarica la lista dei server pubblici da syncplay.pl.",
|
||||||
|
|
||||||
"joinroom-tooltip" : u"Lascia la stanza attuale e entra in quella specificata.",
|
"joinroom-tooltip" : "Lascia la stanza attuale e entra in quella specificata.",
|
||||||
"seektime-msgbox-label" : u"Salta all'istante di tempo specificato (in secondi / min:sec). Usa +/- per una ricerca relativa.",
|
"seektime-msgbox-label" : "Salta all'istante di tempo specificato (in secondi / min:sec). Usa +/- per una ricerca relativa.",
|
||||||
"ready-tooltip" : u"Indica quando sei pronto a guardare.",
|
"ready-tooltip" : "Indica quando sei pronto a guardare.",
|
||||||
"autoplay-tooltip" : u"Avvia la riproduzione automatica quando il numero minimo di utenti è pronto.",
|
"autoplay-tooltip" : "Avvia la riproduzione automatica quando il numero minimo di utenti è pronto.",
|
||||||
"switch-to-file-tooltip" : u"Doppio click per passare a {}", # Filename
|
"switch-to-file-tooltip" : "Doppio click per passare a {}", # Filename
|
||||||
"sendmessage-tooltip" : u"Invia il messaggio alla stanza",
|
"sendmessage-tooltip" : "Invia il messaggio alla stanza",
|
||||||
|
|
||||||
# In-userlist notes (GUI)
|
# In-userlist notes (GUI)
|
||||||
"differentsize-note" : u"Dimensione file diversa!",
|
"differentsize-note" : "Dimensione file diversa!",
|
||||||
"differentsizeandduration-note" : u"Durata e dimensione file diversi!",
|
"differentsizeandduration-note" : "Durata e dimensione file diversi!",
|
||||||
"differentduration-note" : u"Durata diversa!",
|
"differentduration-note" : "Durata diversa!",
|
||||||
"nofile-note" : u"(Nessun file in riproduzione)",
|
"nofile-note" : "(Nessun file in riproduzione)",
|
||||||
|
|
||||||
# Server messages to client
|
# Server messages to client
|
||||||
"new-syncplay-available-motd-message" : u"<NOTICE> Stai usando Syncplay {} ma una nuova versione è disponibile presso https://syncplay.pl </NOTICE>", # ClientVersion
|
"new-syncplay-available-motd-message" : "<NOTICE> Stai usando Syncplay {} ma una nuova versione è disponibile presso https://syncplay.pl </NOTICE>", # ClientVersion
|
||||||
|
|
||||||
# Server notifications
|
# Server notifications
|
||||||
"welcome-server-notification" : u"Benvenuto nel server Syncplay, ver. {0}", # version
|
"welcome-server-notification" : "Benvenuto nel server Syncplay, ver. {0}", # version
|
||||||
"client-connected-room-server-notification" : u"{0}({2}) connesso alla stanza '{1}'", # username, host, room
|
"client-connected-room-server-notification" : "{0}({2}) connesso alla stanza '{1}'", # username, host, room
|
||||||
"client-left-server-notification" : u"{0} ha lasciato il server", # name
|
"client-left-server-notification" : "{0} ha lasciato il server", # name
|
||||||
"no-salt-notification" : u"NOTA BENE: In futuro, per consentire il corretto funzionamento delle password generate da questo server (per le stanze gestite), aggiungi da linea di comando il seguente argomento prima di avviare il server Syncplay: --salt {}", #Salt
|
"no-salt-notification" : "NOTA BENE: In futuro, per consentire il corretto funzionamento delle password generate da questo server (per le stanze gestite), aggiungi da linea di comando il seguente argomento prima di avviare il server Syncplay: --salt {}", #Salt
|
||||||
|
|
||||||
|
|
||||||
# Server arguments
|
# Server arguments
|
||||||
"server-argument-description" : u'Programma per sincronizzare la riproduzione di media player multipli attraverso la rete. Modulo server.',
|
"server-argument-description" : 'Programma per sincronizzare la riproduzione di media player multipli attraverso la rete. Modulo server.',
|
||||||
"server-argument-epilog" : u'Se non è specificata alcuna opzione saranno utilizzati i valori _config',
|
"server-argument-epilog" : 'Se non è specificata alcuna opzione saranno utilizzati i valori _config',
|
||||||
"server-port-argument" : u'Porta TCP del server',
|
"server-port-argument" : 'Porta TCP del server',
|
||||||
"server-password-argument" : u'password del server',
|
"server-password-argument" : 'password del server',
|
||||||
"server-isolate-room-argument" : u'Mantiene le stanze isolate',
|
"server-isolate-room-argument" : 'Mantiene le stanze isolate',
|
||||||
"server-salt-argument" : u"usare stringhe casuali per generare le password delle stanze gestite",
|
"server-salt-argument" : "usare stringhe casuali per generare le password delle stanze gestite",
|
||||||
"server-disable-ready-argument" : u"disabilita la funzionalità \"pronto\"",
|
"server-disable-ready-argument" : "disabilita la funzionalità \"pronto\"",
|
||||||
"server-motd-argument": u"percorso del file da cui verrà letto il messaggio del giorno",
|
"server-motd-argument": "percorso del file da cui verrà letto il messaggio del giorno",
|
||||||
"server-chat-argument" : u"abilita o disabilita la chat",
|
"server-chat-argument" : "abilita o disabilita la chat",
|
||||||
"server-chat-maxchars-argument" : u"Numero massimo di caratteri in un messaggio di chat (default è {})", # Default number of characters
|
"server-chat-maxchars-argument" : "Numero massimo di caratteri in un messaggio di chat (default è {})", # Default number of characters
|
||||||
"server-maxusernamelength-argument": u"Maximum number of charactrs in a username (default is {})", # TODO: Translate
|
"server-maxusernamelength-argument": "Maximum number of charactrs in a username (default is {})", # TODO: Translate
|
||||||
"server-messed-up-motd-unescaped-placeholders": u"Il messaggio del giorno ha dei caratteri non 'escaped'. Tutti i simboli $ devono essere doppi ($$).",
|
"server-messed-up-motd-unescaped-placeholders": "Il messaggio del giorno ha dei caratteri non 'escaped'. Tutti i simboli $ devono essere doppi ($$).",
|
||||||
"server-messed-up-motd-too-long": u"Il messaggio del giorno è troppo lungo - numero massimo di caratteri è {}, {} trovati.",
|
"server-messed-up-motd-too-long": "Il messaggio del giorno è troppo lungo - numero massimo di caratteri è {}, {} trovati.",
|
||||||
|
|
||||||
# Server errors
|
# Server errors
|
||||||
"unknown-command-server-error" : u"Comando non riconosciuto {}", # message
|
"unknown-command-server-error" : "Comando non riconosciuto {}", # message
|
||||||
"not-json-server-error" : u"Non è una stringa in codifica JSON {}", # message
|
"not-json-server-error" : "Non è una stringa in codifica JSON {}", # message
|
||||||
"not-known-server-error" : u"Devi essere autenticato dal server prima di poter inviare questo comando",
|
"not-known-server-error" : "Devi essere autenticato dal server prima di poter inviare questo comando",
|
||||||
"client-drop-server-error" : u"Il client è caduto: {} -- {}", # host, error
|
"client-drop-server-error" : "Il client è caduto: {} -- {}", # host, error
|
||||||
"password-required-server-error" : u"È richiesta una password",
|
"password-required-server-error" : "È richiesta una password",
|
||||||
"wrong-password-server-error" : u"La password inserita è errata",
|
"wrong-password-server-error" : "La password inserita è errata",
|
||||||
"hello-server-error" : "Not enough Hello arguments", #DO NOT TRANSLATE
|
"hello-server-error" : "Not enough Hello arguments", #DO NOT TRANSLATE
|
||||||
|
|
||||||
# Playlists
|
# Playlists
|
||||||
"playlist-selection-changed-notification" : u"{} ha cambiato il file selezionato nella playlist", # Username
|
"playlist-selection-changed-notification" : "{} ha cambiato il file selezionato nella playlist", # Username
|
||||||
"playlist-contents-changed-notification" : u"{} ha aggiornato la playlist", # Username
|
"playlist-contents-changed-notification" : "{} ha aggiornato la playlist", # Username
|
||||||
"cannot-find-file-for-playlist-switch-error" : u"Impossibile trovare il file {} nelle cartelle multimediali per permettere il cambio di file tramite la playlist!", # Filename
|
"cannot-find-file-for-playlist-switch-error" : "Impossibile trovare il file {} nelle cartelle multimediali per permettere il cambio di file tramite la playlist!", # Filename
|
||||||
"cannot-add-duplicate-error" : u"Impossibile aggiungere una seconda voce per '{}' alla playlist. Non è possibile avere file duplicati.", #Filename
|
"cannot-add-duplicate-error" : "Impossibile aggiungere una seconda voce per '{}' alla playlist. Non è possibile avere file duplicati.", #Filename
|
||||||
"cannot-add-unsafe-path-error" : u"Impossibile caricare automaticamente {} perché non è presente nei domini fidati. Puoi passare all'inserimento manuale facendo doppio click sull'indirizzo nella playlist, oppure aggiungerlo ai domini fidati tramite File->Avanzate->Imposta domini fidati. Cliccando col tasto destro del mouse su un indirizzo puoi impostare il suo dominio come fidato tramite il menù contestuale.", # Filename
|
"cannot-add-unsafe-path-error" : "Impossibile caricare automaticamente {} perché non è presente nei domini fidati. Puoi passare all'inserimento manuale facendo doppio click sull'indirizzo nella playlist, oppure aggiungerlo ai domini fidati tramite File->Avanzate->Imposta domini fidati. Cliccando col tasto destro del mouse su un indirizzo puoi impostare il suo dominio come fidato tramite il menù contestuale.", # Filename
|
||||||
"sharedplaylistenabled-label" : u"Abilita le playlist condivise",
|
"sharedplaylistenabled-label" : "Abilita le playlist condivise",
|
||||||
"removefromplaylist-menu-label" : u"Rimuovi dalla playlist",
|
"removefromplaylist-menu-label" : "Rimuovi dalla playlist",
|
||||||
"shuffleremainingplaylist-menu-label" : u"Mescola i file non ancora riprodotti",
|
"shuffleremainingplaylist-menu-label" : "Mescola i file non ancora riprodotti",
|
||||||
"shuffleentireplaylist-menu-label" : u"Mescola l'intera playlist",
|
"shuffleentireplaylist-menu-label" : "Mescola l'intera playlist",
|
||||||
"undoplaylist-menu-label" : u"Annulla l'ultima modifica alla playlist",
|
"undoplaylist-menu-label" : "Annulla l'ultima modifica alla playlist",
|
||||||
"addfilestoplaylist-menu-label" : u"Aggiungi un file alla fine della playlist",
|
"addfilestoplaylist-menu-label" : "Aggiungi un file alla fine della playlist",
|
||||||
"addurlstoplaylist-menu-label" : u"Aggiungi un indirizzo alla fine della playlist",
|
"addurlstoplaylist-menu-label" : "Aggiungi un indirizzo alla fine della playlist",
|
||||||
"editplaylist-menu-label": u"Modifica la playlist",
|
"editplaylist-menu-label": "Modifica la playlist",
|
||||||
|
|
||||||
"open-containing-folder": u"Apri la cartella contenente questo file",
|
"open-containing-folder": "Apri la cartella contenente questo file",
|
||||||
"addusersfiletoplaylist-menu-label" : u"Aggiungi il file {} alla playlist", # item owner indicator # TODO needs testing
|
"addusersfiletoplaylist-menu-label" : "Aggiungi il file {} alla playlist", # item owner indicator # TODO needs testing
|
||||||
"addusersstreamstoplaylist-menu-label" : u"Aggiungi l'indirizzo {} alla playlist", # item owner indicator # TODO needs testing
|
"addusersstreamstoplaylist-menu-label" : "Aggiungi l'indirizzo {} alla playlist", # item owner indicator # TODO needs testing
|
||||||
"openusersstream-menu-label" : u"Apri l'indirizzo di {}", # [username]'s
|
"openusersstream-menu-label" : "Apri l'indirizzo di {}", # [username]'s
|
||||||
"openusersfile-menu-label" : u"Apri il file di {}", # [username]'s
|
"openusersfile-menu-label" : "Apri il file di {}", # [username]'s
|
||||||
"item-is-yours-indicator" : u"tuo", # Goes with addusersfiletoplaylist/addusersstreamstoplaylist # TODO needs testing
|
"item-is-yours-indicator" : "tuo", # Goes with addusersfiletoplaylist/addusersstreamstoplaylist # TODO needs testing
|
||||||
"item-is-others-indicator" : u"di {}", # username - goes with addusersfiletoplaylist/addusersstreamstoplaylist # TODO needs testing
|
"item-is-others-indicator" : "di {}", # username - goes with addusersfiletoplaylist/addusersstreamstoplaylist # TODO needs testing
|
||||||
|
|
||||||
"playlist-instruction-item-message" : u"Trascina qui i file per aggiungerli alla playlist condivisa.",
|
"playlist-instruction-item-message" : "Trascina qui i file per aggiungerli alla playlist condivisa.",
|
||||||
"sharedplaylistenabled-tooltip" : u"Gli operatori della stanza possono aggiungere i file a una playlist sincronizzata per garantire che tutti i partecipanti stiano guardando la stessa cosa. Configura le cartelle multimediali alla voce 'Miscellanea'.",
|
"sharedplaylistenabled-tooltip" : "Gli operatori della stanza possono aggiungere i file a una playlist sincronizzata per garantire che tutti i partecipanti stiano guardando la stessa cosa. Configura le cartelle multimediali alla voce 'Miscellanea'.",
|
||||||
}
|
}
|
||||||
|
|||||||
774
syncplay/messages_ru.py
Normal file → Executable file
774
syncplay/messages_ru.py
Normal file → Executable file
@ -3,478 +3,478 @@
|
|||||||
"""Russian dictionary"""
|
"""Russian dictionary"""
|
||||||
|
|
||||||
ru = {
|
ru = {
|
||||||
"LANGUAGE" : u"Русский", # (Russian)
|
"LANGUAGE" : "Русский", # (Russian)
|
||||||
|
|
||||||
# Client notifications
|
# Client notifications
|
||||||
"config-cleared-notification" : u"Настройки сброшены. Изменения вступят в силу при сохранении корректной конфигурации.",
|
"config-cleared-notification" : "Настройки сброшены. Изменения вступят в силу при сохранении корректной конфигурации.",
|
||||||
|
|
||||||
"relative-config-notification" : u"Загружены файлы относительной конфигурации: {}",
|
"relative-config-notification" : "Загружены файлы относительной конфигурации: {}",
|
||||||
|
|
||||||
"connection-attempt-notification" : u"Подключение к {}:{}", # Port, IP
|
"connection-attempt-notification" : "Подключение к {}:{}", # Port, IP
|
||||||
"reconnection-attempt-notification" : u"Соединение с сервером потеряно, переподключение",
|
"reconnection-attempt-notification" : "Соединение с сервером потеряно, переподключение",
|
||||||
"disconnection-notification" : u"Отключились от сервера",
|
"disconnection-notification" : "Отключились от сервера",
|
||||||
"connection-failed-notification" : u"Не удалось подключиться к серверу",
|
"connection-failed-notification" : "Не удалось подключиться к серверу",
|
||||||
"connected-successful-notification" : u"Соединение с сервером установлено",
|
"connected-successful-notification" : "Соединение с сервером установлено",
|
||||||
"retrying-notification" : u"%s, следующая попытка через %d секунд(ы)...", # Seconds
|
"retrying-notification" : "%s, следующая попытка через %d секунд(ы)...", # Seconds
|
||||||
|
|
||||||
"rewind-notification" : u"Перемотано из-за разницы во времени с {}", # User
|
"rewind-notification" : "Перемотано из-за разницы во времени с {}", # User
|
||||||
"fastforward-notification" : u"Ускорено из-за разницы во времени с {}", # User
|
"fastforward-notification" : "Ускорено из-за разницы во времени с {}", # User
|
||||||
"slowdown-notification" : u"Воспроизведение замедлено из-за разницы во времени с {}", # User
|
"slowdown-notification" : "Воспроизведение замедлено из-за разницы во времени с {}", # User
|
||||||
"revert-notification" : u"Возвращаемся к нормальной скорости воспроизведения",
|
"revert-notification" : "Возвращаемся к нормальной скорости воспроизведения",
|
||||||
|
|
||||||
"pause-notification" : u"{} приостановил воспроизведение", # User
|
"pause-notification" : "{} приостановил воспроизведение", # User
|
||||||
"unpause-notification" : u"{} возобновил воспроизведение", # User
|
"unpause-notification" : "{} возобновил воспроизведение", # User
|
||||||
"seek-notification" : u"{} перемотал с {} на {}", # User, from time, to time
|
"seek-notification" : "{} перемотал с {} на {}", # User, from time, to time
|
||||||
|
|
||||||
"current-offset-notification" : u"Текущее смещение: {} секунд(ы)", # Offset
|
"current-offset-notification" : "Текущее смещение: {} секунд(ы)", # Offset
|
||||||
|
|
||||||
"media-directory-list-updated-notification" : u"Папки воспроизведения обновлены.",
|
"media-directory-list-updated-notification" : "Папки воспроизведения обновлены.",
|
||||||
|
|
||||||
"room-join-notification" : u"{} зашел в комнату: '{}'", # User
|
"room-join-notification" : "{} зашел в комнату: '{}'", # User
|
||||||
"left-notification" : u"{} покинул комнату", # User
|
"left-notification" : "{} покинул комнату", # User
|
||||||
"left-paused-notification" : u"{} покинул комнату, {} приостановил воспроизведение", # User who left, User who paused
|
"left-paused-notification" : "{} покинул комнату, {} приостановил воспроизведение", # User who left, User who paused
|
||||||
"playing-notification" : u"{} включил '{}' ({})", # User, file, duration
|
"playing-notification" : "{} включил '{}' ({})", # User, file, duration
|
||||||
"playing-notification/room-addendum" : u" в комнате: '{}'", # Room
|
"playing-notification/room-addendum" : " в комнате: '{}'", # Room
|
||||||
|
|
||||||
"not-all-ready" : u"Не готовы: {}", # Usernames
|
"not-all-ready" : "Не готовы: {}", # Usernames
|
||||||
"all-users-ready" : u"Все зрители готовы ({} чел.)", #Number of ready users
|
"all-users-ready" : "Все зрители готовы ({} чел.)", #Number of ready users
|
||||||
"ready-to-unpause-notification" : u"Вы помечены как готовый - нажмите еще раз, чтобы продолжить воспроизведение",
|
"ready-to-unpause-notification" : "Вы помечены как готовый - нажмите еще раз, чтобы продолжить воспроизведение",
|
||||||
"set-as-ready-notification" : u"Вы помечены как готовый",
|
"set-as-ready-notification" : "Вы помечены как готовый",
|
||||||
"set-as-not-ready-notification" : u"Вы помечены как неготовый",
|
"set-as-not-ready-notification" : "Вы помечены как неготовый",
|
||||||
"autoplaying-notification" : u"Автовоспроизведение через {}...", # Number of seconds until playback will start
|
"autoplaying-notification" : "Автовоспроизведение через {}...", # Number of seconds until playback will start
|
||||||
|
|
||||||
"identifying-as-controller-notification" : u"Идентификация как оператора комнаты с паролем '{}'...",
|
"identifying-as-controller-notification" : "Идентификация как оператора комнаты с паролем '{}'...",
|
||||||
"failed-to-identify-as-controller-notification" : u"{} не прошел идентификацию в качестве оператора комнаты.",
|
"failed-to-identify-as-controller-notification" : "{} не прошел идентификацию в качестве оператора комнаты.",
|
||||||
"authenticated-as-controller-notification" : u"{} вошел как оператор комнаты.",
|
"authenticated-as-controller-notification" : "{} вошел как оператор комнаты.",
|
||||||
"created-controlled-room-notification" : u"Создана управляемая комната '{}' с паролем '{}'. Сохраните эти данные!", # RoomName, operatorPassword
|
"created-controlled-room-notification" : "Создана управляемая комната '{}' с паролем '{}'. Сохраните эти данные!", # RoomName, operatorPassword
|
||||||
|
|
||||||
"file-different-notification" : u"Вероятно, файл, который Вы смотрите, отличается от того, который смотрит {}.", # User
|
"file-different-notification" : "Вероятно, файл, который Вы смотрите, отличается от того, который смотрит {}.", # User
|
||||||
"file-differences-notification" : u"Ваш файл отличается: {}", # Differences
|
"file-differences-notification" : "Ваш файл отличается: {}", # Differences
|
||||||
"room-file-differences" : u"Несовпадения файла: {}", # File differences (filename, size, and/or duration)
|
"room-file-differences" : "Несовпадения файла: {}", # File differences (filename, size, and/or duration)
|
||||||
"file-difference-filename" : u"имя",
|
"file-difference-filename" : "имя",
|
||||||
"file-difference-filesize" : u"размер",
|
"file-difference-filesize" : "размер",
|
||||||
"file-difference-duration" : u"длительность",
|
"file-difference-duration" : "длительность",
|
||||||
"alone-in-the-room" : u"В комнате кроме Вас никого нет.",
|
"alone-in-the-room" : "В комнате кроме Вас никого нет.",
|
||||||
|
|
||||||
"different-filesize-notification" : u" (размер Вашего файла не совпадает с размером их файла!)",
|
"different-filesize-notification" : " (размер Вашего файла не совпадает с размером их файла!)",
|
||||||
"userlist-playing-notification" : u"{} смотрит:", #Username
|
"userlist-playing-notification" : "{} смотрит:", #Username
|
||||||
"file-played-by-notification" : u"Файл: {} просматривают:", # File
|
"file-played-by-notification" : "Файл: {} просматривают:", # File
|
||||||
"no-file-played-notification" : u"{} не смотрит ничего", # Username
|
"no-file-played-notification" : "{} не смотрит ничего", # Username
|
||||||
"notplaying-notification" : u"Люди, которые не смотрят ничего:",
|
"notplaying-notification" : "Люди, которые не смотрят ничего:",
|
||||||
"userlist-room-notification" : u"В комнате '{}':", # Room
|
"userlist-room-notification" : "В комнате '{}':", # Room
|
||||||
"userlist-file-notification" : u"Файл",
|
"userlist-file-notification" : "Файл",
|
||||||
"controller-userlist-userflag" : u"Оператор",
|
"controller-userlist-userflag" : "Оператор",
|
||||||
"ready-userlist-userflag" : u"Готов",
|
"ready-userlist-userflag" : "Готов",
|
||||||
|
|
||||||
"update-check-failed-notification" : u"Невозможно автоматически проверить, что версия Syncplay {} все еще актуальна. Хотите зайти на https://syncplay.pl/ и вручную проверить наличие обновлений?",
|
"update-check-failed-notification" : "Невозможно автоматически проверить, что версия Syncplay {} все еще актуальна. Хотите зайти на https://syncplay.pl/ и вручную проверить наличие обновлений?",
|
||||||
"syncplay-uptodate-notification" : u"У вас последняя версия Syncplay",
|
"syncplay-uptodate-notification" : "У вас последняя версия Syncplay",
|
||||||
"syncplay-updateavailable-notification" : u"Доступна новая версия Syncplay. Хотите открыть страницу релиза?",
|
"syncplay-updateavailable-notification" : "Доступна новая версия Syncplay. Хотите открыть страницу релиза?",
|
||||||
|
|
||||||
"mplayer-file-required-notification" : u"Для использования Syncplay с mplayer необходимо передать файл в качестве параметра",
|
"mplayer-file-required-notification" : "Для использования Syncplay с mplayer необходимо передать файл в качестве параметра",
|
||||||
"mplayer-file-required-notification/example" : u"Пример использования: syncplay [options] [url|path/]filename",
|
"mplayer-file-required-notification/example" : "Пример использования: syncplay [options] [url|path/]filename",
|
||||||
"mplayer2-required" : u"Syncplay не совместим с MPlayer 1.x, пожалуйста, используйте mplayer2 или mpv",
|
"mplayer2-required" : "Syncplay не совместим с MPlayer 1.x, пожалуйста, используйте mplayer2 или mpv",
|
||||||
|
|
||||||
"unrecognized-command-notification" : u"Неизвестная команда.",
|
"unrecognized-command-notification" : "Неизвестная команда.",
|
||||||
"commandlist-notification" : u"Доступные команды:",
|
"commandlist-notification" : "Доступные команды:",
|
||||||
"commandlist-notification/room" : u"\tr [name] - сменить комнату",
|
"commandlist-notification/room" : "\tr [name] - сменить комнату",
|
||||||
"commandlist-notification/list" : u"\tl - показать список пользователей",
|
"commandlist-notification/list" : "\tl - показать список пользователей",
|
||||||
"commandlist-notification/undo" : u"\tu - отменить последнюю перемотку",
|
"commandlist-notification/undo" : "\tu - отменить последнюю перемотку",
|
||||||
"commandlist-notification/pause" : u"\tp - вкл./выкл. паузу",
|
"commandlist-notification/pause" : "\tp - вкл./выкл. паузу",
|
||||||
"commandlist-notification/seek" : u"\t[s][+-]time - перемотать к заданному моменту времени, если не указан + или -, то время считается абсолютным (от начала файла) в секундах или мин:сек",
|
"commandlist-notification/seek" : "\t[s][+-]time - перемотать к заданному моменту времени, если не указан + или -, то время считается абсолютным (от начала файла) в секундах или мин:сек",
|
||||||
"commandlist-notification/help" : u"\th - помощь",
|
"commandlist-notification/help" : "\th - помощь",
|
||||||
"commandlist-notification/toggle" : u"\tt - переключить статус готов/не готов к просмотру",
|
"commandlist-notification/toggle" : "\tt - переключить статус готов/не готов к просмотру",
|
||||||
"commandlist-notification/create" : u"\tc [name] - создать управляемую комнату с таким же именем, как у текущей",
|
"commandlist-notification/create" : "\tc [name] - создать управляемую комнату с таким же именем, как у текущей",
|
||||||
"commandlist-notification/auth" : u"\ta [password] - авторизоваться как оператор комнаты с помощью пароля",
|
"commandlist-notification/auth" : "\ta [password] - авторизоваться как оператор комнаты с помощью пароля",
|
||||||
"commandlist-notification/chat" : "\tch [message] - send a chat message in a room", # TODO: Translate
|
"commandlist-notification/chat" : "\tch [message] - send a chat message in a room", # TODO: Translate
|
||||||
"syncplay-version-notification" : u"Версия Syncplay: {}", # syncplay.version
|
"syncplay-version-notification" : "Версия Syncplay: {}", # syncplay.version
|
||||||
"more-info-notification" : u"Больше информации на {}", # projectURL
|
"more-info-notification" : "Больше информации на {}", # projectURL
|
||||||
|
|
||||||
"gui-data-cleared-notification" : u"Syncplay очистил путь и информацию о состоянии окна, использованного GUI.",
|
"gui-data-cleared-notification" : "Syncplay очистил путь и информацию о состоянии окна, использованного GUI.",
|
||||||
"language-changed-msgbox-label" : u"Язык переключится при следующем запуске Syncplay.",
|
"language-changed-msgbox-label" : "Язык переключится при следующем запуске Syncplay.",
|
||||||
"promptforupdate-label" : u"Вы не против, если Syncplay будет автоматически изредка проверять наличие обновлений?",
|
"promptforupdate-label" : "Вы не против, если Syncplay будет автоматически изредка проверять наличие обновлений?",
|
||||||
|
|
||||||
"vlc-version-mismatch": u"Syncplay не поддерживает данную версию VLC. Syncplay поддерживает VLC {}+, но не VLC 3. Используйте другой проигрыватель.", # VLC min version
|
"vlc-version-mismatch": "Syncplay не поддерживает данную версию VLC. Syncplay поддерживает VLC {}+, но не VLC 3. Используйте другой проигрыватель.", # VLC min version
|
||||||
"vlc-interface-version-mismatch" : u"Вы используете модуль интерфейса Syncplay устаревшей версии {} для VLC. К сожалению, Syncplay способен работать с версией {} и выше. Пожалуйста, обратитесь к Руководству Пользователя Syncplay (https://syncplay.pl/guide/) за инструкциями о том, как установить syncplay.lua.", # VLC interface version, VLC interface min version
|
"vlc-interface-version-mismatch" : "Вы используете модуль интерфейса Syncplay устаревшей версии {} для VLC. К сожалению, Syncplay способен работать с версией {} и выше. Пожалуйста, обратитесь к Руководству Пользователя Syncplay (https://syncplay.pl/guide/) за инструкциями о том, как установить syncplay.lua.", # VLC interface version, VLC interface min version
|
||||||
"vlc-interface-oldversion-warning" : u"Внимание: Syncplay обнаружил, что старая версия модуля интерфейса Syncplay для VLC уже установлена в директорию VLC. Пожалуйста, обратитесь к Руководству Пользователя Syncplay (https://syncplay.pl/guide/) за инструкциями о том, как установить syncplay.lua.",
|
"vlc-interface-oldversion-warning" : "Внимание: Syncplay обнаружил, что старая версия модуля интерфейса Syncplay для VLC уже установлена в директорию VLC. Пожалуйста, обратитесь к Руководству Пользователя Syncplay (https://syncplay.pl/guide/) за инструкциями о том, как установить syncplay.lua.",
|
||||||
"vlc-interface-not-installed" : u"Внимание: Модуль интерфейса Syncplay для VLC не обнаружен в директории VLC. По существу, если Вы используете VLC 2.0, то VLC будет использовать модуль syncplay.lua из директории Syncplay, но в таком случае другие пользовательские скрипты и расширения интерфейса не будут работать. Пожалуйста, обратитесь к Руководству Пользователя Syncplay (https://syncplay.pl/guide/) за инструкциями о том, как установить syncplay.lua.",
|
"vlc-interface-not-installed" : "Внимание: Модуль интерфейса Syncplay для VLC не обнаружен в директории VLC. По существу, если Вы используете VLC 2.0, то VLC будет использовать модуль syncplay.lua из директории Syncplay, но в таком случае другие пользовательские скрипты и расширения интерфейса не будут работать. Пожалуйста, обратитесь к Руководству Пользователя Syncplay (https://syncplay.pl/guide/) за инструкциями о том, как установить syncplay.lua.",
|
||||||
"media-player-latency-warning": u"Внимание: У Вашего проигрывателя слишком большой отклик ({} секунд). Если Вы замечаете проблемы с синхронизацией, то закройте ресурсоемкие приложения. Если это не помогло - попробуйте другой проигрыватель.", # Seconds to respond
|
"media-player-latency-warning": "Внимание: У Вашего проигрывателя слишком большой отклик ({} секунд). Если Вы замечаете проблемы с синхронизацией, то закройте ресурсоемкие приложения. Если это не помогло - попробуйте другой проигрыватель.", # Seconds to respond
|
||||||
"mpv-unresponsive-error": u"mpv не отвечает {} секунд, по-видимому, произошел сбой. Пожалуйста, перезапустите Syncplay.", # Seconds to respond
|
"mpv-unresponsive-error": "mpv не отвечает {} секунд, по-видимому, произошел сбой. Пожалуйста, перезапустите Syncplay.", # Seconds to respond
|
||||||
|
|
||||||
# Client prompts
|
# Client prompts
|
||||||
"enter-to-exit-prompt" : u"Для выхода нажмите Enter\n",
|
"enter-to-exit-prompt" : "Для выхода нажмите Enter\n",
|
||||||
|
|
||||||
# Client errors
|
# Client errors
|
||||||
"missing-arguments-error" : u"Некоторые необходимые аргументы отсутствуют, обратитесь к --help",
|
"missing-arguments-error" : "Некоторые необходимые аргументы отсутствуют, обратитесь к --help",
|
||||||
"server-timeout-error" : u"Подключение к серверу превысило лимит времени",
|
"server-timeout-error" : "Подключение к серверу превысило лимит времени",
|
||||||
"mpc-slave-error" : u"Невозможно запустить MPC в slave режиме!",
|
"mpc-slave-error" : "Невозможно запустить MPC в slave режиме!",
|
||||||
"mpc-version-insufficient-error" : u"Версия MPC слишком старая, пожалуйста, используйте `mpc-hc` >= `{}`",
|
"mpc-version-insufficient-error" : "Версия MPC слишком старая, пожалуйста, используйте `mpc-hc` >= `{}`",
|
||||||
"mpc-be-version-insufficient-error" : u"Версия MPC слишком старая, пожалуйста, используйте `mpc-be` >= `{}`",
|
"mpc-be-version-insufficient-error" : "Версия MPC слишком старая, пожалуйста, используйте `mpc-be` >= `{}`",
|
||||||
"mpv-version-error" : u"Syncplay не совместим с данной версией mpv. Пожалуйста, используйте другую версию mpv (лучше свежайшую).",
|
"mpv-version-error" : "Syncplay не совместим с данной версией mpv. Пожалуйста, используйте другую версию mpv (лучше свежайшую).",
|
||||||
"player-file-open-error" : u"Проигрыватель не может открыть файл.",
|
"player-file-open-error" : "Проигрыватель не может открыть файл.",
|
||||||
"player-path-error" : u"Путь к проигрывателю задан неверно. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2.", # TODO: Translate last sentence
|
"player-path-error" : "Путь к проигрывателю задан неверно. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2.", # TODO: Translate last sentence
|
||||||
"hostname-empty-error" : u"Имя пользователя не может быть пустым.",
|
"hostname-empty-error" : "Имя пользователя не может быть пустым.",
|
||||||
"empty-error" : u"{} не может быть пустым.", # Configuration
|
"empty-error" : "{} не может быть пустым.", # Configuration
|
||||||
"media-player-error" : u"Ошибка проигрывателя: \"{}\"", # Error line
|
"media-player-error" : "Ошибка проигрывателя: \"{}\"", # Error line
|
||||||
"unable-import-gui-error" : u"Невозможно импортировать библиотеки GUI (графического интерфейса). Необходимо установить PySide, иначе графический интерфейс не будет работать.",
|
"unable-import-gui-error" : "Невозможно импортировать библиотеки GUI (графического интерфейса). Необходимо установить PySide, иначе графический интерфейс не будет работать.",
|
||||||
|
|
||||||
"arguments-missing-error" : u"Некоторые необходимые аргументы отсутствуют, обратитесь к --help",
|
"arguments-missing-error" : "Некоторые необходимые аргументы отсутствуют, обратитесь к --help",
|
||||||
|
|
||||||
"unable-to-start-client-error" : u"Невозможно запустить клиент",
|
"unable-to-start-client-error" : "Невозможно запустить клиент",
|
||||||
|
|
||||||
"player-path-config-error": u"Путь к проигрывателю установлен неверно. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2", # To do: Translate end
|
"player-path-config-error": "Путь к проигрывателю установлен неверно. Supported players are: mpv, VLC, MPC-HC, MPC-BE and mplayer2", # To do: Translate end
|
||||||
"no-file-path-config-error" : u"Файл должен быть указан до включения проигрывателя",
|
"no-file-path-config-error" : "Файл должен быть указан до включения проигрывателя",
|
||||||
"no-hostname-config-error": u"Имя сервера не может быть пустым",
|
"no-hostname-config-error": "Имя сервера не может быть пустым",
|
||||||
"invalid-port-config-error" : u"Неверный номер порта",
|
"invalid-port-config-error" : "Неверный номер порта",
|
||||||
"empty-value-config-error" : u"Поле '{}' не может быть пустым", # Config option
|
"empty-value-config-error" : "Поле '{}' не может быть пустым", # Config option
|
||||||
|
|
||||||
"not-json-error" : u"Не является закодированной json-строкой\n",
|
"not-json-error" : "Не является закодированной json-строкой\n",
|
||||||
"hello-arguments-error" : u"Не хватает аргументов Hello\n",
|
"hello-arguments-error" : "Не хватает аргументов Hello\n",
|
||||||
"version-mismatch-error" : u"Конфликт версий между клиентом и сервером\n",
|
"version-mismatch-error" : "Конфликт версий между клиентом и сервером\n",
|
||||||
"vlc-failed-connection" : u"Ошибка подключения к VLC. Если у Вас не установлен syncplay.lua, то обратитесь к https://syncplay.pl/LUA/ за инструкциями.",
|
"vlc-failed-connection" : "Ошибка подключения к VLC. Если у Вас не установлен syncplay.lua, то обратитесь к https://syncplay.pl/LUA/ за инструкциями.",
|
||||||
"vlc-failed-noscript" : u"VLC сообщает, что скрипт интерфейса syncplay.lua не установлен. Пожалуйста, обратитесь к https://syncplay.pl/LUA/ за инструкциями.",
|
"vlc-failed-noscript" : "VLC сообщает, что скрипт интерфейса syncplay.lua не установлен. Пожалуйста, обратитесь к https://syncplay.pl/LUA/ за инструкциями.",
|
||||||
"vlc-failed-versioncheck" : u"Данная версия VLC не поддерживается Syncplay. Пожалуйста, используйте VLC версии 2 или выше.",
|
"vlc-failed-versioncheck" : "Данная версия VLC не поддерживается Syncplay. Пожалуйста, используйте VLC версии 2 или выше.",
|
||||||
"vlc-failed-other" : u"Во время загрузки скрипта интерфейса syncplay.lua в VLC произошла следующая ошибка: {}", # Syncplay Error
|
"vlc-failed-other" : "Во время загрузки скрипта интерфейса syncplay.lua в VLC произошла следующая ошибка: {}", # Syncplay Error
|
||||||
|
|
||||||
"feature-sharedPlaylists": u"shared playlists", # used for not-supported-by-server-error # TODO: Translate
|
"feature-sharedPlaylists": "shared playlists", # used for not-supported-by-server-error # TODO: Translate
|
||||||
"feature-chat": u"chat", # used for not-supported-by-server-error # TODO: Translate
|
"feature-chat": "chat", # used for not-supported-by-server-error # TODO: Translate
|
||||||
"feature-readiness": u"readiness", # used for not-supported-by-server-error # TODO: Translate
|
"feature-readiness": "readiness", # used for not-supported-by-server-error # TODO: Translate
|
||||||
"feature-managedRooms": u"managed rooms", # used for not-supported-by-server-error # TODO: Translate
|
"feature-managedRooms": "managed rooms", # used for not-supported-by-server-error # TODO: Translate
|
||||||
|
|
||||||
"not-supported-by-server-error": u"The {} feature is not supported by this server..", # feature # TODO: Translate
|
"not-supported-by-server-error": "The {} feature is not supported by this server..", # feature # TODO: Translate
|
||||||
#OLD TRANSLATION: "not-supported-by-server-error" : u"Эта возможность не поддерживается сервером. Требуется сервер Syncplay {}+, вы подключены к серверу Syncplay {}.", #minVersion, serverVersion
|
#OLD TRANSLATION: "not-supported-by-server-error" : u"Эта возможность не поддерживается сервером. Требуется сервер Syncplay {}+, вы подключены к серверу Syncplay {}.", #minVersion, serverVersion
|
||||||
"shared-playlists-not-supported-by-server-error" : u"Общие списки воспроизведения могут не поддерживаться сервером. Для корректной работы требуется сервер Syncplay {}+, вы подключены к серверу Syncplay {}.", #minVersion, serverVersion
|
"shared-playlists-not-supported-by-server-error" : "Общие списки воспроизведения могут не поддерживаться сервером. Для корректной работы требуется сервер Syncplay {}+, вы подключены к серверу Syncplay {}.", #minVersion, serverVersion
|
||||||
"shared-playlists-disabled-by-server-error" : "The shared playlist feature has been disabled in the server configuration. To use this feature you will need to connect to a different server.", # TODO: Translate
|
"shared-playlists-disabled-by-server-error" : "The shared playlist feature has been disabled in the server configuration. To use this feature you will need to connect to a different server.", # TODO: Translate
|
||||||
|
|
||||||
"invalid-seek-value" : u"Некорректное значение для перемотки",
|
"invalid-seek-value" : "Некорректное значение для перемотки",
|
||||||
"invalid-offset-value" : u"Некорректное смещение",
|
"invalid-offset-value" : "Некорректное смещение",
|
||||||
|
|
||||||
"switch-file-not-found-error" : u"Невозможно найти файл '{0}'. Проверьте папки воспроизведения.", # File not found
|
"switch-file-not-found-error" : "Невозможно найти файл '{0}'. Проверьте папки воспроизведения.", # File not found
|
||||||
"folder-search-timeout-error" : u"Поиск файла был прерван в папке '{}'. Это может происходить из-за большого количества подпапок. Для корректной работы поиска файлов зайдите через выпадающее меню в Файл->Папки воспроизведения и удалите данную папку из списка, или замените её на нужную подпапку. If the folder is actually fine then you can re-enable it by selecting File->Set Media Directories and pressing 'OK'.", #Folder # TODO: Translate last sentence
|
"folder-search-timeout-error" : "Поиск файла был прерван в папке '{}'. Это может происходить из-за большого количества подпапок. Для корректной работы поиска файлов зайдите через выпадающее меню в Файл->Папки воспроизведения и удалите данную папку из списка, или замените её на нужную подпапку. If the folder is actually fine then you can re-enable it by selecting File->Set Media Directories and pressing 'OK'.", #Folder # TODO: Translate last sentence
|
||||||
"folder-search-first-file-timeout-error" : u"Поиск файла в '{}' был прерван, так как невозможно открыть каталог. Это может происходить, если это сетевой диск или диск перешел в режим экономии энергии. Для корректной работы поиска файлов зайдите через выпадающее меню в Файл->Папки воспроизведения и удалите данную папку, или решите проблему через изменение параметров энергосбережения.", #Folder
|
"folder-search-first-file-timeout-error" : "Поиск файла в '{}' был прерван, так как невозможно открыть каталог. Это может происходить, если это сетевой диск или диск перешел в режим экономии энергии. Для корректной работы поиска файлов зайдите через выпадающее меню в Файл->Папки воспроизведения и удалите данную папку, или решите проблему через изменение параметров энергосбережения.", #Folder
|
||||||
"added-file-not-in-media-directory-error" : u"Вы загрузили файл из '{}', который не числится в папках воспроизведения. Вы можете добавить его через выпадающее меню Файл->Папки воспроизведения.", #Folder
|
"added-file-not-in-media-directory-error" : "Вы загрузили файл из '{}', который не числится в папках воспроизведения. Вы можете добавить его через выпадающее меню Файл->Папки воспроизведения.", #Folder
|
||||||
"no-media-directories-error" : u"Вы не указали папки воспроизведения. Для корректной работы зайдите через выпадающее меню в Файл->Папки воспроизведения и укажите нужные каталоги.",
|
"no-media-directories-error" : "Вы не указали папки воспроизведения. Для корректной работы зайдите через выпадающее меню в Файл->Папки воспроизведения и укажите нужные каталоги.",
|
||||||
"cannot-find-directory-error" : u"Не удалось найти папку воспроизведения '{}'. Для обновления списка папок, через выпадающее меню, перейдите в Файл->Папки воспроизведения и укажите нужные каталоги.",
|
"cannot-find-directory-error" : "Не удалось найти папку воспроизведения '{}'. Для обновления списка папок, через выпадающее меню, перейдите в Файл->Папки воспроизведения и укажите нужные каталоги.",
|
||||||
|
|
||||||
"failed-to-load-server-list-error" : u"Не удалось загрузить список публичных серверов. Откройте https://www.syncplay.pl/ через браузер.",
|
"failed-to-load-server-list-error" : "Не удалось загрузить список публичных серверов. Откройте https://www.syncplay.pl/ через браузер.",
|
||||||
|
|
||||||
# Client arguments
|
# Client arguments
|
||||||
"argument-description" : u'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC/BE через Интернет.',
|
"argument-description" : 'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC/BE через Интернет.',
|
||||||
"argument-epilog" : u'Если параметр не будет передан, то будет использоваться значение, указанное в _config.',
|
"argument-epilog" : 'Если параметр не будет передан, то будет использоваться значение, указанное в _config.',
|
||||||
"nogui-argument" : u'не использовать GUI',
|
"nogui-argument" : 'не использовать GUI',
|
||||||
"host-argument" : u'адрес сервера',
|
"host-argument" : 'адрес сервера',
|
||||||
"name-argument" : u'желательное имя пользователя',
|
"name-argument" : 'желательное имя пользователя',
|
||||||
"debug-argument" : u'режим отладки',
|
"debug-argument" : 'режим отладки',
|
||||||
"force-gui-prompt-argument" : u'показать окно настройки',
|
"force-gui-prompt-argument" : 'показать окно настройки',
|
||||||
"no-store-argument" : u'не сохранять данные в .syncplay',
|
"no-store-argument" : 'не сохранять данные в .syncplay',
|
||||||
"room-argument" : u'начальная комната',
|
"room-argument" : 'начальная комната',
|
||||||
"password-argument" : u'пароль для доступа к серверу',
|
"password-argument" : 'пароль для доступа к серверу',
|
||||||
"player-path-argument" : u'путь к исполняемому файлу Вашего проигрывателя',
|
"player-path-argument" : 'путь к исполняемому файлу Вашего проигрывателя',
|
||||||
"file-argument" : u'воспроизводимый файл',
|
"file-argument" : 'воспроизводимый файл',
|
||||||
"args-argument" : u'параметры проигрывателя; если нужно передать параметры, начинающиеся с - , то сначала пишите \'--\'',
|
"args-argument" : 'параметры проигрывателя; если нужно передать параметры, начинающиеся с - , то сначала пишите \'--\'',
|
||||||
"clear-gui-data-argument" : u'сбрасывает путь и данные о состоянии окна GUI, хранимые как QSettings',
|
"clear-gui-data-argument" : 'сбрасывает путь и данные о состоянии окна GUI, хранимые как QSettings',
|
||||||
"language-argument" : u'язык сообщений Syncplay (de/en/ru)',
|
"language-argument" : 'язык сообщений Syncplay (de/en/ru)',
|
||||||
|
|
||||||
"version-argument" : u'выводит номер версии',
|
"version-argument" : 'выводит номер версии',
|
||||||
"version-message" : u"Вы используете Syncplay версии {} ({})",
|
"version-message" : "Вы используете Syncplay версии {} ({})",
|
||||||
|
|
||||||
# Client labels
|
# Client labels
|
||||||
"config-window-title" : u"Настройка Syncplay",
|
"config-window-title" : "Настройка Syncplay",
|
||||||
|
|
||||||
"connection-group-title" : u"Подключение",
|
"connection-group-title" : "Подключение",
|
||||||
"host-label" : u"Адрес сервера: ",
|
"host-label" : "Адрес сервера: ",
|
||||||
"name-label" : u"Имя пользователя (не обязательно):",
|
"name-label" : "Имя пользователя (не обязательно):",
|
||||||
"password-label" : u"Пароль сервера (если требуется):",
|
"password-label" : "Пароль сервера (если требуется):",
|
||||||
"room-label" : u"Комната:",
|
"room-label" : "Комната:",
|
||||||
|
|
||||||
"media-setting-title" : u"Воспроизведение",
|
"media-setting-title" : "Воспроизведение",
|
||||||
"executable-path-label" : u"Путь к проигрывателю:",
|
"executable-path-label" : "Путь к проигрывателю:",
|
||||||
"media-path-label" : u"Путь к видеофайлу:", # Todo: Translate to 'Path to video (optional)'
|
"media-path-label" : "Путь к видеофайлу:", # Todo: Translate to 'Path to video (optional)'
|
||||||
"player-arguments-label" : u"Аргументы запуска проигрывателя:",
|
"player-arguments-label" : "Аргументы запуска проигрывателя:",
|
||||||
"browse-label" : u"Выбрать",
|
"browse-label" : "Выбрать",
|
||||||
"update-server-list-label" : u"Обновить список",
|
"update-server-list-label" : "Обновить список",
|
||||||
|
|
||||||
"more-title" : u"Больше настроек",
|
"more-title" : "Больше настроек",
|
||||||
"never-rewind-value" : u"Никогда",
|
"never-rewind-value" : "Никогда",
|
||||||
"seconds-suffix" : u" секунд(ы)",
|
"seconds-suffix" : " секунд(ы)",
|
||||||
"privacy-sendraw-option" : u"отпр. как есть",
|
"privacy-sendraw-option" : "отпр. как есть",
|
||||||
"privacy-sendhashed-option" : u"отпр. хэш",
|
"privacy-sendhashed-option" : "отпр. хэш",
|
||||||
"privacy-dontsend-option" : u"не отпр.",
|
"privacy-dontsend-option" : "не отпр.",
|
||||||
"filename-privacy-label" : u"Имя файла:",
|
"filename-privacy-label" : "Имя файла:",
|
||||||
"filesize-privacy-label" : u"Размер файла:",
|
"filesize-privacy-label" : "Размер файла:",
|
||||||
"checkforupdatesautomatically-label" : u"Проверять обновления автоматически",
|
"checkforupdatesautomatically-label" : "Проверять обновления автоматически",
|
||||||
"slowondesync-label" : u"Замедлять при небольших рассинхронизациях (не поддерживаетя в MPC-HC/BE)",
|
"slowondesync-label" : "Замедлять при небольших рассинхронизациях (не поддерживаетя в MPC-HC/BE)",
|
||||||
"rewindondesync-label" : u"Перемотка при больших рассинхронизациях (настоятельно рекомендуется)",
|
"rewindondesync-label" : "Перемотка при больших рассинхронизациях (настоятельно рекомендуется)",
|
||||||
"dontslowdownwithme-label" : u"Никогда не замедлять и не перематывать видео другим (функция тестируется)",
|
"dontslowdownwithme-label" : "Никогда не замедлять и не перематывать видео другим (функция тестируется)",
|
||||||
"pausing-title" : u"Приостановка",
|
"pausing-title" : "Приостановка",
|
||||||
"pauseonleave-label" : u"Приостанавливать, когда кто-то уходит (например, отключился)",
|
"pauseonleave-label" : "Приостанавливать, когда кто-то уходит (например, отключился)",
|
||||||
"readiness-title" : u"Готовность",
|
"readiness-title" : "Готовность",
|
||||||
"readyatstart-label" : u"Выставить статус 'Я готов' по умолчанию",
|
"readyatstart-label" : "Выставить статус 'Я готов' по умолчанию",
|
||||||
"fastforwardondesync-label" : u"Ускорять видео при отставании (рекомендуется)",
|
"fastforwardondesync-label" : "Ускорять видео при отставании (рекомендуется)",
|
||||||
"forceguiprompt-label" : u"Не показывать больше этот диалог", # (Inverted)
|
"forceguiprompt-label" : "Не показывать больше этот диалог", # (Inverted)
|
||||||
"showosd-label" : u"Включить экранные сообщения (поверх видео)",
|
"showosd-label" : "Включить экранные сообщения (поверх видео)",
|
||||||
|
|
||||||
"showosdwarnings-label" : u"Показывать предупреждения (напр., когда файлы не совпадают)",
|
"showosdwarnings-label" : "Показывать предупреждения (напр., когда файлы не совпадают)",
|
||||||
"showsameroomosd-label" : u"Показывать события Вашей комнаты",
|
"showsameroomosd-label" : "Показывать события Вашей комнаты",
|
||||||
"shownoncontrollerosd-label" : u"Включить события, связанные с не-операторами в управляемой комнате.",
|
"shownoncontrollerosd-label" : "Включить события, связанные с не-операторами в управляемой комнате.",
|
||||||
"showdifferentroomosd-label" : u"Показывать события других комнат",
|
"showdifferentroomosd-label" : "Показывать события других комнат",
|
||||||
"showslowdownosd-label" : u"Показывать уведомления о замедлении/перемотке",
|
"showslowdownosd-label" : "Показывать уведомления о замедлении/перемотке",
|
||||||
"language-label" : u"Язык:",
|
"language-label" : "Язык:",
|
||||||
"automatic-language" : u"По умолчанию ({})", # Automatic language
|
"automatic-language" : "По умолчанию ({})", # Automatic language
|
||||||
"showdurationnotification-label" : u"Предупреждать о несовпадении продолжительности видео",
|
"showdurationnotification-label" : "Предупреждать о несовпадении продолжительности видео",
|
||||||
"basics-label" : u"Основное",
|
"basics-label" : "Основное",
|
||||||
"readiness-label" : u"Поведение",
|
"readiness-label" : "Поведение",
|
||||||
"misc-label" : u"Прочее",
|
"misc-label" : "Прочее",
|
||||||
"core-behaviour-title" : u"Информация о файлах",
|
"core-behaviour-title" : "Информация о файлах",
|
||||||
"syncplay-internals-title" : u"Системные настройки",
|
"syncplay-internals-title" : "Системные настройки",
|
||||||
"syncplay-mediasearchdirectories-title" : u"Папки воспроизведения", #needs to be checked
|
"syncplay-mediasearchdirectories-title" : "Папки воспроизведения", #needs to be checked
|
||||||
"syncplay-mediasearchdirectories-label" : u"Папки воспроизведения (один путь на строку)",
|
"syncplay-mediasearchdirectories-label" : "Папки воспроизведения (один путь на строку)",
|
||||||
"sync-label" : u"Синхронизация",
|
"sync-label" : "Синхронизация",
|
||||||
"sync-otherslagging-title" : u"Опережение",
|
"sync-otherslagging-title" : "Опережение",
|
||||||
"sync-youlaggging-title" : u"Отставание",
|
"sync-youlaggging-title" : "Отставание",
|
||||||
"messages-label" : u"Сообщения",
|
"messages-label" : "Сообщения",
|
||||||
"messages-osd-title" : u"Настройки OSD",
|
"messages-osd-title" : "Настройки OSD",
|
||||||
"messages-other-title" : u"Другие настройки отображения",
|
"messages-other-title" : "Другие настройки отображения",
|
||||||
"chat-label" : u"Chat", # TODO: Translate
|
"chat-label" : "Chat", # TODO: Translate
|
||||||
"privacy-label" : u"Приватность",
|
"privacy-label" : "Приватность",
|
||||||
"privacy-title" : u"Настройки приватности",
|
"privacy-title" : "Настройки приватности",
|
||||||
"unpause-title" : u"Если вы стартуете, то:",
|
"unpause-title" : "Если вы стартуете, то:",
|
||||||
"unpause-ifalreadyready-option" : u"Снять паузу, если уже готов",
|
"unpause-ifalreadyready-option" : "Снять паузу, если уже готов",
|
||||||
"unpause-ifothersready-option" : u"Снять паузу, если Вы и остальные в комнате готовы (по-умолчанию)",
|
"unpause-ifothersready-option" : "Снять паузу, если Вы и остальные в комнате готовы (по-умолчанию)",
|
||||||
"unpause-ifminusersready-option" : u"Снять паузу, если все в комнате готовы и присутствует минимум зрителей",
|
"unpause-ifminusersready-option" : "Снять паузу, если все в комнате готовы и присутствует минимум зрителей",
|
||||||
"unpause-always" : u"Всегда снимать паузу",
|
"unpause-always" : "Всегда снимать паузу",
|
||||||
"syncplay-trusteddomains-title": u"Доверенные сайты (стрим-сервисы, видеохостинги, файлы в сети)",
|
"syncplay-trusteddomains-title": "Доверенные сайты (стрим-сервисы, видеохостинги, файлы в сети)",
|
||||||
"addtrusteddomain-menu-label" : u"Добавить {} как доверенный сайт", # Domain
|
"addtrusteddomain-menu-label" : "Добавить {} как доверенный сайт", # Domain
|
||||||
|
|
||||||
"chat-title": u"Chat message input", # TODO: Translate
|
"chat-title": "Chat message input", # TODO: Translate
|
||||||
"chatinputenabled-label": u"Enable chat input via mpv (using enter key)", # TODO: Translate
|
"chatinputenabled-label": "Enable chat input via mpv (using enter key)", # TODO: Translate
|
||||||
"chatdirectinput-label" : u"Allow instant chat input (bypass having to press enter key to chat)", # TODO: Translate
|
"chatdirectinput-label" : "Allow instant chat input (bypass having to press enter key to chat)", # TODO: Translate
|
||||||
"chatinputfont-label": u"Chat input font", # TODO: Translate
|
"chatinputfont-label": "Chat input font", # TODO: Translate
|
||||||
"chatfont-label": u"Set font", # TODO: Translate
|
"chatfont-label": "Set font", # TODO: Translate
|
||||||
"chatcolour-label": u"Set colour", # TODO: Translate
|
"chatcolour-label": "Set colour", # TODO: Translate
|
||||||
"chatinputposition-label": u"Position of message input area in mpv", # TODO: Translate
|
"chatinputposition-label": "Position of message input area in mpv", # TODO: Translate
|
||||||
"chat-top-option": u"Top", # TODO: Translate
|
"chat-top-option": "Top", # TODO: Translate
|
||||||
"chat-middle-option": u"Middle", # TODO: Translate
|
"chat-middle-option": "Middle", # TODO: Translate
|
||||||
"chat-bottom-option": u"Bottom", # TODO: Translate
|
"chat-bottom-option": "Bottom", # TODO: Translate
|
||||||
"chatoutputheader-label" : u"Chat message output", # TODO: Traslate
|
"chatoutputheader-label" : "Chat message output", # TODO: Traslate
|
||||||
"chatoutputfont-label": u"Chat output font", # TODO: Translate
|
"chatoutputfont-label": "Chat output font", # TODO: Translate
|
||||||
"chatoutputenabled-label": u"Enable chat output in media player (mpv only for now)", # TODO: Translate
|
"chatoutputenabled-label": "Enable chat output in media player (mpv only for now)", # TODO: Translate
|
||||||
"chatoutputposition-label": u"Output mode", # TODO: Translate
|
"chatoutputposition-label": "Output mode", # TODO: Translate
|
||||||
"chat-chatroom-option": u"Chatroom style", # TODO: Translate
|
"chat-chatroom-option": "Chatroom style", # TODO: Translate
|
||||||
"chat-scrolling-option": u"Scrolling style", # TODO: Translate
|
"chat-scrolling-option": "Scrolling style", # TODO: Translate
|
||||||
|
|
||||||
"mpv-key-tab-hint": u"[TAB] to toggle access to alphabet row key shortcuts.", # TODO: Translate
|
"mpv-key-tab-hint": "[TAB] to toggle access to alphabet row key shortcuts.", # TODO: Translate
|
||||||
"mpv-key-hint": u"[ENTER] to send message. [ESC] to escape chat mode.", # TODO: Translate
|
"mpv-key-hint": "[ENTER] to send message. [ESC] to escape chat mode.", # TODO: Translate
|
||||||
"alphakey-mode-warning-first-line": u"You can temporarily use old mpv bindings with a-z keys.", # TODO: Translate
|
"alphakey-mode-warning-first-line": "You can temporarily use old mpv bindings with a-z keys.", # TODO: Translate
|
||||||
"alphakey-mode-warning-second-line": u"Press [TAB] to return to Syncplay chat mode.", # TODO: Translate
|
"alphakey-mode-warning-second-line": "Press [TAB] to return to Syncplay chat mode.", # TODO: Translate
|
||||||
|
|
||||||
"help-label" : u"Помощь",
|
"help-label" : "Помощь",
|
||||||
"reset-label" : u"Сброс настроек",
|
"reset-label" : "Сброс настроек",
|
||||||
"run-label" : u"Запустить",
|
"run-label" : "Запустить",
|
||||||
"storeandrun-label" : u"Сохранить и запустить",
|
"storeandrun-label" : "Сохранить и запустить",
|
||||||
|
|
||||||
"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=\"https://syncplay.pl/\">www.syncplay.pl</a> за инорфмацией, помощью и обновлениями! NOTE: Chat messages are not encrypted so do not use Syncplay to send sensitive information.", # TODO: Translate last sentence
|
"contact-label" : "Есть идея, нашли ошибку или хотите оставить отзыв? Пишите на <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=\"https://syncplay.pl/\">www.syncplay.pl</a> за инорфмацией, помощью и обновлениями! NOTE: Chat messages are not encrypted so do not use Syncplay to send sensitive information.", # TODO: Translate last sentence
|
||||||
|
|
||||||
"joinroom-label" : u"Зайти в комнату",
|
"joinroom-label" : "Зайти в комнату",
|
||||||
"joinroom-menu-label" : u"Зайти в комнату {}",
|
"joinroom-menu-label" : "Зайти в комнату {}",
|
||||||
"seektime-menu-label" : u"Пере&мотать",
|
"seektime-menu-label" : "Пере&мотать",
|
||||||
"undoseek-menu-label" : u"&Отменить перемотку",
|
"undoseek-menu-label" : "&Отменить перемотку",
|
||||||
"play-menu-label" : u"&Старт",
|
"play-menu-label" : "&Старт",
|
||||||
"pause-menu-label" : u"&Пауза",
|
"pause-menu-label" : "&Пауза",
|
||||||
"playbackbuttons-menu-label" : u"&Показывать кнопки управления",
|
"playbackbuttons-menu-label" : "&Показывать кнопки управления",
|
||||||
"autoplay-menu-label" : u"Показывать кнопку &автовоспроизведения",
|
"autoplay-menu-label" : "Показывать кнопку &автовоспроизведения",
|
||||||
"autoplay-guipushbuttonlabel" : u"Стартовать, когда все будут готовы",
|
"autoplay-guipushbuttonlabel" : "Стартовать, когда все будут готовы",
|
||||||
"autoplay-minimum-label" : u"Минимум зрителей:",
|
"autoplay-minimum-label" : "Минимум зрителей:",
|
||||||
"sendmessage-label" : u"Send", # TODO: Translate
|
"sendmessage-label" : "Send", # TODO: Translate
|
||||||
|
|
||||||
"ready-guipushbuttonlabel" : u"Я готов",
|
"ready-guipushbuttonlabel" : "Я готов",
|
||||||
|
|
||||||
"roomuser-heading-label" : u"Комната / Зритель",
|
"roomuser-heading-label" : "Комната / Зритель",
|
||||||
|
|
||||||
"size-heading-label" : u"Размер",
|
"size-heading-label" : "Размер",
|
||||||
"duration-heading-label" : u"Время",
|
"duration-heading-label" : "Время",
|
||||||
"filename-heading-label" : u"Имя файла",
|
"filename-heading-label" : "Имя файла",
|
||||||
"notifications-heading-label" : u"Уведомления",
|
"notifications-heading-label" : "Уведомления",
|
||||||
"userlist-heading-label" : u"Кто что смотрит",
|
"userlist-heading-label" : "Кто что смотрит",
|
||||||
|
|
||||||
"browseformedia-label" : u"Выбрать файл",
|
"browseformedia-label" : "Выбрать файл",
|
||||||
|
|
||||||
"file-menu-label" : u"&Файл", # & precedes shortcut key
|
"file-menu-label" : "&Файл", # & precedes shortcut key
|
||||||
"openmedia-menu-label" : u"&Открыть файл",
|
"openmedia-menu-label" : "&Открыть файл",
|
||||||
"openstreamurl-menu-label" : u"Открыть &ссылку",
|
"openstreamurl-menu-label" : "Открыть &ссылку",
|
||||||
"setmediadirectories-menu-label" : u"&Папки воспроизведения",
|
"setmediadirectories-menu-label" : "&Папки воспроизведения",
|
||||||
"exit-menu-label" : u"&Выход",
|
"exit-menu-label" : "&Выход",
|
||||||
"advanced-menu-label" : u"&Дополнительно",
|
"advanced-menu-label" : "&Дополнительно",
|
||||||
"window-menu-label" : u"&Вид",
|
"window-menu-label" : "&Вид",
|
||||||
"setoffset-menu-label" : u"&Установить смещение",
|
"setoffset-menu-label" : "&Установить смещение",
|
||||||
"createcontrolledroom-menu-label" : u"Создать управляемую &комнату",
|
"createcontrolledroom-menu-label" : "Создать управляемую &комнату",
|
||||||
"identifyascontroller-menu-label" : u"&Войти как оператор комнаты",
|
"identifyascontroller-menu-label" : "&Войти как оператор комнаты",
|
||||||
"settrusteddomains-menu-label" : u"Доверенные &сайты",
|
"settrusteddomains-menu-label" : "Доверенные &сайты",
|
||||||
|
|
||||||
"playback-menu-label" : u"&Управление",
|
"playback-menu-label" : "&Управление",
|
||||||
|
|
||||||
"help-menu-label" : u"&Помощь",
|
"help-menu-label" : "&Помощь",
|
||||||
"userguide-menu-label" : u"&Руководство пользователя",
|
"userguide-menu-label" : "&Руководство пользователя",
|
||||||
"update-menu-label" : u"Проверить &обновления",
|
"update-menu-label" : "Проверить &обновления",
|
||||||
|
|
||||||
#About dialog - TODO: Translate
|
#About dialog - TODO: Translate
|
||||||
"about-menu-label": u"&About Syncplay",
|
"about-menu-label": "&About Syncplay",
|
||||||
"about-dialog-title": u"About Syncplay",
|
"about-dialog-title": "About Syncplay",
|
||||||
"about-dialog-release": u"Version {} release {}",
|
"about-dialog-release": "Version {} release {}",
|
||||||
"about-dialog-license-text" : u"Licensed under the Apache License, Version 2.0",
|
"about-dialog-license-text" : "Licensed under the Apache License, Version 2.0",
|
||||||
"about-dialog-license-button": u"License",
|
"about-dialog-license-button": "License",
|
||||||
"about-dialog-dependencies": u"Dependencies",
|
"about-dialog-dependencies": "Dependencies",
|
||||||
|
|
||||||
"setoffset-msgbox-label" : u"Установить смещение",
|
"setoffset-msgbox-label" : "Установить смещение",
|
||||||
"offsetinfo-msgbox-label" : u"Смещение (см. инструкцию на странице www.syncplay.pl/guide):",
|
"offsetinfo-msgbox-label" : "Смещение (см. инструкцию на странице www.syncplay.pl/guide):",
|
||||||
|
|
||||||
"promptforstreamurl-msgbox-label" : u"Открыть ссылку",
|
"promptforstreamurl-msgbox-label" : "Открыть ссылку",
|
||||||
"promptforstreamurlinfo-msgbox-label" : u"Ссылка:",
|
"promptforstreamurlinfo-msgbox-label" : "Ссылка:",
|
||||||
|
|
||||||
"addfolder-label" : u"Добавить папку",
|
"addfolder-label" : "Добавить папку",
|
||||||
|
|
||||||
"adduris-msgbox-label" : u"Список ссылок (одна на строку)",
|
"adduris-msgbox-label" : "Список ссылок (одна на строку)",
|
||||||
"editplaylist-msgbox-label" : u"Список воспроизведения (один на строку)",
|
"editplaylist-msgbox-label" : "Список воспроизведения (один на строку)",
|
||||||
"trusteddomains-msgbox-label" : u"Список доверенных сайтов для автоматического воспроизведения (один на строку)",
|
"trusteddomains-msgbox-label" : "Список доверенных сайтов для автоматического воспроизведения (один на строку)",
|
||||||
|
|
||||||
"createcontrolledroom-msgbox-label" : u"Создать управляемую комнату",
|
"createcontrolledroom-msgbox-label" : "Создать управляемую комнату",
|
||||||
"controlledroominfo-msgbox-label" : u"Введите имя управляемой комнаты\r\n(см. инструкцию на странице www.syncplay.pl/guide):",
|
"controlledroominfo-msgbox-label" : "Введите имя управляемой комнаты\r\n(см. инструкцию на странице www.syncplay.pl/guide):",
|
||||||
|
|
||||||
"identifyascontroller-msgbox-label" : u"Войти как оператор комнаты",
|
"identifyascontroller-msgbox-label" : "Войти как оператор комнаты",
|
||||||
"identifyinfo-msgbox-label" : u"Введите пароль оператора комнаты\r\n(см. инструкцию на странице www.syncplay.pl/guide):",
|
"identifyinfo-msgbox-label" : "Введите пароль оператора комнаты\r\n(см. инструкцию на странице www.syncplay.pl/guide):",
|
||||||
|
|
||||||
"public-server-msgbox-label" : u"Выбите публичный сервер для данной сессии",
|
"public-server-msgbox-label" : "Выбите публичный сервер для данной сессии",
|
||||||
|
|
||||||
"megabyte-suffix" : u" МБ", # Technically it is a mebibyte
|
"megabyte-suffix" : " МБ", # Technically it is a mebibyte
|
||||||
|
|
||||||
# Tooltips
|
# Tooltips
|
||||||
|
|
||||||
"host-tooltip" : u"Имя или IP-адрес, к которому будет произведено подключение, может содержать номер порта (напр., syncplay.pl:8999). Синхронизация возможна только в рамках одного сервера/порта.",
|
"host-tooltip" : "Имя или IP-адрес, к которому будет произведено подключение, может содержать номер порта (напр., syncplay.pl:8999). Синхронизация возможна только в рамках одного сервера/порта.",
|
||||||
"name-tooltip" : u"Имя, под которым Вы будете известны. Регистриция не требуется, так что имя пользователя можно легко сменить в любой момент. Будет сгенерировано случайным образом, если не указать.",
|
"name-tooltip" : "Имя, под которым Вы будете известны. Регистриция не требуется, так что имя пользователя можно легко сменить в любой момент. Будет сгенерировано случайным образом, если не указать.",
|
||||||
"password-tooltip" : u"Пароли нужны для подключения к приватным серверам.",
|
"password-tooltip" : "Пароли нужны для подключения к приватным серверам.",
|
||||||
"room-tooltip" : u"Комната, в которую Вы попадете сразу после подключения. Синхронизация возможна только между людьми в одной и той же комнате.",
|
"room-tooltip" : "Комната, в которую Вы попадете сразу после подключения. Синхронизация возможна только между людьми в одной и той же комнате.",
|
||||||
|
|
||||||
"executable-path-tooltip" : u"Расположение Вашего видеопроигрывателя (MPC-HC, MPC-BE, VLC, mplayer2 или mpv).",
|
"executable-path-tooltip" : "Расположение Вашего видеопроигрывателя (MPC-HC, MPC-BE, VLC, mplayer2 или mpv).",
|
||||||
"media-path-tooltip" : u"Расположение видеофайла или потока для просмотра. Обязательно для mplayer2.", # TODO: Confirm translation
|
"media-path-tooltip" : "Расположение видеофайла или потока для просмотра. Обязательно для mplayer2.", # TODO: Confirm translation
|
||||||
"player-arguments-tooltip" : u"Передавать дополнительные аргументы командной строки этому проигрывателю.",
|
"player-arguments-tooltip" : "Передавать дополнительные аргументы командной строки этому проигрывателю.",
|
||||||
"mediasearcdirectories-arguments-tooltip" : u"Папки, где Syncplay будет искать медиа файлы, включая подпапки.",
|
"mediasearcdirectories-arguments-tooltip" : "Папки, где Syncplay будет искать медиа файлы, включая подпапки.",
|
||||||
|
|
||||||
"more-tooltip" : u"Показать дополнительные настройки.",
|
"more-tooltip" : "Показать дополнительные настройки.",
|
||||||
"filename-privacy-tooltip" : u"Режим приватности для передачи имени воспроизводимого файла на сервер.",
|
"filename-privacy-tooltip" : "Режим приватности для передачи имени воспроизводимого файла на сервер.",
|
||||||
"filesize-privacy-tooltip" : u"Режим приватности для передачи размера воспроизводимого файла на сервер.",
|
"filesize-privacy-tooltip" : "Режим приватности для передачи размера воспроизводимого файла на сервер.",
|
||||||
"privacy-sendraw-tooltip" : u"Отправляет эту информацию без шифрования. Рекомендуемая опция с наибольшей функциональностью.",
|
"privacy-sendraw-tooltip" : "Отправляет эту информацию без шифрования. Рекомендуемая опция с наибольшей функциональностью.",
|
||||||
"privacy-sendhashed-tooltip" : u"Отправляет хэш-сумму этой информации, делая ее невидимой для других пользователей.",
|
"privacy-sendhashed-tooltip" : "Отправляет хэш-сумму этой информации, делая ее невидимой для других пользователей.",
|
||||||
"privacy-dontsend-tooltip" : u"Не отправлять эту информацию на сервер. Предоставляет наибольшую приватность.",
|
"privacy-dontsend-tooltip" : "Не отправлять эту информацию на сервер. Предоставляет наибольшую приватность.",
|
||||||
"checkforupdatesautomatically-tooltip" : u"Syncplay будет регулярно заходить на сайт и проверять наличие новых версий.",
|
"checkforupdatesautomatically-tooltip" : "Syncplay будет регулярно заходить на сайт и проверять наличие новых версий.",
|
||||||
"slowondesync-tooltip" : u"Временно уменьшить скорость воспроизведения в целях синхронизации с другими зрителями. Не поддерживается в MPC-HC/BE.",
|
"slowondesync-tooltip" : "Временно уменьшить скорость воспроизведения в целях синхронизации с другими зрителями. Не поддерживается в MPC-HC/BE.",
|
||||||
"dontslowdownwithme-tooltip" : u"Ваши лаги не будут влиять на других зрителей.",
|
"dontslowdownwithme-tooltip" : "Ваши лаги не будут влиять на других зрителей.",
|
||||||
"pauseonleave-tooltip" : u"Приостановить воспроизведение, если Вы покинули комнату или кто-то из зрителей отключился от сервера.",
|
"pauseonleave-tooltip" : "Приостановить воспроизведение, если Вы покинули комнату или кто-то из зрителей отключился от сервера.",
|
||||||
"readyatstart-tooltip" : u"Отметить Вас готовым к просмотру сразу же (по умолчанию Вы отмечены не готовым)",
|
"readyatstart-tooltip" : "Отметить Вас готовым к просмотру сразу же (по умолчанию Вы отмечены не готовым)",
|
||||||
"forceguiprompt-tooltip" : u"Окно настройки не будет отображаться при открытии файла в Syncplay.", # (Inverted)
|
"forceguiprompt-tooltip" : "Окно настройки не будет отображаться при открытии файла в Syncplay.", # (Inverted)
|
||||||
"nostore-tooltip" : u"Запустить Syncplay с данной конфигурацией, но не сохранять изменения навсегда.",
|
"nostore-tooltip" : "Запустить Syncplay с данной конфигурацией, но не сохранять изменения навсегда.",
|
||||||
"rewindondesync-tooltip" : u"Перематывать назад, когда это необходимо для синхронизации. Отключение этой опции может привести к большим рассинхронизациям!",
|
"rewindondesync-tooltip" : "Перематывать назад, когда это необходимо для синхронизации. Отключение этой опции может привести к большим рассинхронизациям!",
|
||||||
"fastforwardondesync-tooltip" : u"Перематывать вперед при рассинхронизации с оператором комнаты (или если включена опция 'Никогда не замедлять и не перематывать видео другим').",
|
"fastforwardondesync-tooltip" : "Перематывать вперед при рассинхронизации с оператором комнаты (или если включена опция 'Никогда не замедлять и не перематывать видео другим').",
|
||||||
"showosd-tooltip" : u"Отправлять сообщения Syncplay в видеопроигрыватель и отображать их поверх видео (OSD - On Screen Display).",
|
"showosd-tooltip" : "Отправлять сообщения Syncplay в видеопроигрыватель и отображать их поверх видео (OSD - On Screen Display).",
|
||||||
"showosdwarnings-tooltip" : u"Показывать OSC-предупреждения, если проигрываются разные файлы или если Вы в комнате больше никого нет.",
|
"showosdwarnings-tooltip" : "Показывать OSC-предупреждения, если проигрываются разные файлы или если Вы в комнате больше никого нет.",
|
||||||
"showsameroomosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к комнате, в которой Вы находитесь.",
|
"showsameroomosd-tooltip" : "Показывать OSD-уведомления о событиях, относящихся к комнате, в которой Вы находитесь.",
|
||||||
"shownoncontrollerosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к не-операторам в управляемой комнате.",
|
"shownoncontrollerosd-tooltip" : "Показывать OSD-уведомления о событиях, относящихся к не-операторам в управляемой комнате.",
|
||||||
"showdifferentroomosd-tooltip" : u"Показывать OSD-уведомления о событиях, относящихся к любым другим комнатам.",
|
"showdifferentroomosd-tooltip" : "Показывать OSD-уведомления о событиях, относящихся к любым другим комнатам.",
|
||||||
"showslowdownosd-tooltip" : u"Показывать уведомления о замедлении или перемотке в целях синхронизации.",
|
"showslowdownosd-tooltip" : "Показывать уведомления о замедлении или перемотке в целях синхронизации.",
|
||||||
"showdurationnotification-tooltip" : u"Полезно, когда сегмент составного файла отсутствует. Возможны ложные срабатывания.",
|
"showdurationnotification-tooltip" : "Полезно, когда сегмент составного файла отсутствует. Возможны ложные срабатывания.",
|
||||||
"language-tooltip" : u"Язык, используемый Syncplay.",
|
"language-tooltip" : "Язык, используемый Syncplay.",
|
||||||
"unpause-always-tooltip" : u"Когда вы стартуете, статус изменится на готов и начнется воспроизведение, а не просто смена статуса.",
|
"unpause-always-tooltip" : "Когда вы стартуете, статус изменится на готов и начнется воспроизведение, а не просто смена статуса.",
|
||||||
"unpause-ifalreadyready-tooltip" : u"Когда вы стартуете не готовым, это меняет статус на готов - нажмите старт еще раз для начала воспроизведения.",
|
"unpause-ifalreadyready-tooltip" : "Когда вы стартуете не готовым, это меняет статус на готов - нажмите старт еще раз для начала воспроизведения.",
|
||||||
"unpause-ifothersready-tooltip" : u"Когда вы стартуете не готовым, воспроизведение начнется, если остальные готовы.",
|
"unpause-ifothersready-tooltip" : "Когда вы стартуете не готовым, воспроизведение начнется, если остальные готовы.",
|
||||||
"unpause-ifminusersready-tooltip" : u"Когда вы стартуете не готовым, воспроизведение начнется, если остальные готовы и присутствует достаточное число зрителей.",
|
"unpause-ifminusersready-tooltip" : "Когда вы стартуете не готовым, воспроизведение начнется, если остальные готовы и присутствует достаточное число зрителей.",
|
||||||
"trusteddomains-arguments-tooltip" : u"Сайты, которые разрешены для автоматического воспроизведения из общего списка воспроизведения.",
|
"trusteddomains-arguments-tooltip" : "Сайты, которые разрешены для автоматического воспроизведения из общего списка воспроизведения.",
|
||||||
|
|
||||||
"chatinputenabled-tooltip": u"Enable chat input in mpv (press enter to chat, enter to send, escape to cancel)",# TODO: Translate
|
"chatinputenabled-tooltip": "Enable chat input in mpv (press enter to chat, enter to send, escape to cancel)",# TODO: Translate
|
||||||
"chatdirectinput-tooltip" : u"Skip having to press 'enter' to go into chat input mode in mpv. Press TAB in mpv to temporarily disable this feature.", # TODO: Translate
|
"chatdirectinput-tooltip" : "Skip having to press 'enter' to go into chat input mode in mpv. Press TAB in mpv to temporarily disable this feature.", # TODO: Translate
|
||||||
"font-label-tooltip": u"Font used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",# TODO: Translate
|
"font-label-tooltip": "Font used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",# TODO: Translate
|
||||||
"set-input-font-tooltip": u"Font family used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",# TODO: Translate
|
"set-input-font-tooltip": "Font family used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",# TODO: Translate
|
||||||
"set-input-colour-tooltip": u"Font colour used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",# TODO: Translate
|
"set-input-colour-tooltip": "Font colour used for when entering chat messages in mpv. Client-side only, so doesn't affect what other see.",# TODO: Translate
|
||||||
"chatinputposition-tooltip": u"Location in mpv where chat input text will appear when you press enter and type.",# TODO: Translate
|
"chatinputposition-tooltip": "Location in mpv where chat input text will appear when you press enter and type.",# TODO: Translate
|
||||||
"chatinputposition-top-tooltip": u"Place chat input at top of mpv window.", # TODO: Translate
|
"chatinputposition-top-tooltip": "Place chat input at top of mpv window.", # TODO: Translate
|
||||||
"chatinputposition-middle-tooltip": u"Place chat input in dead centre of mpv window.", # TODO: Translate
|
"chatinputposition-middle-tooltip": "Place chat input in dead centre of mpv window.", # TODO: Translate
|
||||||
"chatinputposition-bottom-tooltip": u"Place chat input at bottom of mpv window.", # TODO: Translate
|
"chatinputposition-bottom-tooltip": "Place chat input at bottom of mpv window.", # TODO: Translate
|
||||||
"chatoutputenabled-tooltip": u"Show chat messages in OSD (if supported by media player).", # TODO: Translate
|
"chatoutputenabled-tooltip": "Show chat messages in OSD (if supported by media player).", # TODO: Translate
|
||||||
"font-output-label-tooltip": u"Chat output font.", # TODO: Translate
|
"font-output-label-tooltip": "Chat output font.", # TODO: Translate
|
||||||
"set-output-font-tooltip": u"Font used for when displaying chat messages.", # TODO: Translate
|
"set-output-font-tooltip": "Font used for when displaying chat messages.", # TODO: Translate
|
||||||
"chatoutputmode-tooltip": u"How chat messages are displayed.", # TODO: Translate
|
"chatoutputmode-tooltip": "How chat messages are displayed.", # TODO: Translate
|
||||||
"chatoutputmode-chatroom-tooltip": u"Display new lines of chat directly below previous line.", # TODO: Translate
|
"chatoutputmode-chatroom-tooltip": "Display new lines of chat directly below previous line.", # TODO: Translate
|
||||||
"chatoutputmode-scrolling-tooltip": u"Scroll chat text from right to left.", # TODO: Translate
|
"chatoutputmode-scrolling-tooltip": "Scroll chat text from right to left.", # TODO: Translate
|
||||||
|
|
||||||
"help-tooltip" : u"Открыть Руководство Пользователя на Syncplay.pl.",
|
"help-tooltip" : "Открыть Руководство Пользователя на Syncplay.pl.",
|
||||||
"reset-tooltip" : u"Сбрасывает все настройки Syncplay в начальное состояние.",
|
"reset-tooltip" : "Сбрасывает все настройки Syncplay в начальное состояние.",
|
||||||
"update-server-list-tooltip" : u"Обновить список публичных серверов от syncplay.pl.",
|
"update-server-list-tooltip" : "Обновить список публичных серверов от syncplay.pl.",
|
||||||
|
|
||||||
"joinroom-tooltip" : u"Покинуть комнату и зайти в другую, указанную комнату.",
|
"joinroom-tooltip" : "Покинуть комнату и зайти в другую, указанную комнату.",
|
||||||
"seektime-msgbox-label" : u"Перемотать к определенному моменту времени (указывать в секундах или мин:сек). Используйте +/-, чтобы перемотать вперед/назад относительно настоящего момента.",
|
"seektime-msgbox-label" : "Перемотать к определенному моменту времени (указывать в секундах или мин:сек). Используйте +/-, чтобы перемотать вперед/назад относительно настоящего момента.",
|
||||||
"ready-tooltip" : u"Показывает, готовы ли Вы к просмотру или нет.",
|
"ready-tooltip" : "Показывает, готовы ли Вы к просмотру или нет.",
|
||||||
"autoplay-tooltip" : u"Автоматическое воспроизведение, когда все пользователи с индикаторами готовности будут готовы и присутствует достаточное число зрителей.",
|
"autoplay-tooltip" : "Автоматическое воспроизведение, когда все пользователи с индикаторами готовности будут готовы и присутствует достаточное число зрителей.",
|
||||||
"switch-to-file-tooltip" : u"Кликните два раза для воспроизведения {}", # Filename
|
"switch-to-file-tooltip" : "Кликните два раза для воспроизведения {}", # Filename
|
||||||
"sendmessage-tooltip" : u"Send message to room", # TODO: Translate
|
"sendmessage-tooltip" : "Send message to room", # TODO: Translate
|
||||||
|
|
||||||
# In-userlist notes (GUI)
|
# In-userlist notes (GUI)
|
||||||
"differentsize-note" : u"Размер файла не совпадает!",
|
"differentsize-note" : "Размер файла не совпадает!",
|
||||||
"differentsizeandduration-note" : u"Размер и продолжительность файла не совпадают!",
|
"differentsizeandduration-note" : "Размер и продолжительность файла не совпадают!",
|
||||||
"differentduration-note" : u"Продолжительность файла не совпадает!",
|
"differentduration-note" : "Продолжительность файла не совпадает!",
|
||||||
"nofile-note" : u"(ничего)",
|
"nofile-note" : "(ничего)",
|
||||||
|
|
||||||
# Server messages to client
|
# Server messages to client
|
||||||
"new-syncplay-available-motd-message" : u"<NOTICE> Вы используете Syncplay версии {}. Доступна более новая версия на https://syncplay.pl/ . </NOTICE>", # ClientVersion
|
"new-syncplay-available-motd-message" : "<NOTICE> Вы используете Syncplay версии {}. Доступна более новая версия на https://syncplay.pl/ . </NOTICE>", # ClientVersion
|
||||||
|
|
||||||
# Server notifications
|
# Server notifications
|
||||||
"welcome-server-notification" : u"Добро пожаловать на сервер Syncplay версии {0}", # version
|
"welcome-server-notification" : "Добро пожаловать на сервер Syncplay версии {0}", # version
|
||||||
"client-connected-room-server-notification" : u"{0}({2}) подключился к комнате '{1}'", # username, host, room
|
"client-connected-room-server-notification" : "{0}({2}) подключился к комнате '{1}'", # username, host, room
|
||||||
"client-left-server-notification" : u"{0} покинул сервер", # name
|
"client-left-server-notification" : "{0} покинул сервер", # name
|
||||||
"no-salt-notification" : u"ВНИМАНИЕ: Чтобы сгенерированные сервером пароли операторов комнат работали после перезагрузки сервера, необходимо указать следующий аргумент командной строки при запуске сервера Syncplay: --salt {}", #Salt
|
"no-salt-notification" : "ВНИМАНИЕ: Чтобы сгенерированные сервером пароли операторов комнат работали после перезагрузки сервера, необходимо указать следующий аргумент командной строки при запуске сервера Syncplay: --salt {}", #Salt
|
||||||
|
|
||||||
# Server arguments
|
# Server arguments
|
||||||
"server-argument-description" : u'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC/BE через Интернет. Серверная часть',
|
"server-argument-description" : 'Решение для синхронного воспроизведения в VLC, MPlayer или MPC-HC/BE через Интернет. Серверная часть',
|
||||||
"server-argument-epilog" : u'Если параметр не будет передан, то будет использоваться значение, указанное в _config.',
|
"server-argument-epilog" : 'Если параметр не будет передан, то будет использоваться значение, указанное в _config.',
|
||||||
"server-port-argument" : u'номер TCP порта сервера',
|
"server-port-argument" : 'номер TCP порта сервера',
|
||||||
"server-password-argument" : u'пароль к серверу',
|
"server-password-argument" : 'пароль к серверу',
|
||||||
"server-isolate-room-argument" : u'должны ли комнаты быть изолированными?',
|
"server-isolate-room-argument" : 'должны ли комнаты быть изолированными?',
|
||||||
"server-salt-argument" : u"генерировать пароли к управляемым комнатам на основании указанной строки (соли)",
|
"server-salt-argument" : "генерировать пароли к управляемым комнатам на основании указанной строки (соли)",
|
||||||
"server-disable-ready-argument" : u"отключить статусы готов/не готов",
|
"server-disable-ready-argument" : "отключить статусы готов/не готов",
|
||||||
"server-motd-argument" : u"путь к файлу, из которого будет извлекаться MOTD-сообщение",
|
"server-motd-argument" : "путь к файлу, из которого будет извлекаться MOTD-сообщение",
|
||||||
"server-chat-argument" : "Should chat be disabled?", # TODO: Translate
|
"server-chat-argument" : "Should chat be disabled?", # TODO: Translate
|
||||||
"server-chat-maxchars-argument": u"Maximum number of characters in a chat message (default is {})", # TODO: Translate
|
"server-chat-maxchars-argument": "Maximum number of characters in a chat message (default is {})", # TODO: Translate
|
||||||
"server-maxusernamelength-argument": u"Maximum number of charactrs in a username (default is {})", # TODO: Translate
|
"server-maxusernamelength-argument": "Maximum number of charactrs in a username (default is {})", # TODO: Translate
|
||||||
"server-messed-up-motd-unescaped-placeholders" : u"MOTD-сообщение содержит неэкранированные спец.символы. Все знаки $ должны быть продублированы ($$).",
|
"server-messed-up-motd-unescaped-placeholders" : "MOTD-сообщение содержит неэкранированные спец.символы. Все знаки $ должны быть продублированы ($$).",
|
||||||
"server-messed-up-motd-too-long" : u"MOTD-сообщение слишком длинное: максимальная длина - {} символ(ов), текущая длина - {} символ(ов).",
|
"server-messed-up-motd-too-long" : "MOTD-сообщение слишком длинное: максимальная длина - {} символ(ов), текущая длина - {} символ(ов).",
|
||||||
|
|
||||||
# Server errors
|
# Server errors
|
||||||
"unknown-command-server-error" : u"Неизвестная команда: {}", # message
|
"unknown-command-server-error" : "Неизвестная команда: {}", # message
|
||||||
"not-json-server-error" : u"Не является закодированной json-строкой: {}", # message
|
"not-json-server-error" : "Не является закодированной json-строкой: {}", # message
|
||||||
"not-known-server-error" : u"Данную команду могут выполнять только авторизованные пользователи.",
|
"not-known-server-error" : "Данную команду могут выполнять только авторизованные пользователи.",
|
||||||
"client-drop-server-error" : u"Клиент отключен с ошибкой: {} -- {}", # host, error
|
"client-drop-server-error" : "Клиент отключен с ошибкой: {} -- {}", # host, error
|
||||||
"password-required-server-error" : u"Необходимо указать пароль.",
|
"password-required-server-error" : "Необходимо указать пароль.",
|
||||||
"wrong-password-server-error" : u"Указан неверный пароль.",
|
"wrong-password-server-error" : "Указан неверный пароль.",
|
||||||
"hello-server-error" : u"Не хватает аргументов Hello.",
|
"hello-server-error" : "Не хватает аргументов Hello.",
|
||||||
|
|
||||||
"playlist-selection-changed-notification" : u"{} изменил выбор в списке воспроизведения", # Username
|
"playlist-selection-changed-notification" : "{} изменил выбор в списке воспроизведения", # Username
|
||||||
"playlist-contents-changed-notification" : u"{} обновил список воспроизведения", # Username
|
"playlist-contents-changed-notification" : "{} обновил список воспроизведения", # Username
|
||||||
"cannot-find-file-for-playlist-switch-error" : u"Не удалось найти файл {} в папках воспроизведения!", # Filename
|
"cannot-find-file-for-playlist-switch-error" : "Не удалось найти файл {} в папках воспроизведения!", # Filename
|
||||||
"cannot-add-duplicate-error" : u"'{}' уже есть в списке воспроизведения.", #Filename
|
"cannot-add-duplicate-error" : "'{}' уже есть в списке воспроизведения.", #Filename
|
||||||
"cannot-add-unsafe-path-error" : u"Не удалось автоматически переключиться на {}, потому что ссылка не соответствует доверенным сайтам. Её можно включить вручную, дважны кливнув по ссылке в списке воспроизведения. Добавить доверенный сайт можно в выпадающем меню 'Дополнительно' или просто кликнув по ссылке правой кнопкой мыши.", # Filename
|
"cannot-add-unsafe-path-error" : "Не удалось автоматически переключиться на {}, потому что ссылка не соответствует доверенным сайтам. Её можно включить вручную, дважны кливнув по ссылке в списке воспроизведения. Добавить доверенный сайт можно в выпадающем меню 'Дополнительно' или просто кликнув по ссылке правой кнопкой мыши.", # Filename
|
||||||
"sharedplaylistenabled-label" : u"Включить общий список воспроизведения",
|
"sharedplaylistenabled-label" : "Включить общий список воспроизведения",
|
||||||
"removefromplaylist-menu-label" : u"Удалить",
|
"removefromplaylist-menu-label" : "Удалить",
|
||||||
"shufflepremaininglaylist-menuu-label" : u"Shuffle remaining playlist", # Was: Перемешать список # TODO: Translate
|
"shufflepremaininglaylist-menuu-label" : "Shuffle remaining playlist", # Was: Перемешать список # TODO: Translate
|
||||||
"shuffleentireplaylist-menu-label" : u"Shuffle entire playlist", # TODO: Translate
|
"shuffleentireplaylist-menu-label" : "Shuffle entire playlist", # TODO: Translate
|
||||||
"undoplaylist-menu-label" : u"Отменить последнее действие",
|
"undoplaylist-menu-label" : "Отменить последнее действие",
|
||||||
"addfilestoplaylist-menu-label" : u"Добавить файлы в очередь",
|
"addfilestoplaylist-menu-label" : "Добавить файлы в очередь",
|
||||||
"addurlstoplaylist-menu-label" : u"Добавить ссылку в очередь",
|
"addurlstoplaylist-menu-label" : "Добавить ссылку в очередь",
|
||||||
"editplaylist-menu-label": u"Редактировать список",
|
"editplaylist-menu-label": "Редактировать список",
|
||||||
|
|
||||||
"open-containing-folder": u"Open folder containing this file", # TODO: Traslate
|
"open-containing-folder": "Open folder containing this file", # TODO: Traslate
|
||||||
"addusersfiletoplaylist-menu-label" : u"Добавить файл {} в список воспроизведения", # item owner indicator
|
"addusersfiletoplaylist-menu-label" : "Добавить файл {} в список воспроизведения", # item owner indicator
|
||||||
"addusersstreamstoplaylist-menu-label" : u"Добавить поток {} в список воспроизведения", # item owner indicator
|
"addusersstreamstoplaylist-menu-label" : "Добавить поток {} в список воспроизведения", # item owner indicator
|
||||||
"openusersstream-menu-label" : u"Открыть поток от {}", # [username]'s
|
"openusersstream-menu-label" : "Открыть поток от {}", # [username]'s
|
||||||
"openusersfile-menu-label" : u"Открыть файл от {}", # [username]'s
|
"openusersfile-menu-label" : "Открыть файл от {}", # [username]'s
|
||||||
"item-is-yours-indicator" : u"от вас", # Goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
"item-is-yours-indicator" : "от вас", # Goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
||||||
"item-is-others-indicator" : u"{}", # username - goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
"item-is-others-indicator" : "{}", # username - goes with addusersfiletoplaylist/addusersstreamstoplaylist
|
||||||
|
|
||||||
"playlist-instruction-item-message" : u"Перетащите сюда файлы, чтобы добавить их в общий список.",
|
"playlist-instruction-item-message" : "Перетащите сюда файлы, чтобы добавить их в общий список.",
|
||||||
"sharedplaylistenabled-tooltip" : u"Оператор комнаты может добавлять файлы в список общего воспроизведения для удобного совместного просмотра. Папки воспроизведения настраиваются во вкладке 'Файл'.",
|
"sharedplaylistenabled-tooltip" : "Оператор комнаты может добавлять файлы в список общего воспроизведения для удобного совместного просмотра. Папки воспроизведения настраиваются во вкладке 'Файл'.",
|
||||||
}
|
}
|
||||||
|
|||||||
32
syncplay/players/__init__.py
Normal file → Executable file
32
syncplay/players/__init__.py
Normal file → Executable file
@ -1,16 +1,16 @@
|
|||||||
from syncplay.players.mplayer import MplayerPlayer
|
from syncplay.players.mplayer import MplayerPlayer
|
||||||
from syncplay.players.mpv import MpvPlayer
|
from syncplay.players.mpv import MpvPlayer
|
||||||
from syncplay.players.vlc import VlcPlayer
|
from syncplay.players.vlc import VlcPlayer
|
||||||
try:
|
try:
|
||||||
from syncplay.players.mpc import MPCHCAPIPlayer
|
from syncplay.players.mpc import MPCHCAPIPlayer
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from syncplay.players.basePlayer import DummyPlayer
|
from syncplay.players.basePlayer import DummyPlayer
|
||||||
MPCHCAPIPlayer = DummyPlayer
|
MPCHCAPIPlayer = DummyPlayer
|
||||||
try:
|
try:
|
||||||
from syncplay.players.mpcbe import MpcBePlayer
|
from syncplay.players.mpcbe import MpcBePlayer
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from syncplay.players.basePlayer import DummyPlayer
|
from syncplay.players.basePlayer import DummyPlayer
|
||||||
MpcBePlayer = DummyPlayer
|
MpcBePlayer = DummyPlayer
|
||||||
|
|
||||||
def getAvailablePlayers():
|
def getAvailablePlayers():
|
||||||
return [MPCHCAPIPlayer, MplayerPlayer, MpvPlayer, VlcPlayer, MpcBePlayer]
|
return [MPCHCAPIPlayer, MplayerPlayer, MpvPlayer, VlcPlayer, MpcBePlayer]
|
||||||
|
|||||||
258
syncplay/players/basePlayer.py
Normal file → Executable file
258
syncplay/players/basePlayer.py
Normal file → Executable file
@ -1,130 +1,130 @@
|
|||||||
from syncplay import constants
|
from syncplay import constants
|
||||||
class BasePlayer(object):
|
class BasePlayer(object):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
This method is supposed to
|
This method is supposed to
|
||||||
execute updatePlayerStatus(paused, position) on client
|
execute updatePlayerStatus(paused, position) on client
|
||||||
Given the arguments: boolean paused and float position in seconds
|
Given the arguments: boolean paused and float position in seconds
|
||||||
'''
|
'''
|
||||||
def askForStatus(self):
|
def askForStatus(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Display given message on player's OSD or similar means
|
Display given message on player's OSD or similar means
|
||||||
'''
|
'''
|
||||||
def displayMessage(self, message, duration = (constants.OSD_DURATION*1000), secondaryOSD=False, mood=constants.MESSAGE_NEUTRAL):
|
def displayMessage(self, message, duration = (constants.OSD_DURATION*1000), secondaryOSD=False, mood=constants.MESSAGE_NEUTRAL):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Cleanup connection with player before syncplay will close down
|
Cleanup connection with player before syncplay will close down
|
||||||
'''
|
'''
|
||||||
def drop(self):
|
def drop(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Start up the player, returns its instance
|
Start up the player, returns its instance
|
||||||
'''
|
'''
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(client, playerPath, filePath, args):
|
def run(client, playerPath, filePath, args):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@type value: boolean
|
@type value: boolean
|
||||||
'''
|
'''
|
||||||
def setPaused(self, value):
|
def setPaused(self, value):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@type value: list
|
@type value: list
|
||||||
'''
|
'''
|
||||||
def setFeatures(self, featureList):
|
def setFeatures(self, featureList):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@type value: float
|
@type value: float
|
||||||
'''
|
'''
|
||||||
def setPosition(self, value):
|
def setPosition(self, value):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@type value: float
|
@type value: float
|
||||||
'''
|
'''
|
||||||
def setSpeed(self, value):
|
def setSpeed(self, value):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@type filePath: string
|
@type filePath: string
|
||||||
'''
|
'''
|
||||||
def openFile(self, filePath, resetPosition=False):
|
def openFile(self, filePath, resetPosition=False):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@return: list of strings
|
@return: list of strings
|
||||||
'''
|
'''
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getDefaultPlayerPathsList():
|
def getDefaultPlayerPathsList():
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@type path: string
|
@type path: string
|
||||||
'''
|
'''
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isValidPlayerPath(path):
|
def isValidPlayerPath(path):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@type path: string
|
@type path: string
|
||||||
@return: string
|
@return: string
|
||||||
'''
|
'''
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getIconPath(path):
|
def getIconPath(path):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@type path: string
|
@type path: string
|
||||||
@return: string
|
@return: string
|
||||||
'''
|
'''
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getExpandedPath(path):
|
def getExpandedPath(path):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Opens a custom media browse dialog, and then changes to that media if appropriate
|
Opens a custom media browse dialog, and then changes to that media if appropriate
|
||||||
'''
|
'''
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def openCustomOpenDialog(self):
|
def openCustomOpenDialog(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@type playerPath: string
|
@type playerPath: string
|
||||||
@type filePath: string
|
@type filePath: string
|
||||||
@return errorMessage: string
|
@return errorMessage: string
|
||||||
|
|
||||||
Checks if the player has any problems with the given player/file path
|
Checks if the player has any problems with the given player/file path
|
||||||
'''
|
'''
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getPlayerPathErrors(playerPath, filePath):
|
def getPlayerPathErrors(playerPath, filePath):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
class DummyPlayer(BasePlayer):
|
class DummyPlayer(BasePlayer):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getDefaultPlayerPathsList():
|
def getDefaultPlayerPathsList():
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isValidPlayerPath(path):
|
def isValidPlayerPath(path):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getIconPath(path):
|
def getIconPath(path):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getExpandedPath(path):
|
def getExpandedPath(path):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getPlayerPathErrors(playerPath, filePath):
|
def getPlayerPathErrors(playerPath, filePath):
|
||||||
return None
|
return None
|
||||||
88
syncplay/players/mpc.py
Normal file → Executable file
88
syncplay/players/mpc.py
Normal file → Executable file
@ -1,7 +1,7 @@
|
|||||||
#coding:utf8
|
#coding:utf8
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
import thread
|
import _thread
|
||||||
import win32con, win32api, win32gui, ctypes, ctypes.wintypes #@UnresolvedImport @UnusedImport
|
import win32con, win32api, win32gui, ctypes, ctypes.wintypes #@UnresolvedImport @UnusedImport
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from syncplay.players.basePlayer import BasePlayer
|
from syncplay.players.basePlayer import BasePlayer
|
||||||
@ -49,7 +49,7 @@ class MpcHcApi:
|
|||||||
self.__listener.SendCommand(self.CMD_OPENFILE, filePath)
|
self.__listener.SendCommand(self.CMD_OPENFILE, filePath)
|
||||||
|
|
||||||
def isPaused(self):
|
def isPaused(self):
|
||||||
return self.playState <> self.__MPC_PLAYSTATE.PS_PLAY and self.playState <> None
|
return self.playState != self.__MPC_PLAYSTATE.PS_PLAY and self.playState != None
|
||||||
|
|
||||||
def askForVersion(self):
|
def askForVersion(self):
|
||||||
self.__listener.SendCommand(self.CMD_GETVERSION)
|
self.__listener.SendCommand(self.CMD_GETVERSION)
|
||||||
@ -72,11 +72,11 @@ class MpcHcApi:
|
|||||||
|
|
||||||
@waitForFileStateReady
|
@waitForFileStateReady
|
||||||
def seek(self, position):
|
def seek(self, position):
|
||||||
self.__listener.SendCommand(self.CMD_SETPOSITION, unicode(position))
|
self.__listener.SendCommand(self.CMD_SETPOSITION, str(position))
|
||||||
|
|
||||||
@waitForFileStateReady
|
@waitForFileStateReady
|
||||||
def setSpeed(self, rate):
|
def setSpeed(self, rate):
|
||||||
self.__listener.SendCommand(self.CMD_SETSPEED, unicode(rate))
|
self.__listener.SendCommand(self.CMD_SETSPEED, str(rate))
|
||||||
|
|
||||||
def sendOsd(self, message, MsgPos=constants.MPC_OSD_POSITION, DurationMs=(constants.OSD_DURATION*1000)):
|
def sendOsd(self, message, MsgPos=constants.MPC_OSD_POSITION, DurationMs=(constants.OSD_DURATION*1000)):
|
||||||
class __OSDDATASTRUCT(ctypes.Structure):
|
class __OSDDATASTRUCT(ctypes.Structure):
|
||||||
@ -99,7 +99,7 @@ class MpcHcApi:
|
|||||||
self.__listener.mpcHandle = int(value)
|
self.__listener.mpcHandle = int(value)
|
||||||
self.__locks.mpcStart.set()
|
self.__locks.mpcStart.set()
|
||||||
if self.callbacks.onConnected:
|
if self.callbacks.onConnected:
|
||||||
thread.start_new_thread(self.callbacks.onConnected, ())
|
_thread.start_new_thread(self.callbacks.onConnected, ())
|
||||||
|
|
||||||
elif cmd == self.CMD_STATE:
|
elif cmd == self.CMD_STATE:
|
||||||
self.loadState = int(value)
|
self.loadState = int(value)
|
||||||
@ -110,12 +110,12 @@ class MpcHcApi:
|
|||||||
else:
|
else:
|
||||||
self.__locks.fileReady.set()
|
self.__locks.fileReady.set()
|
||||||
if self.callbacks.onFileStateChange:
|
if self.callbacks.onFileStateChange:
|
||||||
thread.start_new_thread(self.callbacks.onFileStateChange, (self.loadState,))
|
_thread.start_new_thread(self.callbacks.onFileStateChange, (self.loadState,))
|
||||||
|
|
||||||
elif cmd == self.CMD_PLAYMODE:
|
elif cmd == self.CMD_PLAYMODE:
|
||||||
self.playState = int(value)
|
self.playState = int(value)
|
||||||
if self.callbacks.onUpdatePlaystate:
|
if self.callbacks.onUpdatePlaystate:
|
||||||
thread.start_new_thread(self.callbacks.onUpdatePlaystate, (self.playState,))
|
_thread.start_new_thread(self.callbacks.onUpdatePlaystate, (self.playState,))
|
||||||
|
|
||||||
elif cmd == self.CMD_NOWPLAYING:
|
elif cmd == self.CMD_NOWPLAYING:
|
||||||
value = re.split(r'(?<!\\)\|', value)
|
value = re.split(r'(?<!\\)\|', value)
|
||||||
@ -125,31 +125,31 @@ class MpcHcApi:
|
|||||||
self.filePlaying = value[3].split('\\').pop()
|
self.filePlaying = value[3].split('\\').pop()
|
||||||
self.fileDuration = float(value[4])
|
self.fileDuration = float(value[4])
|
||||||
if self.callbacks.onUpdatePath:
|
if self.callbacks.onUpdatePath:
|
||||||
thread.start_new_thread(self.callbacks.onUpdatePath, (self.onUpdatePath,))
|
_thread.start_new_thread(self.callbacks.onUpdatePath, (self.onUpdatePath,))
|
||||||
if self.callbacks.onUpdateFilename:
|
if self.callbacks.onUpdateFilename:
|
||||||
thread.start_new_thread(self.callbacks.onUpdateFilename, (self.filePlaying,))
|
_thread.start_new_thread(self.callbacks.onUpdateFilename, (self.filePlaying,))
|
||||||
if self.callbacks.onUpdateFileDuration:
|
if self.callbacks.onUpdateFileDuration:
|
||||||
thread.start_new_thread(self.callbacks.onUpdateFileDuration, (self.fileDuration,))
|
_thread.start_new_thread(self.callbacks.onUpdateFileDuration, (self.fileDuration,))
|
||||||
|
|
||||||
elif cmd == self.CMD_CURRENTPOSITION:
|
elif cmd == self.CMD_CURRENTPOSITION:
|
||||||
self.lastFilePosition = float(value)
|
self.lastFilePosition = float(value)
|
||||||
if self.callbacks.onGetCurrentPosition:
|
if self.callbacks.onGetCurrentPosition:
|
||||||
thread.start_new_thread(self.callbacks.onGetCurrentPosition, (self.lastFilePosition,))
|
_thread.start_new_thread(self.callbacks.onGetCurrentPosition, (self.lastFilePosition,))
|
||||||
|
|
||||||
elif cmd == self.CMD_NOTIFYSEEK:
|
elif cmd == self.CMD_NOTIFYSEEK:
|
||||||
if self.lastFilePosition <> float(value): #Notify seek is sometimes sent twice
|
if self.lastFilePosition != float(value): #Notify seek is sometimes sent twice
|
||||||
self.lastFilePosition = float(value)
|
self.lastFilePosition = float(value)
|
||||||
if self.callbacks.onSeek:
|
if self.callbacks.onSeek:
|
||||||
thread.start_new_thread(self.callbacks.onSeek, (self.lastFilePosition,))
|
_thread.start_new_thread(self.callbacks.onSeek, (self.lastFilePosition,))
|
||||||
|
|
||||||
elif cmd == self.CMD_DISCONNECT:
|
elif cmd == self.CMD_DISCONNECT:
|
||||||
if self.callbacks.onMpcClosed:
|
if self.callbacks.onMpcClosed:
|
||||||
thread.start_new_thread(self.callbacks.onMpcClosed, (None,))
|
_thread.start_new_thread(self.callbacks.onMpcClosed, (None,))
|
||||||
|
|
||||||
elif cmd == self.CMD_VERSION:
|
elif cmd == self.CMD_VERSION:
|
||||||
if self.callbacks.onVersion:
|
if self.callbacks.onVersion:
|
||||||
self.version = value
|
self.version = value
|
||||||
thread.start_new_thread(self.callbacks.onVersion, (value,))
|
_thread.start_new_thread(self.callbacks.onVersion, (value,))
|
||||||
|
|
||||||
class PlayerNotReadyException(Exception):
|
class PlayerNotReadyException(Exception):
|
||||||
pass
|
pass
|
||||||
@ -278,7 +278,7 @@ class MpcHcApi:
|
|||||||
#print "API:\tin>\t 0x%X\t" % int(pCDS.contents.dwData), ctypes.wstring_at(pCDS.contents.lpData)
|
#print "API:\tin>\t 0x%X\t" % int(pCDS.contents.dwData), ctypes.wstring_at(pCDS.contents.lpData)
|
||||||
self.__mpcApi.handleCommand(pCDS.contents.dwData, ctypes.wstring_at(pCDS.contents.lpData))
|
self.__mpcApi.handleCommand(pCDS.contents.dwData, ctypes.wstring_at(pCDS.contents.lpData))
|
||||||
|
|
||||||
def SendCommand(self, cmd, message=u''):
|
def SendCommand(self, cmd, message=''):
|
||||||
#print "API:\t<out\t 0x%X\t" % int(cmd), message
|
#print "API:\t<out\t 0x%X\t" % int(cmd), message
|
||||||
if not win32gui.IsWindow(self.mpcHandle):
|
if not win32gui.IsWindow(self.mpcHandle):
|
||||||
if self.__mpcApi.callbacks.onMpcClosed:
|
if self.__mpcApi.callbacks.onMpcClosed:
|
||||||
@ -286,7 +286,7 @@ class MpcHcApi:
|
|||||||
cs = self.__COPYDATASTRUCT()
|
cs = self.__COPYDATASTRUCT()
|
||||||
cs.dwData = cmd;
|
cs.dwData = cmd;
|
||||||
|
|
||||||
if isinstance(message, (unicode, str)):
|
if isinstance(message, str):
|
||||||
message = ctypes.create_unicode_buffer(message, len(message) + 1)
|
message = ctypes.create_unicode_buffer(message, len(message) + 1)
|
||||||
elif isinstance(message, ctypes.Structure):
|
elif isinstance(message, ctypes.Structure):
|
||||||
pass
|
pass
|
||||||
@ -383,7 +383,7 @@ class MPCHCAPIPlayer(BasePlayer):
|
|||||||
self._mpcApi.callbacks.onUpdateFilename = lambda _: self.__handleUpdatedFilename()
|
self._mpcApi.callbacks.onUpdateFilename = lambda _: self.__handleUpdatedFilename()
|
||||||
self.__handleUpdatedFilename()
|
self.__handleUpdatedFilename()
|
||||||
self.askForStatus()
|
self.askForStatus()
|
||||||
except Exception, err:
|
except Exception as err:
|
||||||
self.reactor.callFromThread(self.__client.ui.showErrorMessage, err.message, True)
|
self.reactor.callFromThread(self.__client.ui.showErrorMessage, err.message, True)
|
||||||
self.reactor.callFromThread(self.__client.stop)
|
self.reactor.callFromThread(self.__client.stop)
|
||||||
|
|
||||||
@ -445,21 +445,21 @@ class MPCHCAPIPlayer(BasePlayer):
|
|||||||
self.__client.updatePlayerStatus(self.__client.getGlobalPaused(), self.__client.getGlobalPosition())
|
self.__client.updatePlayerStatus(self.__client.getGlobalPaused(), self.__client.getGlobalPosition())
|
||||||
|
|
||||||
def __forcePause(self):
|
def __forcePause(self):
|
||||||
for _ in xrange(constants.MPC_MAX_RETRIES):
|
for _ in range(constants.MPC_MAX_RETRIES):
|
||||||
self.setPaused(True)
|
self.setPaused(True)
|
||||||
time.sleep(constants.MPC_RETRY_WAIT_TIME)
|
time.sleep(constants.MPC_RETRY_WAIT_TIME)
|
||||||
|
|
||||||
def __refreshMpcPlayState(self):
|
def __refreshMpcPlayState(self):
|
||||||
for _ in xrange(2):
|
for _ in range(2):
|
||||||
self._mpcApi.playPause()
|
self._mpcApi.playPause()
|
||||||
time.sleep(constants.MPC_PAUSE_TOGGLE_DELAY)
|
time.sleep(constants.MPC_PAUSE_TOGGLE_DELAY)
|
||||||
|
|
||||||
def _setPausedAccordinglyToServer(self):
|
def _setPausedAccordinglyToServer(self):
|
||||||
self.__forcePause()
|
self.__forcePause()
|
||||||
self.setPaused(self.__client.getGlobalPaused())
|
self.setPaused(self.__client.getGlobalPaused())
|
||||||
if self._mpcApi.isPaused() <> self.__client.getGlobalPaused():
|
if self._mpcApi.isPaused() != self.__client.getGlobalPaused():
|
||||||
self.__refreshMpcPlayState()
|
self.__refreshMpcPlayState()
|
||||||
if self._mpcApi.isPaused() <> self.__client.getGlobalPaused():
|
if self._mpcApi.isPaused() != self.__client.getGlobalPaused():
|
||||||
self.__setUpStateForNewlyOpenedFile()
|
self.__setUpStateForNewlyOpenedFile()
|
||||||
|
|
||||||
@retry(MpcHcApi.PlayerNotReadyException, constants.MPC_MAX_RETRIES, constants.MPC_RETRY_WAIT_TIME, 1)
|
@retry(MpcHcApi.PlayerNotReadyException, constants.MPC_MAX_RETRIES, constants.MPC_RETRY_WAIT_TIME, 1)
|
||||||
@ -482,7 +482,7 @@ class MPCHCAPIPlayer(BasePlayer):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getIconPath(path):
|
def getIconPath(path):
|
||||||
if MPCHCAPIPlayer.getExpandedPath(path).lower().endswith(u'mpc-hc64.exe'.lower()) or MPCHCAPIPlayer.getExpandedPath(path).lower().endswith(u'mpc-hc64_nvo.exe'.lower()):
|
if MPCHCAPIPlayer.getExpandedPath(path).lower().endswith('mpc-hc64.exe'.lower()) or MPCHCAPIPlayer.getExpandedPath(path).lower().endswith('mpc-hc64_nvo.exe'.lower()):
|
||||||
return constants.MPC64_ICONPATH
|
return constants.MPC64_ICONPATH
|
||||||
else:
|
else:
|
||||||
return constants.MPC_ICONPATH
|
return constants.MPC_ICONPATH
|
||||||
@ -496,36 +496,36 @@ class MPCHCAPIPlayer(BasePlayer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def getExpandedPath(path):
|
def getExpandedPath(path):
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
if path.lower().endswith(u'mpc-hc.exe'.lower()) or path.lower().endswith(u'mpc-hcportable.exe'.lower()) or path.lower().endswith(u'mpc-hc64.exe'.lower()) or path.lower().endswith(u'mpc-hc64_nvo.exe'.lower()) or path.lower().endswith(u'mpc-hc_nvo.exe'.lower()):
|
if path.lower().endswith('mpc-hc.exe'.lower()) or path.lower().endswith('mpc-hcportable.exe'.lower()) or path.lower().endswith('mpc-hc64.exe'.lower()) or path.lower().endswith('mpc-hc64_nvo.exe'.lower()) or path.lower().endswith('mpc-hc_nvo.exe'.lower()):
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"mpc-hc.exe"):
|
if os.path.isfile(path + "mpc-hc.exe"):
|
||||||
path += u"mpc-hc.exe"
|
path += "mpc-hc.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"\\mpc-hc.exe"):
|
if os.path.isfile(path + "\\mpc-hc.exe"):
|
||||||
path += u"\\mpc-hc.exe"
|
path += "\\mpc-hc.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"mpc-hcportable.exe"):
|
if os.path.isfile(path + "mpc-hcportable.exe"):
|
||||||
path += u"mpc-hcportable.exe"
|
path += "mpc-hcportable.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"\\mpc-hcportable.exe"):
|
if os.path.isfile(path + "\\mpc-hcportable.exe"):
|
||||||
path += u"\\mpc-hcportable.exe"
|
path += "\\mpc-hcportable.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"mpc-hc_nvo.exe"):
|
if os.path.isfile(path + "mpc-hc_nvo.exe"):
|
||||||
path += u"mpc-hc_nvo.exe"
|
path += "mpc-hc_nvo.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"\\mpc-hc_nvo.exe"):
|
if os.path.isfile(path + "\\mpc-hc_nvo.exe"):
|
||||||
path += u"\\mpc-hc_nvo.exe"
|
path += "\\mpc-hc_nvo.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"mpc-hc64.exe"):
|
if os.path.isfile(path + "mpc-hc64.exe"):
|
||||||
path += u"mpc-hc64.exe"
|
path += "mpc-hc64.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"\\mpc-hc64.exe"):
|
if os.path.isfile(path + "\\mpc-hc64.exe"):
|
||||||
path += u"\\mpc-hc64.exe"
|
path += "\\mpc-hc64.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"mpc-hc64_nvo.exe"):
|
if os.path.isfile(path + "mpc-hc64_nvo.exe"):
|
||||||
path += u"mpc-hc64_nvo.exe"
|
path += "mpc-hc64_nvo.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"\\mpc-hc64_nvo.exe"):
|
if os.path.isfile(path + "\\mpc-hc64_nvo.exe"):
|
||||||
path += u"\\mpc-hc64_nvo.exe"
|
path += "\\mpc-hc64_nvo.exe"
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|||||||
26
syncplay/players/mpcbe.py
Normal file → Executable file
26
syncplay/players/mpcbe.py
Normal file → Executable file
@ -30,25 +30,25 @@ class MpcBePlayer(MPCHCAPIPlayer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def getExpandedPath(path):
|
def getExpandedPath(path):
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
if path.lower().endswith(u'mpc-be.exe'.lower()) or path.lower().endswith(u'mpc-be64.exe'.lower() or path.lower().endswith(u'mpc-beportable.exe'.lower())):
|
if path.lower().endswith('mpc-be.exe'.lower()) or path.lower().endswith('mpc-be64.exe'.lower() or path.lower().endswith('mpc-beportable.exe'.lower())):
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"mpc-be.exe"):
|
if os.path.isfile(path + "mpc-be.exe"):
|
||||||
path += u"mpc-be.exe"
|
path += "mpc-be.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"\\mpc-be.exe"):
|
if os.path.isfile(path + "\\mpc-be.exe"):
|
||||||
path += u"\\mpc-be.exe"
|
path += "\\mpc-be.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"mpc-beportable.exe"):
|
if os.path.isfile(path + "mpc-beportable.exe"):
|
||||||
path += u"mpc-beportable.exe"
|
path += "mpc-beportable.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"\\mpc-beportable.exe"):
|
if os.path.isfile(path + "\\mpc-beportable.exe"):
|
||||||
path += u"\\mpc-beportable.exe"
|
path += "\\mpc-beportable.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"mpc-be64.exe"):
|
if os.path.isfile(path + "mpc-be64.exe"):
|
||||||
path += u"mpc-be64.exe"
|
path += "mpc-be64.exe"
|
||||||
return path
|
return path
|
||||||
if os.path.isfile(path + u"\\mpc-be64.exe"):
|
if os.path.isfile(path + "\\mpc-be64.exe"):
|
||||||
path += u"\\mpc-be64.exe"
|
path += "\\mpc-be64.exe"
|
||||||
return path
|
return path
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
43
syncplay/players/mplayer.py
Normal file → Executable file
43
syncplay/players/mplayer.py
Normal file → Executable file
@ -92,19 +92,19 @@ class MplayerPlayer(BasePlayer):
|
|||||||
|
|
||||||
def displayMessage(self, message, duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL):
|
def displayMessage(self, message, duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL):
|
||||||
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
|
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
|
||||||
self._listener.sendLine(u'{} "{!s}" {} {}'.format(self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL).encode('utf-8'))
|
self._listener.sendLine('{} "{!s}" {} {}'.format(self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL))
|
||||||
|
|
||||||
def displayChatMessage(self, username, message):
|
def displayChatMessage(self, username, message):
|
||||||
messageString = u"<{}> {}".format(username, message)
|
messageString = "<{}> {}".format(username, message)
|
||||||
messageString = self._sanitizeText(messageString.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
|
messageString = self._sanitizeText(messageString.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
|
||||||
duration = int(constants.OSD_DURATION * 1000)
|
duration = int(constants.OSD_DURATION * 1000)
|
||||||
self._listener.sendLine(u'{} "{!s}" {} {}'.format(self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL).encode('utf-8'))
|
self._listener.sendLine('{} "{!s}" {} {}'.format(self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL))
|
||||||
|
|
||||||
def setSpeed(self, value):
|
def setSpeed(self, value):
|
||||||
self._setProperty('speed', "{:.2f}".format(value))
|
self._setProperty('speed', "{:.2f}".format(value))
|
||||||
|
|
||||||
def _loadFile(self, filePath):
|
def _loadFile(self, filePath):
|
||||||
self._listener.sendLine(u'loadfile {}'.format(self._quoteArg(filePath)))
|
self._listener.sendLine('loadfile {}'.format(self._quoteArg(filePath)))
|
||||||
|
|
||||||
def openFile(self, filePath, resetPosition=False):
|
def openFile(self, filePath, resetPosition=False):
|
||||||
self._filepath = filePath
|
self._filepath = filePath
|
||||||
@ -123,7 +123,7 @@ class MplayerPlayer(BasePlayer):
|
|||||||
time.sleep(0.03)
|
time.sleep(0.03)
|
||||||
|
|
||||||
def setPaused(self, value):
|
def setPaused(self, value):
|
||||||
if self._paused <> value:
|
if self._paused != value:
|
||||||
self._paused = not self._paused
|
self._paused = not self._paused
|
||||||
self._listener.sendLine('pause')
|
self._listener.sendLine('pause')
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ class MplayerPlayer(BasePlayer):
|
|||||||
arg = arg.replace('"', '\\"')
|
arg = arg.replace('"', '\\"')
|
||||||
arg = arg.replace("\r", "")
|
arg = arg.replace("\r", "")
|
||||||
arg = arg.replace("\n", "")
|
arg = arg.replace("\n", "")
|
||||||
return u'"{}"'.format(arg)
|
return '"{}"'.format(arg)
|
||||||
|
|
||||||
def _fileIsLoaded(self):
|
def _fileIsLoaded(self):
|
||||||
return True
|
return True
|
||||||
@ -213,7 +213,7 @@ class MplayerPlayer(BasePlayer):
|
|||||||
self._filepath = value
|
self._filepath = value
|
||||||
self._pathAsk.set()
|
self._pathAsk.set()
|
||||||
elif name == "filename":
|
elif name == "filename":
|
||||||
self._filename = value.decode('utf-8')
|
self._filename = value
|
||||||
self._filenameAsk.set()
|
self._filenameAsk.set()
|
||||||
elif name == "exiting":
|
elif name == "exiting":
|
||||||
if value != 'Quit':
|
if value != 'Quit':
|
||||||
@ -262,11 +262,11 @@ class MplayerPlayer(BasePlayer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def getExpandedPath(playerPath):
|
def getExpandedPath(playerPath):
|
||||||
if not os.path.isfile(playerPath):
|
if not os.path.isfile(playerPath):
|
||||||
if os.path.isfile(playerPath + u"mplayer.exe"):
|
if os.path.isfile(playerPath + "mplayer.exe"):
|
||||||
playerPath += u"mplayer.exe"
|
playerPath += "mplayer.exe"
|
||||||
return playerPath
|
return playerPath
|
||||||
elif os.path.isfile(playerPath + u"\\mplayer.exe"):
|
elif os.path.isfile(playerPath + "\\mplayer.exe"):
|
||||||
playerPath += u"\\mplayer.exe"
|
playerPath += "\\mplayer.exe"
|
||||||
return playerPath
|
return playerPath
|
||||||
if os.access(playerPath, os.X_OK):
|
if os.access(playerPath, os.X_OK):
|
||||||
return playerPath
|
return playerPath
|
||||||
@ -324,9 +324,9 @@ class MplayerPlayer(BasePlayer):
|
|||||||
if 'TERM' in env:
|
if 'TERM' in env:
|
||||||
del env['TERM']
|
del env['TERM']
|
||||||
if filePath:
|
if filePath:
|
||||||
self.__process = subprocess.Popen(call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.__getCwd(filePath, env), env=env)
|
self.__process = subprocess.Popen(call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.__getCwd(filePath, env), env=env, bufsize=0)
|
||||||
else:
|
else:
|
||||||
self.__process = subprocess.Popen(call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
|
self.__process = subprocess.Popen(call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, env=env, bufsize=0)
|
||||||
threading.Thread.__init__(self, name="MPlayer Listener")
|
threading.Thread.__init__(self, name="MPlayer Listener")
|
||||||
|
|
||||||
|
|
||||||
@ -345,6 +345,7 @@ class MplayerPlayer(BasePlayer):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
line = self.__process.stdout.readline()
|
line = self.__process.stdout.readline()
|
||||||
|
line = line.decode('utf-8')
|
||||||
if "MPlayer 1" in line:
|
if "MPlayer 1" in line:
|
||||||
self.__playerController.notMplayer2()
|
self.__playerController.notMplayer2()
|
||||||
else:
|
else:
|
||||||
@ -352,13 +353,14 @@ class MplayerPlayer(BasePlayer):
|
|||||||
self.__playerController.lineReceived(line)
|
self.__playerController.lineReceived(line)
|
||||||
while self.__process.poll() is None:
|
while self.__process.poll() is None:
|
||||||
line = self.__process.stdout.readline()
|
line = self.__process.stdout.readline()
|
||||||
|
line = line.decode('utf-8')
|
||||||
line = line.rstrip("\r\n")
|
line = line.rstrip("\r\n")
|
||||||
self.__playerController.lineReceived(line)
|
self.__playerController.lineReceived(line)
|
||||||
self.__playerController.drop()
|
self.__playerController.drop()
|
||||||
|
|
||||||
def sendChat(self, message):
|
def sendChat(self, message):
|
||||||
if message:
|
if message:
|
||||||
if message[:1] == "/" and message <> "/":
|
if message[:1] == "/" and message != "/":
|
||||||
command = message[1:]
|
command = message[1:]
|
||||||
if command and command[:1] == "/":
|
if command and command[:1] == "/":
|
||||||
message = message[1:]
|
message = message[1:]
|
||||||
@ -399,11 +401,11 @@ class MplayerPlayer(BasePlayer):
|
|||||||
if line.startswith(command):
|
if line.startswith(command):
|
||||||
for itemID, deletionCandidate in enumerate(self.sendQueue):
|
for itemID, deletionCandidate in enumerate(self.sendQueue):
|
||||||
if deletionCandidate.startswith(command):
|
if deletionCandidate.startswith(command):
|
||||||
self.__playerController._client.ui.showDebugMessage(u"<mpv> Remove duplicate (supersede): {}".format(self.sendQueue[itemID]))
|
self.__playerController._client.ui.showDebugMessage("<mpv> Remove duplicate (supersede): {}".format(self.sendQueue[itemID]))
|
||||||
try:
|
try:
|
||||||
self.sendQueue.remove(self.sendQueue[itemID])
|
self.sendQueue.remove(self.sendQueue[itemID])
|
||||||
except UnicodeWarning:
|
except UnicodeWarning:
|
||||||
self.__playerController._client.ui.showDebugMessage(u"<mpv> Unicode mismatch occured when trying to remove duplicate")
|
self.__playerController._client.ui.showDebugMessage("<mpv> Unicode mismatch occured when trying to remove duplicate")
|
||||||
# TODO: Prevent this from being triggered
|
# TODO: Prevent this from being triggered
|
||||||
pass
|
pass
|
||||||
break
|
break
|
||||||
@ -413,7 +415,7 @@ class MplayerPlayer(BasePlayer):
|
|||||||
if line == command:
|
if line == command:
|
||||||
for itemID, deletionCandidate in enumerate(self.sendQueue):
|
for itemID, deletionCandidate in enumerate(self.sendQueue):
|
||||||
if deletionCandidate == command:
|
if deletionCandidate == command:
|
||||||
self.__playerController._client.ui.showDebugMessage(u"<mpv> Remove duplicate (delete both): {}".format(self.sendQueue[itemID]))
|
self.__playerController._client.ui.showDebugMessage("<mpv> Remove duplicate (delete both): {}".format(self.sendQueue[itemID]))
|
||||||
self.__playerController._client.ui.showDebugMessage(self.sendQueue[itemID])
|
self.__playerController._client.ui.showDebugMessage(self.sendQueue[itemID])
|
||||||
return
|
return
|
||||||
except:
|
except:
|
||||||
@ -438,10 +440,11 @@ class MplayerPlayer(BasePlayer):
|
|||||||
|
|
||||||
def actuallySendLine(self, line):
|
def actuallySendLine(self, line):
|
||||||
try:
|
try:
|
||||||
if not isinstance(line, unicode):
|
#if not isinstance(line, str):
|
||||||
line = line.decode('utf8')
|
#line = line.decode('utf8')
|
||||||
line = (line + u"\n").encode('utf8')
|
line = line + "\n"
|
||||||
self.__playerController._client.ui.showDebugMessage("player >> {}".format(line))
|
self.__playerController._client.ui.showDebugMessage("player >> {}".format(line))
|
||||||
|
line = line.encode('utf-8')
|
||||||
self.__process.stdin.write(line)
|
self.__process.stdin.write(line)
|
||||||
except IOError:
|
except IOError:
|
||||||
pass
|
pass
|
||||||
|
|||||||
44
syncplay/players/mpv.py
Normal file → Executable file
44
syncplay/players/mpv.py
Normal file → Executable file
@ -15,13 +15,13 @@ class MpvPlayer(MplayerPlayer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def run(client, playerPath, filePath, args):
|
def run(client, playerPath, filePath, args):
|
||||||
try:
|
try:
|
||||||
ver = MpvPlayer.RE_VERSION.search(subprocess.check_output([playerPath, '--version']))
|
ver = MpvPlayer.RE_VERSION.search(subprocess.check_output([playerPath, '--version']).decode('utf-8'))
|
||||||
except:
|
except:
|
||||||
ver = None
|
ver = None
|
||||||
constants.MPV_NEW_VERSION = ver is None or int(ver.group(1)) > 0 or int(ver.group(2)) >= 6
|
constants.MPV_NEW_VERSION = ver is None or int(ver.group(1)) > 0 or int(ver.group(2)) >= 6
|
||||||
constants.MPV_OSC_VISIBILITY_CHANGE_VERSION = False if ver is None else int(ver.group(1)) > 0 or int(ver.group(2)) >= 28
|
constants.MPV_OSC_VISIBILITY_CHANGE_VERSION = False if ver is None else int(ver.group(1)) > 0 or int(ver.group(2)) >= 28
|
||||||
if not constants.MPV_OSC_VISIBILITY_CHANGE_VERSION:
|
if not constants.MPV_OSC_VISIBILITY_CHANGE_VERSION:
|
||||||
client.ui.showDebugMessage(u"This version of mpv is not known to be compatible with changing the OSC visibility. Please use mpv >=0.28.0.")
|
client.ui.showDebugMessage("This version of mpv is not known to be compatible with changing the OSC visibility. Please use mpv >=0.28.0.")
|
||||||
if constants.MPV_NEW_VERSION:
|
if constants.MPV_NEW_VERSION:
|
||||||
return NewMpvPlayer(client, MpvPlayer.getExpandedPath(playerPath), filePath, args)
|
return NewMpvPlayer(client, MpvPlayer.getExpandedPath(playerPath), filePath, args)
|
||||||
else:
|
else:
|
||||||
@ -35,7 +35,7 @@ class MpvPlayer(MplayerPlayer):
|
|||||||
args.extend(constants.MPV_SLAVE_ARGS)
|
args.extend(constants.MPV_SLAVE_ARGS)
|
||||||
if constants.MPV_NEW_VERSION:
|
if constants.MPV_NEW_VERSION:
|
||||||
args.extend(constants.MPV_SLAVE_ARGS_NEW)
|
args.extend(constants.MPV_SLAVE_ARGS_NEW)
|
||||||
args.extend([u"--script={}".format(findResourcePath("syncplayintf.lua"))])
|
args.extend(["--script={}".format(findResourcePath("syncplayintf.lua"))])
|
||||||
return args
|
return args
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -56,11 +56,11 @@ class MpvPlayer(MplayerPlayer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def getExpandedPath(playerPath):
|
def getExpandedPath(playerPath):
|
||||||
if not os.path.isfile(playerPath):
|
if not os.path.isfile(playerPath):
|
||||||
if os.path.isfile(playerPath + u"mpv.exe"):
|
if os.path.isfile(playerPath + "mpv.exe"):
|
||||||
playerPath += u"mpv.exe"
|
playerPath += "mpv.exe"
|
||||||
return playerPath
|
return playerPath
|
||||||
elif os.path.isfile(playerPath + u"\\mpv.exe"):
|
elif os.path.isfile(playerPath + "\\mpv.exe"):
|
||||||
playerPath += u"\\mpv.exe"
|
playerPath += "\\mpv.exe"
|
||||||
return playerPath
|
return playerPath
|
||||||
if os.access(playerPath, os.X_OK):
|
if os.access(playerPath, os.X_OK):
|
||||||
return playerPath
|
return playerPath
|
||||||
@ -82,10 +82,10 @@ class OldMpvPlayer(MpvPlayer):
|
|||||||
OSD_QUERY = 'show_text'
|
OSD_QUERY = 'show_text'
|
||||||
|
|
||||||
def _setProperty(self, property_, value):
|
def _setProperty(self, property_, value):
|
||||||
self._listener.sendLine(u"no-osd set {} {}".format(property_, value))
|
self._listener.sendLine("no-osd set {} {}".format(property_, value))
|
||||||
|
|
||||||
def setPaused(self, value):
|
def setPaused(self, value):
|
||||||
if self._paused <> value:
|
if self._paused != value:
|
||||||
self._paused = not self._paused
|
self._paused = not self._paused
|
||||||
self._listener.sendLine('cycle pause')
|
self._listener.sendLine('cycle pause')
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
super(self.__class__, self).displayMessage(message=message,duration=duration,OSDType=OSDType,mood=mood)
|
super(self.__class__, self).displayMessage(message=message,duration=duration,OSDType=OSDType,mood=mood)
|
||||||
return
|
return
|
||||||
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace("\\\\",constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER).replace("<NEWLINE>", "\\n")
|
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace("\\\\",constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER).replace("<NEWLINE>", "\\n")
|
||||||
self._listener.sendLine(u'script-message-to syncplayintf {}-osd-{} "{}"'.format(OSDType, mood, messageString))
|
self._listener.sendLine('script-message-to syncplayintf {}-osd-{} "{}"'.format(OSDType, mood, messageString))
|
||||||
|
|
||||||
def displayChatMessage(self, username, message):
|
def displayChatMessage(self, username, message):
|
||||||
if not self._client._config["chatOutputEnabled"]:
|
if not self._client._config["chatOutputEnabled"]:
|
||||||
@ -131,8 +131,8 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
return
|
return
|
||||||
username = self._sanitizeText(username.replace("\\",constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
|
username = self._sanitizeText(username.replace("\\",constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
|
||||||
message = self._sanitizeText(message.replace("\\",constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
|
message = self._sanitizeText(message.replace("\\",constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
|
||||||
messageString = u"<{}> {}".format(username, message)
|
messageString = "<{}> {}".format(username, message)
|
||||||
self._listener.sendLine(u'script-message-to syncplayintf chat "{}"'.format(messageString))
|
self._listener.sendLine('script-message-to syncplayintf chat "{}"'.format(messageString))
|
||||||
|
|
||||||
def setPaused(self, value):
|
def setPaused(self, value):
|
||||||
if self._paused == value:
|
if self._paused == value:
|
||||||
@ -147,12 +147,12 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
def _getProperty(self, property_):
|
def _getProperty(self, property_):
|
||||||
floatProperties = ['time-pos']
|
floatProperties = ['time-pos']
|
||||||
if property_ in floatProperties:
|
if property_ in floatProperties:
|
||||||
propertyID = u"={}".format(property_)
|
propertyID = "={}".format(property_)
|
||||||
elif property_ == 'length':
|
elif property_ == 'length':
|
||||||
propertyID = u'=duration:${=length:0}'
|
propertyID = '=duration:${=length:0}'
|
||||||
else:
|
else:
|
||||||
propertyID = property_
|
propertyID = property_
|
||||||
self._listener.sendLine(u"print_text ""ANS_{}=${{{}}}""".format(property_, propertyID))
|
self._listener.sendLine("print_text ""ANS_{}=${{{}}}""".format(property_, propertyID))
|
||||||
|
|
||||||
def getCalculatedPosition(self):
|
def getCalculatedPosition(self):
|
||||||
if self.fileLoaded == False:
|
if self.fileLoaded == False:
|
||||||
@ -208,7 +208,7 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
self._client.updatePlayerStatus(self._paused if self.fileLoaded else self._client.getGlobalPaused(), self.getCalculatedPosition())
|
self._client.updatePlayerStatus(self._paused if self.fileLoaded else self._client.getGlobalPaused(), self.getCalculatedPosition())
|
||||||
|
|
||||||
def _getPausedAndPosition(self):
|
def _getPausedAndPosition(self):
|
||||||
self._listener.sendLine(u"print_text ANS_pause=${pause}\r\nprint_text ANS_time-pos=${=time-pos}")
|
self._listener.sendLine("print_text ANS_pause=${pause}\r\nprint_text ANS_time-pos=${=time-pos}")
|
||||||
|
|
||||||
def _preparePlayer(self):
|
def _preparePlayer(self):
|
||||||
if self.delayedFilePath:
|
if self.delayedFilePath:
|
||||||
@ -222,7 +222,7 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
|
|
||||||
def _loadFile(self, filePath):
|
def _loadFile(self, filePath):
|
||||||
self._clearFileLoaded()
|
self._clearFileLoaded()
|
||||||
self._listener.sendLine(u'loadfile {}'.format(self._quoteArg(filePath)), notReadyAfterThis=True)
|
self._listener.sendLine('loadfile {}'.format(self._quoteArg(filePath)), notReadyAfterThis=True)
|
||||||
|
|
||||||
def setFeatures(self, featureList):
|
def setFeatures(self, featureList):
|
||||||
self.sendMpvOptions()
|
self.sendMpvOptions()
|
||||||
@ -253,21 +253,21 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
def sendMpvOptions(self):
|
def sendMpvOptions(self):
|
||||||
options = []
|
options = []
|
||||||
for option in constants.MPV_SYNCPLAYINTF_OPTIONS_TO_SEND:
|
for option in constants.MPV_SYNCPLAYINTF_OPTIONS_TO_SEND:
|
||||||
options.append(u"{}={}".format(option, self._client._config[option]))
|
options.append("{}={}".format(option, self._client._config[option]))
|
||||||
for option in constants.MPV_SYNCPLAYINTF_CONSTANTS_TO_SEND:
|
for option in constants.MPV_SYNCPLAYINTF_CONSTANTS_TO_SEND:
|
||||||
options.append(option)
|
options.append(option)
|
||||||
for option in constants.MPV_SYNCPLAYINTF_LANGUAGE_TO_SEND:
|
for option in constants.MPV_SYNCPLAYINTF_LANGUAGE_TO_SEND:
|
||||||
options.append(u"{}={}".format(option, getMessage(option)))
|
options.append("{}={}".format(option, getMessage(option)))
|
||||||
options.append(u"OscVisibilityChangeCompatible={}".format(constants.MPV_OSC_VISIBILITY_CHANGE_VERSION))
|
options.append("OscVisibilityChangeCompatible={}".format(constants.MPV_OSC_VISIBILITY_CHANGE_VERSION))
|
||||||
options_string = ", ".join(options)
|
options_string = ", ".join(options)
|
||||||
self._listener.sendLine(u'script-message-to syncplayintf set_syncplayintf_options "{}"'.format(options_string))
|
self._listener.sendLine('script-message-to syncplayintf set_syncplayintf_options "{}"'.format(options_string))
|
||||||
self._setOSDPosition()
|
self._setOSDPosition()
|
||||||
|
|
||||||
def _handleUnknownLine(self, line):
|
def _handleUnknownLine(self, line):
|
||||||
self.mpvErrorCheck(line)
|
self.mpvErrorCheck(line)
|
||||||
|
|
||||||
if "<chat>" in line:
|
if "<chat>" in line:
|
||||||
line = line.decode("utf-8").replace(constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER, "\\").encode("utf-8")
|
line = line.replace(constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER, "\\")
|
||||||
self._listener.sendChat(line[6:-7])
|
self._listener.sendChat(line[6:-7])
|
||||||
|
|
||||||
if "<get_syncplayintf_options>" in line:
|
if "<get_syncplayintf_options>" in line:
|
||||||
|
|||||||
0
syncplay/players/playerFactory.py
Normal file → Executable file
0
syncplay/players/playerFactory.py
Normal file → Executable file
@ -1,484 +1,490 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
import re
|
import re
|
||||||
import threading
|
import threading
|
||||||
from syncplay.players.basePlayer import BasePlayer
|
from syncplay.players.basePlayer import BasePlayer
|
||||||
from syncplay import constants, utils
|
from syncplay import constants, utils
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import random
|
import random
|
||||||
import socket
|
import socket
|
||||||
import asynchat, asyncore
|
import asynchat, asyncore
|
||||||
import urllib
|
import urllib.request, urllib.parse, urllib.error
|
||||||
import time
|
import time
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
from syncplay.utils import isBSD, isLinux, isWindows, isMacOS
|
from syncplay.utils import isBSD, isLinux, isWindows, isMacOS
|
||||||
|
|
||||||
class VlcPlayer(BasePlayer):
|
class VlcPlayer(BasePlayer):
|
||||||
speedSupported = True
|
speedSupported = True
|
||||||
customOpenDialog = False
|
customOpenDialog = False
|
||||||
chatOSDSupported = False
|
chatOSDSupported = False
|
||||||
alertOSDSupported = True
|
alertOSDSupported = True
|
||||||
osdMessageSeparator = "; "
|
osdMessageSeparator = "; "
|
||||||
|
|
||||||
RE_ANSWER = re.compile(constants.VLC_ANSWER_REGEX)
|
RE_ANSWER = re.compile(constants.VLC_ANSWER_REGEX)
|
||||||
SLAVE_ARGS = constants.VLC_SLAVE_ARGS
|
SLAVE_ARGS = constants.VLC_SLAVE_ARGS
|
||||||
if isMacOS():
|
if isMacOS():
|
||||||
SLAVE_ARGS.extend(constants.VLC_SLAVE_MACOS_ARGS)
|
SLAVE_ARGS.extend(constants.VLC_SLAVE_MACOS_ARGS)
|
||||||
else:
|
else:
|
||||||
SLAVE_ARGS.extend(constants.VLC_SLAVE_NONMACOS_ARGS)
|
SLAVE_ARGS.extend(constants.VLC_SLAVE_NONMACOS_ARGS)
|
||||||
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
|
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):
|
def __init__(self, client, playerPath, filePath, args):
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
self.reactor = reactor
|
self.reactor = reactor
|
||||||
self._client = client
|
self._client = client
|
||||||
self._paused = None
|
self._paused = None
|
||||||
self._duration = None
|
self._duration = None
|
||||||
self._filename = None
|
self._filename = None
|
||||||
self._filepath = None
|
self._filepath = None
|
||||||
self._filechanged = False
|
self._filechanged = False
|
||||||
self._lastVLCPositionUpdate = None
|
self._lastVLCPositionUpdate = None
|
||||||
self.shownVLCLatencyError = False
|
self.shownVLCLatencyError = False
|
||||||
self._previousPreviousPosition = -2
|
self._previousPreviousPosition = -2
|
||||||
self._previousPosition = -1
|
self._previousPosition = -1
|
||||||
self._position = 0
|
self._position = 0
|
||||||
try: # Hack to fix locale issue without importing locale library
|
try: # Hack to fix locale issue without importing locale library
|
||||||
self.radixChar = "{:n}".format(1.5)[1:2]
|
self.radixChar = "{:n}".format(1.5)[1:2]
|
||||||
if self.radixChar == "" or self.radixChar == "1" or self.radixChar == "5":
|
if self.radixChar == "" or self.radixChar == "1" or self.radixChar == "5":
|
||||||
raise ValueError
|
raise ValueError
|
||||||
except:
|
except:
|
||||||
self._client.ui.showErrorMessage("Failed to determine locale. As a fallback Syncplay is using the following radix character: \".\".")
|
self._client.ui.showErrorMessage("Failed to determine locale. As a fallback Syncplay is using the following radix character: \".\".")
|
||||||
self.radixChar = "."
|
self.radixChar = "."
|
||||||
|
|
||||||
self._durationAsk = threading.Event()
|
self._durationAsk = threading.Event()
|
||||||
self._filenameAsk = threading.Event()
|
self._filenameAsk = threading.Event()
|
||||||
self._pathAsk = threading.Event()
|
self._pathAsk = threading.Event()
|
||||||
self._positionAsk = threading.Event()
|
self._positionAsk = threading.Event()
|
||||||
self._pausedAsk = threading.Event()
|
self._pausedAsk = threading.Event()
|
||||||
self._vlcready = threading.Event()
|
self._vlcready = threading.Event()
|
||||||
self._vlcclosed = threading.Event()
|
self._vlcclosed = threading.Event()
|
||||||
self._listener = None
|
self._listener = None
|
||||||
try:
|
try:
|
||||||
self._listener = self.__Listener(self, playerPath, filePath, args, self._vlcready, self._vlcclosed)
|
self._listener = self.__Listener(self, playerPath, filePath, args, self._vlcready, self._vlcclosed)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self._client.ui.showErrorMessage(getMessage("vlc-failed-connection"), True)
|
self._client.ui.showErrorMessage(getMessage("vlc-failed-connection"), True)
|
||||||
self.reactor.callFromThread(self._client.stop, True,)
|
self.reactor.callFromThread(self._client.stop, True,)
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
self._listener.setDaemon(True)
|
self._listener.setDaemon(True)
|
||||||
self._listener.start()
|
self._listener.start()
|
||||||
if not self._vlcready.wait(constants.VLC_OPEN_MAX_WAIT_TIME):
|
if not self._vlcready.wait(constants.VLC_OPEN_MAX_WAIT_TIME):
|
||||||
self._vlcready.set()
|
self._vlcready.set()
|
||||||
self._client.ui.showErrorMessage(getMessage("vlc-failed-connection"), True)
|
self._client.ui.showErrorMessage(getMessage("vlc-failed-connection"), True)
|
||||||
self.reactor.callFromThread(self._client.stop, True,)
|
self.reactor.callFromThread(self._client.stop, True,)
|
||||||
self.reactor.callFromThread(self._client.initPlayer, self,)
|
self.reactor.callFromThread(self._client.initPlayer, self,)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _fileUpdateClearEvents(self):
|
def _fileUpdateClearEvents(self):
|
||||||
self._durationAsk.clear()
|
self._durationAsk.clear()
|
||||||
self._filenameAsk.clear()
|
self._filenameAsk.clear()
|
||||||
self._pathAsk.clear()
|
self._pathAsk.clear()
|
||||||
|
|
||||||
def _fileUpdateWaitEvents(self):
|
def _fileUpdateWaitEvents(self):
|
||||||
self._durationAsk.wait()
|
self._durationAsk.wait()
|
||||||
self._filenameAsk.wait()
|
self._filenameAsk.wait()
|
||||||
self._pathAsk.wait()
|
self._pathAsk.wait()
|
||||||
|
|
||||||
def _onFileUpdate(self):
|
def _onFileUpdate(self):
|
||||||
self._fileUpdateClearEvents()
|
self._fileUpdateClearEvents()
|
||||||
self._getFileInfo()
|
self._getFileInfo()
|
||||||
self._fileUpdateWaitEvents()
|
self._fileUpdateWaitEvents()
|
||||||
args = (self._filename, self._duration, self._filepath)
|
args = (self._filename, self._duration, self._filepath)
|
||||||
self.reactor.callFromThread(self._client.updateFile, *args)
|
self.reactor.callFromThread(self._client.updateFile, *args)
|
||||||
self.setPaused(self._client.getGlobalPaused())
|
self.setPaused(self._client.getGlobalPaused())
|
||||||
self.setPosition(self._client.getGlobalPosition())
|
self.setPosition(self._client.getGlobalPosition())
|
||||||
|
|
||||||
def askForStatus(self):
|
def askForStatus(self):
|
||||||
self._filechanged = False
|
self._filechanged = False
|
||||||
self._positionAsk.clear()
|
self._positionAsk.clear()
|
||||||
self._pausedAsk.clear()
|
self._pausedAsk.clear()
|
||||||
self._listener.sendLine(".")
|
self._listener.sendLine(".")
|
||||||
if self._filename and not self._filechanged:
|
if self._filename and not self._filechanged:
|
||||||
self._positionAsk.wait(constants.PLAYER_ASK_DELAY)
|
self._positionAsk.wait(constants.PLAYER_ASK_DELAY)
|
||||||
self._client.updatePlayerStatus(self._paused, self.getCalculatedPosition())
|
self._client.updatePlayerStatus(self._paused, self.getCalculatedPosition())
|
||||||
else:
|
else:
|
||||||
self._client.updatePlayerStatus(self._client.getGlobalPaused(), self._client.getGlobalPosition())
|
self._client.updatePlayerStatus(self._client.getGlobalPaused(), self._client.getGlobalPosition())
|
||||||
|
|
||||||
def getCalculatedPosition(self):
|
def getCalculatedPosition(self):
|
||||||
if self._lastVLCPositionUpdate is None:
|
if self._lastVLCPositionUpdate is None:
|
||||||
return self._client.getGlobalPosition()
|
return self._client.getGlobalPosition()
|
||||||
diff = time.time() - self._lastVLCPositionUpdate
|
diff = time.time() - self._lastVLCPositionUpdate
|
||||||
if diff > constants.PLAYER_ASK_DELAY and not self._paused:
|
if diff > constants.PLAYER_ASK_DELAY and not self._paused:
|
||||||
self._client.ui.showDebugMessage("VLC did not response in time, so assuming position is {} ({}+{})".format(self._position + diff, self._position, diff))
|
self._client.ui.showDebugMessage("VLC did not response in time, so assuming position is {} ({}+{})".format(self._position + diff, self._position, diff))
|
||||||
if diff > constants.VLC_LATENCY_ERROR_THRESHOLD:
|
if diff > constants.VLC_LATENCY_ERROR_THRESHOLD:
|
||||||
if not self.shownVLCLatencyError or constants.DEBUG_MODE:
|
if not self.shownVLCLatencyError or constants.DEBUG_MODE:
|
||||||
self._client.ui.showErrorMessage(getMessage("media-player-latency-warning").format(int(diff)))
|
self._client.ui.showErrorMessage(getMessage("media-player-latency-warning").format(int(diff)))
|
||||||
self.shownVLCLatencyError = True
|
self.shownVLCLatencyError = True
|
||||||
return self._position + diff
|
return self._position + diff
|
||||||
else:
|
else:
|
||||||
return self._position
|
return self._position
|
||||||
|
|
||||||
def displayMessage(self, message, duration=constants.OSD_DURATION * 1000, OSDType=constants.OSD_DURATION, mood=constants.MESSAGE_NEUTRAL):
|
def displayMessage(self, message, duration=constants.OSD_DURATION * 1000, OSDType=constants.OSD_DURATION, mood=constants.MESSAGE_NEUTRAL):
|
||||||
duration /= 1000
|
duration /= 1000
|
||||||
if OSDType != constants.OSD_ALERT:
|
if OSDType != constants.OSD_ALERT:
|
||||||
self._listener.sendLine('display-osd: {}, {}, {}'.format('top-right', duration, message.encode('utf8')))
|
self._listener.sendLine('display-osd: {}, {}, {}'.format('top-right', duration, message))
|
||||||
else:
|
else:
|
||||||
self._listener.sendLine('display-secondary-osd: {}, {}, {}'.format('center', duration, message.encode('utf8')))
|
self._listener.sendLine('display-secondary-osd: {}, {}, {}'.format('center', duration, message))
|
||||||
|
|
||||||
def setSpeed(self, value):
|
def setSpeed(self, value):
|
||||||
self._listener.sendLine("set-rate: {:.2n}".format(value))
|
self._listener.sendLine("set-rate: {:.2n}".format(value))
|
||||||
|
|
||||||
def setFeatures(self, featureList):
|
def setFeatures(self, featureList):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def setPosition(self, value):
|
def setPosition(self, value):
|
||||||
self._lastVLCPositionUpdate = time.time()
|
self._lastVLCPositionUpdate = time.time()
|
||||||
self._listener.sendLine("set-position: {}".format(value).replace(".",self.radixChar))
|
self._listener.sendLine("set-position: {}".format(value).replace(".",self.radixChar))
|
||||||
|
|
||||||
def setPaused(self, value):
|
def setPaused(self, value):
|
||||||
self._paused = value
|
self._paused = value
|
||||||
if not value:
|
if not value:
|
||||||
self._lastVLCPositionUpdate = time.time()
|
self._lastVLCPositionUpdate = time.time()
|
||||||
self._listener.sendLine('set-playstate: {}'.format("paused" if value else "playing"))
|
self._listener.sendLine('set-playstate: {}'.format("paused" if value else "playing"))
|
||||||
|
|
||||||
def getMRL(self, fileURL):
|
def getMRL(self, fileURL):
|
||||||
if utils.isURL(fileURL):
|
if utils.isURL(fileURL):
|
||||||
fileURL = fileURL.encode('utf8')
|
fileURL = urllib.parse.quote(fileURL, safe="%/:=&?~#+!$,;'@()*")
|
||||||
fileURL = urllib.quote(fileURL, safe="%/:=&?~#+!$,;'@()*")
|
return fileURL
|
||||||
return fileURL
|
|
||||||
|
fileURL = fileURL.replace('\\', '/')
|
||||||
fileURL = fileURL.replace(u'\\', u'/')
|
fileURL = fileURL.encode('utf8')
|
||||||
fileURL = fileURL.encode('utf8')
|
fileURL = urllib.parse.quote_plus(fileURL)
|
||||||
fileURL = urllib.quote_plus(fileURL)
|
if isWindows():
|
||||||
if isWindows():
|
fileURL = "file:///" + fileURL
|
||||||
fileURL = "file:///" + fileURL
|
else:
|
||||||
else:
|
fileURL = "file://" + fileURL
|
||||||
fileURL = "file://" + fileURL
|
fileURL = fileURL.replace("+", "%20")
|
||||||
fileURL = fileURL.replace("+", "%20")
|
return fileURL
|
||||||
return fileURL
|
|
||||||
|
def openFile(self, filePath, resetPosition=False):
|
||||||
def openFile(self, filePath, resetPosition=False):
|
if not utils.isURL(filePath):
|
||||||
if not utils.isURL(filePath):
|
normedPath = os.path.normpath(filePath)
|
||||||
normedPath = os.path.normpath(filePath)
|
if os.path.isfile(normedPath):
|
||||||
if os.path.isfile(normedPath):
|
filePath = normedPath
|
||||||
filePath = normedPath
|
if utils.isASCII(filePath) and not utils.isURL(filePath):
|
||||||
if utils.isASCII(filePath) and not utils.isURL(filePath):
|
self._listener.sendLine('load-file: {}'.format(filePath))
|
||||||
self._listener.sendLine('load-file: {}'.format(filePath.encode('ascii', 'ignore')))
|
else:
|
||||||
else:
|
fileURL = self.getMRL(filePath)
|
||||||
fileURL = self.getMRL(filePath)
|
self._listener.sendLine('load-file: {}'.format(fileURL))
|
||||||
self._listener.sendLine('load-file: {}'.format(fileURL))
|
|
||||||
|
def _getFileInfo(self):
|
||||||
def _getFileInfo(self):
|
self._listener.sendLine("get-duration")
|
||||||
self._listener.sendLine("get-duration")
|
self._listener.sendLine("get-filepath")
|
||||||
self._listener.sendLine("get-filepath")
|
self._listener.sendLine("get-filename")
|
||||||
self._listener.sendLine("get-filename")
|
|
||||||
|
def lineReceived(self, line):
|
||||||
def lineReceived(self, line):
|
#try:
|
||||||
try:
|
line = line.decode('utf-8')
|
||||||
self._client.ui.showDebugMessage("player << {}".format(line))
|
self._client.ui.showDebugMessage("player << {}".format(line))
|
||||||
except:
|
#except:
|
||||||
pass
|
#pass
|
||||||
match, name, value = self.RE_ANSWER.match(line), "", ""
|
match, name, value = self.RE_ANSWER.match(line), "", ""
|
||||||
if match:
|
if match:
|
||||||
name, value = match.group('command'), match.group('argument')
|
name, value = match.group('command'), match.group('argument')
|
||||||
|
|
||||||
if line == "filepath-change-notification":
|
if line == "filepath-change-notification":
|
||||||
self._filechanged = True
|
self._filechanged = True
|
||||||
t = threading.Thread(target=self._onFileUpdate)
|
t = threading.Thread(target=self._onFileUpdate)
|
||||||
t.setDaemon(True)
|
t.setDaemon(True)
|
||||||
t.start()
|
t.start()
|
||||||
elif name == "filepath":
|
elif name == "filepath":
|
||||||
self._filechanged = True
|
self._filechanged = True
|
||||||
if value == "no-input":
|
if value == "no-input":
|
||||||
self._filepath = None
|
self._filepath = None
|
||||||
else:
|
else:
|
||||||
if "file://" in value:
|
if "file://" in value:
|
||||||
value = value.replace("file://", "")
|
value = value.replace("file://", "")
|
||||||
if not os.path.isfile(value):
|
if not os.path.isfile(value):
|
||||||
value = value.lstrip("/")
|
value = value.lstrip("/")
|
||||||
elif utils.isURL(value):
|
elif utils.isURL(value):
|
||||||
value = urllib.unquote(value)
|
value = urllib.parse.unquote(value)
|
||||||
value = value.decode('utf-8')
|
#value = value.decode('utf-8')
|
||||||
self._filepath = value
|
self._filepath = value
|
||||||
self._pathAsk.set()
|
self._pathAsk.set()
|
||||||
elif name == "duration":
|
elif name == "duration":
|
||||||
if value == "no-input":
|
if value == "no-input":
|
||||||
self._duration = 0
|
self._duration = 0
|
||||||
elif value == "invalid-32-bit-value":
|
elif value == "invalid-32-bit-value":
|
||||||
self._duration = 0
|
self._duration = 0
|
||||||
self.drop(getMessage("vlc-failed-versioncheck"))
|
self.drop(getMessage("vlc-failed-versioncheck"))
|
||||||
else:
|
else:
|
||||||
self._duration = float(value.replace(",", "."))
|
self._duration = float(value.replace(",", "."))
|
||||||
self._durationAsk.set()
|
self._durationAsk.set()
|
||||||
elif name == "playstate":
|
elif name == "playstate":
|
||||||
self._paused = bool(value != 'playing') if(value != "no-input" and self._filechanged == False) else self._client.getGlobalPaused()
|
self._paused = bool(value != 'playing') if(value != "no-input" and self._filechanged == False) else self._client.getGlobalPaused()
|
||||||
diff = time.time() - self._lastVLCPositionUpdate if self._lastVLCPositionUpdate else 0
|
diff = time.time() - self._lastVLCPositionUpdate if self._lastVLCPositionUpdate else 0
|
||||||
if self._paused == False \
|
if self._paused == False \
|
||||||
and self._position == self._previousPreviousPosition \
|
and self._position == self._previousPreviousPosition \
|
||||||
and self._previousPosition == self._position \
|
and self._previousPosition == self._position \
|
||||||
and self._duration > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH \
|
and self._duration > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH \
|
||||||
and (self._duration - self._position) < constants.VLC_EOF_DURATION_THRESHOLD \
|
and (self._duration - self._position) < constants.VLC_EOF_DURATION_THRESHOLD \
|
||||||
and diff > constants.VLC_LATENCY_ERROR_THRESHOLD:
|
and diff > constants.VLC_LATENCY_ERROR_THRESHOLD:
|
||||||
self._client.ui.showDebugMessage("Treating 'playing' response as 'paused' due to VLC EOF bug")
|
self._client.ui.showDebugMessage("Treating 'playing' response as 'paused' due to VLC EOF bug")
|
||||||
self.setPaused(True)
|
self.setPaused(True)
|
||||||
self._pausedAsk.set()
|
self._pausedAsk.set()
|
||||||
elif name == "position":
|
elif name == "position":
|
||||||
newPosition = float(value.replace(",", ".")) if (value != "no-input" and self._filechanged == False) else self._client.getGlobalPosition()
|
newPosition = float(value.replace(",", ".")) if (value != "no-input" and self._filechanged == False) else self._client.getGlobalPosition()
|
||||||
if newPosition == self._previousPosition and newPosition <> self._duration and not self._paused:
|
if newPosition == self._previousPosition and newPosition != self._duration and not self._paused:
|
||||||
self._client.ui.showDebugMessage("Not considering position {} duplicate as new time because of VLC time precision bug".format(newPosition))
|
self._client.ui.showDebugMessage("Not considering position {} duplicate as new time because of VLC time precision bug".format(newPosition))
|
||||||
self._previousPreviousPosition = self._previousPosition
|
self._previousPreviousPosition = self._previousPosition
|
||||||
self._previousPosition = self._position
|
self._previousPosition = self._position
|
||||||
self._positionAsk.set()
|
self._positionAsk.set()
|
||||||
return
|
return
|
||||||
self._previousPreviousPosition = self._previousPosition
|
self._previousPreviousPosition = self._previousPosition
|
||||||
self._previousPosition = self._position
|
self._previousPosition = self._position
|
||||||
self._position = newPosition
|
self._position = newPosition
|
||||||
if self._position < 0 and self._duration > 2147 and self._vlcVersion == "3.0.0":
|
if self._position < 0 and self._duration > 2147 and self._vlcVersion == "3.0.0":
|
||||||
self.drop(getMessage("vlc-failed-versioncheck"))
|
self.drop(getMessage("vlc-failed-versioncheck"))
|
||||||
self._lastVLCPositionUpdate = time.time()
|
self._lastVLCPositionUpdate = time.time()
|
||||||
self._positionAsk.set()
|
self._positionAsk.set()
|
||||||
elif name == "filename":
|
elif name == "filename":
|
||||||
self._filechanged = True
|
self._filechanged = True
|
||||||
self._filename = value.decode('utf-8')
|
self._filename = value
|
||||||
self._filenameAsk.set()
|
self._filenameAsk.set()
|
||||||
elif line.startswith("vlc-version: "):
|
elif line.startswith("vlc-version: "):
|
||||||
self._vlcVersion = line.split(': ')[1].replace(' ','-').split('-')[0]
|
self._vlcVersion = line.split(': ')[1].replace(' ','-').split('-')[0]
|
||||||
if not utils.meetsMinVersion(self._vlcVersion, constants.VLC_MIN_VERSION):
|
if not utils.meetsMinVersion(self._vlcVersion, constants.VLC_MIN_VERSION):
|
||||||
self._client.ui.showErrorMessage(getMessage("vlc-version-mismatch").format(constants.VLC_MIN_VERSION))
|
self._client.ui.showErrorMessage(getMessage("vlc-version-mismatch").format(constants.VLC_MIN_VERSION))
|
||||||
self._vlcready.set()
|
self._vlcready.set()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(client, playerPath, filePath, args):
|
def run(client, playerPath, filePath, args):
|
||||||
vlc = VlcPlayer(client, VlcPlayer.getExpandedPath(playerPath), filePath, args)
|
vlc = VlcPlayer(client, VlcPlayer.getExpandedPath(playerPath), filePath, args)
|
||||||
return vlc
|
return vlc
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getDefaultPlayerPathsList():
|
def getDefaultPlayerPathsList():
|
||||||
l = []
|
l = []
|
||||||
for path in constants.VLC_PATHS:
|
for path in constants.VLC_PATHS:
|
||||||
p = VlcPlayer.getExpandedPath(path)
|
p = VlcPlayer.getExpandedPath(path)
|
||||||
if p:
|
if p:
|
||||||
l.append(p)
|
l.append(p)
|
||||||
return l
|
return l
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isValidPlayerPath(path):
|
def isValidPlayerPath(path):
|
||||||
if "vlc" in path.lower() and VlcPlayer.getExpandedPath(path):
|
if "vlc" in path.lower() and VlcPlayer.getExpandedPath(path):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getPlayerPathErrors(playerPath, filePath):
|
def getPlayerPathErrors(playerPath, filePath):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getIconPath(path):
|
def getIconPath(path):
|
||||||
return constants.VLC_ICONPATH
|
return constants.VLC_ICONPATH
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getExpandedPath(playerPath):
|
def getExpandedPath(playerPath):
|
||||||
if not os.path.isfile(playerPath):
|
if not os.path.isfile(playerPath):
|
||||||
if os.path.isfile(playerPath + u"vlc.exe"):
|
if os.path.isfile(playerPath + "vlc.exe"):
|
||||||
playerPath += u"vlc.exe"
|
playerPath += "vlc.exe"
|
||||||
return playerPath
|
return playerPath
|
||||||
elif os.path.isfile(playerPath + u"\\vlc.exe"):
|
elif os.path.isfile(playerPath + "\\vlc.exe"):
|
||||||
playerPath += u"\\vlc.exe"
|
playerPath += "\\vlc.exe"
|
||||||
return playerPath
|
return playerPath
|
||||||
elif os.path.isfile(playerPath + u"VLCPortable.exe"):
|
elif os.path.isfile(playerPath + "VLCPortable.exe"):
|
||||||
playerPath += u"VLCPortable.exe"
|
playerPath += "VLCPortable.exe"
|
||||||
return playerPath
|
return playerPath
|
||||||
elif os.path.isfile(playerPath + u"\\VLCPortable.exe"):
|
elif os.path.isfile(playerPath + "\\VLCPortable.exe"):
|
||||||
playerPath += u"\\VLCPortable.exe"
|
playerPath += "\\VLCPortable.exe"
|
||||||
return playerPath
|
return playerPath
|
||||||
if os.access(playerPath, os.X_OK):
|
if os.access(playerPath, os.X_OK):
|
||||||
return playerPath
|
return playerPath
|
||||||
for path in os.environ['PATH'].split(':'):
|
for path in os.environ['PATH'].split(':'):
|
||||||
path = os.path.join(os.path.realpath(path), playerPath)
|
path = os.path.join(os.path.realpath(path), playerPath)
|
||||||
if os.access(path, os.X_OK):
|
if os.access(path, os.X_OK):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def drop(self, dropErrorMessage=None):
|
def drop(self, dropErrorMessage=None):
|
||||||
if self._listener:
|
if self._listener:
|
||||||
self._vlcclosed.clear()
|
self._vlcclosed.clear()
|
||||||
self._listener.sendLine('close-vlc')
|
self._listener.sendLine('close-vlc')
|
||||||
self._vlcclosed.wait()
|
self._vlcclosed.wait()
|
||||||
self._durationAsk.set()
|
self._durationAsk.set()
|
||||||
self._filenameAsk.set()
|
self._filenameAsk.set()
|
||||||
self._pathAsk.set()
|
self._pathAsk.set()
|
||||||
self._positionAsk.set()
|
self._positionAsk.set()
|
||||||
self._vlcready.set()
|
self._vlcready.set()
|
||||||
self._pausedAsk.set()
|
self._pausedAsk.set()
|
||||||
if dropErrorMessage:
|
if dropErrorMessage:
|
||||||
self.reactor.callFromThread(self._client.ui.showErrorMessage, dropErrorMessage, True)
|
self.reactor.callFromThread(self._client.ui.showErrorMessage, dropErrorMessage, True)
|
||||||
self.reactor.callFromThread(self._client.stop, False,)
|
self.reactor.callFromThread(self._client.stop, False,)
|
||||||
|
|
||||||
class __Listener(threading.Thread, asynchat.async_chat):
|
class __Listener(threading.Thread, asynchat.async_chat):
|
||||||
def __init__(self, playerController, playerPath, filePath, args, vlcReady, vlcClosed):
|
def __init__(self, playerController, playerPath, filePath, args, vlcReady, vlcClosed):
|
||||||
self.__playerController = playerController
|
self.__playerController = playerController
|
||||||
self.requestedVLCVersion = False
|
self.requestedVLCVersion = False
|
||||||
self.vlcHasResponded = False
|
self.vlcHasResponded = False
|
||||||
self.oldIntfVersion = None
|
self.oldIntfVersion = None
|
||||||
self.timeVLCLaunched = None
|
self.timeVLCLaunched = None
|
||||||
call = [playerPath]
|
call = [playerPath]
|
||||||
if filePath:
|
if filePath:
|
||||||
if utils.isASCII(filePath):
|
if utils.isASCII(filePath):
|
||||||
call.append(filePath)
|
call.append(filePath)
|
||||||
else:
|
else:
|
||||||
call.append(self.__playerController.getMRL(filePath))
|
call.append(self.__playerController.getMRL(filePath))
|
||||||
def _usevlcintf(vlcIntfPath, vlcIntfUserPath):
|
def _usevlcintf(vlcIntfPath, vlcIntfUserPath):
|
||||||
vlcSyncplayInterfacePath = vlcIntfPath + "syncplay.lua"
|
vlcSyncplayInterfacePath = vlcIntfPath + "syncplay.lua"
|
||||||
if not os.path.isfile(vlcSyncplayInterfacePath):
|
if not os.path.isfile(vlcSyncplayInterfacePath):
|
||||||
vlcSyncplayInterfacePath = vlcIntfUserPath + "syncplay.lua"
|
vlcSyncplayInterfacePath = vlcIntfUserPath + "syncplay.lua"
|
||||||
if os.path.isfile(vlcSyncplayInterfacePath):
|
if os.path.isfile(vlcSyncplayInterfacePath):
|
||||||
with open(vlcSyncplayInterfacePath, 'rU') as interfacefile:
|
with open(vlcSyncplayInterfacePath, 'rU') as interfacefile:
|
||||||
for line in interfacefile:
|
for line in interfacefile:
|
||||||
if "local connectorversion" in line:
|
if "local connectorversion" in line:
|
||||||
interface_version = line[26:31]
|
interface_version = line[26:31]
|
||||||
if utils.meetsMinVersion(interface_version, constants.VLC_INTERFACE_MIN_VERSION):
|
if utils.meetsMinVersion(interface_version, constants.VLC_INTERFACE_MIN_VERSION):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
self.oldIntfVersion = line[26:31]
|
self.oldIntfVersion = line[26:31]
|
||||||
return False
|
return False
|
||||||
playerController._client.ui.showErrorMessage(getMessage("vlc-interface-not-installed"))
|
playerController._client.ui.showErrorMessage(getMessage("vlc-interface-not-installed"))
|
||||||
return False
|
return False
|
||||||
if isLinux():
|
if isLinux():
|
||||||
playerController.vlcIntfPath = "/usr/lib/vlc/lua/intf/"
|
playerController.vlcIntfPath = "/usr/lib/vlc/lua/intf/"
|
||||||
playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), ".local/share/vlc/lua/intf/")
|
playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), ".local/share/vlc/lua/intf/")
|
||||||
elif isMacOS():
|
elif isMacOS():
|
||||||
playerController.vlcIntfPath = "/Applications/VLC.app/Contents/MacOS/share/lua/intf/"
|
playerController.vlcIntfPath = "/Applications/VLC.app/Contents/MacOS/share/lua/intf/"
|
||||||
playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), "Library/Application Support/org.videolan.vlc/lua/intf/")
|
playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), "Library/Application Support/org.videolan.vlc/lua/intf/")
|
||||||
elif isBSD():
|
elif isBSD():
|
||||||
# *BSD ports/pkgs install to /usr/local by default.
|
# *BSD ports/pkgs install to /usr/local by default.
|
||||||
# This should also work for all the other BSDs, such as OpenBSD or DragonFly.
|
# This should also work for all the other BSDs, such as OpenBSD or DragonFly.
|
||||||
playerController.vlcIntfPath = "/usr/local/lib/vlc/lua/intf/"
|
playerController.vlcIntfPath = "/usr/local/lib/vlc/lua/intf/"
|
||||||
playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), ".local/share/vlc/lua/intf/")
|
playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), ".local/share/vlc/lua/intf/")
|
||||||
else:
|
else:
|
||||||
playerController.vlcIntfPath = os.path.dirname(playerPath).replace("\\", "/") + "/lua/intf/"
|
playerController.vlcIntfPath = os.path.dirname(playerPath).replace("\\", "/") + "/lua/intf/"
|
||||||
playerController.vlcIntfUserPath = os.path.join(os.getenv('APPDATA', '.'), "VLC\\lua\\intf\\")
|
playerController.vlcIntfUserPath = os.path.join(os.getenv('APPDATA', '.'), "VLC\\lua\\intf\\")
|
||||||
playerController.vlcModulePath = playerController.vlcIntfPath + "modules/?.luac"
|
playerController.vlcModulePath = playerController.vlcIntfPath + "modules/?.luac"
|
||||||
if _usevlcintf(playerController.vlcIntfPath, playerController.vlcIntfUserPath):
|
if _usevlcintf(playerController.vlcIntfPath, playerController.vlcIntfUserPath):
|
||||||
playerController.SLAVE_ARGS.append('--lua-config=syncplay={{port=\"{}\"}}'.format(str(playerController.vlcport)))
|
playerController.SLAVE_ARGS.append('--lua-config=syncplay={{port=\"{}\"}}'.format(str(playerController.vlcport)))
|
||||||
else:
|
else:
|
||||||
if isLinux():
|
if isLinux():
|
||||||
playerController.vlcDataPath = "/usr/lib/syncplay/resources"
|
playerController.vlcDataPath = "/usr/lib/syncplay/resources"
|
||||||
else:
|
else:
|
||||||
playerController.vlcDataPath = utils.findWorkingDir() + "\\resources"
|
playerController.vlcDataPath = utils.findWorkingDir() + "\\resources"
|
||||||
playerController.SLAVE_ARGS.append('--data-path={}'.format(playerController.vlcDataPath))
|
playerController.SLAVE_ARGS.append('--data-path={}'.format(playerController.vlcDataPath))
|
||||||
playerController.SLAVE_ARGS.append('--lua-config=syncplay={{modulepath=\"{}\",port=\"{}\"}}'.format(playerController.vlcModulePath, str(playerController.vlcport)))
|
playerController.SLAVE_ARGS.append('--lua-config=syncplay={{modulepath=\"{}\",port=\"{}\"}}'.format(playerController.vlcModulePath, str(playerController.vlcport)))
|
||||||
|
|
||||||
call.extend(playerController.SLAVE_ARGS)
|
call.extend(playerController.SLAVE_ARGS)
|
||||||
if args:
|
if args:
|
||||||
call.extend(args)
|
call.extend(args)
|
||||||
|
|
||||||
self._vlcready = vlcReady
|
self._vlcready = vlcReady
|
||||||
self._vlcclosed = vlcClosed
|
self._vlcclosed = vlcClosed
|
||||||
self._vlcVersion = None
|
self._vlcVersion = None
|
||||||
|
|
||||||
if self.oldIntfVersion:
|
if self.oldIntfVersion:
|
||||||
self.__playerController.drop(getMessage("vlc-interface-version-mismatch").format(self.oldIntfVersion,constants.VLC_INTERFACE_MIN_VERSION))
|
self.__playerController.drop(getMessage("vlc-interface-version-mismatch").format(self.oldIntfVersion,constants.VLC_INTERFACE_MIN_VERSION))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.__process = subprocess.Popen(call, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
if isWindows() and getattr(sys, 'frozen', '') and getattr(sys, '_MEIPASS', '') is not None: #Needed for pyinstaller --onefile bundle
|
||||||
self.timeVLCLaunched = time.time()
|
self.__process = subprocess.Popen(call, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=False, creationflags=0x08000000)
|
||||||
if self._shouldListenForSTDOUT():
|
else:
|
||||||
for line in iter(self.__process.stderr.readline, ''):
|
self.__process = subprocess.Popen(call, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
self.vlcHasResponded = True
|
self.timeVLCLaunched = time.time()
|
||||||
self.timeVLCLaunched = None
|
if self._shouldListenForSTDOUT():
|
||||||
if "[syncplay]" in line:
|
for line in iter(self.__process.stderr.readline, ''):
|
||||||
if "Listening on host" in line:
|
line = line.decode('utf-8')
|
||||||
break
|
self.vlcHasResponded = True
|
||||||
if "Hosting Syncplay" in line:
|
self.timeVLCLaunched = None
|
||||||
break
|
if "[syncplay]" in line:
|
||||||
elif "Couldn't find lua interface" in line:
|
if "Listening on host" in line:
|
||||||
playerController._client.ui.showErrorMessage(
|
break
|
||||||
getMessage("vlc-failed-noscript").format(line), True)
|
if "Hosting Syncplay" in line:
|
||||||
break
|
break
|
||||||
elif "lua interface error" in line:
|
elif "Couldn't find lua interface" in line:
|
||||||
playerController._client.ui.showErrorMessage(
|
playerController._client.ui.showErrorMessage(
|
||||||
getMessage("media-player-error").format(line), True)
|
getMessage("vlc-failed-noscript").format(line), True)
|
||||||
break
|
break
|
||||||
if not isMacOS():
|
elif "lua interface error" in line:
|
||||||
self.__process.stderr = None
|
playerController._client.ui.showErrorMessage(
|
||||||
else:
|
getMessage("media-player-error").format(line), True)
|
||||||
vlcoutputthread = threading.Thread(target = self.handle_vlcoutput, args=())
|
break
|
||||||
vlcoutputthread.setDaemon(True)
|
if not isMacOS():
|
||||||
vlcoutputthread.start()
|
self.__process.stderr = None
|
||||||
threading.Thread.__init__(self, name="VLC Listener")
|
else:
|
||||||
asynchat.async_chat.__init__(self)
|
vlcoutputthread = threading.Thread(target = self.handle_vlcoutput, args=())
|
||||||
self.set_terminator("\n")
|
vlcoutputthread.setDaemon(True)
|
||||||
self._ibuffer = []
|
vlcoutputthread.start()
|
||||||
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
threading.Thread.__init__(self, name="VLC Listener")
|
||||||
self._sendingData = threading.Lock()
|
asynchat.async_chat.__init__(self)
|
||||||
|
self.set_terminator(b'\n')
|
||||||
def _shouldListenForSTDOUT(self):
|
self._ibuffer = []
|
||||||
if isWindows():
|
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
return False # Due to VLC3 not using STDOUT/STDERR
|
self._sendingData = threading.Lock()
|
||||||
else:
|
|
||||||
return True
|
def _shouldListenForSTDOUT(self):
|
||||||
|
if isWindows():
|
||||||
def initiate_send(self):
|
return False # Due to VLC3 not using STDOUT/STDERR
|
||||||
with self._sendingData:
|
else:
|
||||||
asynchat.async_chat.initiate_send(self)
|
return True
|
||||||
|
|
||||||
def run(self):
|
def initiate_send(self):
|
||||||
self._vlcready.clear()
|
with self._sendingData:
|
||||||
self.connect(('localhost', self.__playerController.vlcport))
|
asynchat.async_chat.initiate_send(self)
|
||||||
asyncore.loop()
|
|
||||||
|
def run(self):
|
||||||
def handle_connect(self):
|
self._vlcready.clear()
|
||||||
asynchat.async_chat.handle_connect(self)
|
self.connect(('localhost', self.__playerController.vlcport))
|
||||||
self._vlcready.set()
|
asyncore.loop()
|
||||||
self.timeVLCLaunched = None
|
|
||||||
|
def handle_connect(self):
|
||||||
def collect_incoming_data(self, data):
|
asynchat.async_chat.handle_connect(self)
|
||||||
self._ibuffer.append(data)
|
self._vlcready.set()
|
||||||
|
self.timeVLCLaunched = None
|
||||||
def handle_close(self):
|
|
||||||
if self.timeVLCLaunched and time.time() - self.timeVLCLaunched < constants.VLC_OPEN_MAX_WAIT_TIME:
|
def collect_incoming_data(self, data):
|
||||||
try:
|
self._ibuffer.append(data)
|
||||||
self.__playerController._client.ui.showDebugMessage("Failed to connect to VLC, but reconnecting as within max wait time")
|
|
||||||
except:
|
def handle_close(self):
|
||||||
pass
|
if self.timeVLCLaunched and time.time() - self.timeVLCLaunched < constants.VLC_OPEN_MAX_WAIT_TIME:
|
||||||
self.run()
|
try:
|
||||||
elif self.vlcHasResponded:
|
self.__playerController._client.ui.showDebugMessage("Failed to connect to VLC, but reconnecting as within max wait time")
|
||||||
asynchat.async_chat.handle_close(self)
|
except:
|
||||||
self.__playerController.drop()
|
pass
|
||||||
else:
|
self.run()
|
||||||
self.vlcHasResponded = True
|
elif self.vlcHasResponded:
|
||||||
asynchat.async_chat.handle_close(self)
|
asynchat.async_chat.handle_close(self)
|
||||||
self.__playerController.drop(getMessage("vlc-failed-connection").format(constants.VLC_MIN_VERSION))
|
self.__playerController.drop()
|
||||||
|
else:
|
||||||
def handle_vlcoutput(self):
|
self.vlcHasResponded = True
|
||||||
out = self.__process.stderr
|
asynchat.async_chat.handle_close(self)
|
||||||
for line in iter(out.readline, ''):
|
self.__playerController.drop(getMessage("vlc-failed-connection").format(constants.VLC_MIN_VERSION))
|
||||||
if '[syncplay] core interface debug: removing module' in line:
|
|
||||||
self.__playerController.drop()
|
def handle_vlcoutput(self):
|
||||||
break
|
out = self.__process.stderr
|
||||||
out.close()
|
for line in iter(out.readline, ''):
|
||||||
|
line = line.decode('utf-8')
|
||||||
|
if '[syncplay] core interface debug: removing module' in line:
|
||||||
def found_terminator(self):
|
self.__playerController.drop()
|
||||||
self.vlcHasResponded = True
|
break
|
||||||
self.__playerController.lineReceived("".join(self._ibuffer))
|
out.close()
|
||||||
self._ibuffer = []
|
|
||||||
|
|
||||||
def sendLine(self, line):
|
def found_terminator(self):
|
||||||
if self.connected:
|
self.vlcHasResponded = True
|
||||||
if not self.requestedVLCVersion:
|
self.__playerController.lineReceived(b"".join(self._ibuffer))
|
||||||
self.requestedVLCVersion = True
|
self._ibuffer = []
|
||||||
self.sendLine("get-vlc-version")
|
|
||||||
try:
|
def sendLine(self, line):
|
||||||
self.push(line + "\n")
|
if self.connected:
|
||||||
if self.__playerController._client and self.__playerController._client.ui:
|
if not self.requestedVLCVersion:
|
||||||
self.__playerController._client.ui.showDebugMessage("player >> {}".format(line))
|
self.requestedVLCVersion = True
|
||||||
except:
|
self.sendLine("get-vlc-version")
|
||||||
pass
|
#try:
|
||||||
if line == "close-vlc":
|
lineToSend = line + "\n"
|
||||||
self._vlcclosed.set()
|
self.push(lineToSend.encode('utf-8'))
|
||||||
if not self.connected and not self.timeVLCLaunched:
|
if self.__playerController._client and self.__playerController._client.ui:
|
||||||
# For circumstances where Syncplay is not connected to VLC and is not reconnecting
|
self.__playerController._client.ui.showDebugMessage("player >> {}".format(line))
|
||||||
try:
|
#except:
|
||||||
self.__process.terminate()
|
#pass
|
||||||
except: # When VLC is already closed
|
if line == "close-vlc":
|
||||||
|
self._vlcclosed.set()
|
||||||
|
if not self.connected and not self.timeVLCLaunched:
|
||||||
|
# For circumstances where Syncplay is not connected to VLC and is not reconnecting
|
||||||
|
try:
|
||||||
|
self.__process.terminate()
|
||||||
|
except: # When VLC is already closed
|
||||||
pass
|
pass
|
||||||
110
syncplay/protocols.py
Normal file → Executable file
110
syncplay/protocols.py
Normal file → Executable file
@ -10,7 +10,7 @@ from syncplay.utils import meetsMinVersion
|
|||||||
|
|
||||||
class JSONCommandProtocol(LineReceiver):
|
class JSONCommandProtocol(LineReceiver):
|
||||||
def handleMessages(self, messages):
|
def handleMessages(self, messages):
|
||||||
for message in messages.iteritems():
|
for message in messages.items():
|
||||||
command = message[0]
|
command = message[0]
|
||||||
if command == "Hello":
|
if command == "Hello":
|
||||||
self.handleHello(message[1])
|
self.handleHello(message[1])
|
||||||
@ -28,7 +28,7 @@ class JSONCommandProtocol(LineReceiver):
|
|||||||
self.dropWithError(getMessage("unknown-command-server-error").format(message[1])) # TODO: log, not drop
|
self.dropWithError(getMessage("unknown-command-server-error").format(message[1])) # TODO: log, not drop
|
||||||
|
|
||||||
def lineReceived(self, line):
|
def lineReceived(self, line):
|
||||||
line = line.strip()
|
line = line.decode('utf-8').strip()
|
||||||
if not line:
|
if not line:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -41,7 +41,7 @@ class JSONCommandProtocol(LineReceiver):
|
|||||||
|
|
||||||
def sendMessage(self, dict_):
|
def sendMessage(self, dict_):
|
||||||
line = json.dumps(dict_)
|
line = json.dumps(dict_)
|
||||||
self.sendLine(line)
|
self.sendLine(line.encode('utf-8'))
|
||||||
self.showDebugMessage("client/server >> {}".format(line))
|
self.showDebugMessage("client/server >> {}".format(line))
|
||||||
|
|
||||||
def drop(self):
|
def drop(self):
|
||||||
@ -75,12 +75,12 @@ class SyncClientProtocol(JSONCommandProtocol):
|
|||||||
self.drop()
|
self.drop()
|
||||||
|
|
||||||
def _extractHelloArguments(self, hello):
|
def _extractHelloArguments(self, hello):
|
||||||
username = hello["username"] if hello.has_key("username") else None
|
username = hello["username"] if "username" in hello else None
|
||||||
roomName = hello["room"]["name"] if hello.has_key("room") else None
|
roomName = hello["room"]["name"] if "room" in hello else None
|
||||||
version = hello["version"] if hello.has_key("version") else None
|
version = hello["version"] if "version" in hello else None
|
||||||
version = hello["realversion"] if hello.has_key("realversion") else version # Used for 1.2.X compatibility
|
version = hello["realversion"] if "realversion" in hello else version # Used for 1.2.X compatibility
|
||||||
motd = hello["motd"] if hello.has_key("motd") else None
|
motd = hello["motd"] if "motd" in hello else None
|
||||||
features = hello["features"] if hello.has_key("features") else None
|
features = hello["features"] if "features" in hello else None
|
||||||
return username, roomName, version, motd, features
|
return username, roomName, version, motd, features
|
||||||
|
|
||||||
def handleHello(self, hello):
|
def handleHello(self, hello):
|
||||||
@ -111,23 +111,23 @@ class SyncClientProtocol(JSONCommandProtocol):
|
|||||||
self.sendMessage({"Hello": hello})
|
self.sendMessage({"Hello": hello})
|
||||||
|
|
||||||
def _SetUser(self, users):
|
def _SetUser(self, users):
|
||||||
for user in users.iteritems():
|
for user in users.items():
|
||||||
username = user[0]
|
username = user[0]
|
||||||
settings = user[1]
|
settings = user[1]
|
||||||
room = settings["room"]["name"] if settings.has_key("room") else None
|
room = settings["room"]["name"] if "room" in settings else None
|
||||||
file_ = settings["file"] if settings.has_key("file") else None
|
file_ = settings["file"] if "file" in settings else None
|
||||||
if settings.has_key("event"):
|
if "event" in settings:
|
||||||
if settings["event"].has_key("joined"):
|
if "joined" in settings["event"]:
|
||||||
self._client.userlist.addUser(username, room, file_)
|
self._client.userlist.addUser(username, room, file_)
|
||||||
elif settings["event"].has_key("left"):
|
elif "left" in settings["event"]:
|
||||||
self._client.removeUser(username)
|
self._client.removeUser(username)
|
||||||
else:
|
else:
|
||||||
self._client.userlist.modUser(username, room, file_)
|
self._client.userlist.modUser(username, room, file_)
|
||||||
|
|
||||||
def handleSet(self, settings):
|
def handleSet(self, settings):
|
||||||
for (command, values) in settings.iteritems():
|
for (command, values) in settings.items():
|
||||||
if command == "room":
|
if command == "room":
|
||||||
roomName = values["name"] if values.has_key("name") else None
|
roomName = values["name"] if "name" in values else None
|
||||||
self._client.setRoom(roomName)
|
self._client.setRoom(roomName)
|
||||||
elif command == "user":
|
elif command == "user":
|
||||||
self._SetUser(values)
|
self._SetUser(values)
|
||||||
@ -142,7 +142,7 @@ class SyncClientProtocol(JSONCommandProtocol):
|
|||||||
self._client.controlledRoomCreated(roomName, controlPassword)
|
self._client.controlledRoomCreated(roomName, controlPassword)
|
||||||
elif command == "ready":
|
elif command == "ready":
|
||||||
user, isReady = values["username"], values["isReady"]
|
user, isReady = values["username"], values["isReady"]
|
||||||
manuallyInitiated = values["manuallyInitiated"] if values.has_key("manuallyInitiated") else True
|
manuallyInitiated = values["manuallyInitiated"] if "manuallyInitiated" in values else True
|
||||||
self._client.setReady(user, isReady, manuallyInitiated)
|
self._client.setReady(user, isReady, manuallyInitiated)
|
||||||
elif command == "playlistIndex":
|
elif command == "playlistIndex":
|
||||||
self._client.playlist.changeToPlaylistIndex(values['index'], values['user'])
|
self._client.playlist.changeToPlaylistIndex(values['index'], values['user'])
|
||||||
@ -172,11 +172,11 @@ class SyncClientProtocol(JSONCommandProtocol):
|
|||||||
|
|
||||||
def handleList(self, userList):
|
def handleList(self, userList):
|
||||||
self._client.userlist.clearList()
|
self._client.userlist.clearList()
|
||||||
for room in userList.iteritems():
|
for room in userList.items():
|
||||||
roomName = room[0]
|
roomName = room[0]
|
||||||
for user in room[1].iteritems():
|
for user in room[1].items():
|
||||||
userName = user[0]
|
userName = user[0]
|
||||||
file_ = user[1]['file'] if user[1]['file'] <> {} else None
|
file_ = user[1]['file'] if user[1]['file'] != {} else None
|
||||||
isController = user[1]['controller'] if 'controller' in user[1] else False
|
isController = user[1]['controller'] if 'controller' in user[1] else False
|
||||||
isReady = user[1]['isReady'] if 'isReady' in user[1] else None
|
isReady = user[1]['isReady'] if 'isReady' in user[1] else None
|
||||||
features = user[1]['features'] if 'features' in user[1] else None
|
features = user[1]['features'] if 'features' in user[1] else None
|
||||||
@ -187,14 +187,14 @@ class SyncClientProtocol(JSONCommandProtocol):
|
|||||||
self.sendMessage({"List": None})
|
self.sendMessage({"List": None})
|
||||||
|
|
||||||
def _extractStatePlaystateArguments(self, state):
|
def _extractStatePlaystateArguments(self, state):
|
||||||
position = state["playstate"]["position"] if state["playstate"].has_key("position") else 0
|
position = state["playstate"]["position"] if "position" in state["playstate"] else 0
|
||||||
paused = state["playstate"]["paused"] if state["playstate"].has_key("paused") else None
|
paused = state["playstate"]["paused"] if "paused" in state["playstate"] else None
|
||||||
doSeek = state["playstate"]["doSeek"] if state["playstate"].has_key("doSeek") else None
|
doSeek = state["playstate"]["doSeek"] if "doSeek" in state["playstate"] else None
|
||||||
setBy = state["playstate"]["setBy"] if state["playstate"].has_key("setBy") else None
|
setBy = state["playstate"]["setBy"] if "setBy" in state["playstate"] else None
|
||||||
return position, paused, doSeek, setBy
|
return position, paused, doSeek, setBy
|
||||||
|
|
||||||
def _handleStatePing(self, state):
|
def _handleStatePing(self, state):
|
||||||
if state["ping"].has_key("latencyCalculation"):
|
if "latencyCalculation" in state["ping"]:
|
||||||
latencyCalculation = state["ping"]["latencyCalculation"]
|
latencyCalculation = state["ping"]["latencyCalculation"]
|
||||||
if "clientLatencyCalculation" in state["ping"]:
|
if "clientLatencyCalculation" in state["ping"]:
|
||||||
timestamp = state["ping"]["clientLatencyCalculation"]
|
timestamp = state["ping"]["clientLatencyCalculation"]
|
||||||
@ -206,17 +206,17 @@ class SyncClientProtocol(JSONCommandProtocol):
|
|||||||
def handleState(self, state):
|
def handleState(self, state):
|
||||||
position, paused, doSeek, setBy = None, None, None, None
|
position, paused, doSeek, setBy = None, None, None, None
|
||||||
messageAge = 0
|
messageAge = 0
|
||||||
if state.has_key("ignoringOnTheFly"):
|
if "ignoringOnTheFly" in state:
|
||||||
ignore = state["ignoringOnTheFly"]
|
ignore = state["ignoringOnTheFly"]
|
||||||
if ignore.has_key("server"):
|
if "server" in ignore:
|
||||||
self.serverIgnoringOnTheFly = ignore["server"]
|
self.serverIgnoringOnTheFly = ignore["server"]
|
||||||
self.clientIgnoringOnTheFly = 0
|
self.clientIgnoringOnTheFly = 0
|
||||||
elif ignore.has_key("client"):
|
elif "client" in ignore:
|
||||||
if(ignore['client']) == self.clientIgnoringOnTheFly:
|
if(ignore['client']) == self.clientIgnoringOnTheFly:
|
||||||
self.clientIgnoringOnTheFly = 0
|
self.clientIgnoringOnTheFly = 0
|
||||||
if state.has_key("playstate"):
|
if "playstate" in state:
|
||||||
position, paused, doSeek, setBy = self._extractStatePlaystateArguments(state)
|
position, paused, doSeek, setBy = self._extractStatePlaystateArguments(state)
|
||||||
if state.has_key("ping"):
|
if "ping" in state:
|
||||||
messageAge, latencyCalculation = self._handleStatePing(state)
|
messageAge, latencyCalculation = self._handleStatePing(state)
|
||||||
if position is not None and paused is not None and not self.clientIgnoringOnTheFly:
|
if position is not None and paused is not None and not self.clientIgnoringOnTheFly:
|
||||||
self._client.updateGlobalState(position, paused, doSeek, setBy, messageAge)
|
self._client.updateGlobalState(position, paused, doSeek, setBy, messageAge)
|
||||||
@ -320,7 +320,7 @@ class SyncServerProtocol(JSONCommandProtocol):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def dropWithError(self, error):
|
def dropWithError(self, error):
|
||||||
print getMessage("client-drop-server-error").format(self.transport.getPeer().host, error)
|
print(getMessage("client-drop-server-error").format(self.transport.getPeer().host, error))
|
||||||
self.sendError(error)
|
self.sendError(error)
|
||||||
self.drop()
|
self.drop()
|
||||||
|
|
||||||
@ -348,22 +348,22 @@ class SyncServerProtocol(JSONCommandProtocol):
|
|||||||
|
|
||||||
def _extractHelloArguments(self, hello):
|
def _extractHelloArguments(self, hello):
|
||||||
roomName = None
|
roomName = None
|
||||||
if hello.has_key("username"):
|
if "username" in hello:
|
||||||
username = hello["username"]
|
username = hello["username"]
|
||||||
username = username.strip()
|
username = username.strip()
|
||||||
else:
|
else:
|
||||||
username = None
|
username = None
|
||||||
serverPassword = hello["password"] if hello.has_key("password") else None
|
serverPassword = hello["password"] if "password" in hello else None
|
||||||
room = hello["room"] if hello.has_key("room") else None
|
room = hello["room"] if "room" in hello else None
|
||||||
if room:
|
if room:
|
||||||
if room.has_key("name"):
|
if "name" in room:
|
||||||
roomName = room["name"]
|
roomName = room["name"]
|
||||||
roomName = roomName.strip()
|
roomName = roomName.strip()
|
||||||
else:
|
else:
|
||||||
roomName = None
|
roomName = None
|
||||||
version = hello["version"] if hello.has_key("version") else None
|
version = hello["version"] if "version" in hello else None
|
||||||
version = hello["realversion"] if hello.has_key("realversion") else version
|
version = hello["realversion"] if "realversion" in hello else version
|
||||||
features = hello["features"] if hello.has_key("features") else None
|
features = hello["features"] if "features" in hello else None
|
||||||
return username, serverPassword, roomName, version, features
|
return username, serverPassword, roomName, version, features
|
||||||
|
|
||||||
def _checkPassword(self, serverPassword):
|
def _checkPassword(self, serverPassword):
|
||||||
@ -419,19 +419,19 @@ class SyncServerProtocol(JSONCommandProtocol):
|
|||||||
|
|
||||||
@requireLogged
|
@requireLogged
|
||||||
def handleSet(self, settings):
|
def handleSet(self, settings):
|
||||||
for set_ in settings.iteritems():
|
for set_ in settings.items():
|
||||||
command = set_[0]
|
command = set_[0]
|
||||||
if command == "room":
|
if command == "room":
|
||||||
roomName = set_[1]["name"] if set_[1].has_key("name") else None
|
roomName = set_[1]["name"] if "name" in set_[1] else None
|
||||||
self._factory.setWatcherRoom(self._watcher, roomName)
|
self._factory.setWatcherRoom(self._watcher, roomName)
|
||||||
elif command == "file":
|
elif command == "file":
|
||||||
self._watcher.setFile(set_[1])
|
self._watcher.setFile(set_[1])
|
||||||
elif command == "controllerAuth":
|
elif command == "controllerAuth":
|
||||||
password = set_[1]["password"] if set_[1].has_key("password") else None
|
password = set_[1]["password"] if "password" in set_[1] else None
|
||||||
room = set_[1]["room"] if set_[1].has_key("room") else None
|
room = set_[1]["room"] if "room" in set_[1] else None
|
||||||
self._factory.authRoomController(self._watcher, password, room)
|
self._factory.authRoomController(self._watcher, password, room)
|
||||||
elif command == "ready":
|
elif command == "ready":
|
||||||
manuallyInitiated = set_[1]['manuallyInitiated'] if set_[1].has_key("manuallyInitiated") else False
|
manuallyInitiated = set_[1]['manuallyInitiated'] if "manuallyInitiated" in set_[1] else False
|
||||||
self._factory.setReady(self._watcher, set_[1]['isReady'], manuallyInitiated=manuallyInitiated)
|
self._factory.setReady(self._watcher, set_[1]['isReady'], manuallyInitiated=manuallyInitiated)
|
||||||
elif command == "playlistChange":
|
elif command == "playlistChange":
|
||||||
self._factory.setPlaylist(self._watcher, set_[1]['files'])
|
self._factory.setPlaylist(self._watcher, set_[1]['files'])
|
||||||
@ -558,27 +558,27 @@ class SyncServerProtocol(JSONCommandProtocol):
|
|||||||
|
|
||||||
|
|
||||||
def _extractStatePlaystateArguments(self, state):
|
def _extractStatePlaystateArguments(self, state):
|
||||||
position = state["playstate"]["position"] if state["playstate"].has_key("position") else 0
|
position = state["playstate"]["position"] if "position" in state["playstate"] else 0
|
||||||
paused = state["playstate"]["paused"] if state["playstate"].has_key("paused") else None
|
paused = state["playstate"]["paused"] if "paused" in state["playstate"] else None
|
||||||
doSeek = state["playstate"]["doSeek"] if state["playstate"].has_key("doSeek") else None
|
doSeek = state["playstate"]["doSeek"] if "doSeek" in state["playstate"] else None
|
||||||
return position, paused, doSeek
|
return position, paused, doSeek
|
||||||
|
|
||||||
@requireLogged
|
@requireLogged
|
||||||
def handleState(self, state):
|
def handleState(self, state):
|
||||||
position, paused, doSeek, latencyCalculation = None, None, None, None
|
position, paused, doSeek, latencyCalculation = None, None, None, None
|
||||||
if state.has_key("ignoringOnTheFly"):
|
if "ignoringOnTheFly" in state:
|
||||||
ignore = state["ignoringOnTheFly"]
|
ignore = state["ignoringOnTheFly"]
|
||||||
if ignore.has_key("server"):
|
if "server" in ignore:
|
||||||
if self.serverIgnoringOnTheFly == ignore["server"]:
|
if self.serverIgnoringOnTheFly == ignore["server"]:
|
||||||
self.serverIgnoringOnTheFly = 0
|
self.serverIgnoringOnTheFly = 0
|
||||||
if ignore.has_key("client"):
|
if "client" in ignore:
|
||||||
self.clientIgnoringOnTheFly = ignore["client"]
|
self.clientIgnoringOnTheFly = ignore["client"]
|
||||||
if state.has_key("playstate"):
|
if "playstate" in state:
|
||||||
position, paused, doSeek = self._extractStatePlaystateArguments(state)
|
position, paused, doSeek = self._extractStatePlaystateArguments(state)
|
||||||
if state.has_key("ping"):
|
if "ping" in state:
|
||||||
latencyCalculation = state["ping"]["latencyCalculation"] if state["ping"].has_key("latencyCalculation") else 0
|
latencyCalculation = state["ping"]["latencyCalculation"] if "latencyCalculation" in state["ping"] else 0
|
||||||
clientRtt = state["ping"]["clientRtt"] if state["ping"].has_key("clientRtt") else 0
|
clientRtt = state["ping"]["clientRtt"] if "clientRtt" in state["ping"] else 0
|
||||||
self._clientLatencyCalculation = state["ping"]["clientLatencyCalculation"] if state["ping"].has_key("clientLatencyCalculation") else 0
|
self._clientLatencyCalculation = state["ping"]["clientLatencyCalculation"] if "clientLatencyCalculation" in state["ping"] else 0
|
||||||
self._clientLatencyCalculationArrivalTime = time.time()
|
self._clientLatencyCalculationArrivalTime = time.time()
|
||||||
self._pingService.receiveMessage(latencyCalculation, clientRtt)
|
self._pingService.receiveMessage(latencyCalculation, clientRtt)
|
||||||
if self.serverIgnoringOnTheFly == 0:
|
if self.serverIgnoringOnTheFly == 0:
|
||||||
|
|||||||
16
syncplay/server.py
Normal file → Executable file
16
syncplay/server.py
Normal file → Executable file
@ -16,13 +16,13 @@ from syncplay.utils import RoomPasswordProvider, NotControlledRoom, RandomString
|
|||||||
class SyncFactory(Factory):
|
class SyncFactory(Factory):
|
||||||
def __init__(self, password='', motdFilePath=None, isolateRooms=False, salt=None, disableReady=False,disableChat=False, maxChatMessageLength=constants.MAX_CHAT_MESSAGE_LENGTH, maxUsernameLength=constants.MAX_USERNAME_LENGTH):
|
def __init__(self, password='', motdFilePath=None, isolateRooms=False, salt=None, disableReady=False,disableChat=False, maxChatMessageLength=constants.MAX_CHAT_MESSAGE_LENGTH, maxUsernameLength=constants.MAX_USERNAME_LENGTH):
|
||||||
self.isolateRooms = isolateRooms
|
self.isolateRooms = isolateRooms
|
||||||
print getMessage("welcome-server-notification").format(syncplay.version)
|
print(getMessage("welcome-server-notification").format(syncplay.version))
|
||||||
if password:
|
if password:
|
||||||
password = hashlib.md5(password).hexdigest()
|
password = hashlib.md5(password).hexdigest()
|
||||||
self.password = password
|
self.password = password
|
||||||
if salt is None:
|
if salt is None:
|
||||||
salt = RandomStringGenerator.generate_server_salt()
|
salt = RandomStringGenerator.generate_server_salt()
|
||||||
print getMessage("no-salt-notification").format(salt)
|
print(getMessage("no-salt-notification").format(salt))
|
||||||
self._salt = salt
|
self._salt = salt
|
||||||
self._motdFilePath = motdFilePath
|
self._motdFilePath = motdFilePath
|
||||||
self.disableReady = disableReady
|
self.disableReady = disableReady
|
||||||
@ -190,13 +190,13 @@ class RoomManager(object):
|
|||||||
whatLambda(receiver)
|
whatLambda(receiver)
|
||||||
|
|
||||||
def broadcast(self, sender, whatLambda):
|
def broadcast(self, sender, whatLambda):
|
||||||
for room in self._rooms.itervalues():
|
for room in self._rooms.values():
|
||||||
for receiver in room.getWatchers():
|
for receiver in room.getWatchers():
|
||||||
whatLambda(receiver)
|
whatLambda(receiver)
|
||||||
|
|
||||||
def getAllWatchersForUser(self, sender):
|
def getAllWatchersForUser(self, sender):
|
||||||
watchers = []
|
watchers = []
|
||||||
for room in self._rooms.itervalues():
|
for room in self._rooms.values():
|
||||||
for watcher in room.getWatchers():
|
for watcher in room.getWatchers():
|
||||||
watchers.append(watcher)
|
watchers.append(watcher)
|
||||||
return watchers
|
return watchers
|
||||||
@ -231,7 +231,7 @@ class RoomManager(object):
|
|||||||
def findFreeUsername(self, username):
|
def findFreeUsername(self, username):
|
||||||
username = truncateText(username,constants.MAX_USERNAME_LENGTH)
|
username = truncateText(username,constants.MAX_USERNAME_LENGTH)
|
||||||
allnames = []
|
allnames = []
|
||||||
for room in self._rooms.itervalues():
|
for room in self._rooms.values():
|
||||||
for watcher in room.getWatchers():
|
for watcher in room.getWatchers():
|
||||||
allnames.append(watcher.getName().lower())
|
allnames.append(watcher.getName().lower())
|
||||||
while username.lower() in allnames:
|
while username.lower() in allnames:
|
||||||
@ -293,7 +293,7 @@ class Room(object):
|
|||||||
|
|
||||||
def setPosition(self, position, setBy=None):
|
def setPosition(self, position, setBy=None):
|
||||||
self._position = position
|
self._position = position
|
||||||
for watcher in self._watchers.itervalues():
|
for watcher in self._watchers.values():
|
||||||
watcher.setPosition(position)
|
watcher.setPosition(position)
|
||||||
self._setBy = setBy
|
self._setBy = setBy
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ class Room(object):
|
|||||||
return self._playState == self.STATE_PAUSED
|
return self._playState == self.STATE_PAUSED
|
||||||
|
|
||||||
def getWatchers(self):
|
def getWatchers(self):
|
||||||
return self._watchers.values()
|
return list(self._watchers.values())
|
||||||
|
|
||||||
def addWatcher(self, watcher):
|
def addWatcher(self, watcher):
|
||||||
if self._watchers:
|
if self._watchers:
|
||||||
@ -404,7 +404,7 @@ class Watcher(object):
|
|||||||
reactor.callLater(0.1, self._scheduleSendState)
|
reactor.callLater(0.1, self._scheduleSendState)
|
||||||
|
|
||||||
def setFile(self, file_):
|
def setFile(self, file_):
|
||||||
if file_ and file_.has_key("name"):
|
if file_ and "name" in file_:
|
||||||
file_["name"] = truncateText(file_["name"],constants.MAX_FILENAME_LENGTH)
|
file_["name"] = truncateText(file_["name"],constants.MAX_FILENAME_LENGTH)
|
||||||
self._file = file_
|
self._file = file_
|
||||||
self._server.sendFileUpdate(self)
|
self._server.sendFileUpdate(self)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
from ConfigParser import SafeConfigParser, DEFAULTSECT
|
from configparser import SafeConfigParser, DEFAULTSECT
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@ -241,7 +241,7 @@ class ConfigurationGetter(object):
|
|||||||
for key in self._serialised:
|
for key in self._serialised:
|
||||||
if self._config[key] is None or self._config[key] == "":
|
if self._config[key] is None or self._config[key] == "":
|
||||||
self._config[key] = {}
|
self._config[key] = {}
|
||||||
elif isinstance(self._config[key], (str, unicode)):
|
elif isinstance(self._config[key], str):
|
||||||
self._config[key] = ast.literal_eval(self._config[key])
|
self._config[key] = ast.literal_eval(self._config[key])
|
||||||
|
|
||||||
for key in self._tristate:
|
for key in self._tristate:
|
||||||
@ -258,7 +258,7 @@ class ConfigurationGetter(object):
|
|||||||
for key in self._hexadecimal:
|
for key in self._hexadecimal:
|
||||||
match = re.search(r'^#(?:[0-9a-fA-F]){6}$', self._config[key])
|
match = re.search(r'^#(?:[0-9a-fA-F]){6}$', self._config[key])
|
||||||
if not match:
|
if not match:
|
||||||
self._config[key] = u"#FFFFFF"
|
self._config[key] = "#FFFFFF"
|
||||||
|
|
||||||
for key in self._required:
|
for key in self._required:
|
||||||
if key == "playerPath":
|
if key == "playerPath":
|
||||||
@ -284,7 +284,7 @@ class ConfigurationGetter(object):
|
|||||||
raise InvalidConfigValue(getMessage("empty-value-config-error").format(key.capitalize()))
|
raise InvalidConfigValue(getMessage("empty-value-config-error").format(key.capitalize()))
|
||||||
|
|
||||||
def _overrideConfigWithArgs(self, args):
|
def _overrideConfigWithArgs(self, args):
|
||||||
for key, val in vars(args).items():
|
for key, val in list(vars(args).items()):
|
||||||
if val:
|
if val:
|
||||||
if key == "force_gui_prompt":
|
if key == "force_gui_prompt":
|
||||||
key = "forceGuiPrompt"
|
key = "forceGuiPrompt"
|
||||||
@ -347,14 +347,14 @@ class ConfigurationGetter(object):
|
|||||||
return path
|
return path
|
||||||
|
|
||||||
def _parseConfigFile(self, iniPath, createConfig=True):
|
def _parseConfigFile(self, iniPath, createConfig=True):
|
||||||
parser = SafeConfigParserUnicode()
|
parser = SafeConfigParserUnicode(strict=False)
|
||||||
if not os.path.isfile(iniPath):
|
if not os.path.isfile(iniPath):
|
||||||
if createConfig:
|
if createConfig:
|
||||||
open(iniPath, 'w').close()
|
open(iniPath, 'w').close()
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
parser.readfp(codecs.open(iniPath, "r", "utf_8_sig"))
|
parser.readfp(codecs.open(iniPath, "r", "utf_8_sig"))
|
||||||
for section, options in self._iniStructure.items():
|
for section, options in list(self._iniStructure.items()):
|
||||||
if parser.has_section(section):
|
if parser.has_section(section):
|
||||||
for option in options:
|
for option in options:
|
||||||
if parser.has_option(section, option):
|
if parser.has_option(section, option):
|
||||||
@ -365,7 +365,7 @@ class ConfigurationGetter(object):
|
|||||||
self._validateArguments()
|
self._validateArguments()
|
||||||
except InvalidConfigValue as e:
|
except InvalidConfigValue as e:
|
||||||
try:
|
try:
|
||||||
for key, value in self._promptForMissingArguments(e.message).items():
|
for key, value in list(self._promptForMissingArguments(e).items()):
|
||||||
self._config[key] = value
|
self._config[key] = value
|
||||||
self._checkConfig()
|
self._checkConfig()
|
||||||
except:
|
except:
|
||||||
@ -374,8 +374,8 @@ class ConfigurationGetter(object):
|
|||||||
def _promptForMissingArguments(self, error=None):
|
def _promptForMissingArguments(self, error=None):
|
||||||
if self._config['noGui']:
|
if self._config['noGui']:
|
||||||
if error:
|
if error:
|
||||||
print "{}!".format(error)
|
print("{}!".format(error))
|
||||||
print getMessage("missing-arguments-error")
|
print(getMessage("missing-arguments-error"))
|
||||||
sys.exit()
|
sys.exit()
|
||||||
else:
|
else:
|
||||||
from syncplay.ui.GuiConfiguration import GuiConfiguration
|
from syncplay.ui.GuiConfiguration import GuiConfiguration
|
||||||
@ -386,7 +386,7 @@ class ConfigurationGetter(object):
|
|||||||
|
|
||||||
def __wasOptionChanged(self, parser, section, option):
|
def __wasOptionChanged(self, parser, section, option):
|
||||||
if parser.has_option(section, option):
|
if parser.has_option(section, option):
|
||||||
if parser.get(section, option) != unicode(self._config[option]):
|
if parser.get(section, option) != str(self._config[option]):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
@ -395,16 +395,16 @@ class ConfigurationGetter(object):
|
|||||||
changed = False
|
changed = False
|
||||||
if self._config['noStore']:
|
if self._config['noStore']:
|
||||||
return
|
return
|
||||||
parser = SafeConfigParserUnicode()
|
parser = SafeConfigParserUnicode(strict=False)
|
||||||
parser.readfp(codecs.open(iniPath, "r", "utf_8_sig"))
|
parser.readfp(codecs.open(iniPath, "r", "utf_8_sig"))
|
||||||
for section, options in self._iniStructure.items():
|
for section, options in list(self._iniStructure.items()):
|
||||||
if not parser.has_section(section):
|
if not parser.has_section(section):
|
||||||
parser.add_section(section)
|
parser.add_section(section)
|
||||||
changed = True
|
changed = True
|
||||||
for option in options:
|
for option in options:
|
||||||
if self.__wasOptionChanged(parser, section, option):
|
if self.__wasOptionChanged(parser, section, option):
|
||||||
changed = True
|
changed = True
|
||||||
parser.set(section, option, unicode(self._config[option]).replace('%', '%%'))
|
parser.set(section, option, str(self._config[option]).replace('%', '%%'))
|
||||||
if changed:
|
if changed:
|
||||||
parser.write(codecs.open(iniPath, "wb", "utf_8_sig"))
|
parser.write(codecs.open(iniPath, "wb", "utf_8_sig"))
|
||||||
|
|
||||||
@ -417,7 +417,7 @@ class ConfigurationGetter(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for key, value in self._promptForMissingArguments().items():
|
for key, value in list(self._promptForMissingArguments().items()):
|
||||||
self._config[key] = value
|
self._config[key] = value
|
||||||
except GuiConfiguration.WindowClosed:
|
except GuiConfiguration.WindowClosed:
|
||||||
sys.exit()
|
sys.exit()
|
||||||
@ -439,7 +439,7 @@ class ConfigurationGetter(object):
|
|||||||
for name in constants.CONFIG_NAMES:
|
for name in constants.CONFIG_NAMES:
|
||||||
path = location + os.path.sep + name
|
path = location + os.path.sep + name
|
||||||
if os.path.isfile(path) and (os.name == 'nt' or path != os.path.join(os.getenv('HOME', '.'), name)):
|
if os.path.isfile(path) and (os.name == 'nt' or path != os.path.join(os.getenv('HOME', '.'), name)):
|
||||||
loadedPaths.append(u"'{}'".format(os.path.normpath(path)))
|
loadedPaths.append("'{}'".format(os.path.normpath(path)))
|
||||||
self._parseConfigFile(path, createConfig=False)
|
self._parseConfigFile(path, createConfig=False)
|
||||||
self._checkConfig()
|
self._checkConfig()
|
||||||
return loadedPaths
|
return loadedPaths
|
||||||
@ -464,13 +464,13 @@ class ConfigurationGetter(object):
|
|||||||
self._argparser.add_argument('-p', '--password', metavar='password', type=str, nargs='?', help=getMessage("password-argument"))
|
self._argparser.add_argument('-p', '--password', metavar='password', type=str, nargs='?', help=getMessage("password-argument"))
|
||||||
self._argparser.add_argument('--player-path', metavar='path', type=str, help=getMessage("player-path-argument"))
|
self._argparser.add_argument('--player-path', metavar='path', type=str, help=getMessage("player-path-argument"))
|
||||||
self._argparser.add_argument('--language', metavar='language', type=str, help=getMessage("language-argument"))
|
self._argparser.add_argument('--language', metavar='language', type=str, help=getMessage("language-argument"))
|
||||||
self._argparser.add_argument('file', metavar='file', type=lambda s: unicode(s, 'utf8'), nargs='?', help=getMessage("file-argument"))
|
self._argparser.add_argument('file', metavar='file', type=lambda s: str(s, 'utf8'), nargs='?', help=getMessage("file-argument"))
|
||||||
self._argparser.add_argument('--clear-gui-data', action='store_true', help=getMessage("clear-gui-data-argument"))
|
self._argparser.add_argument('--clear-gui-data', action='store_true', help=getMessage("clear-gui-data-argument"))
|
||||||
self._argparser.add_argument('-v', '--version', action='store_true', help=getMessage("version-argument"))
|
self._argparser.add_argument('-v', '--version', action='store_true', help=getMessage("version-argument"))
|
||||||
self._argparser.add_argument('_args', metavar='options', type=str, nargs='*', help=getMessage("args-argument"))
|
self._argparser.add_argument('_args', metavar='options', type=str, nargs='*', help=getMessage("args-argument"))
|
||||||
args = self._argparser.parse_args()
|
args = self._argparser.parse_args()
|
||||||
if args.version:
|
if args.version:
|
||||||
print getMessage("version-message").format(version, milestone)
|
print(getMessage("version-message").format(version, milestone))
|
||||||
sys.exit()
|
sys.exit()
|
||||||
self._overrideConfigWithArgs(args)
|
self._overrideConfigWithArgs(args)
|
||||||
if not self._config['noGui']:
|
if not self._config['noGui']:
|
||||||
@ -487,7 +487,7 @@ class ConfigurationGetter(object):
|
|||||||
import appnope
|
import appnope
|
||||||
appnope.nope()
|
appnope.nope()
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print getMessage("unable-import-gui-error")
|
print(getMessage("unable-import-gui-error"))
|
||||||
self._config['noGui'] = True
|
self._config['noGui'] = True
|
||||||
if self._config['file'] and self._config['file'][:2] == "--":
|
if self._config['file'] and self._config['file'][:2] == "--":
|
||||||
self._config['playerArgs'].insert(0, self._config['file'])
|
self._config['playerArgs'].insert(0, self._config['file'])
|
||||||
@ -519,15 +519,15 @@ class SafeConfigParserUnicode(SafeConfigParser):
|
|||||||
"""Write an .ini-format representation of the configuration state."""
|
"""Write an .ini-format representation of the configuration state."""
|
||||||
if self._defaults:
|
if self._defaults:
|
||||||
fp.write("[%s]\n" % DEFAULTSECT)
|
fp.write("[%s]\n" % DEFAULTSECT)
|
||||||
for (key, value) in self._defaults.items():
|
for (key, value) in list(self._defaults.items()):
|
||||||
fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
|
fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
|
||||||
fp.write("\n")
|
fp.write("\n")
|
||||||
for section in self._sections:
|
for section in self._sections:
|
||||||
fp.write("[%s]\n" % section)
|
fp.write("[%s]\n" % section)
|
||||||
for (key, value) in self._sections[section].items():
|
for (key, value) in list(self._sections[section].items()):
|
||||||
if key == "__name__":
|
if key == "__name__":
|
||||||
continue
|
continue
|
||||||
if (value is not None) or (self._optcre == self.OPTCRE):
|
if (value is not None) or (self._optcre == self.OPTCRE):
|
||||||
key = " = ".join((key, unicode(value).replace('\n', '\n\t')))
|
key = " = ".join((key, str(value).replace('\n', '\n\t')))
|
||||||
fp.write("%s\n" % key)
|
fp.write("%s\n" % key)
|
||||||
fp.write("\n")
|
fp.write("\n")
|
||||||
|
|||||||
@ -212,7 +212,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
take a long time to perform their checks and hang the GUI while doing
|
take a long time to perform their checks and hang the GUI while doing
|
||||||
so.
|
so.
|
||||||
"""
|
"""
|
||||||
currentplayerpath = unicode(self.executablepathCombobox.currentText())
|
currentplayerpath = str(self.executablepathCombobox.currentText())
|
||||||
self._playerProbeThread.setPlayerPath(currentplayerpath)
|
self._playerProbeThread.setPlayerPath(currentplayerpath)
|
||||||
|
|
||||||
def updatePlayerArguments(self, currentplayerpath):
|
def updatePlayerArguments(self, currentplayerpath):
|
||||||
@ -225,11 +225,11 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
currentplayerpath = self.executablepathCombobox.currentText()
|
currentplayerpath = self.executablepathCombobox.currentText()
|
||||||
|
|
||||||
if currentplayerpath:
|
if currentplayerpath:
|
||||||
NewPlayerArgs = self.playerargsTextbox.text().split(u" ") if self.playerargsTextbox.text() else ""
|
NewPlayerArgs = self.playerargsTextbox.text().split(" ") if self.playerargsTextbox.text() else ""
|
||||||
self.perPlayerArgs[self.executablepathCombobox.currentText()]=NewPlayerArgs
|
self.perPlayerArgs[self.executablepathCombobox.currentText()]=NewPlayerArgs
|
||||||
|
|
||||||
def languageChanged(self):
|
def languageChanged(self):
|
||||||
setLanguage(unicode(self.languageCombobox.itemData(self.languageCombobox.currentIndex())))
|
setLanguage(str(self.languageCombobox.itemData(self.languageCombobox.currentIndex())))
|
||||||
QtWidgets.QMessageBox.information(self, "Syncplay", getMessage("language-changed-msgbox-label"))
|
QtWidgets.QMessageBox.information(self, "Syncplay", getMessage("language-changed-msgbox-label"))
|
||||||
|
|
||||||
def browsePlayerpath(self):
|
def browsePlayerpath(self):
|
||||||
@ -326,7 +326,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
def getMoreState(self):
|
def getMoreState(self):
|
||||||
settings = QSettings("Syncplay", "MoreSettings")
|
settings = QSettings("Syncplay", "MoreSettings")
|
||||||
settings.beginGroup("MoreSettings")
|
settings.beginGroup("MoreSettings")
|
||||||
morestate = unicode.lower(unicode(settings.value("ShowMoreSettings", "false")))
|
morestate = str.lower(str(settings.value("ShowMoreSettings", "false")))
|
||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
if morestate == "true":
|
if morestate == "true":
|
||||||
return True
|
return True
|
||||||
@ -411,18 +411,18 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.config['password'] = self.serverpassTextbox.text()
|
self.config['password'] = self.serverpassTextbox.text()
|
||||||
self.processWidget(self, lambda w: self.saveValues(w))
|
self.processWidget(self, lambda w: self.saveValues(w))
|
||||||
if self.hostCombobox.currentText():
|
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.hostCombobox.currentText() if ":" in self.hostCombobox.currentText() else self.hostCombobox.currentText() + ":" + str(constants.DEFAULT_PORT)
|
||||||
self.config['host'] = self.config['host'].replace(" ","").replace("\t", "").replace("\n","").replace("\r","")
|
self.config['host'] = self.config['host'].replace(" ","").replace("\t", "").replace("\n","").replace("\r","")
|
||||||
else:
|
else:
|
||||||
self.config['host'] = None
|
self.config['host'] = None
|
||||||
self.config['playerPath'] = unicode(self.safenormcaseandpath(self.executablepathCombobox.currentText()))
|
self.config['playerPath'] = str(self.safenormcaseandpath(self.executablepathCombobox.currentText()))
|
||||||
self.config['language'] = unicode(self.languageCombobox.itemData(self.languageCombobox.currentIndex()))
|
self.config['language'] = str(self.languageCombobox.itemData(self.languageCombobox.currentIndex()))
|
||||||
if self.mediapathTextbox.text() == "":
|
if self.mediapathTextbox.text() == "":
|
||||||
self.config['file'] = None
|
self.config['file'] = None
|
||||||
elif os.path.isfile(os.path.abspath(self.mediapathTextbox.text())):
|
elif os.path.isfile(os.path.abspath(self.mediapathTextbox.text())):
|
||||||
self.config['file'] = os.path.abspath(self.mediapathTextbox.text())
|
self.config['file'] = os.path.abspath(self.mediapathTextbox.text())
|
||||||
else:
|
else:
|
||||||
self.config['file'] = unicode(self.mediapathTextbox.text())
|
self.config['file'] = str(self.mediapathTextbox.text())
|
||||||
self.config['publicServers'] = self.publicServerAddresses
|
self.config['publicServers'] = self.publicServerAddresses
|
||||||
|
|
||||||
self.pressedclosebutton = False
|
self.pressedclosebutton = False
|
||||||
@ -449,7 +449,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
data = event.mimeData()
|
data = event.mimeData()
|
||||||
urls = data.urls()
|
urls = data.urls()
|
||||||
if urls and urls[0].scheme() == 'file':
|
if urls and urls[0].scheme() == 'file':
|
||||||
dropfilepath = os.path.abspath(unicode(event.mimeData().urls()[0].toLocalFile()))
|
dropfilepath = os.path.abspath(str(event.mimeData().urls()[0].toLocalFile()))
|
||||||
if dropfilepath[-4:].lower() == ".exe":
|
if dropfilepath[-4:].lower() == ".exe":
|
||||||
self.executablepathCombobox.setEditText(dropfilepath)
|
self.executablepathCombobox.setEditText(dropfilepath)
|
||||||
else:
|
else:
|
||||||
@ -525,7 +525,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
|
|
||||||
def connectChildren(self, widget):
|
def connectChildren(self, widget):
|
||||||
widgetName = str(widget.objectName())
|
widgetName = str(widget.objectName())
|
||||||
if self.subitems.has_key(widgetName):
|
if widgetName in self.subitems:
|
||||||
widget.stateChanged.connect(lambda: self.updateSubwidgets(self, widget))
|
widget.stateChanged.connect(lambda: self.updateSubwidgets(self, widget))
|
||||||
self.updateSubwidgets(self, widget)
|
self.updateSubwidgets(self, widget)
|
||||||
|
|
||||||
@ -661,6 +661,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.basicOptionsFrame = QtWidgets.QFrame()
|
self.basicOptionsFrame = QtWidgets.QFrame()
|
||||||
self.basicOptionsLayout = QtWidgets.QVBoxLayout()
|
self.basicOptionsLayout = QtWidgets.QVBoxLayout()
|
||||||
if error:
|
if error:
|
||||||
|
error = str(error)
|
||||||
self.errorLabel = QLabel(self)
|
self.errorLabel = QLabel(self)
|
||||||
if error[:1] != constants.ERROR_MESSAGE_MARKER:
|
if error[:1] != constants.ERROR_MESSAGE_MARKER:
|
||||||
self.errorLabel.setStyleSheet(constants.STYLE_ERRORLABEL)
|
self.errorLabel.setStyleSheet(constants.STYLE_ERRORLABEL)
|
||||||
@ -895,7 +896,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.chatDirectInputCheckbox = QCheckBox(getMessage("chatdirectinput-label"))
|
self.chatDirectInputCheckbox = QCheckBox(getMessage("chatdirectinput-label"))
|
||||||
self.chatDirectInputCheckbox.setObjectName("chatDirectInput")
|
self.chatDirectInputCheckbox.setObjectName("chatDirectInput")
|
||||||
self.chatDirectInputCheckbox.setStyleSheet(
|
self.chatDirectInputCheckbox.setStyleSheet(
|
||||||
constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png"))
|
constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png"))
|
||||||
self.chatInputLayout.addWidget(self.chatDirectInputCheckbox, 2, 0, 1,1, Qt.AlignLeft)
|
self.chatInputLayout.addWidget(self.chatDirectInputCheckbox, 2, 0, 1,1, Qt.AlignLeft)
|
||||||
|
|
||||||
self.inputFontLayout = QtWidgets.QHBoxLayout()
|
self.inputFontLayout = QtWidgets.QHBoxLayout()
|
||||||
@ -904,7 +905,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.inputFontFrame.setLayout(self.inputFontLayout)
|
self.inputFontFrame.setLayout(self.inputFontLayout)
|
||||||
self.inputFontFrame.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
self.inputFontFrame.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
||||||
self.chatFontLabel = QLabel(getMessage("chatinputfont-label"), self)
|
self.chatFontLabel = QLabel(getMessage("chatinputfont-label"), self)
|
||||||
self.chatFontLabel.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png"))
|
self.chatFontLabel.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png"))
|
||||||
self.chatFontLabel.setObjectName("font-label")
|
self.chatFontLabel.setObjectName("font-label")
|
||||||
self.chatInputFontButton = QtWidgets.QPushButton(getMessage("chatfont-label"))
|
self.chatInputFontButton = QtWidgets.QPushButton(getMessage("chatfont-label"))
|
||||||
self.chatInputFontButton.setObjectName("set-input-font")
|
self.chatInputFontButton.setObjectName("set-input-font")
|
||||||
@ -927,7 +928,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.chatInputPositionFrame.setLayout(self.chatInputPositionLayout)
|
self.chatInputPositionFrame.setLayout(self.chatInputPositionLayout)
|
||||||
self.chatInputPositionFrame.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
self.chatInputPositionFrame.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
||||||
self.chatInputPositionLabel = QLabel(getMessage("chatinputposition-label"), self)
|
self.chatInputPositionLabel = QLabel(getMessage("chatinputposition-label"), self)
|
||||||
self.chatInputPositionLabel.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png"))
|
self.chatInputPositionLabel.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png"))
|
||||||
self.chatInputPositionGroup = QButtonGroup()
|
self.chatInputPositionGroup = QButtonGroup()
|
||||||
self.chatInputTopOption = QRadioButton(getMessage("chat-top-option"))
|
self.chatInputTopOption = QRadioButton(getMessage("chat-top-option"))
|
||||||
self.chatInputMiddleOption = QRadioButton(getMessage("chat-middle-option"))
|
self.chatInputMiddleOption = QRadioButton(getMessage("chat-middle-option"))
|
||||||
@ -966,7 +967,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.outputFontFrame.setLayout(self.outputFontLayout)
|
self.outputFontFrame.setLayout(self.outputFontLayout)
|
||||||
self.outputFontFrame.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
self.outputFontFrame.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
||||||
self.chatOutputFontLabel = QLabel(getMessage("chatoutputfont-label"), self)
|
self.chatOutputFontLabel = QLabel(getMessage("chatoutputfont-label"), self)
|
||||||
self.chatOutputFontLabel.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png"))
|
self.chatOutputFontLabel.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png"))
|
||||||
self.chatOutputFontLabel.setObjectName("font-output-label")
|
self.chatOutputFontLabel.setObjectName("font-output-label")
|
||||||
self.chatOutputFontButton = QtWidgets.QPushButton(getMessage("chatfont-label"))
|
self.chatOutputFontButton = QtWidgets.QPushButton(getMessage("chatfont-label"))
|
||||||
self.chatOutputFontButton.setObjectName("set-output-font")
|
self.chatOutputFontButton.setObjectName("set-output-font")
|
||||||
@ -979,7 +980,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.chatOutputLayout.addWidget(self.outputFontFrame, 2, 0, 1, 3, Qt.AlignLeft)
|
self.chatOutputLayout.addWidget(self.outputFontFrame, 2, 0, 1, 3, Qt.AlignLeft)
|
||||||
|
|
||||||
self.chatOutputModeLabel = QLabel(getMessage("chatoutputposition-label"), self)
|
self.chatOutputModeLabel = QLabel(getMessage("chatoutputposition-label"), self)
|
||||||
self.chatOutputModeLabel.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + u"chevrons_right.png"))
|
self.chatOutputModeLabel.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(self.posixresourcespath + "chevrons_right.png"))
|
||||||
self.chatOutputModeGroup = QButtonGroup()
|
self.chatOutputModeGroup = QButtonGroup()
|
||||||
self.chatOutputChatroomOption = QRadioButton(getMessage("chat-chatroom-option"))
|
self.chatOutputChatroomOption = QRadioButton(getMessage("chat-chatroom-option"))
|
||||||
self.chatOutputScrollingOption = QRadioButton(getMessage("chat-scrolling-option"))
|
self.chatOutputScrollingOption = QRadioButton(getMessage("chat-scrolling-option"))
|
||||||
@ -1009,23 +1010,23 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
|
|
||||||
def fontDialog(self, configName):
|
def fontDialog(self, configName):
|
||||||
font = QtGui.QFont()
|
font = QtGui.QFont()
|
||||||
font.setFamily(self.config[configName+ u"FontFamily"])
|
font.setFamily(self.config[configName+ "FontFamily"])
|
||||||
font.setPointSize(self.config[configName + u"RelativeFontSize"])
|
font.setPointSize(self.config[configName + "RelativeFontSize"])
|
||||||
font.setWeight(self.config[configName + u"FontWeight"])
|
font.setWeight(self.config[configName + "FontWeight"])
|
||||||
font.setUnderline(self.config[configName + u"FontUnderline"])
|
font.setUnderline(self.config[configName + "FontUnderline"])
|
||||||
value, ok = QtWidgets.QFontDialog.getFont(font)
|
value, ok = QtWidgets.QFontDialog.getFont(font)
|
||||||
if ok:
|
if ok:
|
||||||
self.config[configName + u"FontFamily"] = value.family()
|
self.config[configName + "FontFamily"] = value.family()
|
||||||
self.config[configName + u"RelativeFontSize"] = value.pointSize()
|
self.config[configName + "RelativeFontSize"] = value.pointSize()
|
||||||
self.config[configName + u"FontWeight"] = value.weight()
|
self.config[configName + "FontWeight"] = value.weight()
|
||||||
self.config[configName + u"FontUnderline"] = value.underline()
|
self.config[configName + "FontUnderline"] = value.underline()
|
||||||
|
|
||||||
def colourDialog(self, configName):
|
def colourDialog(self, configName):
|
||||||
oldColour = QtGui.QColor()
|
oldColour = QtGui.QColor()
|
||||||
oldColour.setNamedColor(self.config[configName+ u"FontColor"])
|
oldColour.setNamedColor(self.config[configName+ "FontColor"])
|
||||||
colour = QtWidgets.QColorDialog.getColor(oldColour, self)
|
colour = QtWidgets.QColorDialog.getColor(oldColour, self)
|
||||||
if colour.isValid():
|
if colour.isValid():
|
||||||
self.config[configName + u"FontColor"] = colour.name()
|
self.config[configName + "FontColor"] = colour.name()
|
||||||
|
|
||||||
def addMessageTab(self):
|
def addMessageTab(self):
|
||||||
self.messageFrame = QtWidgets.QFrame()
|
self.messageFrame = QtWidgets.QFrame()
|
||||||
@ -1043,27 +1044,27 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
|
|
||||||
self.showSameRoomOSDCheckbox = QCheckBox(getMessage("showsameroomosd-label"))
|
self.showSameRoomOSDCheckbox = QCheckBox(getMessage("showsameroomosd-label"))
|
||||||
self.showSameRoomOSDCheckbox.setObjectName("showSameRoomOSD")
|
self.showSameRoomOSDCheckbox.setObjectName("showSameRoomOSD")
|
||||||
self.showSameRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + u"chevrons_right.png"))
|
self.showSameRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + "chevrons_right.png"))
|
||||||
self.osdSettingsLayout.addWidget(self.showSameRoomOSDCheckbox)
|
self.osdSettingsLayout.addWidget(self.showSameRoomOSDCheckbox)
|
||||||
|
|
||||||
self.showNonControllerOSDCheckbox = QCheckBox(getMessage("shownoncontrollerosd-label"))
|
self.showNonControllerOSDCheckbox = QCheckBox(getMessage("shownoncontrollerosd-label"))
|
||||||
self.showNonControllerOSDCheckbox.setObjectName("showNonControllerOSD")
|
self.showNonControllerOSDCheckbox.setObjectName("showNonControllerOSD")
|
||||||
self.showNonControllerOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + u"chevrons_right.png"))
|
self.showNonControllerOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + "chevrons_right.png"))
|
||||||
self.osdSettingsLayout.addWidget(self.showNonControllerOSDCheckbox)
|
self.osdSettingsLayout.addWidget(self.showNonControllerOSDCheckbox)
|
||||||
|
|
||||||
self.showDifferentRoomOSDCheckbox = QCheckBox(getMessage("showdifferentroomosd-label"))
|
self.showDifferentRoomOSDCheckbox = QCheckBox(getMessage("showdifferentroomosd-label"))
|
||||||
self.showDifferentRoomOSDCheckbox.setObjectName("showDifferentRoomOSD")
|
self.showDifferentRoomOSDCheckbox.setObjectName("showDifferentRoomOSD")
|
||||||
self.showDifferentRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + u"chevrons_right.png"))
|
self.showDifferentRoomOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + "chevrons_right.png"))
|
||||||
self.osdSettingsLayout.addWidget(self.showDifferentRoomOSDCheckbox)
|
self.osdSettingsLayout.addWidget(self.showDifferentRoomOSDCheckbox)
|
||||||
|
|
||||||
self.slowdownOSDCheckbox = QCheckBox(getMessage("showslowdownosd-label"))
|
self.slowdownOSDCheckbox = QCheckBox(getMessage("showslowdownosd-label"))
|
||||||
self.slowdownOSDCheckbox.setObjectName("showSlowdownOSD")
|
self.slowdownOSDCheckbox.setObjectName("showSlowdownOSD")
|
||||||
self.slowdownOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + u"chevrons_right.png"))
|
self.slowdownOSDCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + "chevrons_right.png"))
|
||||||
self.osdSettingsLayout.addWidget(self.slowdownOSDCheckbox)
|
self.osdSettingsLayout.addWidget(self.slowdownOSDCheckbox)
|
||||||
|
|
||||||
self.showOSDWarningsCheckbox = QCheckBox(getMessage("showosdwarnings-label"))
|
self.showOSDWarningsCheckbox = QCheckBox(getMessage("showosdwarnings-label"))
|
||||||
self.showOSDWarningsCheckbox.setObjectName("showOSDWarnings")
|
self.showOSDWarningsCheckbox.setObjectName("showOSDWarnings")
|
||||||
self.showOSDWarningsCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + u"chevrons_right.png"))
|
self.showOSDWarningsCheckbox.setStyleSheet(constants.STYLE_SUBCHECKBOX.format(posixresourcespath + "chevrons_right.png"))
|
||||||
self.osdSettingsLayout.addWidget(self.showOSDWarningsCheckbox)
|
self.osdSettingsLayout.addWidget(self.showOSDWarningsCheckbox)
|
||||||
|
|
||||||
self.subitems['showOSD'] = ["showSameRoomOSD", "showDifferentRoomOSD", "showSlowdownOSD", "showOSDWarnings", "showNonControllerOSD"]
|
self.subitems['showOSD'] = ["showSameRoomOSD", "showDifferentRoomOSD", "showSlowdownOSD", "showOSDWarnings", "showNonControllerOSD"]
|
||||||
@ -1122,22 +1123,22 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
|
|
||||||
self.bottomButtonFrame = QtWidgets.QFrame()
|
self.bottomButtonFrame = QtWidgets.QFrame()
|
||||||
self.bottomButtonLayout = QtWidgets.QHBoxLayout()
|
self.bottomButtonLayout = QtWidgets.QHBoxLayout()
|
||||||
self.helpButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + u'help.png'), getMessage("help-label"))
|
self.helpButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + 'help.png'), getMessage("help-label"))
|
||||||
self.helpButton.setObjectName("help")
|
self.helpButton.setObjectName("help")
|
||||||
self.helpButton.setMaximumSize(self.helpButton.sizeHint())
|
self.helpButton.setMaximumSize(self.helpButton.sizeHint())
|
||||||
self.helpButton.released.connect(self.openHelp)
|
self.helpButton.released.connect(self.openHelp)
|
||||||
|
|
||||||
self.resetButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + u'cog_delete.png'),getMessage("reset-label"))
|
self.resetButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + 'cog_delete.png'),getMessage("reset-label"))
|
||||||
self.resetButton.setMaximumSize(self.resetButton.sizeHint())
|
self.resetButton.setMaximumSize(self.resetButton.sizeHint())
|
||||||
self.resetButton.setObjectName("reset")
|
self.resetButton.setObjectName("reset")
|
||||||
self.resetButton.released.connect(self.resetSettings)
|
self.resetButton.released.connect(self.resetSettings)
|
||||||
|
|
||||||
self.runButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + u'accept.png'), getMessage("run-label"))
|
self.runButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + 'accept.png'), getMessage("run-label"))
|
||||||
self.runButton.released.connect(self._runWithoutStoringConfig)
|
self.runButton.released.connect(self._runWithoutStoringConfig)
|
||||||
self.runButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + u'accept.png'), getMessage("run-label"))
|
self.runButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + 'accept.png'), getMessage("run-label"))
|
||||||
self.runButton.pressed.connect(self._runWithoutStoringConfig)
|
self.runButton.pressed.connect(self._runWithoutStoringConfig)
|
||||||
self.runButton.setToolTip(getMessage("nostore-tooltip"))
|
self.runButton.setToolTip(getMessage("nostore-tooltip"))
|
||||||
self.storeAndRunButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + u'accept.png'), getMessage("storeandrun-label"))
|
self.storeAndRunButton = QtWidgets.QPushButton(QtGui.QIcon(resourcespath + 'accept.png'), getMessage("storeandrun-label"))
|
||||||
self.storeAndRunButton.released.connect(self._saveDataAndLeave)
|
self.storeAndRunButton.released.connect(self._saveDataAndLeave)
|
||||||
self.bottomButtonLayout.addWidget(self.helpButton)
|
self.bottomButtonLayout.addWidget(self.helpButton)
|
||||||
self.bottomButtonLayout.addWidget(self.resetButton)
|
self.bottomButtonLayout.addWidget(self.resetButton)
|
||||||
@ -1165,12 +1166,12 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.tabListLayout = QtWidgets.QHBoxLayout()
|
self.tabListLayout = QtWidgets.QHBoxLayout()
|
||||||
self.tabListFrame = QtWidgets.QFrame()
|
self.tabListFrame = QtWidgets.QFrame()
|
||||||
self.tabListWidget = QtWidgets.QListWidget()
|
self.tabListWidget = QtWidgets.QListWidget()
|
||||||
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + u"house.png"),getMessage("basics-label")))
|
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + "house.png"),getMessage("basics-label")))
|
||||||
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + u"control_pause_blue.png"),getMessage("readiness-label")))
|
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + "control_pause_blue.png"),getMessage("readiness-label")))
|
||||||
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + u"film_link.png"),getMessage("sync-label")))
|
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + "film_link.png"),getMessage("sync-label")))
|
||||||
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + u"user_comment.png"), getMessage("chat-label")))
|
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + "user_comment.png"), getMessage("chat-label")))
|
||||||
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + u"error.png"),getMessage("messages-label")))
|
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + "error.png"),getMessage("messages-label")))
|
||||||
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + u"cog.png"),getMessage("misc-label")))
|
self.tabListWidget.addItem(QtWidgets.QListWidgetItem(QtGui.QIcon(resourcespath + "cog.png"),getMessage("misc-label")))
|
||||||
self.tabListLayout.addWidget(self.tabListWidget)
|
self.tabListLayout.addWidget(self.tabListWidget)
|
||||||
self.tabListFrame.setLayout(self.tabListLayout)
|
self.tabListFrame.setLayout(self.tabListLayout)
|
||||||
self.tabListFrame.setFixedWidth(self.tabListFrame.minimumSizeHint().width() + constants.TAB_PADDING)
|
self.tabListFrame.setFixedWidth(self.tabListFrame.minimumSizeHint().width() + constants.TAB_PADDING)
|
||||||
@ -1238,7 +1239,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.hostCombobox.setEditText(currentServer)
|
self.hostCombobox.setEditText(currentServer)
|
||||||
|
|
||||||
def updatePasswordVisibilty(self):
|
def updatePasswordVisibilty(self):
|
||||||
if (self.hostCombobox.currentText() == "" and self.serverpassTextbox.text() == "") or unicode(self.hostCombobox.currentText()) in self.publicServerAddresses:
|
if (self.hostCombobox.currentText() == "" and self.serverpassTextbox.text() == "") or str(self.hostCombobox.currentText()) in self.publicServerAddresses:
|
||||||
self.serverpassTextbox.setDisabled(True)
|
self.serverpassTextbox.setDisabled(True)
|
||||||
self.serverpassTextbox.setReadOnly(True)
|
self.serverpassTextbox.setReadOnly(True)
|
||||||
if self.serverpassTextbox.text() != "":
|
if self.serverpassTextbox.text() != "":
|
||||||
@ -1273,15 +1274,15 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
if isWindows():
|
if isWindows():
|
||||||
resourcespath = utils.findWorkingDir() + "\\resources\\"
|
resourcespath = utils.findWorkingDir() + "\\resources\\"
|
||||||
else:
|
else:
|
||||||
resourcespath = utils.findWorkingDir() + u"/resources/"
|
resourcespath = utils.findWorkingDir() + "/resources/"
|
||||||
self.posixresourcespath = utils.findWorkingDir().replace(u"\\","/") + u"/resources/"
|
self.posixresourcespath = utils.findWorkingDir().replace("\\","/") + "/resources/"
|
||||||
self.resourcespath = resourcespath
|
self.resourcespath = resourcespath
|
||||||
|
|
||||||
super(ConfigDialog, self).__init__()
|
super(ConfigDialog, self).__init__()
|
||||||
|
|
||||||
self.setWindowTitle(getMessage("config-window-title"))
|
self.setWindowTitle(getMessage("config-window-title"))
|
||||||
self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint)
|
self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & ~Qt.WindowContextHelpButtonHint)
|
||||||
self.setWindowIcon(QtGui.QIcon(resourcespath + u"syncplay.png"))
|
self.setWindowIcon(QtGui.QIcon(resourcespath + "syncplay.png"))
|
||||||
|
|
||||||
self.stackedLayout = QtWidgets.QStackedLayout()
|
self.stackedLayout = QtWidgets.QStackedLayout()
|
||||||
self.stackedFrame = QtWidgets.QFrame()
|
self.stackedFrame = QtWidgets.QFrame()
|
||||||
|
|||||||
0
syncplay/ui/__init__.py
Normal file → Executable file
0
syncplay/ui/__init__.py
Normal file → Executable file
20
syncplay/ui/consoleUI.py
Normal file → Executable file
20
syncplay/ui/consoleUI.py
Normal file → Executable file
@ -1,4 +1,4 @@
|
|||||||
from __future__ import print_function
|
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import syncplay
|
import syncplay
|
||||||
@ -32,7 +32,7 @@ class ConsoleUI(threading.Thread):
|
|||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
data = raw_input().decode(sys.stdin.encoding)
|
data = input()
|
||||||
data = data.rstrip('\n\r')
|
data = data.rstrip('\n\r')
|
||||||
if not self.promptMode.isSet():
|
if not self.promptMode.isSet():
|
||||||
self.PromptResult = data
|
self.PromptResult = data
|
||||||
@ -49,7 +49,7 @@ class ConsoleUI(threading.Thread):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def promptFor(self, prompt=">", message=""):
|
def promptFor(self, prompt=">", message=""):
|
||||||
if message <> "":
|
if message != "":
|
||||||
print(message)
|
print(message)
|
||||||
self.promptMode.clear()
|
self.promptMode.clear()
|
||||||
print(prompt, end='')
|
print(prompt, end='')
|
||||||
@ -58,20 +58,20 @@ class ConsoleUI(threading.Thread):
|
|||||||
|
|
||||||
def showUserList(self, currentUser, rooms):
|
def showUserList(self, currentUser, rooms):
|
||||||
for room in rooms:
|
for room in rooms:
|
||||||
message = u"In room '{}':".format(room)
|
message = "In room '{}':".format(room)
|
||||||
self.showMessage(message, True)
|
self.showMessage(message, True)
|
||||||
for user in rooms[room]:
|
for user in rooms[room]:
|
||||||
userflags = u""
|
userflags = ""
|
||||||
if user.isController():
|
if user.isController():
|
||||||
userflags += u"({}) ".format(getMessage("controller-userlist-userflag"))
|
userflags += "({}) ".format(getMessage("controller-userlist-userflag"))
|
||||||
if user.isReady():
|
if user.isReady():
|
||||||
userflags += u"({}) ".format(getMessage("ready-userlist-userflag"))
|
userflags += "({}) ".format(getMessage("ready-userlist-userflag"))
|
||||||
|
|
||||||
username = userflags + u"*<{}>*".format(user.username) if user == currentUser else userflags + u"<{}>".format(user.username)
|
username = userflags + "*<{}>*".format(user.username) if user == currentUser else userflags + "<{}>".format(user.username)
|
||||||
if user.file:
|
if user.file:
|
||||||
message = getMessage("userlist-playing-notification").format(username)
|
message = getMessage("userlist-playing-notification").format(username)
|
||||||
self.showMessage(message, True)
|
self.showMessage(message, True)
|
||||||
message = u" {}: '{}' ({})".format(getMessage("userlist-file-notification"),user.file['name'], formatTime(user.file['duration']))
|
message = " {}: '{}' ({})".format(getMessage("userlist-file-notification"),user.file['name'], formatTime(user.file['duration']))
|
||||||
if currentUser.file:
|
if currentUser.file:
|
||||||
if user.file['name'] == currentUser.file['name'] and user.file['size'] != currentUser.file['size']:
|
if user.file['name'] == currentUser.file['name'] and user.file['size'] != currentUser.file['size']:
|
||||||
message += getMessage("different-filesize-notification")
|
message += getMessage("different-filesize-notification")
|
||||||
@ -98,7 +98,7 @@ class ConsoleUI(threading.Thread):
|
|||||||
if noTimestamp:
|
if noTimestamp:
|
||||||
print(message)
|
print(message)
|
||||||
else:
|
else:
|
||||||
print(time.strftime(constants.UI_TIME_FORMAT, time.localtime()).decode('utf-8') + message)
|
print(time.strftime(constants.UI_TIME_FORMAT, time.localtime()) + message)
|
||||||
|
|
||||||
def showDebugMessage(self, message):
|
def showDebugMessage(self, message):
|
||||||
print(message)
|
print(message)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
from syncplay.vendor import Qt
|
from syncplay.vendor import Qt
|
||||||
from syncplay.vendor.Qt import QtWidgets, QtGui, __binding__, __binding_version__, __qt_version__, IsPySide, IsPySide2
|
from syncplay.vendor.Qt import QtWidgets, QtGui, __binding__, __binding_version__, __qt_version__, IsPySide, IsPySide2
|
||||||
from syncplay.vendor.Qt.QtCore import Qt, QSettings, QSize, QPoint, QUrl, QLine, QDateTime
|
from syncplay.vendor.Qt.QtCore import Qt, QSettings, QSize, QPoint, QUrl, QLine, QDateTime
|
||||||
from platform import python_version
|
from platform import python_version
|
||||||
if IsPySide2:
|
if IsPySide2:
|
||||||
@ -9,7 +9,7 @@ from syncplay.messages import getMessage
|
|||||||
from syncplay.utils import resourcespath
|
from syncplay.utils import resourcespath
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import urllib
|
import urllib.request, urllib.parse, urllib.error
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from syncplay.utils import isLinux, isWindows, isMacOS
|
from syncplay.utils import isLinux, isWindows, isMacOS
|
||||||
import re
|
import re
|
||||||
@ -55,9 +55,9 @@ class UserlistItemDelegate(QtWidgets.QStyledItemDelegate):
|
|||||||
if column == constants.USERLIST_GUI_USERNAME_COLUMN:
|
if column == constants.USERLIST_GUI_USERNAME_COLUMN:
|
||||||
currentQAbstractItemModel = indexQModelIndex.model()
|
currentQAbstractItemModel = indexQModelIndex.model()
|
||||||
itemQModelIndex = currentQAbstractItemModel.index(indexQModelIndex.row(), constants.USERLIST_GUI_USERNAME_COLUMN, indexQModelIndex.parent())
|
itemQModelIndex = currentQAbstractItemModel.index(indexQModelIndex.row(), constants.USERLIST_GUI_USERNAME_COLUMN, indexQModelIndex.parent())
|
||||||
controlIconQPixmap = QtGui.QPixmap(resourcespath + u"user_key.png")
|
controlIconQPixmap = QtGui.QPixmap(resourcespath + "user_key.png")
|
||||||
tickIconQPixmap = QtGui.QPixmap(resourcespath + u"tick.png")
|
tickIconQPixmap = QtGui.QPixmap(resourcespath + "tick.png")
|
||||||
crossIconQPixmap = QtGui.QPixmap(resourcespath + u"cross.png")
|
crossIconQPixmap = QtGui.QPixmap(resourcespath + "cross.png")
|
||||||
roomController = currentQAbstractItemModel.data(itemQModelIndex, Qt.UserRole + constants.USERITEM_CONTROLLER_ROLE)
|
roomController = currentQAbstractItemModel.data(itemQModelIndex, Qt.UserRole + constants.USERITEM_CONTROLLER_ROLE)
|
||||||
userReady = currentQAbstractItemModel.data(itemQModelIndex, Qt.UserRole + constants.USERITEM_READY_ROLE)
|
userReady = currentQAbstractItemModel.data(itemQModelIndex, Qt.UserRole + constants.USERITEM_READY_ROLE)
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ class UserlistItemDelegate(QtWidgets.QStyledItemDelegate):
|
|||||||
itemQModelIndex = currentQAbstractItemModel.index(indexQModelIndex.row(), constants.USERLIST_GUI_FILENAME_COLUMN, indexQModelIndex.parent())
|
itemQModelIndex = currentQAbstractItemModel.index(indexQModelIndex.row(), constants.USERLIST_GUI_FILENAME_COLUMN, indexQModelIndex.parent())
|
||||||
fileSwitchRole = currentQAbstractItemModel.data(itemQModelIndex, Qt.UserRole + constants.FILEITEM_SWITCH_ROLE)
|
fileSwitchRole = currentQAbstractItemModel.data(itemQModelIndex, Qt.UserRole + constants.FILEITEM_SWITCH_ROLE)
|
||||||
if fileSwitchRole == constants.FILEITEM_SWITCH_FILE_SWITCH:
|
if fileSwitchRole == constants.FILEITEM_SWITCH_FILE_SWITCH:
|
||||||
fileSwitchIconQPixmap = QtGui.QPixmap(resourcespath + u"film_go.png")
|
fileSwitchIconQPixmap = QtGui.QPixmap(resourcespath + "film_go.png")
|
||||||
itemQPainter.drawPixmap (
|
itemQPainter.drawPixmap (
|
||||||
(optionQStyleOptionViewItem.rect.x()),
|
(optionQStyleOptionViewItem.rect.x()),
|
||||||
midY - 8,
|
midY - 8,
|
||||||
@ -94,7 +94,7 @@ class UserlistItemDelegate(QtWidgets.QStyledItemDelegate):
|
|||||||
optionQStyleOptionViewItem.rect.setX(optionQStyleOptionViewItem.rect.x()+16)
|
optionQStyleOptionViewItem.rect.setX(optionQStyleOptionViewItem.rect.x()+16)
|
||||||
|
|
||||||
elif fileSwitchRole == constants.FILEITEM_SWITCH_STREAM_SWITCH:
|
elif fileSwitchRole == constants.FILEITEM_SWITCH_STREAM_SWITCH:
|
||||||
streamSwitchIconQPixmap = QtGui.QPixmap(resourcespath + u"world_go.png")
|
streamSwitchIconQPixmap = QtGui.QPixmap(resourcespath + "world_go.png")
|
||||||
itemQPainter.drawPixmap (
|
itemQPainter.drawPixmap (
|
||||||
(optionQStyleOptionViewItem.rect.x()),
|
(optionQStyleOptionViewItem.rect.x()),
|
||||||
midY - 8,
|
midY - 8,
|
||||||
@ -118,8 +118,9 @@ class AboutDialog(QtWidgets.QDialog):
|
|||||||
linkLabel.setOpenExternalLinks(True)
|
linkLabel.setOpenExternalLinks(True)
|
||||||
versionExtString = version + revision
|
versionExtString = version + revision
|
||||||
versionLabel = QtWidgets.QLabel("<p><center>" + getMessage("about-dialog-release").format(versionExtString, release_number) + "<br />Python " + python_version() + " - " + __binding__ + " " + __binding_version__ + " - Qt " + __qt_version__ + "</center></p>")
|
versionLabel = QtWidgets.QLabel("<p><center>" + getMessage("about-dialog-release").format(versionExtString, release_number) + "<br />Python " + python_version() + " - " + __binding__ + " " + __binding_version__ + " - Qt " + __qt_version__ + "</center></p>")
|
||||||
|
#versionLabel = QtWidgets.QLabel("<p><center>Version 1.5.4 release 62<br />Python 3.4.5 - PySide 1.2.4 - Qt 4.8.7</center></p>")
|
||||||
licenseLabel = QtWidgets.QLabel("<center><p>Copyright © 2012–2018 Syncplay</p><p>" + getMessage("about-dialog-license-text") + "</p></center>")
|
licenseLabel = QtWidgets.QLabel("<center><p>Copyright © 2012–2018 Syncplay</p><p>" + getMessage("about-dialog-license-text") + "</p></center>")
|
||||||
aboutIconPixmap = QtGui.QPixmap(resourcespath + u"syncplay.png")
|
aboutIconPixmap = QtGui.QPixmap(resourcespath + "syncplay.png")
|
||||||
aboutIconLabel = QtWidgets.QLabel()
|
aboutIconLabel = QtWidgets.QLabel()
|
||||||
aboutIconLabel.setPixmap(aboutIconPixmap.scaled(65, 65, Qt.KeepAspectRatio))
|
aboutIconLabel.setPixmap(aboutIconPixmap.scaled(65, 65, Qt.KeepAspectRatio))
|
||||||
aboutLayout = QtWidgets.QGridLayout()
|
aboutLayout = QtWidgets.QGridLayout()
|
||||||
@ -143,15 +144,15 @@ class AboutDialog(QtWidgets.QDialog):
|
|||||||
|
|
||||||
def openLicense(self):
|
def openLicense(self):
|
||||||
if isWindows():
|
if isWindows():
|
||||||
QtGui.QDesktopServices.openUrl(QUrl("file:///" + resourcespath + u"license.rtf"))
|
QtGui.QDesktopServices.openUrl(QUrl("file:///" + resourcespath + "license.rtf"))
|
||||||
else:
|
else:
|
||||||
QtGui.QDesktopServices.openUrl(QUrl("file://" + resourcespath + u"license.rtf"))
|
QtGui.QDesktopServices.openUrl(QUrl("file://" + resourcespath + "license.rtf"))
|
||||||
|
|
||||||
def openDependencies(self):
|
def openDependencies(self):
|
||||||
if isWindows():
|
if isWindows():
|
||||||
QtGui.QDesktopServices.openUrl(QUrl("file:///" + resourcespath + u"third-party-notices.rtf"))
|
QtGui.QDesktopServices.openUrl(QUrl("file:///" + resourcespath + "third-party-notices.rtf"))
|
||||||
else:
|
else:
|
||||||
QtGui.QDesktopServices.openUrl(QUrl("file://" + resourcespath + u"third-party-notices.rtf"))
|
QtGui.QDesktopServices.openUrl(QUrl("file://" + resourcespath + "third-party-notices.rtf"))
|
||||||
|
|
||||||
class MainWindow(QtWidgets.QMainWindow):
|
class MainWindow(QtWidgets.QMainWindow):
|
||||||
insertPosition = None
|
insertPosition = None
|
||||||
@ -162,7 +163,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
def setPlaylistInsertPosition(self, newPosition):
|
def setPlaylistInsertPosition(self, newPosition):
|
||||||
if not self.playlist.isEnabled():
|
if not self.playlist.isEnabled():
|
||||||
return
|
return
|
||||||
if MainWindow.insertPosition <> newPosition:
|
if MainWindow.insertPosition != newPosition:
|
||||||
MainWindow.insertPosition = newPosition
|
MainWindow.insertPosition = newPosition
|
||||||
self.playlist.forceUpdate()
|
self.playlist.forceUpdate()
|
||||||
|
|
||||||
@ -172,7 +173,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
currentQAbstractItemModel = indexQModelIndex.model()
|
currentQAbstractItemModel = indexQModelIndex.model()
|
||||||
currentlyPlayingFile = currentQAbstractItemModel.data(indexQModelIndex, Qt.UserRole + constants.PLAYLISTITEM_CURRENTLYPLAYING_ROLE)
|
currentlyPlayingFile = currentQAbstractItemModel.data(indexQModelIndex, Qt.UserRole + constants.PLAYLISTITEM_CURRENTLYPLAYING_ROLE)
|
||||||
if currentlyPlayingFile:
|
if currentlyPlayingFile:
|
||||||
currentlyplayingIconQPixmap = QtGui.QPixmap(resourcespath + u"bullet_right_grey.png")
|
currentlyplayingIconQPixmap = QtGui.QPixmap(resourcespath + "bullet_right_grey.png")
|
||||||
midY = int((optionQStyleOptionViewItem.rect.y() + optionQStyleOptionViewItem.rect.bottomLeft().y()) / 2)
|
midY = int((optionQStyleOptionViewItem.rect.y() + optionQStyleOptionViewItem.rect.bottomLeft().y()) / 2)
|
||||||
itemQPainter.drawPixmap (
|
itemQPainter.drawPixmap (
|
||||||
(optionQStyleOptionViewItem.rect.x()+4),
|
(optionQStyleOptionViewItem.rect.x()+4),
|
||||||
@ -227,11 +228,11 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
for url in urls[::-1]:
|
for url in urls[::-1]:
|
||||||
if isMacOS() and IsPySide:
|
if isMacOS() and IsPySide:
|
||||||
macURL = NSString.alloc().initWithString_(unicode(url.toString()))
|
macURL = NSString.alloc().initWithString_(str(url.toString()))
|
||||||
pathString = macURL.stringByAddingPercentEscapesUsingEncoding_(NSUTF8StringEncoding)
|
pathString = macURL.stringByAddingPercentEscapesUsingEncoding_(NSUTF8StringEncoding)
|
||||||
dropfilepath = os.path.abspath(NSURL.URLWithString_(pathString).filePathURL().path())
|
dropfilepath = os.path.abspath(NSURL.URLWithString_(pathString).filePathURL().path())
|
||||||
else:
|
else:
|
||||||
dropfilepath = os.path.abspath(unicode(url.toLocalFile()))
|
dropfilepath = os.path.abspath(str(url.toLocalFile()))
|
||||||
if os.path.isfile(dropfilepath):
|
if os.path.isfile(dropfilepath):
|
||||||
window.addFileToPlaylist(dropfilepath, indexRow)
|
window.addFileToPlaylist(dropfilepath, indexRow)
|
||||||
elif os.path.isdir(dropfilepath):
|
elif os.path.isdir(dropfilepath):
|
||||||
@ -244,12 +245,12 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
playlistIndexFilename = None
|
playlistIndexFilename = None
|
||||||
|
|
||||||
def setPlaylistIndexFilename(self, filename):
|
def setPlaylistIndexFilename(self, filename):
|
||||||
if filename <> self.playlistIndexFilename:
|
if filename != self.playlistIndexFilename:
|
||||||
self.playlistIndexFilename = filename
|
self.playlistIndexFilename = filename
|
||||||
self.updatePlaylistIndexIcon()
|
self.updatePlaylistIndexIcon()
|
||||||
|
|
||||||
def updatePlaylistIndexIcon(self):
|
def updatePlaylistIndexIcon(self):
|
||||||
for item in xrange(self.count()):
|
for item in range(self.count()):
|
||||||
itemFilename = self.item(item).text()
|
itemFilename = self.item(item).text()
|
||||||
isPlayingFilename = itemFilename == self.playlistIndexFilename
|
isPlayingFilename = itemFilename == self.playlistIndexFilename
|
||||||
self.item(item).setData(Qt.UserRole + constants.PLAYLISTITEM_CURRENTLYPLAYING_ROLE, isPlayingFilename)
|
self.item(item).setData(Qt.UserRole + constants.PLAYLISTITEM_CURRENTLYPLAYING_ROLE, isPlayingFilename)
|
||||||
@ -282,7 +283,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
super(MainWindow.PlaylistWidget, self).keyPressEvent(event)
|
super(MainWindow.PlaylistWidget, self).keyPressEvent(event)
|
||||||
|
|
||||||
def updatePlaylist(self, newPlaylist):
|
def updatePlaylist(self, newPlaylist):
|
||||||
for index in xrange(self.count()):
|
for index in range(self.count()):
|
||||||
self.takeItem(0)
|
self.takeItem(0)
|
||||||
uniquePlaylist = []
|
uniquePlaylist = []
|
||||||
for item in newPlaylist:
|
for item in newPlaylist:
|
||||||
@ -334,11 +335,11 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
indexRow = window.playlist.count()
|
indexRow = window.playlist.count()
|
||||||
for url in urls[::-1]:
|
for url in urls[::-1]:
|
||||||
if isMacOS() and IsPySide:
|
if isMacOS() and IsPySide:
|
||||||
macURL = NSString.alloc().initWithString_(unicode(url.toString()))
|
macURL = NSString.alloc().initWithString_(str(url.toString()))
|
||||||
pathString = macURL.stringByAddingPercentEscapesUsingEncoding_(NSUTF8StringEncoding)
|
pathString = macURL.stringByAddingPercentEscapesUsingEncoding_(NSUTF8StringEncoding)
|
||||||
dropfilepath = os.path.abspath(NSURL.URLWithString_(pathString).filePathURL().path())
|
dropfilepath = os.path.abspath(NSURL.URLWithString_(pathString).filePathURL().path())
|
||||||
else:
|
else:
|
||||||
dropfilepath = os.path.abspath(unicode(url.toLocalFile()))
|
dropfilepath = os.path.abspath(str(url.toLocalFile()))
|
||||||
if os.path.isfile(dropfilepath):
|
if os.path.isfile(dropfilepath):
|
||||||
window.addFileToPlaylist(dropfilepath, indexRow)
|
window.addFileToPlaylist(dropfilepath, indexRow)
|
||||||
elif os.path.isdir(dropfilepath):
|
elif os.path.isdir(dropfilepath):
|
||||||
@ -416,20 +417,20 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
self.roomInput.setMaxLength(constants.MAX_ROOM_NAME_LENGTH)
|
self.roomInput.setMaxLength(constants.MAX_ROOM_NAME_LENGTH)
|
||||||
|
|
||||||
def showMessage(self, message, noTimestamp=False):
|
def showMessage(self, message, noTimestamp=False):
|
||||||
message = unicode(message)
|
message = str(message)
|
||||||
username = None
|
username = None
|
||||||
messageWithUsername = re.match(constants.MESSAGE_WITH_USERNAME_REGEX, message, re.UNICODE)
|
messageWithUsername = re.match(constants.MESSAGE_WITH_USERNAME_REGEX, message, re.UNICODE)
|
||||||
if messageWithUsername:
|
if messageWithUsername:
|
||||||
username = messageWithUsername.group("username")
|
username = messageWithUsername.group("username")
|
||||||
message = messageWithUsername.group("message")
|
message = messageWithUsername.group("message")
|
||||||
message = message.replace(u"&", u"&").replace(u'"', u""").replace(u"<", u"<").replace(u">", u">")
|
message = message.replace("&", "&").replace('"', """).replace("<", "<").replace(">", ">")
|
||||||
if username:
|
if username:
|
||||||
message = constants.STYLE_USER_MESSAGE.format(constants.STYLE_USERNAME, username, message)
|
message = constants.STYLE_USER_MESSAGE.format(constants.STYLE_USERNAME, username, message)
|
||||||
message = message.replace(u"\n", u"<br />")
|
message = message.replace("\n", "<br />")
|
||||||
if noTimestamp:
|
if noTimestamp:
|
||||||
self.newMessage(u"{}<br />".format(message))
|
self.newMessage("{}<br />".format(message))
|
||||||
else:
|
else:
|
||||||
self.newMessage(time.strftime(constants.UI_TIME_FORMAT, time.localtime()).decode('utf-8') + message + u"<br />")
|
self.newMessage(time.strftime(constants.UI_TIME_FORMAT, time.localtime()) + message + "<br />")
|
||||||
|
|
||||||
@needsClient
|
@needsClient
|
||||||
def getFileSwitchState(self, filename):
|
def getFileSwitchState(self, filename):
|
||||||
@ -506,14 +507,10 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
useritem.setData(isReadyWithFile, Qt.UserRole + constants.USERITEM_READY_ROLE)
|
useritem.setData(isReadyWithFile, Qt.UserRole + constants.USERITEM_READY_ROLE)
|
||||||
if user.file:
|
if user.file:
|
||||||
filesizeitem = QtGui.QStandardItem(formatSize(user.file['size']))
|
filesizeitem = QtGui.QStandardItem(formatSize(user.file['size']))
|
||||||
filedurationitem = QtGui.QStandardItem(u"({})".format(formatTime(user.file['duration'])))
|
filedurationitem = QtGui.QStandardItem("({})".format(formatTime(user.file['duration'])))
|
||||||
filename = user.file['name']
|
filename = user.file['name']
|
||||||
if isURL(filename):
|
if isURL(filename):
|
||||||
filename = urllib.unquote(filename)
|
filename = urllib.parse.unquote(filename)
|
||||||
try:
|
|
||||||
filename = filename.decode('utf-8')
|
|
||||||
except UnicodeEncodeError:
|
|
||||||
pass
|
|
||||||
filenameitem = QtGui.QStandardItem(filename)
|
filenameitem = QtGui.QStandardItem(filename)
|
||||||
fileSwitchState = self.getFileSwitchState(user.file['name']) if room == currentUser.room else None
|
fileSwitchState = self.getFileSwitchState(user.file['name']) if room == currentUser.room else None
|
||||||
if fileSwitchState != constants.FILEITEM_SWITCH_NO_SWITCH:
|
if fileSwitchState != constants.FILEITEM_SWITCH_NO_SWITCH:
|
||||||
@ -591,29 +588,29 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
if item:
|
if item:
|
||||||
firstFile = item.sibling(item.row(), 0).data()
|
firstFile = item.sibling(item.row(), 0).data()
|
||||||
pathFound = self._syncplayClient.fileSwitch.findFilepath(firstFile) if not isURL(firstFile) else None
|
pathFound = self._syncplayClient.fileSwitch.findFilepath(firstFile) if not isURL(firstFile) else None
|
||||||
if self._syncplayClient.userlist.currentUser.file is None or firstFile <> self._syncplayClient.userlist.currentUser.file["name"]:
|
if self._syncplayClient.userlist.currentUser.file is None or firstFile != self._syncplayClient.userlist.currentUser.file["name"]:
|
||||||
if isURL(firstFile):
|
if isURL(firstFile):
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"world_go.png"), getMessage("openstreamurl-menu-label"), lambda: self.openFile(firstFile,resetPosition=True))
|
menu.addAction(QtGui.QPixmap(resourcespath + "world_go.png"), getMessage("openstreamurl-menu-label"), lambda: self.openFile(firstFile,resetPosition=True))
|
||||||
elif pathFound:
|
elif pathFound:
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"film_go.png"), getMessage("openmedia-menu-label"), lambda: self.openFile(pathFound,resetPosition=True))
|
menu.addAction(QtGui.QPixmap(resourcespath + "film_go.png"), getMessage("openmedia-menu-label"), lambda: self.openFile(pathFound,resetPosition=True))
|
||||||
if pathFound:
|
if pathFound:
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"folder_film.png"),
|
menu.addAction(QtGui.QPixmap(resourcespath + "folder_film.png"),
|
||||||
getMessage('open-containing-folder'),
|
getMessage('open-containing-folder'),
|
||||||
lambda: utils.open_system_file_browser(pathFound))
|
lambda: utils.open_system_file_browser(pathFound))
|
||||||
if self._syncplayClient.isUntrustedTrustableURI(firstFile):
|
if self._syncplayClient.isUntrustedTrustableURI(firstFile):
|
||||||
domain = utils.getDomainFromURL(firstFile)
|
domain = utils.getDomainFromURL(firstFile)
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"shield_add.png"),getMessage("addtrusteddomain-menu-label").format(domain), lambda: self.addTrustedDomain(domain))
|
menu.addAction(QtGui.QPixmap(resourcespath + "shield_add.png"),getMessage("addtrusteddomain-menu-label").format(domain), lambda: self.addTrustedDomain(domain))
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"delete.png"), getMessage("removefromplaylist-menu-label"), lambda: self.deleteSelectedPlaylistItems())
|
menu.addAction(QtGui.QPixmap(resourcespath + "delete.png"), getMessage("removefromplaylist-menu-label"), lambda: self.deleteSelectedPlaylistItems())
|
||||||
menu.addSeparator()
|
menu.addSeparator()
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"arrow_switch.png"), getMessage("shuffleremainingplaylist-menu-label"), lambda: self.shuffleRemainingPlaylist())
|
menu.addAction(QtGui.QPixmap(resourcespath + "arrow_switch.png"), getMessage("shuffleremainingplaylist-menu-label"), lambda: self.shuffleRemainingPlaylist())
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"arrow_switch.png"), getMessage("shuffleentireplaylist-menu-label"), lambda: self.shuffleEntirePlaylist())
|
menu.addAction(QtGui.QPixmap(resourcespath + "arrow_switch.png"), getMessage("shuffleentireplaylist-menu-label"), lambda: self.shuffleEntirePlaylist())
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"arrow_undo.png"), getMessage("undoplaylist-menu-label"), lambda: self.undoPlaylistChange())
|
menu.addAction(QtGui.QPixmap(resourcespath + "arrow_undo.png"), getMessage("undoplaylist-menu-label"), lambda: self.undoPlaylistChange())
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"film_edit.png"), getMessage("editplaylist-menu-label"), lambda: self.openEditPlaylistDialog())
|
menu.addAction(QtGui.QPixmap(resourcespath + "film_edit.png"), getMessage("editplaylist-menu-label"), lambda: self.openEditPlaylistDialog())
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"film_add.png"),getMessage("addfilestoplaylist-menu-label"), lambda: self.OpenAddFilesToPlaylistDialog())
|
menu.addAction(QtGui.QPixmap(resourcespath + "film_add.png"),getMessage("addfilestoplaylist-menu-label"), lambda: self.OpenAddFilesToPlaylistDialog())
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"world_add.png"), getMessage("addurlstoplaylist-menu-label"), lambda: self.OpenAddURIsToPlaylistDialog())
|
menu.addAction(QtGui.QPixmap(resourcespath + "world_add.png"), getMessage("addurlstoplaylist-menu-label"), lambda: self.OpenAddURIsToPlaylistDialog())
|
||||||
menu.addSeparator()
|
menu.addSeparator()
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"film_folder_edit.png"), getMessage("setmediadirectories-menu-label"), lambda: self.openSetMediaDirectoriesDialog())
|
menu.addAction(QtGui.QPixmap(resourcespath + "film_folder_edit.png"), getMessage("setmediadirectories-menu-label"), lambda: self.openSetMediaDirectoriesDialog())
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"shield_edit.png"), getMessage("settrusteddomains-menu-label"), lambda: self.openSetTrustedDomainsDialog())
|
menu.addAction(QtGui.QPixmap(resourcespath + "shield_edit.png"), getMessage("settrusteddomains-menu-label"), lambda: self.openSetTrustedDomainsDialog())
|
||||||
menu.exec_(self.playlist.viewport().mapToGlobal(position))
|
menu.exec_(self.playlist.viewport().mapToGlobal(position))
|
||||||
|
|
||||||
|
|
||||||
@ -632,36 +629,36 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
elif len(username) < 15:
|
elif len(username) < 15:
|
||||||
shortUsername = getMessage("item-is-others-indicator").format(username)
|
shortUsername = getMessage("item-is-others-indicator").format(username)
|
||||||
else:
|
else:
|
||||||
shortUsername = u"{}...".format(getMessage("item-is-others-indicator").format(username[0:12])) # TODO: Enforce username limits in client and server
|
shortUsername = "{}...".format(getMessage("item-is-others-indicator").format(username[0:12])) # TODO: Enforce username limits in client and server
|
||||||
|
|
||||||
filename = item.sibling(item.row(), 3).data()
|
filename = item.sibling(item.row(), 3).data()
|
||||||
while item.parent().row() != -1:
|
while item.parent().row() != -1:
|
||||||
item = item.parent()
|
item = item.parent()
|
||||||
roomToJoin = item.sibling(item.row(), 0).data()
|
roomToJoin = item.sibling(item.row(), 0).data()
|
||||||
if roomToJoin <> self._syncplayClient.getRoom():
|
if roomToJoin != self._syncplayClient.getRoom():
|
||||||
menu.addAction(getMessage("joinroom-menu-label").format(roomToJoin), lambda: self.joinRoom(roomToJoin))
|
menu.addAction(getMessage("joinroom-menu-label").format(roomToJoin), lambda: self.joinRoom(roomToJoin))
|
||||||
elif username and filename and filename <> getMessage("nofile-note"):
|
elif username and filename and filename != getMessage("nofile-note"):
|
||||||
if self.config['sharedPlaylistEnabled'] and not self.isItemInPlaylist(filename):
|
if self.config['sharedPlaylistEnabled'] and not self.isItemInPlaylist(filename):
|
||||||
if isURL(filename):
|
if isURL(filename):
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"world_add.png"),getMessage("addusersstreamstoplaylist-menu-label").format(shortUsername), lambda: self.addStreamToPlaylist(filename))
|
menu.addAction(QtGui.QPixmap(resourcespath + "world_add.png"),getMessage("addusersstreamstoplaylist-menu-label").format(shortUsername), lambda: self.addStreamToPlaylist(filename))
|
||||||
else:
|
else:
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"film_add.png"), getMessage("addusersfiletoplaylist-menu-label").format(shortUsername), lambda: self.addStreamToPlaylist(filename))
|
menu.addAction(QtGui.QPixmap(resourcespath + "film_add.png"), getMessage("addusersfiletoplaylist-menu-label").format(shortUsername), lambda: self.addStreamToPlaylist(filename))
|
||||||
|
|
||||||
if self._syncplayClient.userlist.currentUser.file is None or filename <> self._syncplayClient.userlist.currentUser.file["name"]:
|
if self._syncplayClient.userlist.currentUser.file is None or filename != self._syncplayClient.userlist.currentUser.file["name"]:
|
||||||
if isURL(filename):
|
if isURL(filename):
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"world_go.png"), getMessage("openusersstream-menu-label").format(shortUsername), lambda: self.openFile(filename))
|
menu.addAction(QtGui.QPixmap(resourcespath + "world_go.png"), getMessage("openusersstream-menu-label").format(shortUsername), lambda: self.openFile(filename))
|
||||||
else:
|
else:
|
||||||
pathFound = self._syncplayClient.fileSwitch.findFilepath(filename)
|
pathFound = self._syncplayClient.fileSwitch.findFilepath(filename)
|
||||||
if pathFound:
|
if pathFound:
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"film_go.png"), getMessage("openusersfile-menu-label").format(shortUsername), lambda: self.openFile(pathFound))
|
menu.addAction(QtGui.QPixmap(resourcespath + "film_go.png"), getMessage("openusersfile-menu-label").format(shortUsername), lambda: self.openFile(pathFound))
|
||||||
if self._syncplayClient.isUntrustedTrustableURI(filename):
|
if self._syncplayClient.isUntrustedTrustableURI(filename):
|
||||||
domain = utils.getDomainFromURL(filename)
|
domain = utils.getDomainFromURL(filename)
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"shield_add.png"),getMessage("addtrusteddomain-menu-label").format(domain), lambda: self.addTrustedDomain(domain))
|
menu.addAction(QtGui.QPixmap(resourcespath + "shield_add.png"),getMessage("addtrusteddomain-menu-label").format(domain), lambda: self.addTrustedDomain(domain))
|
||||||
|
|
||||||
if not isURL(filename) and filename <> getMessage("nofile-note"):
|
if not isURL(filename) and filename != getMessage("nofile-note"):
|
||||||
path = self._syncplayClient.fileSwitch.findFilepath(filename)
|
path = self._syncplayClient.fileSwitch.findFilepath(filename)
|
||||||
if path:
|
if path:
|
||||||
menu.addAction(QtGui.QPixmap(resourcespath + u"folder_film.png"), getMessage('open-containing-folder'), lambda: utils.open_system_file_browser(path))
|
menu.addAction(QtGui.QPixmap(resourcespath + "folder_film.png"), getMessage('open-containing-folder'), lambda: utils.open_system_file_browser(path))
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
menu.exec_(self.listTreeView.viewport().mapToGlobal(position))
|
menu.exec_(self.listTreeView.viewport().mapToGlobal(position))
|
||||||
@ -731,9 +728,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
while item.parent().row() != -1:
|
while item.parent().row() != -1:
|
||||||
item = item.parent()
|
item = item.parent()
|
||||||
roomToJoin = item.sibling(item.row(), 0).data()
|
roomToJoin = item.sibling(item.row(), 0).data()
|
||||||
if roomToJoin <> self._syncplayClient.getRoom():
|
if roomToJoin != self._syncplayClient.getRoom():
|
||||||
self.joinRoom(item.sibling(item.row(), 0).data())
|
self.joinRoom(item.sibling(item.row(), 0).data())
|
||||||
elif username and filename and username <> self._syncplayClient.userlist.currentUser.username:
|
elif username and filename and username != self._syncplayClient.userlist.currentUser.username:
|
||||||
if self._isTryingToChangeToCurrentFile(filename):
|
if self._isTryingToChangeToCurrentFile(filename):
|
||||||
return
|
return
|
||||||
if isURL(filename):
|
if isURL(filename):
|
||||||
@ -761,13 +758,13 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
print(message)
|
print(message)
|
||||||
|
|
||||||
def showErrorMessage(self, message, criticalerror=False):
|
def showErrorMessage(self, message, criticalerror=False):
|
||||||
message = unicode(message)
|
message = str(message)
|
||||||
if criticalerror:
|
if criticalerror:
|
||||||
QtWidgets.QMessageBox.critical(self, "Syncplay", message)
|
QtWidgets.QMessageBox.critical(self, "Syncplay", message)
|
||||||
message = message.replace(u"&", u"&").replace(u'"', u""").replace(u"<", u"<").replace(u">", u">")
|
message = message.replace("&", "&").replace('"', """).replace("<", "<").replace(">", ">")
|
||||||
message = message.replace(u"\n", u"<br />")
|
message = message.replace("\n", "<br />")
|
||||||
message = u"<span style=\"{}\">".format(constants.STYLE_ERRORNOTIFICATION) + message + u"</span>"
|
message = "<span style=\"{}\">".format(constants.STYLE_ERRORNOTIFICATION) + message + "</span>"
|
||||||
self.newMessage(time.strftime(constants.UI_TIME_FORMAT, time.localtime()).decode('utf-8') + message + u"<br />")
|
self.newMessage(time.strftime(constants.UI_TIME_FORMAT, time.localtime()) + message + "<br />")
|
||||||
|
|
||||||
@needsClient
|
@needsClient
|
||||||
def joinRoom(self, room=None):
|
def joinRoom(self, room=None):
|
||||||
@ -786,7 +783,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
def seekPositionDialog(self):
|
def seekPositionDialog(self):
|
||||||
seekTime, ok = QtWidgets.QInputDialog.getText(self, getMessage("seektime-menu-label"),
|
seekTime, ok = QtWidgets.QInputDialog.getText(self, getMessage("seektime-menu-label"),
|
||||||
getMessage("seektime-msgbox-label"), QtWidgets.QLineEdit.Normal,
|
getMessage("seektime-msgbox-label"), QtWidgets.QLineEdit.Normal,
|
||||||
u"0:00")
|
"0:00")
|
||||||
if ok and seekTime != '':
|
if ok and seekTime != '':
|
||||||
self.seekPosition(seekTime)
|
self.seekPosition(seekTime)
|
||||||
|
|
||||||
@ -961,9 +958,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
URI = URI.encode('utf-8')
|
URI = URI.encode('utf-8')
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
pass
|
pass
|
||||||
URI = urllib.unquote(URI)
|
URI = urllib.parse.unquote(URI)
|
||||||
URI = URI.decode('utf-8')
|
URI = URI.decode('utf-8')
|
||||||
if URI <> "":
|
if URI != "":
|
||||||
self.addStreamToPlaylist(URI)
|
self.addStreamToPlaylist(URI)
|
||||||
self.updatingPlaylist = False
|
self.updatingPlaylist = False
|
||||||
|
|
||||||
@ -992,7 +989,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
result = editPlaylistDialog.exec_()
|
result = editPlaylistDialog.exec_()
|
||||||
if result == QtWidgets.QDialog.Accepted:
|
if result == QtWidgets.QDialog.Accepted:
|
||||||
newPlaylist = utils.convertMultilineStringToList(editPlaylistTextbox.toPlainText())
|
newPlaylist = utils.convertMultilineStringToList(editPlaylistTextbox.toPlainText())
|
||||||
if newPlaylist <> self.playlistState and self._syncplayClient and not self.updatingPlaylist:
|
if newPlaylist != self.playlistState and self._syncplayClient and not self.updatingPlaylist:
|
||||||
self.setPlaylist(newPlaylist)
|
self.setPlaylist(newPlaylist)
|
||||||
self._syncplayClient.playlist.changePlaylist(newPlaylist)
|
self._syncplayClient.playlist.changePlaylist(newPlaylist)
|
||||||
self._syncplayClient.fileSwitch.updateInfo()
|
self._syncplayClient.fileSwitch.updateInfo()
|
||||||
@ -1062,14 +1059,14 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog)
|
options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.ShowDirsOnly | QtWidgets.QFileDialog.DontUseNativeDialog)
|
||||||
else:
|
else:
|
||||||
options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.ShowDirsOnly)
|
options = QtWidgets.QFileDialog.Options(QtWidgets.QFileDialog.ShowDirsOnly)
|
||||||
folderName = unicode(QtWidgets.QFileDialog.getExistingDirectory(self,None,self.getInitialMediaDirectory(includeUserSpecifiedDirectories=False),options))
|
folderName = str(QtWidgets.QFileDialog.getExistingDirectory(self,None,self.getInitialMediaDirectory(includeUserSpecifiedDirectories=False),options))
|
||||||
|
|
||||||
if folderName:
|
if folderName:
|
||||||
existingMediaDirs = MediaDirectoriesTextbox.toPlainText()
|
existingMediaDirs = MediaDirectoriesTextbox.toPlainText()
|
||||||
if existingMediaDirs == "":
|
if existingMediaDirs == "":
|
||||||
newMediaDirList = folderName
|
newMediaDirList = folderName
|
||||||
else:
|
else:
|
||||||
newMediaDirList = existingMediaDirs + u"\n" + folderName
|
newMediaDirList = existingMediaDirs + "\n" + folderName
|
||||||
MediaDirectoriesTextbox.setPlainText(newMediaDirList)
|
MediaDirectoriesTextbox.setPlainText(newMediaDirList)
|
||||||
MediaDirectoriesDialog.raise_()
|
MediaDirectoriesDialog.raise_()
|
||||||
MediaDirectoriesDialog.activateWindow()
|
MediaDirectoriesDialog.activateWindow()
|
||||||
@ -1140,9 +1137,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
def getPlaylistState(self):
|
def getPlaylistState(self):
|
||||||
playlistItems = []
|
playlistItems = []
|
||||||
for playlistItem in xrange(self.playlist.count()):
|
for playlistItem in range(self.playlist.count()):
|
||||||
playlistItemText = self.playlist.item(playlistItem).text()
|
playlistItemText = self.playlist.item(playlistItem).text()
|
||||||
if playlistItemText <> getMessage("playlist-instruction-item-message"):
|
if playlistItemText != getMessage("playlist-instruction-item-message"):
|
||||||
playlistItems.append(playlistItemText)
|
playlistItems.append(playlistItemText)
|
||||||
return playlistItems
|
return playlistItems
|
||||||
|
|
||||||
@ -1150,20 +1147,20 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
if self.updatingPlaylist:
|
if self.updatingPlaylist:
|
||||||
return
|
return
|
||||||
newPlaylist = self.getPlaylistState()
|
newPlaylist = self.getPlaylistState()
|
||||||
if newPlaylist <> self.playlistState and self._syncplayClient and not self.updatingPlaylist:
|
if newPlaylist != self.playlistState and self._syncplayClient and not self.updatingPlaylist:
|
||||||
self.playlistState = newPlaylist
|
self.playlistState = newPlaylist
|
||||||
self._syncplayClient.playlist.changePlaylist(newPlaylist)
|
self._syncplayClient.playlist.changePlaylist(newPlaylist)
|
||||||
self._syncplayClient.fileSwitch.updateInfo()
|
self._syncplayClient.fileSwitch.updateInfo()
|
||||||
|
|
||||||
def executeCommand(self, command):
|
def executeCommand(self, command):
|
||||||
self.showMessage(u"/{}".format(command))
|
self.showMessage("/{}".format(command))
|
||||||
self.console.executeCommand(command)
|
self.console.executeCommand(command)
|
||||||
|
|
||||||
def sendChatMessage(self):
|
def sendChatMessage(self):
|
||||||
chatText = self.chatInput.text()
|
chatText = self.chatInput.text()
|
||||||
self.chatInput.setText("")
|
self.chatInput.setText("")
|
||||||
if chatText <> "":
|
if chatText != "":
|
||||||
if chatText[:1] == "/" and chatText <> "/":
|
if chatText[:1] == "/" and chatText != "/":
|
||||||
command = chatText[1:]
|
command = chatText[1:]
|
||||||
if command and command[:1] == "/":
|
if command and command[:1] == "/":
|
||||||
chatText = chatText[1:]
|
chatText = chatText[1:]
|
||||||
@ -1367,20 +1364,20 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
window.playbackFrame.setLayout(window.playbackLayout)
|
window.playbackFrame.setLayout(window.playbackLayout)
|
||||||
window.seekInput = QtWidgets.QLineEdit()
|
window.seekInput = QtWidgets.QLineEdit()
|
||||||
window.seekInput.returnPressed.connect(self.seekFromButton)
|
window.seekInput.returnPressed.connect(self.seekFromButton)
|
||||||
window.seekButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + u'clock_go.png'), "")
|
window.seekButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + 'clock_go.png'), "")
|
||||||
window.seekButton.setToolTip(getMessage("seektime-menu-label"))
|
window.seekButton.setToolTip(getMessage("seektime-menu-label"))
|
||||||
window.seekButton.pressed.connect(self.seekFromButton)
|
window.seekButton.pressed.connect(self.seekFromButton)
|
||||||
window.seekInput.setText("0:00")
|
window.seekInput.setText("0:00")
|
||||||
window.seekInput.setFixedWidth(60)
|
window.seekInput.setFixedWidth(60)
|
||||||
window.playbackLayout.addWidget(window.seekInput)
|
window.playbackLayout.addWidget(window.seekInput)
|
||||||
window.playbackLayout.addWidget(window.seekButton)
|
window.playbackLayout.addWidget(window.seekButton)
|
||||||
window.unseekButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + u'arrow_undo.png'), "")
|
window.unseekButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + 'arrow_undo.png'), "")
|
||||||
window.unseekButton.setToolTip(getMessage("undoseek-menu-label"))
|
window.unseekButton.setToolTip(getMessage("undoseek-menu-label"))
|
||||||
window.unseekButton.pressed.connect(self.undoSeek)
|
window.unseekButton.pressed.connect(self.undoSeek)
|
||||||
|
|
||||||
window.miscLayout = QtWidgets.QHBoxLayout()
|
window.miscLayout = QtWidgets.QHBoxLayout()
|
||||||
window.playbackLayout.addWidget(window.unseekButton)
|
window.playbackLayout.addWidget(window.unseekButton)
|
||||||
window.playButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + u'control_play_blue.png'), "")
|
window.playButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + 'control_play_blue.png'), "")
|
||||||
window.playButton.setToolTip(getMessage("play-menu-label"))
|
window.playButton.setToolTip(getMessage("play-menu-label"))
|
||||||
window.playButton.pressed.connect(self.play)
|
window.playButton.pressed.connect(self.play)
|
||||||
window.playbackLayout.addWidget(window.playButton)
|
window.playbackLayout.addWidget(window.playButton)
|
||||||
@ -1470,12 +1467,12 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
window.updateAction = window.helpMenu.addAction(QtGui.QPixmap(resourcespath + 'application_get.png'),
|
window.updateAction = window.helpMenu.addAction(QtGui.QPixmap(resourcespath + 'application_get.png'),
|
||||||
getMessage("update-menu-label"))
|
getMessage("update-menu-label"))
|
||||||
window.updateAction.triggered.connect(self.userCheckForUpdates)
|
window.updateAction.triggered.connect(self.userCheckForUpdates)
|
||||||
|
|
||||||
if not isMacOS():
|
if not isMacOS():
|
||||||
window.helpMenu.addSeparator()
|
window.helpMenu.addSeparator()
|
||||||
window.about = window.helpMenu.addAction(QtGui.QPixmap(resourcespath + 'syncplay.png'),
|
window.about = window.helpMenu.addAction(QtGui.QPixmap(resourcespath + 'syncplay.png'),
|
||||||
getMessage("about-menu-label"))
|
getMessage("about-menu-label"))
|
||||||
else:
|
else:
|
||||||
window.about = window.helpMenu.addAction("&About")
|
window.about = window.helpMenu.addAction("&About")
|
||||||
window.about.triggered.connect(self.openAbout)
|
window.about.triggered.connect(self.openAbout)
|
||||||
|
|
||||||
@ -1486,7 +1483,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
def openAbout(self):
|
def openAbout(self):
|
||||||
aboutMsgBox = AboutDialog()
|
aboutMsgBox = AboutDialog()
|
||||||
aboutMsgBox.exec_()
|
aboutMsgBox.exec_()
|
||||||
|
|
||||||
def addMainFrame(self, window):
|
def addMainFrame(self, window):
|
||||||
window.mainFrame = QtWidgets.QFrame()
|
window.mainFrame = QtWidgets.QFrame()
|
||||||
window.mainFrame.setLineWidth(0)
|
window.mainFrame.setLineWidth(0)
|
||||||
@ -1575,7 +1572,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
if timeDelta.total_seconds() > constants.AUTOMATIC_UPDATE_CHECK_FREQUENCY:
|
if timeDelta.total_seconds() > constants.AUTOMATIC_UPDATE_CHECK_FREQUENCY:
|
||||||
self.checkForUpdates()
|
self.checkForUpdates()
|
||||||
except:
|
except:
|
||||||
self.showDebugMessage(u"Automatic check for updates failed. An update check was manually trigggered.")
|
self.showDebugMessage("Automatic check for updates failed. An update check was manually trigggered.")
|
||||||
self.checkForUpdates()
|
self.checkForUpdates()
|
||||||
|
|
||||||
def userCheckForUpdates(self):
|
def userCheckForUpdates(self):
|
||||||
@ -1622,11 +1619,11 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
if urls and urls[0].scheme() == 'file':
|
if urls and urls[0].scheme() == 'file':
|
||||||
url = event.mimeData().urls()[0]
|
url = event.mimeData().urls()[0]
|
||||||
if isMacOS() and IsPySide:
|
if isMacOS() and IsPySide:
|
||||||
macURL = NSString.alloc().initWithString_(unicode(url.toString()))
|
macURL = NSString.alloc().initWithString_(str(url.toString()))
|
||||||
pathString = macURL.stringByAddingPercentEscapesUsingEncoding_(NSUTF8StringEncoding)
|
pathString = macURL.stringByAddingPercentEscapesUsingEncoding_(NSUTF8StringEncoding)
|
||||||
dropfilepath = os.path.abspath(NSURL.URLWithString_(pathString).filePathURL().path())
|
dropfilepath = os.path.abspath(NSURL.URLWithString_(pathString).filePathURL().path())
|
||||||
else:
|
else:
|
||||||
dropfilepath = os.path.abspath(unicode(url.toLocalFile()))
|
dropfilepath = os.path.abspath(str(url.toLocalFile()))
|
||||||
if rewindFile == False:
|
if rewindFile == False:
|
||||||
self._syncplayClient._player.openFile(dropfilepath)
|
self._syncplayClient._player.openFile(dropfilepath)
|
||||||
else:
|
else:
|
||||||
@ -1636,7 +1633,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
def setPlaylist(self, newPlaylist, newIndexFilename=None):
|
def setPlaylist(self, newPlaylist, newIndexFilename=None):
|
||||||
if self.updatingPlaylist:
|
if self.updatingPlaylist:
|
||||||
self.ui.showDebugMessage(u"Trying to set playlist while it is already being updated")
|
self.ui.showDebugMessage("Trying to set playlist while it is already being updated")
|
||||||
if newPlaylist == self.playlistState:
|
if newPlaylist == self.playlistState:
|
||||||
if newIndexFilename:
|
if newIndexFilename:
|
||||||
self.playlist.setPlaylistIndexFilename(newIndexFilename)
|
self.playlist.setPlaylistIndexFilename(newIndexFilename)
|
||||||
@ -1684,7 +1681,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def isItemInPlaylist(self, filename):
|
def isItemInPlaylist(self, filename):
|
||||||
for playlistindex in xrange(self.playlist.count()):
|
for playlistindex in range(self.playlist.count()):
|
||||||
if self.playlist.item(playlistindex).text() == filename:
|
if self.playlist.item(playlistindex).text() == filename:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@ -1696,12 +1693,12 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
def removePlaylistNote(self):
|
def removePlaylistNote(self):
|
||||||
if not self.clearedPlaylistNote:
|
if not self.clearedPlaylistNote:
|
||||||
for index in xrange(self.playlist.count()):
|
for index in range(self.playlist.count()):
|
||||||
self.playlist.takeItem(0)
|
self.playlist.takeItem(0)
|
||||||
self.clearedPlaylistNote = True
|
self.clearedPlaylistNote = True
|
||||||
|
|
||||||
def addFolderToPlaylist(self, folderPath):
|
def addFolderToPlaylist(self, folderPath):
|
||||||
self.showErrorMessage(u"You tried to add the folder '{}' to the playlist. Syncplay only currently supports adding files to the playlist.".format(folderPath)) # TODO: Implement "add folder to playlist"
|
self.showErrorMessage("You tried to add the folder '{}' to the playlist. Syncplay only currently supports adding files to the playlist.".format(folderPath)) # TODO: Implement "add folder to playlist"
|
||||||
|
|
||||||
def deleteSelectedPlaylistItems(self):
|
def deleteSelectedPlaylistItems(self):
|
||||||
self.playlist.remove_selected_items()
|
self.playlist.remove_selected_items()
|
||||||
@ -1771,7 +1768,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
self.addMenubar(self)
|
self.addMenubar(self)
|
||||||
self.addMainFrame(self)
|
self.addMainFrame(self)
|
||||||
self.loadSettings()
|
self.loadSettings()
|
||||||
self.setWindowIcon(QtGui.QPixmap(resourcespath + u"syncplay.png"))
|
self.setWindowIcon(QtGui.QPixmap(resourcespath + "syncplay.png"))
|
||||||
self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & Qt.AA_DontUseNativeMenuBar & Qt.WindowMinimizeButtonHint & ~Qt.WindowContextHelpButtonHint)
|
self.setWindowFlags(self.windowFlags() & Qt.WindowCloseButtonHint & Qt.AA_DontUseNativeMenuBar & Qt.WindowMinimizeButtonHint & ~Qt.WindowContextHelpButtonHint)
|
||||||
self.show()
|
self.show()
|
||||||
self.setAcceptDrops(True)
|
self.setAcceptDrops(True)
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import itertools
|
|||||||
import hashlib
|
import hashlib
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
import urllib
|
import urllib.request, urllib.parse, urllib.error
|
||||||
import ast
|
import ast
|
||||||
import unicodedata
|
import unicodedata
|
||||||
import platform
|
import platform
|
||||||
@ -58,7 +58,7 @@ def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
|
|||||||
#try_one_last_time = False
|
#try_one_last_time = False
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
break
|
break
|
||||||
except ExceptionToCheck, e:
|
except ExceptionToCheck as e:
|
||||||
if logger:
|
if logger:
|
||||||
msg = getMessage("retrying-notification").format(str(e), mdelay)
|
msg = getMessage("retrying-notification").format(str(e), mdelay)
|
||||||
logger.warning(msg)
|
logger.warning(msg)
|
||||||
@ -78,7 +78,7 @@ def parseTime(timeStr):
|
|||||||
return
|
return
|
||||||
parts = parts.groupdict()
|
parts = parts.groupdict()
|
||||||
time_params = {}
|
time_params = {}
|
||||||
for (name, param) in parts.iteritems():
|
for (name, param) in parts.items():
|
||||||
if param:
|
if param:
|
||||||
if name == "miliseconds":
|
if name == "miliseconds":
|
||||||
time_params["microseconds"] = int(param) * 1000
|
time_params["microseconds"] = int(param) * 1000
|
||||||
@ -142,23 +142,25 @@ def findWorkingDir():
|
|||||||
frozen = getattr(sys, 'frozen', '')
|
frozen = getattr(sys, 'frozen', '')
|
||||||
if not frozen:
|
if not frozen:
|
||||||
path = os.path.dirname(os.path.dirname(__file__))
|
path = os.path.dirname(os.path.dirname(__file__))
|
||||||
elif frozen in ('dll', 'console_exe', 'windows_exe'):
|
elif frozen in ('dll', 'console_exe', 'windows_exe', 'macosx_app'):
|
||||||
path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
|
path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
|
||||||
elif frozen in ('macosx_app'):
|
elif frozen: #needed for PyInstaller
|
||||||
path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
|
if getattr(sys, '_MEIPASS', '') is not None:
|
||||||
|
path = getattr(sys, '_MEIPASS', '') #--onefile
|
||||||
|
else:
|
||||||
|
path = os.path.dirname(sys.executable) #--onedir
|
||||||
else:
|
else:
|
||||||
path = ""
|
path = ""
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def getResourcesPath():
|
def getResourcesPath():
|
||||||
|
|
||||||
if isWindows():
|
if isWindows():
|
||||||
return findWorkingDir() + u"\\resources\\"
|
return findWorkingDir() + "\\resources\\"
|
||||||
else:
|
else:
|
||||||
return findWorkingDir() + u"/resources/"
|
return findWorkingDir() + "/resources/"
|
||||||
|
|
||||||
resourcespath = getResourcesPath()
|
resourcespath = getResourcesPath()
|
||||||
posixresourcespath = findWorkingDir().replace(u"\\","/") + u"/resources/"
|
posixresourcespath = findWorkingDir().replace("\\","/") + "/resources/"
|
||||||
|
|
||||||
def getDefaultMonospaceFont():
|
def getDefaultMonospaceFont():
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
@ -169,7 +171,7 @@ def getDefaultMonospaceFont():
|
|||||||
return constants.FALLBACK_MONOSPACE_FONT
|
return constants.FALLBACK_MONOSPACE_FONT
|
||||||
|
|
||||||
def limitedPowerset(s, minLength):
|
def limitedPowerset(s, minLength):
|
||||||
return itertools.chain.from_iterable(itertools.combinations(s, r) for r in xrange(len(s), minLength, -1))
|
return itertools.chain.from_iterable(itertools.combinations(s, r) for r in range(len(s), minLength, -1))
|
||||||
|
|
||||||
def blackholeStdoutForFrozenWindow():
|
def blackholeStdoutForFrozenWindow():
|
||||||
if getattr(sys, 'frozen', '') == "windows_exe":
|
if getattr(sys, 'frozen', '') == "windows_exe":
|
||||||
@ -179,7 +181,7 @@ def blackholeStdoutForFrozenWindow():
|
|||||||
_error = None
|
_error = None
|
||||||
def write(self, text, fname='.syncplay.log'):
|
def write(self, text, fname='.syncplay.log'):
|
||||||
if self._file is None and self._error is None:
|
if self._file is None and self._error is None:
|
||||||
if os.name <> 'nt':
|
if os.name != 'nt':
|
||||||
path = os.path.join(os.getenv('HOME', '.'), fname)
|
path = os.path.join(os.getenv('HOME', '.'), fname)
|
||||||
else:
|
else:
|
||||||
path = os.path.join(os.getenv('APPDATA', '.'), fname)
|
path = os.path.join(os.getenv('APPDATA', '.'), fname)
|
||||||
@ -209,7 +211,7 @@ def truncateText(unicodeText, maxLength):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
return(unicode(unicodeText.encode("utf-8"), "utf-8", errors="ignore")[:maxLength])
|
return(str(unicodeText.encode("utf-8"), "utf-8", errors="ignore")[:maxLength])
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
return ""
|
return ""
|
||||||
@ -220,7 +222,7 @@ def splitText(unicodeText, maxLength):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
unicodeText = unicode(unicodeText.encode("utf-8"), "utf-8", errors="ignore")
|
unicodeText = str(unicodeText.encode("utf-8"), "utf-8", errors="ignore")
|
||||||
unicodeArray = [unicodeText[i:i + maxLength] for i in range(0, len(unicodeText), maxLength)]
|
unicodeArray = [unicodeText[i:i + maxLength] for i in range(0, len(unicodeText), maxLength)]
|
||||||
return(unicodeArray)
|
return(unicodeArray)
|
||||||
except:
|
except:
|
||||||
@ -232,15 +234,15 @@ def splitText(unicodeText, maxLength):
|
|||||||
def stripfilename(filename, stripURL):
|
def stripfilename(filename, stripURL):
|
||||||
if filename:
|
if filename:
|
||||||
try:
|
try:
|
||||||
filename = filename.encode('utf-8')
|
filename = filename
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
pass
|
pass
|
||||||
filename = urllib.unquote(filename)
|
filename = urllib.parse.unquote(filename)
|
||||||
if stripURL:
|
if stripURL:
|
||||||
try:
|
try:
|
||||||
filename = urllib.unquote(filename.split(u"/")[-1])
|
filename = urllib.parse.unquote(filename.split("/")[-1])
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
filename = urllib.unquote(filename.split("/")[-1])
|
filename = urllib.parse.unquote(filename.split("/")[-1])
|
||||||
return re.sub(constants.FILENAME_STRIP_REGEX, "", filename)
|
return re.sub(constants.FILENAME_STRIP_REGEX, "", filename)
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
@ -266,7 +268,7 @@ def hashFilename(filename, stripURL = False):
|
|||||||
return filenameHash
|
return filenameHash
|
||||||
|
|
||||||
def hashFilesize(size):
|
def hashFilesize(size):
|
||||||
return hashlib.sha256(str(size)).hexdigest()[:12]
|
return hashlib.sha256(str(size).encode('utf-8')).hexdigest()[:12]
|
||||||
|
|
||||||
def sameHashed(string1raw, string1hashed, string2raw, string2hashed):
|
def sameHashed(string1raw, string1hashed, string2raw, string2hashed):
|
||||||
try:
|
try:
|
||||||
@ -285,11 +287,11 @@ def sameHashed(string1raw, string1hashed, string2raw, string2hashed):
|
|||||||
|
|
||||||
def sameFilename (filename1, filename2):
|
def sameFilename (filename1, filename2):
|
||||||
try:
|
try:
|
||||||
filename1 = filename1.encode('utf-8')
|
filename1 = filename1
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
filename2 = filename2.encode('utf-8')
|
filename2 = filename2
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
pass
|
pass
|
||||||
stripURL = True if isURL(filename1) ^ isURL(filename2) else False
|
stripURL = True if isURL(filename1) ^ isURL(filename2) else False
|
||||||
@ -330,7 +332,7 @@ def isURL(path):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def getPlayerArgumentsByPathAsArray(arguments, path):
|
def getPlayerArgumentsByPathAsArray(arguments, path):
|
||||||
if arguments and not isinstance(arguments, (str, unicode)) and arguments.has_key(path):
|
if arguments and not isinstance(arguments, str) and path in arguments:
|
||||||
return arguments[path]
|
return arguments[path]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
@ -339,18 +341,11 @@ def getPlayerArgumentsByPathAsText(arguments, path):
|
|||||||
argsToReturn = getPlayerArgumentsByPathAsArray(arguments, path)
|
argsToReturn = getPlayerArgumentsByPathAsArray(arguments, path)
|
||||||
return " ".join(argsToReturn) if argsToReturn else ""
|
return " ".join(argsToReturn) if argsToReturn else ""
|
||||||
|
|
||||||
def unicodeReplaceFromFuture(s):
|
|
||||||
return ''.join(chr(ord(c)) for c in s).decode('utf-8')
|
|
||||||
|
|
||||||
def getListAsMultilineString(pathArray):
|
def getListAsMultilineString(pathArray):
|
||||||
try:
|
return "\n".join(pathArray) if pathArray else ""
|
||||||
pathArray = map(unicodeReplaceFromFuture, pathArray)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return u"\n".join(pathArray) if pathArray else ""
|
|
||||||
|
|
||||||
def convertMultilineStringToList(multilineString):
|
def convertMultilineStringToList(multilineString):
|
||||||
return unicode.split(multilineString,u"\n") if multilineString else ""
|
return str.split(multilineString,"\n") if multilineString else ""
|
||||||
|
|
||||||
def playlistIsValid(files):
|
def playlistIsValid(files):
|
||||||
if len(files) > constants.PLAYLIST_MAX_ITEMS:
|
if len(files) > constants.PLAYLIST_MAX_ITEMS:
|
||||||
@ -381,18 +376,19 @@ def open_system_file_browser(path):
|
|||||||
|
|
||||||
def getListOfPublicServers():
|
def getListOfPublicServers():
|
||||||
try:
|
try:
|
||||||
import syncplay, sys, messages, urllib
|
import urllib.request, urllib.parse, urllib.error, syncplay, sys
|
||||||
params = urllib.urlencode({'version': syncplay.version, 'milestone': syncplay.milestone, 'release_number': syncplay.release_number, 'language': messages.messages["CURRENT"]})
|
params = urllib.parse.urlencode({'version': syncplay.version, 'milestone': syncplay.milestone, 'release_number': syncplay.release_number, 'language': syncplay.messages.messages["CURRENT"]})
|
||||||
if isMacOS():
|
if isMacOS():
|
||||||
import requests
|
import requests
|
||||||
response = requests.get(constants.SYNCPLAY_PUBLIC_SERVER_LIST_URL.format(params))
|
response = requests.get(constants.SYNCPLAY_PUBLIC_SERVER_LIST_URL.format(params))
|
||||||
response = response.text
|
response = response.text
|
||||||
else:
|
else:
|
||||||
f = urllib.urlopen(constants.SYNCPLAY_PUBLIC_SERVER_LIST_URL.format(params))
|
f = urllib.request.urlopen(constants.SYNCPLAY_PUBLIC_SERVER_LIST_URL.format(params))
|
||||||
response = f.read()
|
response = f.read()
|
||||||
|
response = response.decode('utf-8')
|
||||||
response = response.replace("<p>","").replace("</p>","").replace("<br />","").replace("“","'").replace("”","'").replace(":’","'").replace("’","'").replace("′","'").replace("\n","").replace("\r","") # Fix Wordpress
|
response = response.replace("<p>","").replace("</p>","").replace("<br />","").replace("“","'").replace("”","'").replace(":’","'").replace("’","'").replace("′","'").replace("\n","").replace("\r","") # Fix Wordpress
|
||||||
response = ast.literal_eval(response)
|
response = ast.literal_eval(response)
|
||||||
|
|
||||||
if response:
|
if response:
|
||||||
return response
|
return response
|
||||||
else:
|
else:
|
||||||
@ -456,11 +452,11 @@ class RandomStringGenerator(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_random_letters(quantity):
|
def _get_random_letters(quantity):
|
||||||
return ''.join(random.choice(string.ascii_uppercase) for _ in xrange(quantity))
|
return ''.join(random.choice(string.ascii_uppercase) for _ in range(quantity))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_random_numbers(quantity):
|
def _get_random_numbers(quantity):
|
||||||
return ''.join(random.choice(string.digits) for _ in xrange(quantity))
|
return ''.join(random.choice(string.digits) for _ in range(quantity))
|
||||||
|
|
||||||
class NotControlledRoom(Exception):
|
class NotControlledRoom(Exception):
|
||||||
pass
|
pass
|
||||||
|
|||||||
126
syncplay/vendor/Qt.py
vendored
126
syncplay/vendor/Qt.py
vendored
@ -43,7 +43,7 @@ import types
|
|||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
|
||||||
__version__ = "1.1.0.b5"
|
__version__ = "1.1.0"
|
||||||
|
|
||||||
# Enable support for `from Qt import *`
|
# Enable support for `from Qt import *`
|
||||||
__all__ = []
|
__all__ = []
|
||||||
@ -110,6 +110,7 @@ _common_members = {
|
|||||||
"QGenericArgument",
|
"QGenericArgument",
|
||||||
"QGenericReturnArgument",
|
"QGenericReturnArgument",
|
||||||
"QHistoryState",
|
"QHistoryState",
|
||||||
|
"QItemSelectionRange",
|
||||||
"QIODevice",
|
"QIODevice",
|
||||||
"QLibraryInfo",
|
"QLibraryInfo",
|
||||||
"QLine",
|
"QLine",
|
||||||
@ -393,6 +394,16 @@ _common_members = {
|
|||||||
"QGLFormat",
|
"QGLFormat",
|
||||||
"QGLWidget"
|
"QGLWidget"
|
||||||
],
|
],
|
||||||
|
"QtPrintSupport": [
|
||||||
|
"QAbstractPrintDialog",
|
||||||
|
"QPageSetupDialog",
|
||||||
|
"QPrintDialog",
|
||||||
|
"QPrintEngine",
|
||||||
|
"QPrintPreviewDialog",
|
||||||
|
"QPrintPreviewWidget",
|
||||||
|
"QPrinter",
|
||||||
|
"QPrinterInfo"
|
||||||
|
],
|
||||||
"QtSql": [
|
"QtSql": [
|
||||||
"QSql",
|
"QSql",
|
||||||
"QSqlDatabase",
|
"QSqlDatabase",
|
||||||
@ -611,6 +622,9 @@ _common_members = {
|
|||||||
"QWizard",
|
"QWizard",
|
||||||
"QWizardPage"
|
"QWizardPage"
|
||||||
],
|
],
|
||||||
|
"QtX11Extras": [
|
||||||
|
"QX11Info"
|
||||||
|
],
|
||||||
"QtXml": [
|
"QtXml": [
|
||||||
"QDomAttr",
|
"QDomAttr",
|
||||||
"QDomCDATASection",
|
"QDomCDATASection",
|
||||||
@ -671,7 +685,7 @@ These members from the original submodule are misplaced relative PySide2
|
|||||||
"""
|
"""
|
||||||
_misplaced_members = {
|
_misplaced_members = {
|
||||||
"PySide2": {
|
"PySide2": {
|
||||||
#"QtGui.QStringListModel": "QtCore.QStringListModel",
|
"QtGui.QStringListModel": "QtCore.QStringListModel",
|
||||||
"QtCore.Property": "QtCore.Property",
|
"QtCore.Property": "QtCore.Property",
|
||||||
"QtCore.Signal": "QtCore.Signal",
|
"QtCore.Signal": "QtCore.Signal",
|
||||||
"QtCore.Slot": "QtCore.Slot",
|
"QtCore.Slot": "QtCore.Slot",
|
||||||
@ -679,6 +693,7 @@ _misplaced_members = {
|
|||||||
"QtCore.QSortFilterProxyModel": "QtCore.QSortFilterProxyModel",
|
"QtCore.QSortFilterProxyModel": "QtCore.QSortFilterProxyModel",
|
||||||
"QtCore.QItemSelection": "QtCore.QItemSelection",
|
"QtCore.QItemSelection": "QtCore.QItemSelection",
|
||||||
"QtCore.QItemSelectionModel": "QtCore.QItemSelectionModel",
|
"QtCore.QItemSelectionModel": "QtCore.QItemSelectionModel",
|
||||||
|
"QtCore.QItemSelectionRange": "QtCore.QItemSelectionRange",
|
||||||
},
|
},
|
||||||
"PyQt5": {
|
"PyQt5": {
|
||||||
"QtCore.pyqtProperty": "QtCore.Property",
|
"QtCore.pyqtProperty": "QtCore.Property",
|
||||||
@ -689,6 +704,7 @@ _misplaced_members = {
|
|||||||
"QtCore.QStringListModel": "QtCore.QStringListModel",
|
"QtCore.QStringListModel": "QtCore.QStringListModel",
|
||||||
"QtCore.QItemSelection": "QtCore.QItemSelection",
|
"QtCore.QItemSelection": "QtCore.QItemSelection",
|
||||||
"QtCore.QItemSelectionModel": "QtCore.QItemSelectionModel",
|
"QtCore.QItemSelectionModel": "QtCore.QItemSelectionModel",
|
||||||
|
"QtCore.QItemSelectionRange": "QtCore.QItemSelectionRange",
|
||||||
},
|
},
|
||||||
"PySide": {
|
"PySide": {
|
||||||
"QtGui.QAbstractProxyModel": "QtCore.QAbstractProxyModel",
|
"QtGui.QAbstractProxyModel": "QtCore.QAbstractProxyModel",
|
||||||
@ -699,7 +715,15 @@ _misplaced_members = {
|
|||||||
"QtCore.Property": "QtCore.Property",
|
"QtCore.Property": "QtCore.Property",
|
||||||
"QtCore.Signal": "QtCore.Signal",
|
"QtCore.Signal": "QtCore.Signal",
|
||||||
"QtCore.Slot": "QtCore.Slot",
|
"QtCore.Slot": "QtCore.Slot",
|
||||||
|
"QtGui.QItemSelectionRange": "QtCore.QItemSelectionRange",
|
||||||
|
"QtGui.QAbstractPrintDialog": "QtPrintSupport.QAbstractPrintDialog",
|
||||||
|
"QtGui.QPageSetupDialog": "QtPrintSupport.QPageSetupDialog",
|
||||||
|
"QtGui.QPrintDialog": "QtPrintSupport.QPrintDialog",
|
||||||
|
"QtGui.QPrintEngine": "QtPrintSupport.QPrintEngine",
|
||||||
|
"QtGui.QPrintPreviewDialog": "QtPrintSupport.QPrintPreviewDialog",
|
||||||
|
"QtGui.QPrintPreviewWidget": "QtPrintSupport.QPrintPreviewWidget",
|
||||||
|
"QtGui.QPrinter": "QtPrintSupport.QPrinter",
|
||||||
|
"QtGui.QPrinterInfo": "QtPrintSupport.QPrinterInfo",
|
||||||
},
|
},
|
||||||
"PyQt4": {
|
"PyQt4": {
|
||||||
"QtGui.QAbstractProxyModel": "QtCore.QAbstractProxyModel",
|
"QtGui.QAbstractProxyModel": "QtCore.QAbstractProxyModel",
|
||||||
@ -710,6 +734,15 @@ _misplaced_members = {
|
|||||||
"QtCore.pyqtProperty": "QtCore.Property",
|
"QtCore.pyqtProperty": "QtCore.Property",
|
||||||
"QtCore.pyqtSignal": "QtCore.Signal",
|
"QtCore.pyqtSignal": "QtCore.Signal",
|
||||||
"QtCore.pyqtSlot": "QtCore.Slot",
|
"QtCore.pyqtSlot": "QtCore.Slot",
|
||||||
|
"QtGui.QItemSelectionRange": "QtCore.QItemSelectionRange",
|
||||||
|
"QtGui.QAbstractPrintDialog": "QtPrintSupport.QAbstractPrintDialog",
|
||||||
|
"QtGui.QPageSetupDialog": "QtPrintSupport.QPageSetupDialog",
|
||||||
|
"QtGui.QPrintDialog": "QtPrintSupport.QPrintDialog",
|
||||||
|
"QtGui.QPrintEngine": "QtPrintSupport.QPrintEngine",
|
||||||
|
"QtGui.QPrintPreviewDialog": "QtPrintSupport.QPrintPreviewDialog",
|
||||||
|
"QtGui.QPrintPreviewWidget": "QtPrintSupport.QPrintPreviewWidget",
|
||||||
|
"QtGui.QPrinter": "QtPrintSupport.QPrinter",
|
||||||
|
"QtGui.QPrinterInfo": "QtPrintSupport.QPrinterInfo",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -903,16 +936,34 @@ def _reassign_misplaced_members(binding):
|
|||||||
src_module, src_member = src.split(".")
|
src_module, src_member = src.split(".")
|
||||||
dst_module, dst_member = dst.split(".")
|
dst_module, dst_member = dst.split(".")
|
||||||
|
|
||||||
|
# Get the member we want to store in the namesapce.
|
||||||
|
try:
|
||||||
|
dst_value = getattr(getattr(Qt, "_" + src_module), src_member)
|
||||||
|
except AttributeError:
|
||||||
|
# If the member we want to store in the namespace does not exist,
|
||||||
|
# there is no need to continue. This can happen if a request was
|
||||||
|
# made to rename a member that didn't exist, for example
|
||||||
|
# if QtWidgets isn't available on the target platform.
|
||||||
|
_log("Misplaced member has no source: {}".format(src))
|
||||||
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
src_object = getattr(Qt, dst_module)
|
src_object = getattr(Qt, dst_module)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# Skip reassignment of non-existing members.
|
if dst_module not in _common_members:
|
||||||
# This can happen if a request was made to
|
# Only create the Qt parent module if its listed in
|
||||||
# rename a member that didn't exist, for example
|
# _common_members. Without this check, if you remove QtCore
|
||||||
# if QtWidgets isn't available on the target platform.
|
# from _common_members, the default _misplaced_members will add
|
||||||
continue
|
# Qt.QtCore so it can add Signal, Slot, etc.
|
||||||
|
msg = 'Not creating missing member module "{m}" for "{c}"'
|
||||||
dst_value = getattr(getattr(Qt, "_" + src_module), src_member)
|
_log(msg.format(m=dst_module, c=dst_member))
|
||||||
|
continue
|
||||||
|
# If the dst is valid but the Qt parent module does not exist
|
||||||
|
# then go ahead and create a new module to contain the member.
|
||||||
|
setattr(Qt, dst_module, _new_module(dst_module))
|
||||||
|
src_object = getattr(Qt, dst_module)
|
||||||
|
# Enable direct import of the new module
|
||||||
|
sys.modules[__name__ + "." + dst_module] = src_object
|
||||||
|
|
||||||
setattr(
|
setattr(
|
||||||
src_object,
|
src_object,
|
||||||
@ -1020,6 +1071,7 @@ def _pyside2():
|
|||||||
|
|
||||||
if hasattr(Qt, "_QtCore"):
|
if hasattr(Qt, "_QtCore"):
|
||||||
Qt.__qt_version__ = Qt._QtCore.qVersion()
|
Qt.__qt_version__ = Qt._QtCore.qVersion()
|
||||||
|
Qt.QtCompat.qInstallMessageHandler = _qInstallMessageHandler
|
||||||
Qt.QtCompat.translate = Qt._QtCore.QCoreApplication.translate
|
Qt.QtCompat.translate = Qt._QtCore.QCoreApplication.translate
|
||||||
|
|
||||||
if hasattr(Qt, "_QtWidgets"):
|
if hasattr(Qt, "_QtWidgets"):
|
||||||
@ -1062,12 +1114,16 @@ def _pyside():
|
|||||||
if hasattr(Qt, "_QtGui"):
|
if hasattr(Qt, "_QtGui"):
|
||||||
setattr(Qt, "QtWidgets", _new_module("QtWidgets"))
|
setattr(Qt, "QtWidgets", _new_module("QtWidgets"))
|
||||||
setattr(Qt, "_QtWidgets", Qt._QtGui)
|
setattr(Qt, "_QtWidgets", Qt._QtGui)
|
||||||
|
if hasattr(Qt._QtGui, "QX11Info"):
|
||||||
|
setattr(Qt, "QtX11Extras", _new_module("QtX11Extras"))
|
||||||
|
Qt.QtX11Extras.QX11Info = Qt._QtGui.QX11Info
|
||||||
|
|
||||||
Qt.QtCompat.setSectionResizeMode = Qt._QtGui.QHeaderView.setResizeMode
|
Qt.QtCompat.setSectionResizeMode = Qt._QtGui.QHeaderView.setResizeMode
|
||||||
|
|
||||||
if hasattr(Qt, "_QtCore"):
|
if hasattr(Qt, "_QtCore"):
|
||||||
Qt.__qt_version__ = Qt._QtCore.qVersion()
|
Qt.__qt_version__ = Qt._QtCore.qVersion()
|
||||||
QCoreApplication = Qt._QtCore.QCoreApplication
|
QCoreApplication = Qt._QtCore.QCoreApplication
|
||||||
|
Qt.QtCompat.qInstallMessageHandler = _qInstallMessageHandler
|
||||||
Qt.QtCompat.translate = (
|
Qt.QtCompat.translate = (
|
||||||
lambda context, sourceText, disambiguation, n:
|
lambda context, sourceText, disambiguation, n:
|
||||||
QCoreApplication.translate(
|
QCoreApplication.translate(
|
||||||
@ -1107,6 +1163,7 @@ def _pyqt5():
|
|||||||
if hasattr(Qt, "_QtCore"):
|
if hasattr(Qt, "_QtCore"):
|
||||||
Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR
|
Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR
|
||||||
Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR
|
Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR
|
||||||
|
Qt.QtCompat.qInstallMessageHandler = _qInstallMessageHandler
|
||||||
Qt.QtCompat.translate = Qt._QtCore.QCoreApplication.translate
|
Qt.QtCompat.translate = Qt._QtCore.QCoreApplication.translate
|
||||||
|
|
||||||
if hasattr(Qt, "_QtWidgets"):
|
if hasattr(Qt, "_QtWidgets"):
|
||||||
@ -1175,6 +1232,9 @@ def _pyqt4():
|
|||||||
if hasattr(Qt, "_QtGui"):
|
if hasattr(Qt, "_QtGui"):
|
||||||
setattr(Qt, "QtWidgets", _new_module("QtWidgets"))
|
setattr(Qt, "QtWidgets", _new_module("QtWidgets"))
|
||||||
setattr(Qt, "_QtWidgets", Qt._QtGui)
|
setattr(Qt, "_QtWidgets", Qt._QtGui)
|
||||||
|
if hasattr(Qt._QtGui, "QX11Info"):
|
||||||
|
setattr(Qt, "QtX11Extras", _new_module("QtX11Extras"))
|
||||||
|
Qt.QtX11Extras.QX11Info = Qt._QtGui.QX11Info
|
||||||
|
|
||||||
Qt.QtCompat.setSectionResizeMode = \
|
Qt.QtCompat.setSectionResizeMode = \
|
||||||
Qt._QtGui.QHeaderView.setResizeMode
|
Qt._QtGui.QHeaderView.setResizeMode
|
||||||
@ -1182,8 +1242,8 @@ def _pyqt4():
|
|||||||
if hasattr(Qt, "_QtCore"):
|
if hasattr(Qt, "_QtCore"):
|
||||||
Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR
|
Qt.__binding_version__ = Qt._QtCore.PYQT_VERSION_STR
|
||||||
Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR
|
Qt.__qt_version__ = Qt._QtCore.QT_VERSION_STR
|
||||||
|
|
||||||
QCoreApplication = Qt._QtCore.QCoreApplication
|
QCoreApplication = Qt._QtCore.QCoreApplication
|
||||||
|
Qt.QtCompat.qInstallMessageHandler = _qInstallMessageHandler
|
||||||
Qt.QtCompat.translate = (
|
Qt.QtCompat.translate = (
|
||||||
lambda context, sourceText, disambiguation, n:
|
lambda context, sourceText, disambiguation, n:
|
||||||
QCoreApplication.translate(
|
QCoreApplication.translate(
|
||||||
@ -1261,10 +1321,6 @@ def _loadUi(uifile, baseinstance=None):
|
|||||||
return the newly created instance of the user interface.
|
return the newly created instance of the user interface.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if hasattr(baseinstance, "layout") and baseinstance.layout():
|
|
||||||
message = ("QLayout: Attempting to add Layout to %s which "
|
|
||||||
"already has a layout")
|
|
||||||
raise RuntimeError(message % (baseinstance))
|
|
||||||
|
|
||||||
if hasattr(Qt, "_uic"):
|
if hasattr(Qt, "_uic"):
|
||||||
return Qt._uic.loadUi(uifile, baseinstance)
|
return Qt._uic.loadUi(uifile, baseinstance)
|
||||||
@ -1345,6 +1401,43 @@ def _loadUi(uifile, baseinstance=None):
|
|||||||
raise NotImplementedError("No implementation available for loadUi")
|
raise NotImplementedError("No implementation available for loadUi")
|
||||||
|
|
||||||
|
|
||||||
|
def _qInstallMessageHandler(handler):
|
||||||
|
"""Install a message handler that works in all bindings
|
||||||
|
|
||||||
|
Args:
|
||||||
|
handler: A function that takes 3 arguments, or None
|
||||||
|
"""
|
||||||
|
def messageOutputHandler(*args):
|
||||||
|
# In Qt4 bindings, message handlers are passed 2 arguments
|
||||||
|
# In Qt5 bindings, message handlers are passed 3 arguments
|
||||||
|
# The first argument is a QtMsgType
|
||||||
|
# The last argument is the message to be printed
|
||||||
|
# The Middle argument (if passed) is a QMessageLogContext
|
||||||
|
if len(args) == 3:
|
||||||
|
msgType, logContext, msg = args
|
||||||
|
elif len(args) == 2:
|
||||||
|
msgType, msg = args
|
||||||
|
logContext = None
|
||||||
|
else:
|
||||||
|
raise TypeError(
|
||||||
|
"handler expected 2 or 3 arguments, got {0}".format(len(args)))
|
||||||
|
|
||||||
|
if isinstance(msg, bytes):
|
||||||
|
# In python 3, some bindings pass a bytestring, which cannot be
|
||||||
|
# used elsewhere. Decoding a python 2 or 3 bytestring object will
|
||||||
|
# consistently return a unicode object.
|
||||||
|
msg = msg.decode()
|
||||||
|
|
||||||
|
handler(msgType, logContext, msg)
|
||||||
|
|
||||||
|
passObject = messageOutputHandler if handler else handler
|
||||||
|
if Qt.IsPySide or Qt.IsPyQt4:
|
||||||
|
return Qt._QtCore.qInstallMsgHandler(passObject)
|
||||||
|
elif Qt.IsPySide2 or Qt.IsPyQt5:
|
||||||
|
return Qt._QtCore.qInstallMessageHandler(passObject)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _convert(lines):
|
def _convert(lines):
|
||||||
"""Convert compiled .ui file from PySide2 to Qt.py
|
"""Convert compiled .ui file from PySide2 to Qt.py
|
||||||
|
|
||||||
@ -1497,6 +1590,9 @@ def _install():
|
|||||||
|
|
||||||
setattr(our_submodule, member, their_member)
|
setattr(our_submodule, member, their_member)
|
||||||
|
|
||||||
|
# Enable direct import of QtCompat
|
||||||
|
sys.modules['Qt.QtCompat'] = Qt.QtCompat
|
||||||
|
|
||||||
# Backwards compatibility
|
# Backwards compatibility
|
||||||
if hasattr(Qt.QtCompat, 'loadUi'):
|
if hasattr(Qt.QtCompat, 'loadUi'):
|
||||||
Qt.QtCompat.load_ui = Qt.QtCompat.loadUi
|
Qt.QtCompat.load_ui = Qt.QtCompat.loadUi
|
||||||
|
|||||||
0
syncplay/vendor/__init__.py
vendored
Normal file → Executable file
0
syncplay/vendor/__init__.py
vendored
Normal file → Executable file
15
syncplay/vendor/qt5reactor.py
vendored
Normal file → Executable file
15
syncplay/vendor/qt5reactor.py
vendored
Normal file → Executable file
@ -106,8 +106,6 @@ Subsequent port by therve
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from syncplay.utils import isMacOS, isWindows
|
|
||||||
from syncplay.vendor.Qt import IsPySide2
|
|
||||||
from syncplay.vendor.Qt.QtCore import (
|
from syncplay.vendor.Qt.QtCore import (
|
||||||
QCoreApplication, QEventLoop, QObject, QSocketNotifier, QTimer, Signal)
|
QCoreApplication, QEventLoop, QObject, QSocketNotifier, QTimer, Signal)
|
||||||
from twisted.internet import posixbase
|
from twisted.internet import posixbase
|
||||||
@ -126,12 +124,7 @@ class TwistedSocketNotifier(QObject):
|
|||||||
self.reactor = reactor
|
self.reactor = reactor
|
||||||
self.watcher = watcher
|
self.watcher = watcher
|
||||||
fd = self.watcher.fileno()
|
fd = self.watcher.fileno()
|
||||||
if (isMacOS() and IsPySide2):
|
self.notifier = QSocketNotifier(fd, socketType, parent)
|
||||||
self.notifier = QSocketNotifier(watcher, socketType, parent)
|
|
||||||
elif (isWindows() and IsPySide2):
|
|
||||||
self.notifier = QSocketNotifier(watcher, socketType, parent)
|
|
||||||
else:
|
|
||||||
self.notifier = QSocketNotifier(fd, socketType, parent)
|
|
||||||
self.notifier.setEnabled(True)
|
self.notifier.setEnabled(True)
|
||||||
if socketType == QSocketNotifier.Read:
|
if socketType == QSocketNotifier.Read:
|
||||||
self.fn = self.read
|
self.fn = self.read
|
||||||
@ -258,10 +251,10 @@ class QtReactor(posixbase.PosixReactorBase):
|
|||||||
return self._removeAll(self._reads, self._writes)
|
return self._removeAll(self._reads, self._writes)
|
||||||
|
|
||||||
def getReaders(self):
|
def getReaders(self):
|
||||||
return self._reads.keys()
|
return list(self._reads.keys())
|
||||||
|
|
||||||
def getWriters(self):
|
def getWriters(self):
|
||||||
return self._writes.keys()
|
return list(self._writes.keys())
|
||||||
|
|
||||||
def callLater(self, howlong, *args, **kargs):
|
def callLater(self, howlong, *args, **kargs):
|
||||||
rval = super(QtReactor, self).callLater(howlong, *args, **kargs)
|
rval = super(QtReactor, self).callLater(howlong, *args, **kargs)
|
||||||
@ -344,7 +337,7 @@ class QtEventReactor(QtReactor):
|
|||||||
del self._events[event]
|
del self._events[event]
|
||||||
|
|
||||||
def doEvents(self):
|
def doEvents(self):
|
||||||
handles = self._events.keys()
|
handles = list(self._events.keys())
|
||||||
if len(handles) > 0:
|
if len(handles) > 0:
|
||||||
val = None
|
val = None
|
||||||
while val != WAIT_TIMEOUT:
|
while val != WAIT_TIMEOUT:
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python2
|
||||||
|
|
||||||
import site, sys
|
import sys
|
||||||
|
|
||||||
# libpath
|
# libpath
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if (sys.version_info.major != 2) or (sys.version_info.minor < 7):
|
if (sys.version_info.major != 3) or (sys.version_info.minor < 4):
|
||||||
raise Exception("You must run Syncplay with Python 2.7!")
|
raise Exception("You must run Syncplay with Python 3.4 or newer!")
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
import warnings
|
import warnings
|
||||||
warnings.warn("You must run Syncplay with Python 2.7!")
|
warnings.warn("You must run Syncplay with Python 3.4 or newer!")
|
||||||
|
|
||||||
from syncplay.clientManager import SyncplayClientManager
|
from syncplay.clientManager import SyncplayClientManager
|
||||||
from syncplay.utils import blackholeStdoutForFrozenWindow
|
from syncplay.utils import blackholeStdoutForFrozenWindow
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python2
|
||||||
#coding:utf8
|
#coding:utf8
|
||||||
|
|
||||||
import site, sys
|
import sys
|
||||||
|
|
||||||
# libpath
|
# libpath
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if (sys.version_info.major != 2) or (sys.version_info.minor < 7):
|
if (sys.version_info.major != 3) or (sys.version_info.minor < 4):
|
||||||
raise Exception("You must run Syncplay with Python 2.7!")
|
raise Exception("You must run Syncplay with Python 3.4 or newer!")
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
import warnings
|
import warnings
|
||||||
warnings.warn("You must run Syncplay with Python 2.7!")
|
warnings.warn("You must run Syncplay with Python 3.4 or newer!")
|
||||||
|
|
||||||
from twisted.internet import reactor
|
from twisted.internet import reactor
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user