Revert "Code Syntax Refactoring"
This commit is contained in:
parent
995f232a3b
commit
51fba3722f
15
appdmg.py
15
appdmg.py
@ -7,7 +7,6 @@ import os.path
|
|||||||
application = defines.get('app', 'dist/Syncplay.app')
|
application = defines.get('app', 'dist/Syncplay.app')
|
||||||
appname = os.path.basename(application)
|
appname = os.path.basename(application)
|
||||||
|
|
||||||
|
|
||||||
def icon_from_app(app_path):
|
def icon_from_app(app_path):
|
||||||
plist_path = os.path.join(app_path, 'Contents', 'Info.plist')
|
plist_path = os.path.join(app_path, 'Contents', 'Info.plist')
|
||||||
plist = biplist.readPlist(plist_path)
|
plist = biplist.readPlist(plist_path)
|
||||||
@ -18,7 +17,6 @@ def icon_from_app(app_path):
|
|||||||
icon_name = icon_root + icon_ext
|
icon_name = icon_root + icon_ext
|
||||||
return os.path.join(app_path, 'Contents', 'Resources', icon_name)
|
return os.path.join(app_path, 'Contents', 'Resources', icon_name)
|
||||||
|
|
||||||
|
|
||||||
# Volume format (see hdiutil create -help)
|
# Volume format (see hdiutil create -help)
|
||||||
format = defines.get('format', 'UDZO')
|
format = defines.get('format', 'UDZO')
|
||||||
|
|
||||||
@ -29,19 +27,10 @@ compression_level = 9
|
|||||||
size = defines.get('size', None)
|
size = defines.get('size', None)
|
||||||
|
|
||||||
# Files to include
|
# Files to include
|
||||||
files = [
|
files = [ application, 'resources/lua/intf/.syncplay.lua', 'resources/.macos_vlc_install.command', 'resources/.macOS_readme.pdf' ]
|
||||||
application,
|
|
||||||
'resources/lua/intf/.syncplay.lua',
|
|
||||||
'resources/.macos_vlc_install.command',
|
|
||||||
'resources/.macOS_readme.pdf'
|
|
||||||
]
|
|
||||||
|
|
||||||
# Symlinks to create
|
# Symlinks to create
|
||||||
symlinks = {
|
symlinks = { 'Applications': '/Applications', 'Install for VLC': '.macos_vlc_install.command', 'Read Me': '.macOS_readme.pdf' }
|
||||||
'Applications': '/Applications',
|
|
||||||
'Install for VLC': '.macos_vlc_install.command',
|
|
||||||
'Read Me': '.macOS_readme.pdf'
|
|
||||||
}
|
|
||||||
|
|
||||||
# Volume icon
|
# Volume icon
|
||||||
#
|
#
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
#*** TROUBLESHOOTING ***
|
#*** 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
|
#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 codecs
|
|
||||||
import sys
|
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!")
|
||||||
@ -14,20 +14,18 @@ import sys
|
|||||||
# import warnings
|
# import warnings
|
||||||
# warnings.warn("You must build Syncplay with Python 2.7!")
|
# warnings.warn("You must build Syncplay with Python 2.7!")
|
||||||
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
from string import Template
|
from string import Template
|
||||||
|
|
||||||
import syncplay
|
import syncplay
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from syncplay.messages import getMissingStrings
|
from syncplay.messages import getMissingStrings
|
||||||
|
|
||||||
|
|
||||||
missingStrings = getMissingStrings()
|
missingStrings = getMissingStrings()
|
||||||
if missingStrings is not None and missingStrings is not "":
|
if missingStrings is not None and missingStrings is not "":
|
||||||
import warnings
|
import warnings
|
||||||
warnings.warn("MISSING/UNUSED STRINGS DETECTED:\n{}".format(missingStrings))
|
warnings.warn("MISSING/UNUSED STRINGS DETECTED:\n{}".format(missingStrings))
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
@ -41,11 +39,9 @@ def get_nsis_path():
|
|||||||
raise Exception("You must install NSIS 3 or later.")
|
raise Exception("You must install NSIS 3 or later.")
|
||||||
except WindowsError:
|
except WindowsError:
|
||||||
return bin_name
|
return bin_name
|
||||||
|
|
||||||
|
|
||||||
NSIS_COMPILE = get_nsis_path()
|
NSIS_COMPILE = get_nsis_path()
|
||||||
|
|
||||||
OUT_DIR = r"dist\Syncplay"
|
OUT_DIR = "dist\Syncplay"
|
||||||
SETUP_SCRIPT_PATH = "syncplay_setup.nsi"
|
SETUP_SCRIPT_PATH = "syncplay_setup.nsi"
|
||||||
NSIS_SCRIPT_TEMPLATE = r"""
|
NSIS_SCRIPT_TEMPLATE = r"""
|
||||||
!include LogicLib.nsh
|
!include LogicLib.nsh
|
||||||
@ -612,7 +608,6 @@ NSIS_SCRIPT_TEMPLATE = r"""
|
|||||||
SectionEnd
|
SectionEnd
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class NSISScript(object):
|
class NSISScript(object):
|
||||||
def create(self):
|
def create(self):
|
||||||
fileList, totalSize = self.getBuildDirContents(OUT_DIR)
|
fileList, totalSize = self.getBuildDirContents(OUT_DIR)
|
||||||
@ -669,9 +664,7 @@ class NSISScript(object):
|
|||||||
delete.append('RMdir "$INSTDIR\\{}"'.format(file_))
|
delete.append('RMdir "$INSTDIR\\{}"'.format(file_))
|
||||||
return "\n".join(delete)
|
return "\n".join(delete)
|
||||||
|
|
||||||
|
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',
|
||||||
'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png',
|
'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png',
|
||||||
'resources/timeline_marker.png','resources/control_play_blue.png',
|
'resources/timeline_marker.png','resources/control_play_blue.png',
|
||||||
@ -693,13 +686,7 @@ guiIcons = [
|
|||||||
'resources/email_go.png',
|
'resources/email_go.png',
|
||||||
'resources/world_add.png', 'resources/film_add.png', 'resources/delete.png', 'resources/spinner.mng'
|
'resources/world_add.png', 'resources/film_add.png', 'resources/delete.png', 'resources/spinner.mng'
|
||||||
]
|
]
|
||||||
resources = [
|
resources = ["resources/icon.ico", "resources/syncplay.png", "resources/syncplayintf.lua", "resources/license.rtf", "resources/third-party-notices.rtf"]
|
||||||
"resources/icon.ico",
|
|
||||||
"resources/syncplay.png",
|
|
||||||
"resources/syncplayintf.lua",
|
|
||||||
"resources/license.rtf",
|
|
||||||
"resources/third-party-notices.rtf"
|
|
||||||
]
|
|
||||||
resources.extend(guiIcons)
|
resources.extend(guiIcons)
|
||||||
intf_resources = ["resources/lua/intf/syncplay.lua"]
|
intf_resources = ["resources/lua/intf/syncplay.lua"]
|
||||||
|
|
||||||
|
|||||||
@ -18,12 +18,7 @@ OPTIONS = {
|
|||||||
'extra_scripts': 'syncplayServer.py',
|
'extra_scripts': 'syncplayServer.py',
|
||||||
'includes': {'PySide2.QtCore', 'PySide2.QtUiTools', 'PySide2.QtGui','PySide2.QtWidgets', 'certifi'},
|
'includes': {'PySide2.QtCore', 'PySide2.QtUiTools', 'PySide2.QtGui','PySide2.QtWidgets', 'certifi'},
|
||||||
'excludes': {'PySide', 'PySide.QtCore', 'PySide.QtUiTools', 'PySide.QtGui'},
|
'excludes': {'PySide', 'PySide.QtCore', 'PySide.QtUiTools', 'PySide.QtGui'},
|
||||||
'qt_plugins': [
|
'qt_plugins': ['platforms/libqcocoa.dylib', 'platforms/libqminimal.dylib','platforms/libqoffscreen.dylib', 'styles/libqmacstyle.dylib'],
|
||||||
'platforms/libqcocoa.dylib',
|
|
||||||
'platforms/libqminimal.dylib',
|
|
||||||
'platforms/libqoffscreen.dylib',
|
|
||||||
'styles/libqmacstyle.dylib'
|
|
||||||
],
|
|
||||||
'plist': {
|
'plist': {
|
||||||
'CFBundleName':'Syncplay',
|
'CFBundleName':'Syncplay',
|
||||||
'CFBundleShortVersionString':syncplay.version,
|
'CFBundleShortVersionString':syncplay.version,
|
||||||
|
|||||||
@ -6,8 +6,7 @@
|
|||||||
#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
|
#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 codecs
|
import sys, codecs
|
||||||
import sys
|
|
||||||
# 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!")
|
||||||
@ -15,26 +14,23 @@ import sys
|
|||||||
# import warnings
|
# import warnings
|
||||||
# warnings.warn("You must build Syncplay with Python 2.7!")
|
# warnings.warn("You must build Syncplay with Python 2.7!")
|
||||||
|
|
||||||
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
from string import Template
|
|
||||||
|
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
try:
|
try:
|
||||||
from py2exe.build_exe import py2exe
|
from py2exe.build_exe import py2exe
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from py2exe.distutils_buildexe import py2exe
|
from py2exe.distutils_buildexe import py2exe
|
||||||
|
from string import Template
|
||||||
|
|
||||||
import syncplay
|
import syncplay
|
||||||
from syncplay.messages import getMissingStrings
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from syncplay.messages import getMissingStrings
|
||||||
missingStrings = getMissingStrings()
|
missingStrings = getMissingStrings()
|
||||||
if missingStrings is not None and missingStrings is not "":
|
if missingStrings is not None and missingStrings is not "":
|
||||||
import warnings
|
import warnings
|
||||||
warnings.warn("MISSING/UNUSED STRINGS DETECTED:\n{}".format(missingStrings))
|
warnings.warn("MISSING/UNUSED STRINGS DETECTED:\n{}".format(missingStrings))
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
@ -48,8 +44,6 @@ def get_nsis_path():
|
|||||||
raise Exception("You must install NSIS 3 or later.")
|
raise Exception("You must install NSIS 3 or later.")
|
||||||
except WindowsError:
|
except WindowsError:
|
||||||
return bin_name
|
return bin_name
|
||||||
|
|
||||||
|
|
||||||
NSIS_COMPILE = get_nsis_path()
|
NSIS_COMPILE = get_nsis_path()
|
||||||
|
|
||||||
OUT_DIR = "syncplay_v{}".format(syncplay.version)
|
OUT_DIR = "syncplay_v{}".format(syncplay.version)
|
||||||
@ -619,7 +613,6 @@ NSIS_SCRIPT_TEMPLATE = r"""
|
|||||||
SectionEnd
|
SectionEnd
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class NSISScript(object):
|
class NSISScript(object):
|
||||||
def create(self):
|
def create(self):
|
||||||
fileList, totalSize = self.getBuildDirContents(OUT_DIR)
|
fileList, totalSize = self.getBuildDirContents(OUT_DIR)
|
||||||
@ -676,7 +669,6 @@ class NSISScript(object):
|
|||||||
delete.append('RMdir "$INSTDIR\\{}"'.format(file_))
|
delete.append('RMdir "$INSTDIR\\{}"'.format(file_))
|
||||||
return "\n".join(delete)
|
return "\n".join(delete)
|
||||||
|
|
||||||
|
|
||||||
class build_installer(py2exe):
|
class build_installer(py2exe):
|
||||||
def run(self):
|
def run(self):
|
||||||
py2exe.run(self)
|
py2exe.run(self)
|
||||||
@ -686,9 +678,7 @@ class build_installer(py2exe):
|
|||||||
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',
|
||||||
'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png',
|
'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png',
|
||||||
'resources/timeline_marker.png','resources/control_play_blue.png',
|
'resources/timeline_marker.png','resources/control_play_blue.png',
|
||||||
@ -710,13 +700,7 @@ guiIcons = [
|
|||||||
'resources/email_go.png',
|
'resources/email_go.png',
|
||||||
'resources/world_add.png', 'resources/film_add.png', 'resources/delete.png', 'resources/spinner.mng'
|
'resources/world_add.png', 'resources/film_add.png', 'resources/delete.png', 'resources/spinner.mng'
|
||||||
]
|
]
|
||||||
resources = [
|
resources = ["resources/icon.ico", "resources/syncplay.png", "resources/syncplayintf.lua", "resources/license.rtf", "resources/third-party-notices.rtf"]
|
||||||
"resources/icon.ico",
|
|
||||||
"resources/syncplay.png",
|
|
||||||
"resources/syncplayintf.lua",
|
|
||||||
"resources/license.rtf",
|
|
||||||
"resources/third-party-notices.rtf"
|
|
||||||
]
|
|
||||||
resources.extend(guiIcons)
|
resources.extend(guiIcons)
|
||||||
intf_resources = ["resources/lua/intf/syncplay.lua"]
|
intf_resources = ["resources/lua/intf/syncplay.lua"]
|
||||||
|
|
||||||
@ -730,16 +714,11 @@ common_info = dict(
|
|||||||
|
|
||||||
info = dict(
|
info = dict(
|
||||||
common_info,
|
common_info,
|
||||||
windows=[{
|
windows=[{"script":"syncplayClient.py", "icon_resources":[(1, "resources\\icon.ico")], 'dest_base': "Syncplay"},],
|
||||||
"script": "syncplayClient.py",
|
|
||||||
"icon_resources": [(1, "resources\\icon.ico")],
|
|
||||||
'dest_base': "Syncplay"},
|
|
||||||
],
|
|
||||||
console=['syncplayServer.py'],
|
console=['syncplayServer.py'],
|
||||||
# *** If you wish to make the Syncplay client use console mode (for --no-gui to work) then comment out the above two lines and uncomment the following line:
|
# *** If you wish to make the Syncplay client use console mode (for --no-gui to work) then comment out the above two lines and uncomment the following line:
|
||||||
# console=['syncplayServer.py', {"script":"syncplayClient.py", "icon_resources":[(1, "resources\\icon.ico")], 'dest_base': "Syncplay"}],
|
# console=['syncplayServer.py', {"script":"syncplayClient.py", "icon_resources":[(1, "resources\\icon.ico")], 'dest_base': "Syncplay"}],
|
||||||
options={
|
options={'py2exe': {
|
||||||
'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, _ssl',
|
'includes': 'twisted, sys, encodings, datetime, os, time, math, PySide, liburl, ast, unicodedata, _ssl',
|
||||||
|
|||||||
@ -1,27 +1,22 @@
|
|||||||
|
|
||||||
import ast
|
|
||||||
import collections
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import os.path
|
import os.path
|
||||||
import random
|
import time
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import ast
|
||||||
|
import random
|
||||||
import threading
|
import threading
|
||||||
import time
|
|
||||||
from copy import deepcopy
|
|
||||||
from functools import wraps
|
|
||||||
|
|
||||||
from twisted.internet.protocol import ClientFactory
|
from twisted.internet.protocol import ClientFactory
|
||||||
from twisted.internet import reactor, task, defer, threads
|
from twisted.internet import reactor, task, defer, threads
|
||||||
|
from functools import wraps
|
||||||
|
from copy import deepcopy
|
||||||
|
from syncplay.protocols import SyncClientProtocol
|
||||||
from syncplay import utils, constants, version
|
from syncplay import utils, constants, version
|
||||||
|
from syncplay.utils import isMacOS
|
||||||
|
from syncplay.messages import getMissingStrings, getMessage
|
||||||
from syncplay.constants import PRIVACY_SENDHASHED_MODE, PRIVACY_DONTSEND_MODE, \
|
from syncplay.constants import PRIVACY_SENDHASHED_MODE, PRIVACY_DONTSEND_MODE, \
|
||||||
PRIVACY_HIDDENFILENAME
|
PRIVACY_HIDDENFILENAME
|
||||||
from syncplay.messages import getMissingStrings, getMessage
|
import collections
|
||||||
from syncplay.protocols import SyncClientProtocol
|
|
||||||
from syncplay.utils import isMacOS
|
|
||||||
|
|
||||||
|
|
||||||
class SyncClientFactory(ClientFactory):
|
class SyncClientFactory(ClientFactory):
|
||||||
def __init__(self, client, retry=constants.RECONNECT_RETRIES):
|
def __init__(self, client, retry=constants.RECONNECT_RETRIES):
|
||||||
self._client = client
|
self._client = client
|
||||||
@ -63,7 +58,6 @@ class SyncClientFactory(ClientFactory):
|
|||||||
def stopRetrying(self):
|
def stopRetrying(self):
|
||||||
self._timesTried = self.retry
|
self._timesTried = self.retry
|
||||||
|
|
||||||
|
|
||||||
class SyncplayClient(object):
|
class SyncplayClient(object):
|
||||||
def __init__(self, playerClass, ui, config):
|
def __init__(self, playerClass, ui, config):
|
||||||
constants.SHOW_OSD = config['showOSD']
|
constants.SHOW_OSD = config['showOSD']
|
||||||
@ -209,19 +203,12 @@ class SyncplayClient(object):
|
|||||||
self._playerPosition = position
|
self._playerPosition = position
|
||||||
self._playerPaused = paused
|
self._playerPaused = paused
|
||||||
currentLength = self.userlist.currentUser.file["duration"] if self.userlist.currentUser.file else 0
|
currentLength = self.userlist.currentUser.file["duration"] if self.userlist.currentUser.file else 0
|
||||||
if (
|
if pauseChange and paused and currentLength > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH\
|
||||||
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 "readiness" in self.serverFeatures and self.serverFeatures["readiness"]:
|
elif pauseChange and "readiness" in self.serverFeatures and self.serverFeatures["readiness"]:
|
||||||
if (
|
if currentLength == 0 or currentLength == -1 or\
|
||||||
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)
|
||||||
|
|
||||||
if self._lastGlobalUpdate:
|
if self._lastGlobalUpdate:
|
||||||
@ -317,7 +304,7 @@ class SyncplayClient(object):
|
|||||||
self.setPosition(self.getGlobalPosition())
|
self.setPosition(self.getGlobalPosition())
|
||||||
self._player.setPaused(True)
|
self._player.setPaused(True)
|
||||||
madeChangeOnPlayer = True
|
madeChangeOnPlayer = True
|
||||||
if (self.lastLeftTime < time.time() - constants.OSD_DURATION) or hideFromOSD:
|
if (self.lastLeftTime < time.time() - constants.OSD_DURATION) or (hideFromOSD == True):
|
||||||
self.ui.showMessage(getMessage("pause-notification").format(setBy), hideFromOSD)
|
self.ui.showMessage(getMessage("pause-notification").format(setBy), hideFromOSD)
|
||||||
else:
|
else:
|
||||||
self.ui.showMessage(getMessage("left-paused-notification").format(self.lastLeftUser, setBy), hideFromOSD)
|
self.ui.showMessage(getMessage("left-paused-notification").format(self.lastLeftUser, setBy), hideFromOSD)
|
||||||
@ -364,9 +351,9 @@ class SyncplayClient(object):
|
|||||||
self._lastGlobalUpdate = time.time()
|
self._lastGlobalUpdate = time.time()
|
||||||
if doSeek:
|
if doSeek:
|
||||||
madeChangeOnPlayer = self._serverSeeked(position, setBy)
|
madeChangeOnPlayer = self._serverSeeked(position, setBy)
|
||||||
if diff > self._config['rewindThreshold'] and not doSeek and self._config['rewindOnDesync']:
|
if diff > self._config['rewindThreshold'] and not doSeek and not self._config['rewindOnDesync'] == False:
|
||||||
madeChangeOnPlayer = self._rewindPlayerDueToTimeDifference(position, setBy)
|
madeChangeOnPlayer = self._rewindPlayerDueToTimeDifference(position, setBy)
|
||||||
if self._config['fastforwardOnDesync'] and (not self.userlist.currentUser.canControl() or self._config['dontSlowDownWithMe']):
|
if self._config['fastforwardOnDesync'] and (self.userlist.currentUser.canControl() == False or self._config['dontSlowDownWithMe'] == True):
|
||||||
if diff < (constants.FASTFORWARD_BEHIND_THRESHOLD * -1) and not doSeek:
|
if diff < (constants.FASTFORWARD_BEHIND_THRESHOLD * -1) and not doSeek:
|
||||||
if self.behindFirstDetected is None:
|
if self.behindFirstDetected is None:
|
||||||
self.behindFirstDetected = time.time()
|
self.behindFirstDetected = time.time()
|
||||||
@ -378,11 +365,11 @@ class SyncplayClient(object):
|
|||||||
self.behindFirstDetected = time.time() + constants.FASTFORWARD_RESET_THRESHOLD
|
self.behindFirstDetected = time.time() + constants.FASTFORWARD_RESET_THRESHOLD
|
||||||
else:
|
else:
|
||||||
self.behindFirstDetected = None
|
self.behindFirstDetected = None
|
||||||
if self._player.speedSupported and not doSeek and not paused and self._config['slowOnDesync']:
|
if self._player.speedSupported and not doSeek and not paused and not self._config['slowOnDesync'] == False:
|
||||||
madeChangeOnPlayer = self._slowDownToCoverTimeDifference(diff, setBy)
|
madeChangeOnPlayer = self._slowDownToCoverTimeDifference(diff, setBy)
|
||||||
if not paused and pauseChanged:
|
if paused == False and pauseChanged:
|
||||||
madeChangeOnPlayer = self._serverUnpaused(setBy)
|
madeChangeOnPlayer = self._serverUnpaused(setBy)
|
||||||
elif paused and pauseChanged:
|
elif paused == True and pauseChanged:
|
||||||
madeChangeOnPlayer = self._serverPaused(setBy)
|
madeChangeOnPlayer = self._serverPaused(setBy)
|
||||||
return madeChangeOnPlayer
|
return madeChangeOnPlayer
|
||||||
|
|
||||||
@ -579,11 +566,11 @@ class SyncplayClient(object):
|
|||||||
constants.MAX_ROOM_NAME_LENGTH = self.serverFeatures["maxRoomNameLength"]
|
constants.MAX_ROOM_NAME_LENGTH = self.serverFeatures["maxRoomNameLength"]
|
||||||
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 = [
|
constants.MPV_SYNCPLAYINTF_CONSTANTS_TO_SEND = ["MaxChatMessageLength={}".format(constants.MAX_CHAT_MESSAGE_LENGTH),
|
||||||
"MaxChatMessageLength={}".format(constants.MAX_CHAT_MESSAGE_LENGTH),
|
|
||||||
"inputPromptStartCharacter={}".format(constants.MPV_INPUT_PROMPT_START_CHARACTER),
|
"inputPromptStartCharacter={}".format(constants.MPV_INPUT_PROMPT_START_CHARACTER),
|
||||||
"inputPromptEndCharacter={}".format(constants.MPV_INPUT_PROMPT_END_CHARACTER),
|
"inputPromptEndCharacter={}".format(constants.MPV_INPUT_PROMPT_END_CHARACTER),
|
||||||
"backslashSubstituteCharacter={}".format(constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER)]
|
"backslashSubstituteCharacter={}".format(
|
||||||
|
constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER)]
|
||||||
self.ui.setFeatures(self.serverFeatures)
|
self.ui.setFeatures(self.serverFeatures)
|
||||||
if self._player:
|
if self._player:
|
||||||
self._player.setFeatures(self.serverFeatures)
|
self._player.setFeatures(self.serverFeatures)
|
||||||
@ -599,6 +586,7 @@ class SyncplayClient(object):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def sendFile(self):
|
def sendFile(self):
|
||||||
file_ = self.getSanitizedCurrentUserFile()
|
file_ = self.getSanitizedCurrentUserFile()
|
||||||
if self._protocol and self._protocol.logged and file_:
|
if self._protocol and self._protocol.logged and file_:
|
||||||
@ -774,7 +762,7 @@ class SyncplayClient(object):
|
|||||||
from syncplay.ui.ConfigurationGetter import ConfigurationGetter
|
from syncplay.ui.ConfigurationGetter import ConfigurationGetter
|
||||||
ConfigurationGetter().setConfigOption("sharedPlaylistEnabled", newState)
|
ConfigurationGetter().setConfigOption("sharedPlaylistEnabled", newState)
|
||||||
self._config["sharedPlaylistEnabled"] = newState
|
self._config["sharedPlaylistEnabled"] = newState
|
||||||
if not oldState and newState:
|
if oldState == False and newState == True:
|
||||||
self.playlist.loadCurrentPlaylistIndex()
|
self.playlist.loadCurrentPlaylistIndex()
|
||||||
|
|
||||||
def changeAutoplayState(self, newState):
|
def changeAutoplayState(self, newState):
|
||||||
@ -785,7 +773,7 @@ class SyncplayClient(object):
|
|||||||
oldAutoplayConditionsMet = self.autoplayConditionsMet()
|
oldAutoplayConditionsMet = self.autoplayConditionsMet()
|
||||||
self.autoPlayThreshold = newThreshold
|
self.autoPlayThreshold = newThreshold
|
||||||
newAutoplayConditionsMet = self.autoplayConditionsMet()
|
newAutoplayConditionsMet = self.autoplayConditionsMet()
|
||||||
if not oldAutoplayConditionsMet and newAutoplayConditionsMet:
|
if oldAutoplayConditionsMet == False and newAutoplayConditionsMet == True:
|
||||||
self.autoplayCheck()
|
self.autoplayCheck()
|
||||||
|
|
||||||
def autoplayCheck(self):
|
def autoplayCheck(self):
|
||||||
@ -811,12 +799,9 @@ class SyncplayClient(object):
|
|||||||
|
|
||||||
def autoplayConditionsMet(self):
|
def autoplayConditionsMet(self):
|
||||||
recentlyReset = (self.lastRewindTime is not None and abs(time.time() - self.lastRewindTime) < 10) and self._playerPosition < 3
|
recentlyReset = (self.lastRewindTime is not None and abs(time.time() - self.lastRewindTime) < 10) and self._playerPosition < 3
|
||||||
return (
|
return self._playerPaused and (self.autoPlay or recentlyReset) and self.userlist.currentUser.canControl() and self.userlist.isReadinessSupported()\
|
||||||
self._playerPaused and (self.autoPlay or recentlyReset) and
|
and self.userlist.areAllUsersInRoomReady(requireSameFilenames=self._config["autoplayRequireSameFilenames"])\
|
||||||
self.userlist.currentUser.canControl() and self.userlist.isReadinessSupported()
|
|
||||||
and self.userlist.areAllUsersInRoomReady(requireSameFilenames=self._config["autoplayRequireSameFilenames"])
|
|
||||||
and ((self.autoPlayThreshold and self.userlist.usersInRoomCount() >= self.autoPlayThreshold) or recentlyReset)
|
and ((self.autoPlayThreshold and self.userlist.usersInRoomCount() >= self.autoPlayThreshold) or recentlyReset)
|
||||||
)
|
|
||||||
|
|
||||||
def autoplayTimerIsRunning(self):
|
def autoplayTimerIsRunning(self):
|
||||||
return self.autoplayTimer.running
|
return self.autoplayTimer.running
|
||||||
@ -1064,7 +1049,6 @@ class SyncplayClient(object):
|
|||||||
elif not self._userlist.currentUser.isReady(): # CurrentUser should always be reminded they are set to not ready
|
elif not self._userlist.currentUser.isReady(): # CurrentUser should always be reminded they are set to not ready
|
||||||
self.checkReadyStates()
|
self.checkReadyStates()
|
||||||
|
|
||||||
|
|
||||||
class SyncplayUser(object):
|
class SyncplayUser(object):
|
||||||
def __init__(self, username=None, room=None, file_=None):
|
def __init__(self, username=None, room=None, file_=None):
|
||||||
self.ready = None
|
self.ready = None
|
||||||
@ -1129,7 +1113,6 @@ class SyncplayUser(object):
|
|||||||
def setFeatures(self, features):
|
def setFeatures(self, features):
|
||||||
self._features = features
|
self._features = features
|
||||||
|
|
||||||
|
|
||||||
class SyncplayUserlist(object):
|
class SyncplayUserlist(object):
|
||||||
def __init__(self, ui, client):
|
def __init__(self, ui, client):
|
||||||
self.currentUser = SyncplayUser()
|
self.currentUser = SyncplayUser()
|
||||||
@ -1158,7 +1141,7 @@ class SyncplayUserlist(object):
|
|||||||
showOnOSD = constants.SHOW_OSD_WARNINGS
|
showOnOSD = constants.SHOW_OSD_WARNINGS
|
||||||
else:
|
else:
|
||||||
showOnOSD = constants.SHOW_DIFFERENT_ROOM_OSD
|
showOnOSD = constants.SHOW_DIFFERENT_ROOM_OSD
|
||||||
if constants.SHOW_NONCONTROLLER_OSD == False and not self.canControl(username):
|
if constants.SHOW_NONCONTROLLER_OSD == False and self.canControl(username) == False:
|
||||||
showOnOSD = False
|
showOnOSD = False
|
||||||
hideFromOSD = not showOnOSD
|
hideFromOSD = not showOnOSD
|
||||||
if not file_:
|
if not file_:
|
||||||
@ -1275,16 +1258,12 @@ class SyncplayUserlist(object):
|
|||||||
return False
|
return False
|
||||||
for user in self._users.values():
|
for user in self._users.values():
|
||||||
if user.room == self.currentUser.room:
|
if user.room == self.currentUser.room:
|
||||||
if not user.isReadyWithFile() == False:
|
if user.isReadyWithFile() == False:
|
||||||
return False
|
return False
|
||||||
elif (
|
elif requireSameFilenames and\
|
||||||
requireSameFilenames and
|
(self.currentUser.file is None
|
||||||
(
|
|
||||||
self.currentUser.file is None
|
|
||||||
or user.file is None
|
or user.file is None
|
||||||
or not utils.sameFilename(self.currentUser.file['name'], user.file['name'])
|
or not utils.sameFilename(self.currentUser.file['name'], user.file['name'])):
|
||||||
)
|
|
||||||
):
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -1415,7 +1394,6 @@ class SyncplayUserlist(object):
|
|||||||
rooms = collections.OrderedDict(sorted(list(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):
|
||||||
def __init__(self, client, ui):
|
def __init__(self, client, ui):
|
||||||
self._client = client
|
self._client = client
|
||||||
@ -1451,8 +1429,7 @@ class UiManager(object):
|
|||||||
self.__ui.showMessage(messageString)
|
self.__ui.showMessage(messageString)
|
||||||
|
|
||||||
def showMessage(self, message, noPlayer=False, noTimestamp=False, OSDType=constants.OSD_NOTIFICATION,mood=constants.MESSAGE_NEUTRAL):
|
def showMessage(self, message, noPlayer=False, noTimestamp=False, OSDType=constants.OSD_NOTIFICATION,mood=constants.MESSAGE_NEUTRAL):
|
||||||
if not noPlayer:
|
if not noPlayer: self.showOSDMessage(message, duration=constants.OSD_DURATION, OSDType=OSDType, mood=mood)
|
||||||
self.showOSDMessage(message, duration=constants.OSD_DURATION, OSDType=OSDType, mood=mood)
|
|
||||||
self.__ui.showMessage(message, noTimestamp)
|
self.__ui.showMessage(message, noTimestamp)
|
||||||
|
|
||||||
def updateAutoPlayState(self, newState):
|
def updateAutoPlayState(self, newState):
|
||||||
@ -1510,7 +1487,6 @@ class UiManager(object):
|
|||||||
def drop(self):
|
def drop(self):
|
||||||
self.__ui.drop()
|
self.__ui.drop()
|
||||||
|
|
||||||
|
|
||||||
class SyncplayPlaylist():
|
class SyncplayPlaylist():
|
||||||
def __init__(self, client):
|
def __init__(self, client):
|
||||||
self._client = client
|
self._client = client
|
||||||
@ -1710,11 +1686,9 @@ class SyncplayPlaylist():
|
|||||||
def advancePlaylistCheck(self):
|
def advancePlaylistCheck(self):
|
||||||
position = self._client.getStoredPlayerPosition()
|
position = self._client.getStoredPlayerPosition()
|
||||||
currentLength = self._client.userlist.currentUser.file["duration"] if self._client.userlist.currentUser.file else 0
|
currentLength = self._client.userlist.currentUser.file["duration"] if self._client.userlist.currentUser.file else 0
|
||||||
if (
|
if currentLength > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH\
|
||||||
currentLength > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH and
|
and abs(position - currentLength ) < constants.PLAYLIST_LOAD_NEXT_FILE_TIME_FROM_END_THRESHOLD\
|
||||||
abs(position - currentLength) < constants.PLAYLIST_LOAD_NEXT_FILE_TIME_FROM_END_THRESHOLD and
|
and self.notJustChangedPlaylist():
|
||||||
self.notJustChangedPlaylist()
|
|
||||||
):
|
|
||||||
self.loadNextFileInPlaylist()
|
self.loadNextFileInPlaylist()
|
||||||
|
|
||||||
def notJustChangedPlaylist(self):
|
def notJustChangedPlaylist(self):
|
||||||
@ -1785,7 +1759,6 @@ class SyncplayPlaylist():
|
|||||||
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):
|
||||||
self._client = client
|
self._client = client
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
|
from syncplay.ui.ConfigurationGetter import ConfigurationGetter
|
||||||
from syncplay import ui
|
from syncplay import ui
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
from syncplay.ui.ConfigurationGetter import ConfigurationGetter
|
|
||||||
|
|
||||||
|
|
||||||
class SyncplayClientManager(object):
|
class SyncplayClientManager(object):
|
||||||
def run(self):
|
def run(self):
|
||||||
@ -15,3 +13,4 @@ class SyncplayClientManager(object):
|
|||||||
syncplayClient.start(config['host'], config['port'])
|
syncplayClient.start(config['host'], config['port'])
|
||||||
else:
|
else:
|
||||||
interface.showErrorMessage(getMessage("unable-to-start-client-error"), True)
|
interface.showErrorMessage(getMessage("unable-to-start-client-error"), True)
|
||||||
|
|
||||||
|
|||||||
@ -16,12 +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 = [
|
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']]
|
||||||
['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)
|
||||||
|
|
||||||
@ -205,11 +200,7 @@ MPV_SYNCPLAYINTF_OPTIONS_TO_SEND = ["chatInputEnabled", "chatInputFontFamily", "
|
|||||||
"chatTopMargin","chatLeftMargin","chatBottomMargin","chatDirectInput",
|
"chatTopMargin","chatLeftMargin","chatBottomMargin","chatDirectInput",
|
||||||
"notificationTimeout","alertTimeout","chatTimeout","chatOutputEnabled"]
|
"notificationTimeout","alertTimeout","chatTimeout","chatOutputEnabled"]
|
||||||
|
|
||||||
MPV_SYNCPLAYINTF_CONSTANTS_TO_SEND = [
|
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)]
|
||||||
"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',
|
||||||
|
|||||||
@ -14,7 +14,6 @@ messages = {
|
|||||||
"CURRENT": None
|
"CURRENT": None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def getLanguages():
|
def getLanguages():
|
||||||
langList = {}
|
langList = {}
|
||||||
for lang in messages:
|
for lang in messages:
|
||||||
@ -22,11 +21,9 @@ def getLanguages():
|
|||||||
langList[lang] = getMessage("LANGUAGE", lang)
|
langList[lang] = getMessage("LANGUAGE", lang)
|
||||||
return langList
|
return langList
|
||||||
|
|
||||||
|
|
||||||
def setLanguage(lang):
|
def setLanguage(lang):
|
||||||
messages["CURRENT"] = lang
|
messages["CURRENT"] = lang
|
||||||
|
|
||||||
|
|
||||||
def getMissingStrings():
|
def getMissingStrings():
|
||||||
missingStrings = ""
|
missingStrings = ""
|
||||||
for lang in messages:
|
for lang in messages:
|
||||||
@ -40,7 +37,6 @@ def getMissingStrings():
|
|||||||
|
|
||||||
return missingStrings
|
return missingStrings
|
||||||
|
|
||||||
|
|
||||||
def getInitialLanguage():
|
def getInitialLanguage():
|
||||||
import locale
|
import locale
|
||||||
try:
|
try:
|
||||||
@ -51,11 +47,9 @@ def getInitialLanguage():
|
|||||||
initialLanguage = constants.FALLBACK_INITIAL_LANGUAGE
|
initialLanguage = constants.FALLBACK_INITIAL_LANGUAGE
|
||||||
return initialLanguage
|
return initialLanguage
|
||||||
|
|
||||||
|
|
||||||
def isValidLanguage(language):
|
def isValidLanguage(language):
|
||||||
return language in messages
|
return language in messages
|
||||||
|
|
||||||
|
|
||||||
def getMessage(type_, locale=None):
|
def getMessage(type_, locale=None):
|
||||||
if constants.SHOW_TOOLTIPS == False:
|
if constants.SHOW_TOOLTIPS == False:
|
||||||
if "-tooltip" in type_:
|
if "-tooltip" in type_:
|
||||||
|
|||||||
@ -12,6 +12,5 @@ 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]
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
from syncplay import constants
|
from syncplay import constants
|
||||||
|
|
||||||
|
|
||||||
class BasePlayer(object):
|
class BasePlayer(object):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -14,9 +12,7 @@ class BasePlayer(object):
|
|||||||
'''
|
'''
|
||||||
Display given message on player's OSD or similar means
|
Display given message on player's OSD or similar means
|
||||||
'''
|
'''
|
||||||
def displayMessage(
|
def displayMessage(self, message, duration = (constants.OSD_DURATION*1000), secondaryOSD=False, mood=constants.MESSAGE_NEUTRAL):
|
||||||
self, message, duration=(constants.OSD_DURATION*1000), secondaryOSD=False, mood=constants.MESSAGE_NEUTRAL
|
|
||||||
):
|
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -62,6 +58,7 @@ class BasePlayer(object):
|
|||||||
def openFile(self, filePath, resetPosition=False):
|
def openFile(self, filePath, resetPosition=False):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@return: list of strings
|
@return: list of strings
|
||||||
'''
|
'''
|
||||||
@ -110,7 +107,6 @@ class BasePlayer(object):
|
|||||||
def getPlayerPathErrors(playerPath, filePath):
|
def getPlayerPathErrors(playerPath, filePath):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class DummyPlayer(BasePlayer):
|
class DummyPlayer(BasePlayer):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@ -1,18 +1,15 @@
|
|||||||
|
#coding:utf8
|
||||||
import os.path
|
|
||||||
import re
|
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
import _thread
|
import _thread
|
||||||
from functools import wraps
|
|
||||||
|
|
||||||
import win32con, win32api, win32gui, ctypes, ctypes.wintypes #@UnresolvedImport @UnusedImport
|
import win32con, win32api, win32gui, ctypes, ctypes.wintypes #@UnresolvedImport @UnusedImport
|
||||||
|
from functools import wraps
|
||||||
|
from syncplay.players.basePlayer import BasePlayer
|
||||||
|
import re
|
||||||
|
from syncplay.utils import retry
|
||||||
from syncplay import constants
|
from syncplay import constants
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
from syncplay.players.basePlayer import BasePlayer
|
import os.path
|
||||||
from syncplay.utils import retry
|
|
||||||
|
|
||||||
|
|
||||||
class MpcHcApi:
|
class MpcHcApi:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -52,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 is not 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)
|
||||||
@ -106,11 +103,7 @@ class MpcHcApi:
|
|||||||
|
|
||||||
elif cmd == self.CMD_STATE:
|
elif cmd == self.CMD_STATE:
|
||||||
self.loadState = int(value)
|
self.loadState = int(value)
|
||||||
fileNotReady = (
|
fileNotReady = self.loadState == self.__MPC_LOADSTATE.MLS_CLOSING or self.loadState == self.__MPC_LOADSTATE.MLS_LOADING or self.loadState == self.__MPC_LOADSTATE.MLS_CLOSED
|
||||||
self.loadState == self.__MPC_LOADSTATE.MLS_CLOSING or
|
|
||||||
self.loadState == self.__MPC_LOADSTATE.MLS_LOADING or
|
|
||||||
self.loadState == self.__MPC_LOADSTATE.MLS_CLOSED
|
|
||||||
)
|
|
||||||
if fileNotReady:
|
if fileNotReady:
|
||||||
self.playState = None
|
self.playState = None
|
||||||
self.__locks.fileReady.clear()
|
self.__locks.fileReady.clear()
|
||||||
@ -279,6 +272,7 @@ class MpcHcApi:
|
|||||||
self.locks.listenerStart.set()
|
self.locks.listenerStart.set()
|
||||||
win32gui.PumpMessages()
|
win32gui.PumpMessages()
|
||||||
|
|
||||||
|
|
||||||
def OnCopyData(self, hwnd, msg, wparam, lparam):
|
def OnCopyData(self, hwnd, msg, wparam, lparam):
|
||||||
pCDS = ctypes.cast(lparam, self.__PCOPYDATASTRUCT)
|
pCDS = ctypes.cast(lparam, self.__PCOPYDATASTRUCT)
|
||||||
#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)
|
||||||
@ -310,7 +304,6 @@ class MpcHcApi:
|
|||||||
('lpData', ctypes.c_void_p)
|
('lpData', ctypes.c_void_p)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class MPCHCAPIPlayer(BasePlayer):
|
class MPCHCAPIPlayer(BasePlayer):
|
||||||
speedSupported = False
|
speedSupported = False
|
||||||
alertOSDSupported = False
|
alertOSDSupported = False
|
||||||
@ -407,10 +400,7 @@ class MPCHCAPIPlayer(BasePlayer):
|
|||||||
def openFile(self, filePath, resetPosition=False):
|
def openFile(self, filePath, resetPosition=False):
|
||||||
self._mpcApi.openFile(filePath)
|
self._mpcApi.openFile(filePath)
|
||||||
|
|
||||||
def displayMessage(
|
def displayMessage(self, message, duration = (constants.OSD_DURATION*1000), OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL):
|
||||||
self, message,
|
|
||||||
duration=(constants.OSD_DURATION*1000), OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL
|
|
||||||
):
|
|
||||||
self._mpcApi.sendOsd(message, constants.MPC_OSD_POSITION, duration)
|
self._mpcApi.sendOsd(message, constants.MPC_OSD_POSITION, duration)
|
||||||
|
|
||||||
@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)
|
||||||
@ -422,7 +412,6 @@ class MPCHCAPIPlayer(BasePlayer):
|
|||||||
self._mpcApi.pause()
|
self._mpcApi.pause()
|
||||||
else:
|
else:
|
||||||
self._mpcApi.unpause()
|
self._mpcApi.unpause()
|
||||||
|
|
||||||
def setFeatures(self, featureList):
|
def setFeatures(self, featureList):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -493,10 +482,7 @@ class MPCHCAPIPlayer(BasePlayer):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getIconPath(path):
|
def getIconPath(path):
|
||||||
if (
|
if MPCHCAPIPlayer.getExpandedPath(path).lower().endswith('mpc-hc64.exe'.lower()) or MPCHCAPIPlayer.getExpandedPath(path).lower().endswith('mpc-hc64_nvo.exe'.lower()):
|
||||||
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
|
||||||
@ -510,11 +496,7 @@ class MPCHCAPIPlayer(BasePlayer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def getExpandedPath(path):
|
def getExpandedPath(path):
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
if (
|
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()):
|
||||||
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 + "mpc-hc.exe"):
|
if os.path.isfile(path + "mpc-hc.exe"):
|
||||||
path += "mpc-hc.exe"
|
path += "mpc-hc.exe"
|
||||||
@ -546,3 +528,4 @@ class MPCHCAPIPlayer(BasePlayer):
|
|||||||
if os.path.isfile(path + "\\mpc-hc64_nvo.exe"):
|
if os.path.isfile(path + "\\mpc-hc64_nvo.exe"):
|
||||||
path += "\\mpc-hc64_nvo.exe"
|
path += "\\mpc-hc64_nvo.exe"
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,8 @@
|
|||||||
|
|
||||||
import os.path
|
|
||||||
|
|
||||||
from syncplay import constants
|
from syncplay import constants
|
||||||
|
import os.path
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
from syncplay.players.mpc import MPCHCAPIPlayer
|
from syncplay.players.mpc import MPCHCAPIPlayer
|
||||||
|
|
||||||
|
|
||||||
class MpcBePlayer(MPCHCAPIPlayer):
|
class MpcBePlayer(MPCHCAPIPlayer):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(client, playerPath, filePath, args):
|
def run(client, playerPath, filePath, args):
|
||||||
@ -33,11 +30,7 @@ class MpcBePlayer(MPCHCAPIPlayer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def getExpandedPath(path):
|
def getExpandedPath(path):
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
if (
|
if path.lower().endswith('mpc-be.exe'.lower()) or path.lower().endswith('mpc-be64.exe'.lower() or path.lower().endswith('mpc-beportable.exe'.lower())):
|
||||||
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 + "mpc-be.exe"):
|
if os.path.isfile(path + "mpc-be.exe"):
|
||||||
path += "mpc-be.exe"
|
path += "mpc-be.exe"
|
||||||
|
|||||||
@ -1,18 +1,14 @@
|
|||||||
# coding:utf8
|
# coding:utf8
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import re
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
from syncplay import constants, utils
|
|
||||||
from syncplay.players.basePlayer import BasePlayer
|
from syncplay.players.basePlayer import BasePlayer
|
||||||
|
from syncplay import constants, utils
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
|
import os, sys
|
||||||
from syncplay.utils import isWindows
|
from syncplay.utils import isWindows
|
||||||
|
|
||||||
|
|
||||||
class MplayerPlayer(BasePlayer):
|
class MplayerPlayer(BasePlayer):
|
||||||
speedSupported = True
|
speedSupported = True
|
||||||
customOpenDialog = False
|
customOpenDialog = False
|
||||||
@ -94,20 +90,15 @@ class MplayerPlayer(BasePlayer):
|
|||||||
def _getProperty(self, property_):
|
def _getProperty(self, property_):
|
||||||
self._listener.sendLine("get_property {}".format(property_))
|
self._listener.sendLine("get_property {}".format(property_))
|
||||||
|
|
||||||
def displayMessage(
|
def displayMessage(self, message, duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL):
|
||||||
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('{} "{!s}" {} {}'.format(
|
self._listener.sendLine('{} "{!s}" {} {}'.format(self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL))
|
||||||
self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL))
|
|
||||||
|
|
||||||
def displayChatMessage(self, username, message):
|
def displayChatMessage(self, username, message):
|
||||||
messageString = "<{}> {}".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('{} "{!s}" {} {}'.format(
|
self._listener.sendLine('{} "{!s}" {} {}'.format(self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL))
|
||||||
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))
|
||||||
@ -190,13 +181,7 @@ class MplayerPlayer(BasePlayer):
|
|||||||
line = line.replace("[term-msg] ", "") # -v workaround
|
line = line.replace("[term-msg] ", "") # -v workaround
|
||||||
line = line.replace(" cplayer: ","") # --msg-module workaround
|
line = line.replace(" cplayer: ","") # --msg-module workaround
|
||||||
line = line.replace(" term-msg: ", "")
|
line = line.replace(" term-msg: ", "")
|
||||||
if (
|
if "Failed to get value of property" in line or "=(unavailable)" in line or line == "ANS_filename=" or line == "ANS_length=" or line == "ANS_path=":
|
||||||
"Failed to get value of property" in line or
|
|
||||||
"=(unavailable)" in line or
|
|
||||||
line == "ANS_filename=" or
|
|
||||||
line == "ANS_length=" or
|
|
||||||
line == "ANS_path="
|
|
||||||
):
|
|
||||||
if "filename" in line:
|
if "filename" in line:
|
||||||
self._getFilename()
|
self._getFilename()
|
||||||
elif "length" in line:
|
elif "length" in line:
|
||||||
@ -265,7 +250,7 @@ class MplayerPlayer(BasePlayer):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isValidPlayerPath(path):
|
def isValidPlayerPath(path):
|
||||||
if "mplayer" in path and MplayerPlayer.getExpandedPath(path) and "mplayerc.exe" not in path: # "mplayerc.exe" is Media Player Classic (not Home Cinema):
|
if "mplayer" in path and MplayerPlayer.getExpandedPath(path) and not "mplayerc.exe" in path: # "mplayerc.exe" is Media Player Classic (not Home Cinema):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -339,15 +324,12 @@ 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(
|
self.__process = subprocess.Popen(call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.__getCwd(filePath, env), env=env, bufsize=0)
|
||||||
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(
|
self.__process = subprocess.Popen(call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, env=env, bufsize=0)
|
||||||
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")
|
||||||
|
|
||||||
|
|
||||||
def __getCwd(self, filePath, env):
|
def __getCwd(self, filePath, env):
|
||||||
if not filePath:
|
if not filePath:
|
||||||
return None
|
return None
|
||||||
@ -383,8 +365,8 @@ class MplayerPlayer(BasePlayer):
|
|||||||
if command and command[:1] == "/":
|
if command and command[:1] == "/":
|
||||||
message = message[1:]
|
message = message[1:]
|
||||||
else:
|
else:
|
||||||
self.__playerController.reactor.callFromThread(
|
self.__playerController.reactor.callFromThread(self.__playerController._client.ui.executeCommand,
|
||||||
self.__playerController._client.ui.executeCommand, command)
|
command)
|
||||||
return
|
return
|
||||||
self.__playerController.reactor.callFromThread(self.__playerController._client.sendChat, message)
|
self.__playerController.reactor.callFromThread(self.__playerController._client.sendChat, message)
|
||||||
|
|
||||||
@ -396,11 +378,11 @@ class MplayerPlayer(BasePlayer):
|
|||||||
oldState = self.readyToSend
|
oldState = self.readyToSend
|
||||||
self.readyToSend = newReadyState
|
self.readyToSend = newReadyState
|
||||||
self.lastNotReadyTime = time.time() if newReadyState == False else None
|
self.lastNotReadyTime = time.time() if newReadyState == False else None
|
||||||
if self.readyToSend:
|
if self.readyToSend == True:
|
||||||
self.__playerController._client.ui.showDebugMessage("<mpv> Ready to send: True")
|
self.__playerController._client.ui.showDebugMessage("<mpv> Ready to send: True")
|
||||||
else:
|
else:
|
||||||
self.__playerController._client.ui.showDebugMessage("<mpv> Ready to send: False")
|
self.__playerController._client.ui.showDebugMessage("<mpv> Ready to send: False")
|
||||||
if self.readyToSend and oldState == False:
|
if self.readyToSend == True and oldState == False:
|
||||||
self.processSendQueue()
|
self.processSendQueue()
|
||||||
|
|
||||||
def checkForReadinessOverride(self):
|
def checkForReadinessOverride(self):
|
||||||
@ -409,7 +391,7 @@ class MplayerPlayer(BasePlayer):
|
|||||||
|
|
||||||
def sendLine(self, line, notReadyAfterThis=None):
|
def sendLine(self, line, notReadyAfterThis=None):
|
||||||
self.checkForReadinessOverride()
|
self.checkForReadinessOverride()
|
||||||
if not self.readyToSend and "print_text ANS_pause" in line:
|
if self.readyToSend == False and "print_text ANS_pause" in line:
|
||||||
self.__playerController._client.ui.showDebugMessage("<mpv> Not ready to get status update, so skipping")
|
self.__playerController._client.ui.showDebugMessage("<mpv> Not ready to get status update, so skipping")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -419,13 +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(
|
self.__playerController._client.ui.showDebugMessage("<mpv> Remove duplicate (supersede): {}".format(self.sendQueue[itemID]))
|
||||||
"<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(
|
self.__playerController._client.ui.showDebugMessage("<mpv> Unicode mismatch occured when trying to remove duplicate")
|
||||||
"<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
|
||||||
@ -435,8 +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(
|
self.__playerController._client.ui.showDebugMessage("<mpv> Remove duplicate (delete both): {}".format(self.sendQueue[itemID]))
|
||||||
"<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:
|
||||||
@ -449,9 +428,7 @@ class MplayerPlayer(BasePlayer):
|
|||||||
def processSendQueue(self):
|
def processSendQueue(self):
|
||||||
while self.sendQueue and self.readyToSend:
|
while self.sendQueue and self.readyToSend:
|
||||||
if self.lastSendTime and time.time() - self.lastSendTime < constants.MPV_SENDMESSAGE_COOLDOWN_TIME:
|
if self.lastSendTime and time.time() - self.lastSendTime < constants.MPV_SENDMESSAGE_COOLDOWN_TIME:
|
||||||
self.__playerController._client.ui.showDebugMessage(
|
self.__playerController._client.ui.showDebugMessage("<mpv> Throttling message send, so sleeping for {}".format(constants.MPV_SENDMESSAGE_COOLDOWN_TIME))
|
||||||
"<mpv> Throttling message send, so sleeping for {}".format(
|
|
||||||
constants.MPV_SENDMESSAGE_COOLDOWN_TIME))
|
|
||||||
time.sleep(constants.MPV_SENDMESSAGE_COOLDOWN_TIME)
|
time.sleep(constants.MPV_SENDMESSAGE_COOLDOWN_TIME)
|
||||||
try:
|
try:
|
||||||
lineToSend = self.sendQueue.pop()
|
lineToSend = self.sendQueue.pop()
|
||||||
|
|||||||
@ -1,18 +1,14 @@
|
|||||||
# coding:utf8
|
# coding:utf8
|
||||||
import os
|
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from syncplay import constants
|
|
||||||
from syncplay.players.mplayer import MplayerPlayer
|
from syncplay.players.mplayer import MplayerPlayer
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
|
from syncplay import constants
|
||||||
from syncplay.utils import isURL, findResourcePath
|
from syncplay.utils import isURL, findResourcePath
|
||||||
|
import os, sys, time
|
||||||
|
|
||||||
class MpvPlayer(MplayerPlayer):
|
class MpvPlayer(MplayerPlayer):
|
||||||
RE_VERSION = re.compile(r'.*mpv (\d+)\.(\d+)\.\d+.*')
|
RE_VERSION = re.compile('.*mpv (\d+)\.(\d+)\.\d+.*')
|
||||||
osdMessageSeparator = "\\n"
|
osdMessageSeparator = "\\n"
|
||||||
osdMessageSeparator = "; " # TODO: Make conditional
|
osdMessageSeparator = "; " # TODO: Make conditional
|
||||||
|
|
||||||
@ -25,9 +21,7 @@ class MpvPlayer(MplayerPlayer):
|
|||||||
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(
|
client.ui.showDebugMessage("This version of mpv is not known to be compatible with changing the OSC visibility. Please use mpv >=0.28.0.")
|
||||||
"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:
|
||||||
@ -83,7 +77,6 @@ class MpvPlayer(MplayerPlayer):
|
|||||||
def getPlayerPathErrors(playerPath, filePath):
|
def getPlayerPathErrors(playerPath, filePath):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class OldMpvPlayer(MpvPlayer):
|
class OldMpvPlayer(MpvPlayer):
|
||||||
POSITION_QUERY = 'time-pos'
|
POSITION_QUERY = 'time-pos'
|
||||||
OSD_QUERY = 'show_text'
|
OSD_QUERY = 'show_text'
|
||||||
@ -118,7 +111,6 @@ class OldMpvPlayer(MpvPlayer):
|
|||||||
self.setPaused(self._client.getGlobalPaused())
|
self.setPaused(self._client.getGlobalPaused())
|
||||||
self.setPosition(self._client.getGlobalPosition())
|
self.setPosition(self._client.getGlobalPosition())
|
||||||
|
|
||||||
|
|
||||||
class NewMpvPlayer(OldMpvPlayer):
|
class NewMpvPlayer(OldMpvPlayer):
|
||||||
lastResetTime = None
|
lastResetTime = None
|
||||||
lastMPVPositionUpdate = None
|
lastMPVPositionUpdate = None
|
||||||
@ -130,15 +122,14 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
if not self._client._config["chatOutputEnabled"]:
|
if not self._client._config["chatOutputEnabled"]:
|
||||||
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(
|
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace("\\\\",constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER).replace("<NEWLINE>", "\\n")
|
||||||
"\\\\", constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER).replace("<NEWLINE>", "\\n")
|
|
||||||
self._listener.sendLine('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"]:
|
||||||
super(self.__class__, self).displayChatMessage(username,message)
|
super(self.__class__, self).displayChatMessage(username,message)
|
||||||
return
|
return
|
||||||
username = self._sanitizeText(username.replace("\\", sconstants.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 = "<{}> {}".format(username, message)
|
messageString = "<{}> {}".format(username, message)
|
||||||
self._listener.sendLine('script-message-to syncplayintf chat "{}"'.format(messageString))
|
self._listener.sendLine('script-message-to syncplayintf chat "{}"'.format(messageString))
|
||||||
@ -164,34 +155,25 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
self._listener.sendLine("print_text ""ANS_{}=${{{}}}""".format(property_, propertyID))
|
self._listener.sendLine("print_text ""ANS_{}=${{{}}}""".format(property_, propertyID))
|
||||||
|
|
||||||
def getCalculatedPosition(self):
|
def getCalculatedPosition(self):
|
||||||
if not self.fileLoaded:
|
if self.fileLoaded == False:
|
||||||
self._client.ui.showDebugMessage(
|
self._client.ui.showDebugMessage("File not loaded so using GlobalPosition for getCalculatedPosition({})".format(self._client.getGlobalPosition()))
|
||||||
"File not loaded so using GlobalPosition for getCalculatedPosition({})".format(
|
|
||||||
self._client.getGlobalPosition()))
|
|
||||||
return self._client.getGlobalPosition()
|
return self._client.getGlobalPosition()
|
||||||
|
|
||||||
if self.lastMPVPositionUpdate is None:
|
if self.lastMPVPositionUpdate is None:
|
||||||
self._client.ui.showDebugMessage(
|
self._client.ui.showDebugMessage("MPV not updated position so using GlobalPosition for getCalculatedPosition ({})".format(self._client.getGlobalPosition()))
|
||||||
"MPV not updated position so using GlobalPosition for getCalculatedPosition ({})".format(
|
|
||||||
self._client.getGlobalPosition()))
|
|
||||||
return self._client.getGlobalPosition()
|
return self._client.getGlobalPosition()
|
||||||
|
|
||||||
if self._recentlyReset():
|
if self._recentlyReset():
|
||||||
self._client.ui.showDebugMessage(
|
self._client.ui.showDebugMessage("Recently reset so using self.position for getCalculatedPosition ({})".format(self._position))
|
||||||
"Recently reset so using self.position for getCalculatedPosition ({})".format(
|
|
||||||
self._position))
|
|
||||||
return self._position
|
return self._position
|
||||||
|
|
||||||
diff = time.time() - self.lastMPVPositionUpdate
|
diff = time.time() - self.lastMPVPositionUpdate
|
||||||
|
|
||||||
if diff > constants.MPV_UNRESPONSIVE_THRESHOLD:
|
if diff > constants.MPV_UNRESPONSIVE_THRESHOLD:
|
||||||
self.reactor.callFromThread(
|
self.reactor.callFromThread(self._client.ui.showErrorMessage, getMessage("mpv-unresponsive-error").format(int(diff)), True)
|
||||||
self._client.ui.showErrorMessage, getMessage("mpv-unresponsive-error").format(int(diff)), True)
|
|
||||||
self.drop()
|
self.drop()
|
||||||
if diff > constants.PLAYER_ASK_DELAY and not self._paused:
|
if diff > constants.PLAYER_ASK_DELAY and not self._paused:
|
||||||
self._client.ui.showDebugMessage(
|
self._client.ui.showDebugMessage("mpv did not response in time, so assuming position is {} ({}+{})".format(self._position + diff, self._position, diff))
|
||||||
"mpv did not response in time, so assuming position is {} ({}+{})".format(
|
|
||||||
self._position + diff, self._position, diff))
|
|
||||||
return self._position + diff
|
return self._position + diff
|
||||||
else:
|
else:
|
||||||
return self._position
|
return self._position
|
||||||
@ -204,8 +186,7 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
elif self._fileIsLoaded() or (value < constants.MPV_NEWFILE_IGNORE_TIME and self._fileIsLoaded(ignoreDelay=True)):
|
elif self._fileIsLoaded() or (value < constants.MPV_NEWFILE_IGNORE_TIME and self._fileIsLoaded(ignoreDelay=True)):
|
||||||
self._position = max(value,0)
|
self._position = max(value,0)
|
||||||
else:
|
else:
|
||||||
self._client.ui.showDebugMessage(
|
self._client.ui.showDebugMessage("No file loaded so storing position as GlobalPosition ({})".format(self._client.getGlobalPosition()))
|
||||||
"No file loaded so storing position as GlobalPosition ({})".format(self._client.getGlobalPosition()))
|
|
||||||
self._position = self._client.getGlobalPosition()
|
self._position = self._client.getGlobalPosition()
|
||||||
|
|
||||||
def _storePauseState(self, value):
|
def _storePauseState(self, value):
|
||||||
@ -224,8 +205,7 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
self._getPausedAndPosition()
|
self._getPausedAndPosition()
|
||||||
self._positionAsk.wait(constants.MPV_LOCK_WAIT_TIME)
|
self._positionAsk.wait(constants.MPV_LOCK_WAIT_TIME)
|
||||||
self._pausedAsk.wait(constants.MPV_LOCK_WAIT_TIME)
|
self._pausedAsk.wait(constants.MPV_LOCK_WAIT_TIME)
|
||||||
self._client.updatePlayerStatus(
|
self._client.updatePlayerStatus(self._paused if self.fileLoaded else self._client.getGlobalPaused(), self.getCalculatedPosition())
|
||||||
self._paused if self.fileLoaded else self._client.getGlobalPaused(), self.getCalculatedPosition())
|
|
||||||
|
|
||||||
def _getPausedAndPosition(self):
|
def _getPausedAndPosition(self):
|
||||||
self._listener.sendLine("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}")
|
||||||
@ -249,8 +229,7 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
|
|
||||||
def setPosition(self, value):
|
def setPosition(self, value):
|
||||||
if value < constants.DO_NOT_RESET_POSITION_THRESHOLD and self._recentlyReset():
|
if value < constants.DO_NOT_RESET_POSITION_THRESHOLD and self._recentlyReset():
|
||||||
self._client.ui.showDebugMessage(
|
self._client.ui.showDebugMessage("Did not seek as recently reset and {} below 'do not reset position' threshold".format(value))
|
||||||
"Did not seek as recently reset and {} below 'do not reset position' threshold".format(value))
|
|
||||||
return
|
return
|
||||||
super(self.__class__, self).setPosition(value)
|
super(self.__class__, self).setPosition(value)
|
||||||
self.lastMPVPositionUpdate = time.time()
|
self.lastMPVPositionUpdate = time.time()
|
||||||
@ -266,7 +245,7 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
self._client.ui.showDebugMessage("Want to set paused to {}".format(self._client.getGlobalPaused()))
|
self._client.ui.showDebugMessage("Want to set paused to {}".format(self._client.getGlobalPaused()))
|
||||||
else:
|
else:
|
||||||
self._client.ui.showDebugMessage("Don't want to set paused to {}".format(self._client.getGlobalPaused()))
|
self._client.ui.showDebugMessage("Don't want to set paused to {}".format(self._client.getGlobalPaused()))
|
||||||
if not resetPosition:
|
if resetPosition == False:
|
||||||
self.setPosition(self._client.getGlobalPosition())
|
self.setPosition(self._client.getGlobalPosition())
|
||||||
else:
|
else:
|
||||||
self._storePosition(0)
|
self._storePosition(0)
|
||||||
@ -306,14 +285,7 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
self._listener.setReadyToSend(True)
|
self._listener.setReadyToSend(True)
|
||||||
|
|
||||||
def _setOSDPosition(self):
|
def _setOSDPosition(self):
|
||||||
if (
|
if self._client._config['chatMoveOSD'] and (self._client._config['chatOutputEnabled'] or (self._client._config['chatInputEnabled'] and self._client._config['chatInputPosition'] == constants.INPUT_POSITION_TOP)):
|
||||||
self._client._config['chatMoveOSD'] and (
|
|
||||||
self._client._config['chatOutputEnabled'] or (
|
|
||||||
self._client._config['chatInputEnabled'] and
|
|
||||||
self._client._config['chatInputPosition'] == constants.INPUT_POSITION_TOP
|
|
||||||
)
|
|
||||||
)
|
|
||||||
):
|
|
||||||
self._setProperty("osd-align-y", "bottom")
|
self._setProperty("osd-align-y", "bottom")
|
||||||
self._setProperty("osd-margin-y", int(self._client._config['chatOSDMargin']))
|
self._setProperty("osd-margin-y", int(self._client._config['chatOSDMargin']))
|
||||||
|
|
||||||
@ -337,9 +309,9 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
def _fileIsLoaded(self, ignoreDelay=False):
|
def _fileIsLoaded(self, ignoreDelay=False):
|
||||||
if ignoreDelay:
|
if ignoreDelay:
|
||||||
self._client.ui.showDebugMessage("Ignoring _fileIsLoaded MPV_NEWFILE delay")
|
self._client.ui.showDebugMessage("Ignoring _fileIsLoaded MPV_NEWFILE delay")
|
||||||
return bool(self.fileLoaded)
|
return True if self.fileLoaded else False
|
||||||
|
|
||||||
return (
|
if self.fileLoaded == True and self.lastLoadedTime != None and time.time() > (self.lastLoadedTime + constants.MPV_NEWFILE_IGNORE_TIME):
|
||||||
self.fileLoaded and self.lastLoadedTime is not None and
|
return True
|
||||||
time.time() > (self.lastLoadedTime + constants.MPV_NEWFILE_IGNORE_TIME)
|
else:
|
||||||
)
|
return False
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import syncplay.players
|
import syncplay.players
|
||||||
|
|
||||||
|
|
||||||
class PlayerFactory(object):
|
class PlayerFactory(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._players = syncplay.players.getAvailablePlayers()
|
self._players = syncplay.players.getAvailablePlayers()
|
||||||
|
|||||||
@ -1,24 +1,18 @@
|
|||||||
|
|
||||||
import asynchat
|
|
||||||
import asyncore
|
|
||||||
import os
|
|
||||||
import random
|
|
||||||
import re
|
|
||||||
import socket
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import re
|
||||||
import threading
|
import threading
|
||||||
import time
|
|
||||||
import urllib.error
|
|
||||||
import urllib.parse
|
|
||||||
import urllib.request
|
|
||||||
|
|
||||||
from syncplay import constants, utils
|
|
||||||
from syncplay.messages import getMessage
|
|
||||||
from syncplay.players.basePlayer import BasePlayer
|
from syncplay.players.basePlayer import BasePlayer
|
||||||
|
from syncplay import constants, utils
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import random
|
||||||
|
import socket
|
||||||
|
import asynchat, asyncore
|
||||||
|
import urllib.request, urllib.parse, urllib.error
|
||||||
|
import time
|
||||||
|
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
|
||||||
@ -53,8 +47,7 @@ class VlcPlayer(BasePlayer):
|
|||||||
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(
|
self._client.ui.showErrorMessage("Failed to determine locale. As a fallback Syncplay is using the following radix character: \".\".")
|
||||||
"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()
|
||||||
@ -117,8 +110,7 @@ class VlcPlayer(BasePlayer):
|
|||||||
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._client.ui.showDebugMessage("VLC did not response in time, so assuming position is {} ({}+{})".format(self._position + diff, self._position, diff))
|
||||||
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)))
|
||||||
@ -127,10 +119,7 @@ class VlcPlayer(BasePlayer):
|
|||||||
else:
|
else:
|
||||||
return self._position
|
return self._position
|
||||||
|
|
||||||
def displayMessage(
|
def displayMessage(self, message, duration=constants.OSD_DURATION * 1000, OSDType=constants.OSD_DURATION, mood=constants.MESSAGE_NEUTRAL):
|
||||||
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))
|
self._listener.sendLine('display-osd: {}, {}, {}'.format('top-right', duration, message))
|
||||||
@ -223,25 +212,21 @@ class VlcPlayer(BasePlayer):
|
|||||||
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 not self._filechanged) 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 (
|
if self._paused == False \
|
||||||
self._paused == False and
|
and self._position == self._previousPreviousPosition \
|
||||||
self._position == self._previousPreviousPosition and
|
and self._previousPosition == self._position \
|
||||||
self._previousPosition == self._position and
|
and self._duration > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH \
|
||||||
self._duration > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH and
|
and (self._duration - self._position) < constants.VLC_EOF_DURATION_THRESHOLD \
|
||||||
(self._duration - self._position) < constants.VLC_EOF_DURATION_THRESHOLD and
|
and diff > constants.VLC_LATENCY_ERROR_THRESHOLD:
|
||||||
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 not self._filechanged) 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 self._paused is False:
|
if newPosition == self._previousPosition and newPosition != self._duration and not self._paused:
|
||||||
self._client.ui.showDebugMessage(
|
self._client.ui.showDebugMessage("Not considering position {} duplicate as new time because of VLC time precision bug".format(newPosition))
|
||||||
"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()
|
||||||
@ -341,7 +326,6 @@ class VlcPlayer(BasePlayer):
|
|||||||
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):
|
||||||
@ -363,8 +347,7 @@ class VlcPlayer(BasePlayer):
|
|||||||
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(
|
playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), "Library/Application Support/org.videolan.vlc/lua/intf/")
|
||||||
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.
|
||||||
@ -375,17 +358,14 @@ class VlcPlayer(BasePlayer):
|
|||||||
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(
|
playerController.SLAVE_ARGS.append('--lua-config=syncplay={{port=\"{}\"}}'.format(str(playerController.vlcport)))
|
||||||
'--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(
|
playerController.SLAVE_ARGS.append('--lua-config=syncplay={{modulepath=\"{}\",port=\"{}\"}}'.format(playerController.vlcModulePath, str(playerController.vlcport)))
|
||||||
'--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:
|
||||||
@ -396,15 +376,11 @@ class VlcPlayer(BasePlayer):
|
|||||||
self._vlcVersion = None
|
self._vlcVersion = None
|
||||||
|
|
||||||
if self.oldIntfVersion:
|
if self.oldIntfVersion:
|
||||||
self.__playerController.drop(
|
self.__playerController.drop(getMessage("vlc-interface-version-mismatch").format(self.oldIntfVersion,constants.VLC_INTERFACE_MIN_VERSION))
|
||||||
getMessage("vlc-interface-version-mismatch").format(
|
|
||||||
self.oldIntfVersion, constants.VLC_INTERFACE_MIN_VERSION))
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if isWindows() and getattr(sys, 'frozen', '') and getattr(sys, '_MEIPASS', '') is not None: #Needed for pyinstaller --onefile bundle
|
if isWindows() and getattr(sys, 'frozen', '') and getattr(sys, '_MEIPASS', '') is not None: #Needed for pyinstaller --onefile bundle
|
||||||
self.__process = subprocess.Popen(
|
self.__process = subprocess.Popen(call, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=False, creationflags=0x08000000)
|
||||||
call, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE,
|
|
||||||
shell=False, creationflags=0x08000000)
|
|
||||||
else:
|
else:
|
||||||
self.__process = subprocess.Popen(call, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
self.__process = subprocess.Popen(call, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
self.timeVLCLaunched = time.time()
|
self.timeVLCLaunched = time.time()
|
||||||
@ -440,7 +416,10 @@ class VlcPlayer(BasePlayer):
|
|||||||
self._sendingData = threading.Lock()
|
self._sendingData = threading.Lock()
|
||||||
|
|
||||||
def _shouldListenForSTDOUT(self):
|
def _shouldListenForSTDOUT(self):
|
||||||
return not isWindows()
|
if isWindows():
|
||||||
|
return False # Due to VLC3 not using STDOUT/STDERR
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
def initiate_send(self):
|
def initiate_send(self):
|
||||||
with self._sendingData:
|
with self._sendingData:
|
||||||
@ -483,6 +462,7 @@ class VlcPlayer(BasePlayer):
|
|||||||
break
|
break
|
||||||
out.close()
|
out.close()
|
||||||
|
|
||||||
|
|
||||||
def found_terminator(self):
|
def found_terminator(self):
|
||||||
self.vlcHasResponded = True
|
self.vlcHasResponded = True
|
||||||
self.__playerController.lineReceived(b"".join(self._ibuffer))
|
self.__playerController.lineReceived(b"".join(self._ibuffer))
|
||||||
|
|||||||
@ -1,16 +1,13 @@
|
|||||||
# coding:utf8
|
# coding:utf8
|
||||||
import json
|
|
||||||
import time
|
|
||||||
from functools import wraps
|
|
||||||
|
|
||||||
from twisted.protocols.basic import LineReceiver
|
from twisted.protocols.basic import LineReceiver
|
||||||
|
import json
|
||||||
import syncplay
|
import syncplay
|
||||||
from syncplay.constants import PING_MOVING_AVERAGE_WEIGHT, CONTROLLED_ROOMS_MIN_VERSION, USER_READY_MIN_VERSION, SHARED_PLAYLIST_MIN_VERSION, CHAT_MIN_VERSION
|
from functools import wraps
|
||||||
|
import time
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
|
from syncplay.constants import PING_MOVING_AVERAGE_WEIGHT, CONTROLLED_ROOMS_MIN_VERSION, USER_READY_MIN_VERSION, SHARED_PLAYLIST_MIN_VERSION, CHAT_MIN_VERSION
|
||||||
from syncplay.utils import meetsMinVersion
|
from syncplay.utils import meetsMinVersion
|
||||||
|
|
||||||
|
|
||||||
class JSONCommandProtocol(LineReceiver):
|
class JSONCommandProtocol(LineReceiver):
|
||||||
def handleMessages(self, messages):
|
def handleMessages(self, messages):
|
||||||
for message in messages.items():
|
for message in messages.items():
|
||||||
@ -105,11 +102,9 @@ class SyncClientProtocol(JSONCommandProtocol):
|
|||||||
hello = {}
|
hello = {}
|
||||||
hello["username"] = self._client.getUsername()
|
hello["username"] = self._client.getUsername()
|
||||||
password = self._client.getPassword()
|
password = self._client.getPassword()
|
||||||
if password:
|
if password: hello["password"] = password
|
||||||
hello["password"] = password
|
|
||||||
room = self._client.getRoom()
|
room = self._client.getRoom()
|
||||||
if room:
|
if room: hello["room"] = {"name" :room}
|
||||||
hello["room"] = {"name": room}
|
|
||||||
hello["version"] = "1.2.255" # Used so newer clients work on 1.2.X server
|
hello["version"] = "1.2.255" # Used so newer clients work on 1.2.X server
|
||||||
hello["realversion"] = syncplay.version
|
hello["realversion"] = syncplay.version
|
||||||
hello["features"] = self._client.getFeatures()
|
hello["features"] = self._client.getFeatures()
|
||||||
@ -165,8 +160,7 @@ class SyncClientProtocol(JSONCommandProtocol):
|
|||||||
def sendRoomSetting(self, roomName, password=None):
|
def sendRoomSetting(self, roomName, password=None):
|
||||||
setting = {}
|
setting = {}
|
||||||
setting["name"] = roomName
|
setting["name"] = roomName
|
||||||
if password:
|
if password: setting["password"] = password
|
||||||
setting["password"] = password
|
|
||||||
self.sendSet({"room": setting})
|
self.sendSet({"room": setting})
|
||||||
|
|
||||||
def sendFileSetting(self, file_):
|
def sendFileSetting(self, file_):
|
||||||
@ -237,8 +231,7 @@ class SyncClientProtocol(JSONCommandProtocol):
|
|||||||
state["playstate"] = {}
|
state["playstate"] = {}
|
||||||
state["playstate"]["position"] = position
|
state["playstate"]["position"] = position
|
||||||
state["playstate"]["paused"] = paused
|
state["playstate"]["paused"] = paused
|
||||||
if doSeek:
|
if doSeek: state["playstate"]["doSeek"] = doSeek
|
||||||
state["playstate"]["doSeek"] = doSeek
|
|
||||||
state["ping"] = {}
|
state["ping"] = {}
|
||||||
if latencyCalculation:
|
if latencyCalculation:
|
||||||
state["ping"]["latencyCalculation"] = latencyCalculation
|
state["ping"]["latencyCalculation"] = latencyCalculation
|
||||||
@ -262,7 +255,6 @@ class SyncClientProtocol(JSONCommandProtocol):
|
|||||||
"password": password
|
"password": password
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
def handleChat(self,message):
|
def handleChat(self,message):
|
||||||
username = message['username']
|
username = message['username']
|
||||||
userMessage = message['message']
|
userMessage = message['message']
|
||||||
@ -290,13 +282,13 @@ class SyncClientProtocol(JSONCommandProtocol):
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def handleError(self, error):
|
def handleError(self, error):
|
||||||
self.dropWithError(error["message"])
|
self.dropWithError(error["message"])
|
||||||
|
|
||||||
def sendError(self, message):
|
def sendError(self, message):
|
||||||
self.sendMessage({"Error": {"message": message}})
|
self.sendMessage({"Error": {"message": message}})
|
||||||
|
|
||||||
|
|
||||||
class SyncServerProtocol(JSONCommandProtocol):
|
class SyncServerProtocol(JSONCommandProtocol):
|
||||||
def __init__(self, factory):
|
def __init__(self, factory):
|
||||||
self._factory = factory
|
self._factory = factory
|
||||||
@ -418,8 +410,7 @@ class SyncServerProtocol(JSONCommandProtocol):
|
|||||||
hello["username"] = username
|
hello["username"] = username
|
||||||
userIp = self.transport.getPeer().host
|
userIp = self.transport.getPeer().host
|
||||||
room = self._watcher.getRoom()
|
room = self._watcher.getRoom()
|
||||||
if room:
|
if room: hello["room"] = {"name": room.getName()}
|
||||||
hello["room"] = {"name": room.getName()}
|
|
||||||
hello["version"] = clientVersion # Used so 1.2.X client works on newer server
|
hello["version"] = clientVersion # Used so 1.2.X client works on newer server
|
||||||
hello["realversion"] = syncplay.version
|
hello["realversion"] = syncplay.version
|
||||||
hello["motd"] = self._factory.getMotd(userIp, username, room, clientVersion)
|
hello["motd"] = self._factory.getMotd(userIp, username, room, clientVersion)
|
||||||
@ -470,6 +461,7 @@ class SyncServerProtocol(JSONCommandProtocol):
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def sendSetReady(self, username, isReady, manuallyInitiated=True):
|
def sendSetReady(self, username, isReady, manuallyInitiated=True):
|
||||||
self.sendSet({
|
self.sendSet({
|
||||||
"ready": {
|
"ready": {
|
||||||
@ -564,6 +556,7 @@ class SyncServerProtocol(JSONCommandProtocol):
|
|||||||
if self.serverIgnoringOnTheFly == 0 or forced:
|
if self.serverIgnoringOnTheFly == 0 or forced:
|
||||||
self.sendMessage({"State": state})
|
self.sendMessage({"State": state})
|
||||||
|
|
||||||
|
|
||||||
def _extractStatePlaystateArguments(self, state):
|
def _extractStatePlaystateArguments(self, state):
|
||||||
position = state["playstate"]["position"] if "position" in state["playstate"] else 0
|
position = state["playstate"]["position"] if "position" in state["playstate"] else 0
|
||||||
paused = state["playstate"]["paused"] if "paused" in state["playstate"] else None
|
paused = state["playstate"]["paused"] if "paused" in state["playstate"] else None
|
||||||
@ -597,7 +590,6 @@ class SyncServerProtocol(JSONCommandProtocol):
|
|||||||
def sendError(self, message):
|
def sendError(self, message):
|
||||||
self.sendMessage({"Error": {"message": message}})
|
self.sendMessage({"Error": {"message": message}})
|
||||||
|
|
||||||
|
|
||||||
class PingService(object):
|
class PingService(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|||||||
@ -1,26 +1,20 @@
|
|||||||
|
|
||||||
import argparse
|
|
||||||
import codecs
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
|
||||||
import random
|
import random
|
||||||
import time
|
|
||||||
from string import Template
|
|
||||||
|
|
||||||
from twisted.internet import task, reactor
|
from twisted.internet import task, reactor
|
||||||
from twisted.internet.protocol import Factory
|
from twisted.internet.protocol import Factory
|
||||||
|
|
||||||
import syncplay
|
import syncplay
|
||||||
|
from syncplay.protocols import SyncServerProtocol
|
||||||
|
import time
|
||||||
from syncplay import constants
|
from syncplay import constants
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
from syncplay.protocols import SyncServerProtocol
|
import codecs
|
||||||
|
import os
|
||||||
|
from string import Template
|
||||||
|
import argparse
|
||||||
from syncplay.utils import RoomPasswordProvider, NotControlledRoom, RandomStringGenerator, meetsMinVersion, playlistIsValid, truncateText
|
from syncplay.utils import RoomPasswordProvider, NotControlledRoom, RandomStringGenerator, meetsMinVersion, playlistIsValid, truncateText
|
||||||
|
|
||||||
|
|
||||||
class SyncFactory(Factory):
|
class SyncFactory(Factory):
|
||||||
def __init__(self, password='', motdFilePath=None, isolateRooms=False, salt=None,
|
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):
|
||||||
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:
|
||||||
@ -185,7 +179,6 @@ class SyncFactory(Factory):
|
|||||||
else:
|
else:
|
||||||
watcher.setPlaylistIndex(room.getName(), room.getPlaylistIndex())
|
watcher.setPlaylistIndex(room.getName(), room.getPlaylistIndex())
|
||||||
|
|
||||||
|
|
||||||
class RoomManager(object):
|
class RoomManager(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._rooms = {}
|
self._rooms = {}
|
||||||
@ -348,7 +341,6 @@ class Room(object):
|
|||||||
def getPlaylistIndex(self):
|
def getPlaylistIndex(self):
|
||||||
return self._playlistIndex
|
return self._playlistIndex
|
||||||
|
|
||||||
|
|
||||||
class ControlledRoom(Room):
|
class ControlledRoom(Room):
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
Room.__init__(self, name)
|
Room.__init__(self, name)
|
||||||
@ -397,7 +389,6 @@ class ControlledRoom(Room):
|
|||||||
def getControllers(self):
|
def getControllers(self):
|
||||||
return self._controllers
|
return self._controllers
|
||||||
|
|
||||||
|
|
||||||
class Watcher(object):
|
class Watcher(object):
|
||||||
def __init__(self, server, connector, name):
|
def __init__(self, server, connector, name):
|
||||||
self._ready = None
|
self._ready = None
|
||||||
@ -540,7 +531,6 @@ class Watcher(object):
|
|||||||
return RoomPasswordProvider.isControlledRoom(self._room.getName()) \
|
return RoomPasswordProvider.isControlledRoom(self._room.getName()) \
|
||||||
and self._room.canControl(self)
|
and self._room.canControl(self)
|
||||||
|
|
||||||
|
|
||||||
class ConfigurationGetter(object):
|
class ConfigurationGetter(object):
|
||||||
def getConfiguration(self):
|
def getConfiguration(self):
|
||||||
self._prepareArgParser()
|
self._prepareArgParser()
|
||||||
@ -550,8 +540,7 @@ class ConfigurationGetter(object):
|
|||||||
return args
|
return args
|
||||||
|
|
||||||
def _prepareArgParser(self):
|
def _prepareArgParser(self):
|
||||||
self._argparser = argparse.ArgumentParser(
|
self._argparser = argparse.ArgumentParser(description=getMessage("server-argument-description"),
|
||||||
description=getMessage("server-argument-description"),
|
|
||||||
epilog=getMessage("server-argument-epilog"))
|
epilog=getMessage("server-argument-epilog"))
|
||||||
self._argparser.add_argument('--port', metavar='port', type=str, nargs='?', help=getMessage("server-port-argument"))
|
self._argparser.add_argument('--port', metavar='port', type=str, nargs='?', help=getMessage("server-port-argument"))
|
||||||
self._argparser.add_argument('--password', metavar='password', type=str, nargs='?', help=getMessage("server-password-argument"))
|
self._argparser.add_argument('--password', metavar='password', type=str, nargs='?', help=getMessage("server-password-argument"))
|
||||||
|
|||||||
@ -1,23 +1,19 @@
|
|||||||
|
from configparser import SafeConfigParser, DEFAULTSECT
|
||||||
import argparse
|
import argparse
|
||||||
import ast
|
|
||||||
import codecs
|
|
||||||
import re
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from configparser import SafeConfigParser, DEFAULTSECT
|
import ast
|
||||||
|
|
||||||
from syncplay import constants, utils, version, milestone
|
from syncplay import constants, utils, version, milestone
|
||||||
from syncplay.messages import getMessage, setLanguage, isValidLanguage
|
from syncplay.messages import getMessage, setLanguage, isValidLanguage
|
||||||
from syncplay.players.playerFactory import PlayerFactory
|
from syncplay.players.playerFactory import PlayerFactory
|
||||||
from syncplay.utils import isMacOS
|
from syncplay.utils import isMacOS
|
||||||
|
import codecs
|
||||||
|
import re
|
||||||
|
|
||||||
class InvalidConfigValue(Exception):
|
class InvalidConfigValue(Exception):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
Exception.__init__(self, message)
|
Exception.__init__(self, message)
|
||||||
|
|
||||||
|
|
||||||
class ConfigurationGetter(object):
|
class ConfigurationGetter(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._config = {
|
self._config = {
|
||||||
@ -179,8 +175,7 @@ class ConfigurationGetter(object):
|
|||||||
|
|
||||||
self._iniStructure = {
|
self._iniStructure = {
|
||||||
"server_data": ["host", "port", "password"],
|
"server_data": ["host", "port", "password"],
|
||||||
"client_settings": [
|
"client_settings": ["name", "room", "playerPath",
|
||||||
"name", "room", "playerPath",
|
|
||||||
"perPlayerArguments", "slowdownThreshold",
|
"perPlayerArguments", "slowdownThreshold",
|
||||||
"rewindThreshold", "fastforwardThreshold",
|
"rewindThreshold", "fastforwardThreshold",
|
||||||
"slowOnDesync", "rewindOnDesync",
|
"slowOnDesync", "rewindOnDesync",
|
||||||
@ -192,8 +187,7 @@ class ConfigurationGetter(object):
|
|||||||
"sharedPlaylistEnabled", "loopAtEndOfPlaylist",
|
"sharedPlaylistEnabled", "loopAtEndOfPlaylist",
|
||||||
"loopSingleFiles",
|
"loopSingleFiles",
|
||||||
"onlySwitchToTrustedDomains", "trustedDomains","publicServers"],
|
"onlySwitchToTrustedDomains", "trustedDomains","publicServers"],
|
||||||
"gui": [
|
"gui": ["showOSD", "showOSDWarnings", "showSlowdownOSD",
|
||||||
"showOSD", "showOSDWarnings", "showSlowdownOSD",
|
|
||||||
"showDifferentRoomOSD", "showSameRoomOSD",
|
"showDifferentRoomOSD", "showSameRoomOSD",
|
||||||
"showNonControllerOSD", "showDurationNotification",
|
"showNonControllerOSD", "showDurationNotification",
|
||||||
"chatInputEnabled","chatInputFontUnderline",
|
"chatInputEnabled","chatInputFontUnderline",
|
||||||
@ -208,8 +202,7 @@ class ConfigurationGetter(object):
|
|||||||
"chatMoveOSD", "chatOSDMargin",
|
"chatMoveOSD", "chatOSDMargin",
|
||||||
"notificationTimeout", "alertTimeout",
|
"notificationTimeout", "alertTimeout",
|
||||||
"chatTimeout","chatOutputEnabled"],
|
"chatTimeout","chatOutputEnabled"],
|
||||||
"general": [
|
"general": ["language", "checkForUpdatesAutomatically",
|
||||||
"language", "checkForUpdatesAutomatically",
|
|
||||||
"lastCheckedForUpdates"]
|
"lastCheckedForUpdates"]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +224,7 @@ class ConfigurationGetter(object):
|
|||||||
try:
|
try:
|
||||||
if varToTest == "" or varToTest is None:
|
if varToTest == "" or varToTest is None:
|
||||||
return False
|
return False
|
||||||
if not str(varToTest).isdigit():
|
if str(varToTest).isdigit() == False:
|
||||||
return False
|
return False
|
||||||
varToTest = int(varToTest)
|
varToTest = int(varToTest)
|
||||||
if varToTest > 65535 or varToTest < 1:
|
if varToTest > 65535 or varToTest < 1:
|
||||||
@ -239,7 +232,6 @@ class ConfigurationGetter(object):
|
|||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
for key in self._boolean:
|
for key in self._boolean:
|
||||||
if self._config[key] == "True":
|
if self._config[key] == "True":
|
||||||
self._config[key] = True
|
self._config[key] = True
|
||||||
@ -277,14 +269,13 @@ class ConfigurationGetter(object):
|
|||||||
self._config["playerClass"] = player
|
self._config["playerClass"] = player
|
||||||
else:
|
else:
|
||||||
raise InvalidConfigValue(getMessage("player-path-config-error"))
|
raise InvalidConfigValue(getMessage("player-path-config-error"))
|
||||||
playerPathErrors = player.getPlayerPathErrors(
|
playerPathErrors = player.getPlayerPathErrors(self._config["playerPath"], self._config['file'] if self._config['file'] else None)
|
||||||
self._config["playerPath"], self._config['file'] if self._config['file'] else None)
|
|
||||||
if playerPathErrors:
|
if playerPathErrors:
|
||||||
raise InvalidConfigValue(playerPathErrors)
|
raise InvalidConfigValue(playerPathErrors)
|
||||||
elif key == "host":
|
elif key == "host":
|
||||||
self._config["host"], self._config["port"] = self._splitPortAndHost(self._config["host"])
|
self._config["host"], self._config["port"] = self._splitPortAndHost(self._config["host"])
|
||||||
hostNotValid = (self._config["host"] == "" or self._config["host"] is None)
|
hostNotValid = (self._config["host"] == "" or self._config["host"] is None)
|
||||||
portNotValid = (not _isPortValid(self._config["port"]))
|
portNotValid = (_isPortValid(self._config["port"]) == False)
|
||||||
if hostNotValid:
|
if hostNotValid:
|
||||||
raise InvalidConfigValue(getMessage("no-hostname-config-error"))
|
raise InvalidConfigValue(getMessage("no-hostname-config-error"))
|
||||||
elif portNotValid:
|
elif portNotValid:
|
||||||
@ -417,6 +408,7 @@ class ConfigurationGetter(object):
|
|||||||
if changed:
|
if changed:
|
||||||
parser.write(codecs.open(iniPath, "wb", "utf_8_sig"))
|
parser.write(codecs.open(iniPath, "wb", "utf_8_sig"))
|
||||||
|
|
||||||
|
|
||||||
def _forceGuiPrompt(self):
|
def _forceGuiPrompt(self):
|
||||||
from syncplay.ui.GuiConfiguration import GuiConfiguration
|
from syncplay.ui.GuiConfiguration import GuiConfiguration
|
||||||
try:
|
try:
|
||||||
@ -460,8 +452,7 @@ class ConfigurationGetter(object):
|
|||||||
#
|
#
|
||||||
if self._config['language']:
|
if self._config['language']:
|
||||||
setLanguage(self._config['language'])
|
setLanguage(self._config['language'])
|
||||||
self._argparser = argparse.ArgumentParser(
|
self._argparser = argparse.ArgumentParser(description=getMessage("argument-description"),
|
||||||
description=getMessage("argument-description"),
|
|
||||||
epilog=getMessage("argument-epilog"))
|
epilog=getMessage("argument-epilog"))
|
||||||
self._argparser.add_argument('--no-gui', action='store_true', help=getMessage("nogui-argument"))
|
self._argparser.add_argument('--no-gui', action='store_true', help=getMessage("nogui-argument"))
|
||||||
self._argparser.add_argument('-a', '--host', metavar='hostname', type=str, help=getMessage("host-argument"))
|
self._argparser.add_argument('-a', '--host', metavar='hostname', type=str, help=getMessage("host-argument"))
|
||||||
@ -523,7 +514,6 @@ class ConfigurationGetter(object):
|
|||||||
self._saveConfig(path)
|
self._saveConfig(path)
|
||||||
self._config = backup
|
self._config = backup
|
||||||
|
|
||||||
|
|
||||||
class SafeConfigParserUnicode(SafeConfigParser):
|
class SafeConfigParserUnicode(SafeConfigParser):
|
||||||
def write(self, fp):
|
def write(self, fp):
|
||||||
"""Write an .ini-format representation of the configuration state."""
|
"""Write an .ini-format representation of the configuration state."""
|
||||||
|
|||||||
@ -1,24 +1,19 @@
|
|||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import threading
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from syncplay import constants
|
|
||||||
from syncplay import utils
|
|
||||||
from syncplay.messages import getMessage, getLanguages, setLanguage, getInitialLanguage
|
|
||||||
from syncplay.players.playerFactory import PlayerFactory
|
|
||||||
from syncplay.utils import isBSD, isLinux, isMacOS, isWindows
|
|
||||||
from syncplay.utils import resourcespath, posixresourcespath
|
|
||||||
|
|
||||||
from syncplay.vendor.Qt import QtCore, QtWidgets, QtGui, __binding__, IsPySide, IsPySide2
|
from syncplay.vendor.Qt import QtCore, QtWidgets, QtGui, __binding__, IsPySide, IsPySide2
|
||||||
from syncplay.vendor.Qt.QtCore import Qt, QSettings, QCoreApplication, QSize, QPoint, QUrl, QLine, QEventLoop, Signal
|
from syncplay.vendor.Qt.QtCore import Qt, QSettings, QCoreApplication, QSize, QPoint, QUrl, QLine, QEventLoop, Signal
|
||||||
from syncplay.vendor.Qt.QtWidgets import QApplication, QLineEdit, QLabel, QCheckBox, QButtonGroup, QRadioButton, QDoubleSpinBox, QPlainTextEdit
|
from syncplay.vendor.Qt.QtWidgets import QApplication, QLineEdit, QLabel, QCheckBox, QButtonGroup, QRadioButton, QDoubleSpinBox, QPlainTextEdit
|
||||||
from syncplay.vendor.Qt.QtGui import QCursor, QIcon, QImage, QDesktopServices
|
from syncplay.vendor.Qt.QtGui import QCursor, QIcon, QImage, QDesktopServices
|
||||||
if IsPySide2:
|
if IsPySide2:
|
||||||
from PySide2.QtCore import QStandardPaths
|
from PySide2.QtCore import QStandardPaths
|
||||||
|
from syncplay.players.playerFactory import PlayerFactory
|
||||||
|
from datetime import datetime
|
||||||
|
from syncplay import utils
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
from syncplay.messages import getMessage, getLanguages, setLanguage, getInitialLanguage
|
||||||
|
from syncplay import constants
|
||||||
|
from syncplay.utils import isBSD, isLinux, isMacOS, isWindows
|
||||||
|
from syncplay.utils import resourcespath, posixresourcespath
|
||||||
class GuiConfiguration:
|
class GuiConfiguration:
|
||||||
def __init__(self, config, error=None, defaultConfig=None):
|
def __init__(self, config, error=None, defaultConfig=None):
|
||||||
self.defaultConfig = defaultConfig
|
self.defaultConfig = defaultConfig
|
||||||
@ -87,10 +82,8 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
|
|
||||||
def automaticUpdatePromptCheck(self):
|
def automaticUpdatePromptCheck(self):
|
||||||
if self.automaticupdatesCheckbox.checkState() == Qt.PartiallyChecked:
|
if self.automaticupdatesCheckbox.checkState() == Qt.PartiallyChecked:
|
||||||
reply = QtWidgets.QMessageBox.question(
|
reply = QtWidgets.QMessageBox.question(self, "Syncplay",
|
||||||
self, "Syncplay",
|
getMessage("promptforupdate-label"), QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No)
|
||||||
getMessage("promptforupdate-label"),
|
|
||||||
QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No)
|
|
||||||
if reply == QtWidgets.QMessageBox.Yes:
|
if reply == QtWidgets.QMessageBox.Yes:
|
||||||
self.automaticupdatesCheckbox.setChecked(True)
|
self.automaticupdatesCheckbox.setChecked(True)
|
||||||
else:
|
else:
|
||||||
@ -98,7 +91,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
|
|
||||||
def moreToggled(self):
|
def moreToggled(self):
|
||||||
self.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
self.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
|
||||||
if self.moreToggling is False:
|
if self.moreToggling == False:
|
||||||
self.moreToggling = True
|
self.moreToggling = True
|
||||||
|
|
||||||
if self.showmoreCheckbox.isChecked():
|
if self.showmoreCheckbox.isChecked():
|
||||||
@ -161,7 +154,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
settings.endGroup()
|
settings.endGroup()
|
||||||
foundpath = ""
|
foundpath = ""
|
||||||
|
|
||||||
if playerpath is not None and playerpath != "":
|
if playerpath != None and playerpath != "":
|
||||||
if utils.isURL(playerpath):
|
if utils.isURL(playerpath):
|
||||||
foundpath = playerpath
|
foundpath = playerpath
|
||||||
self.executablepathCombobox.addItem(foundpath)
|
self.executablepathCombobox.addItem(foundpath)
|
||||||
@ -169,7 +162,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
else:
|
else:
|
||||||
if not os.path.isfile(playerpath):
|
if not os.path.isfile(playerpath):
|
||||||
expandedpath = PlayerFactory().getExpandedPlayerPathByPath(playerpath)
|
expandedpath = PlayerFactory().getExpandedPlayerPathByPath(playerpath)
|
||||||
if expandedpath is not None and os.path.isfile(expandedpath):
|
if expandedpath != None and os.path.isfile(expandedpath):
|
||||||
playerpath = expandedpath
|
playerpath = expandedpath
|
||||||
|
|
||||||
if os.path.isfile(playerpath):
|
if os.path.isfile(playerpath):
|
||||||
@ -259,8 +252,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
elif isBSD():
|
elif isBSD():
|
||||||
defaultdirectory = "/usr/local/bin"
|
defaultdirectory = "/usr/local/bin"
|
||||||
|
|
||||||
fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(
|
fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(self,
|
||||||
self,
|
|
||||||
"Browse for media player executable",
|
"Browse for media player executable",
|
||||||
defaultdirectory,
|
defaultdirectory,
|
||||||
browserfilter, "", options)
|
browserfilter, "", options)
|
||||||
@ -395,8 +387,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
else:
|
else:
|
||||||
defaultdirectory = ""
|
defaultdirectory = ""
|
||||||
browserfilter = "All files (*)"
|
browserfilter = "All files (*)"
|
||||||
fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(
|
fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(self, "Browse for media files", defaultdirectory,
|
||||||
self, "Browse for media files", defaultdirectory,
|
|
||||||
browserfilter, "", options)
|
browserfilter, "", options)
|
||||||
if fileName:
|
if fileName:
|
||||||
self.mediapathTextbox.setText(os.path.normpath(fileName))
|
self.mediapathTextbox.setText(os.path.normpath(fileName))
|
||||||
@ -551,10 +542,10 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
config = self.config
|
config = self.config
|
||||||
playerpaths = self.playerpaths
|
playerpaths = self.playerpaths
|
||||||
error = self.error
|
error = self.error
|
||||||
if self.datacleared:
|
if self.datacleared == True:
|
||||||
error = constants.ERROR_MESSAGE_MARKER + "{}".format(getMessage("gui-data-cleared-notification"))
|
error = constants.ERROR_MESSAGE_MARKER + "{}".format(getMessage("gui-data-cleared-notification"))
|
||||||
self.error = error
|
self.error = error
|
||||||
if config['host'] is None:
|
if config['host'] == None:
|
||||||
host = ""
|
host = ""
|
||||||
elif ":" in config['host']:
|
elif ":" in config['host']:
|
||||||
host = config['host']
|
host = config['host']
|
||||||
@ -575,7 +566,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
serverAddressPort = publicServer[1]
|
serverAddressPort = publicServer[1]
|
||||||
self.hostCombobox.addItem(serverAddressPort)
|
self.hostCombobox.addItem(serverAddressPort)
|
||||||
self.hostCombobox.setItemData(i, serverTitle, Qt.ToolTipRole)
|
self.hostCombobox.setItemData(i, serverTitle, Qt.ToolTipRole)
|
||||||
if serverAddressPort not in self.publicServerAddresses:
|
if not serverAddressPort in self.publicServerAddresses:
|
||||||
self.publicServerAddresses.append(serverAddressPort)
|
self.publicServerAddresses.append(serverAddressPort)
|
||||||
i += 1
|
i += 1
|
||||||
self.hostCombobox.setEditable(True)
|
self.hostCombobox.setEditable(True)
|
||||||
@ -1233,7 +1224,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
|
|
||||||
def populateEmptyServerList(self):
|
def populateEmptyServerList(self):
|
||||||
if self.publicServers is None:
|
if self.publicServers is None:
|
||||||
if self.config["checkForUpdatesAutomatically"]:
|
if self.config["checkForUpdatesAutomatically"] == True:
|
||||||
self.updateServerList()
|
self.updateServerList()
|
||||||
else:
|
else:
|
||||||
currentServer = self.hostCombobox.currentText()
|
currentServer = self.hostCombobox.currentText()
|
||||||
@ -1273,7 +1264,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self._playerProbeThread.done.connect(self._updateExecutableIcon)
|
self._playerProbeThread.done.connect(self._updateExecutableIcon)
|
||||||
self._playerProbeThread.start()
|
self._playerProbeThread.start()
|
||||||
|
|
||||||
if self.config['clearGUIData']:
|
if self.config['clearGUIData'] == True:
|
||||||
self.config['clearGUIData'] = False
|
self.config['clearGUIData'] = False
|
||||||
self.clearGUIData()
|
self.clearGUIData()
|
||||||
|
|
||||||
@ -1314,7 +1305,7 @@ class ConfigDialog(QtWidgets.QDialog):
|
|||||||
self.addBottomLayout()
|
self.addBottomLayout()
|
||||||
self.updatePasswordVisibilty()
|
self.updatePasswordVisibilty()
|
||||||
|
|
||||||
if self.getMoreState() is False:
|
if self.getMoreState() == False:
|
||||||
self.tabListFrame.hide()
|
self.tabListFrame.hide()
|
||||||
self.resetButton.hide()
|
self.resetButton.hide()
|
||||||
self.playerargsTextbox.hide()
|
self.playerargsTextbox.hide()
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
if "QT_PREFERRED_BINDING" not in os.environ:
|
if "QT_PREFERRED_BINDING" not in os.environ:
|
||||||
os.environ["QT_PREFERRED_BINDING"] = os.pathsep.join(
|
os.environ["QT_PREFERRED_BINDING"] = os.pathsep.join(
|
||||||
["PySide2", "PySide", "PyQt5", "PyQt4"]
|
["PySide2", "PySide", "PyQt5", "PyQt4"]
|
||||||
@ -11,9 +10,8 @@ except ImportError:
|
|||||||
pass
|
pass
|
||||||
from syncplay.ui.consoleUI import ConsoleUI
|
from syncplay.ui.consoleUI import ConsoleUI
|
||||||
|
|
||||||
|
|
||||||
def getUi(graphical=True):
|
def getUi(graphical=True):
|
||||||
if graphical:
|
if graphical: #TODO: Add graphical ui
|
||||||
ui = GraphicalUI()
|
ui = GraphicalUI()
|
||||||
else:
|
else:
|
||||||
ui = ConsoleUI()
|
ui = ConsoleUI()
|
||||||
|
|||||||
@ -1,16 +1,14 @@
|
|||||||
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import syncplay
|
import syncplay
|
||||||
from syncplay import constants
|
import re
|
||||||
from syncplay import utils
|
from syncplay import utils
|
||||||
|
from syncplay import constants
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
|
import sys
|
||||||
from syncplay.utils import formatTime
|
from syncplay.utils import formatTime
|
||||||
|
|
||||||
|
|
||||||
class ConsoleUI(threading.Thread):
|
class ConsoleUI(threading.Thread):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.promptMode = threading.Event()
|
self.promptMode = threading.Event()
|
||||||
@ -159,7 +157,7 @@ class ConsoleUI(threading.Thread):
|
|||||||
self._syncplayClient.setPaused(not self._syncplayClient.getPlayerPaused())
|
self._syncplayClient.setPaused(not self._syncplayClient.getPlayerPaused())
|
||||||
elif command.group('command') in constants.COMMANDS_ROOM:
|
elif command.group('command') in constants.COMMANDS_ROOM:
|
||||||
room = command.group('parameter')
|
room = command.group('parameter')
|
||||||
if room is None:
|
if room == None:
|
||||||
if self._syncplayClient.userlist.currentUser.file:
|
if self._syncplayClient.userlist.currentUser.file:
|
||||||
room = self._syncplayClient.userlist.currentUser.file["name"]
|
room = self._syncplayClient.userlist.currentUser.file["name"]
|
||||||
else:
|
else:
|
||||||
@ -169,7 +167,7 @@ class ConsoleUI(threading.Thread):
|
|||||||
self._syncplayClient.sendRoom()
|
self._syncplayClient.sendRoom()
|
||||||
elif command.group('command') in constants.COMMANDS_CREATE:
|
elif command.group('command') in constants.COMMANDS_CREATE:
|
||||||
roombasename = command.group('parameter')
|
roombasename = command.group('parameter')
|
||||||
if roombasename is None:
|
if roombasename == None:
|
||||||
roombasename = self._syncplayClient.getRoom()
|
roombasename = self._syncplayClient.getRoom()
|
||||||
roombasename = utils.stripRoomName(roombasename)
|
roombasename = utils.stripRoomName(roombasename)
|
||||||
self._syncplayClient.createControlledRoom(roombasename)
|
self._syncplayClient.createControlledRoom(roombasename)
|
||||||
|
|||||||
@ -1,34 +1,28 @@
|
|||||||
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import urllib.error
|
|
||||||
import urllib.parse
|
|
||||||
import urllib.request
|
|
||||||
from datetime import datetime
|
|
||||||
from functools import wraps
|
|
||||||
from platform import python_version
|
|
||||||
|
|
||||||
from twisted.internet import task
|
|
||||||
|
|
||||||
from syncplay import utils, constants, version, revision, release_number
|
|
||||||
from syncplay.messages import getMessage
|
|
||||||
from syncplay.ui.consoleUI import ConsoleUI
|
|
||||||
from syncplay.utils import resourcespath
|
|
||||||
from syncplay.utils import isLinux, isWindows, isMacOS
|
|
||||||
from syncplay.utils import formatTime, sameFilename, sameFilesize, sameFileduration, RoomPasswordProvider, formatSize, isURL
|
|
||||||
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
|
||||||
if IsPySide2:
|
if IsPySide2:
|
||||||
from PySide2.QtCore import QStandardPaths
|
from PySide2.QtCore import QStandardPaths
|
||||||
|
from syncplay import utils, constants, version, revision, release_number
|
||||||
|
from syncplay.messages import getMessage
|
||||||
|
from syncplay.utils import resourcespath
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import urllib.request, urllib.parse, urllib.error
|
||||||
|
from datetime import datetime
|
||||||
|
from syncplay.utils import isLinux, isWindows, isMacOS
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
from syncplay.utils import formatTime, sameFilename, sameFilesize, sameFileduration, RoomPasswordProvider, formatSize, isURL
|
||||||
|
from functools import wraps
|
||||||
|
from twisted.internet import task
|
||||||
|
from syncplay.ui.consoleUI import ConsoleUI
|
||||||
if isMacOS() and IsPySide:
|
if isMacOS() and IsPySide:
|
||||||
from Foundation import NSURL
|
from Foundation import NSURL
|
||||||
from Cocoa import NSString, NSUTF8StringEncoding
|
from Cocoa import NSString, NSUTF8StringEncoding
|
||||||
lastCheckedForUpdates = None
|
lastCheckedForUpdates = None
|
||||||
|
|
||||||
|
|
||||||
class ConsoleInGUI(ConsoleUI):
|
class ConsoleInGUI(ConsoleUI):
|
||||||
def showMessage(self, message, noTimestamp=False):
|
def showMessage(self, message, noTimestamp=False):
|
||||||
self._syncplayClient.ui.showMessage(message, True)
|
self._syncplayClient.ui.showMessage(message, True)
|
||||||
@ -45,7 +39,6 @@ class ConsoleInGUI(ConsoleUI):
|
|||||||
def getUserlist(self):
|
def getUserlist(self):
|
||||||
self._syncplayClient.showUserList(self)
|
self._syncplayClient.showUserList(self)
|
||||||
|
|
||||||
|
|
||||||
class UserlistItemDelegate(QtWidgets.QStyledItemDelegate):
|
class UserlistItemDelegate(QtWidgets.QStyledItemDelegate):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
QtWidgets.QStyledItemDelegate.__init__(self)
|
QtWidgets.QStyledItemDelegate.__init__(self)
|
||||||
@ -109,7 +102,6 @@ class UserlistItemDelegate(QtWidgets.QStyledItemDelegate):
|
|||||||
optionQStyleOptionViewItem.rect.setX(optionQStyleOptionViewItem.rect.x()+16)
|
optionQStyleOptionViewItem.rect.setX(optionQStyleOptionViewItem.rect.x()+16)
|
||||||
QtWidgets.QStyledItemDelegate.paint(self, itemQPainter, optionQStyleOptionViewItem, indexQModelIndex)
|
QtWidgets.QStyledItemDelegate.paint(self, itemQPainter, optionQStyleOptionViewItem, indexQModelIndex)
|
||||||
|
|
||||||
|
|
||||||
class AboutDialog(QtWidgets.QDialog):
|
class AboutDialog(QtWidgets.QDialog):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super(AboutDialog, self).__init__(parent)
|
super(AboutDialog, self).__init__(parent)
|
||||||
@ -125,13 +117,9 @@ class AboutDialog(QtWidgets.QDialog):
|
|||||||
linkLabel = QtWidgets.QLabel("<center><a href=\"https://syncplay.pl\">syncplay.pl</a></center>")
|
linkLabel = QtWidgets.QLabel("<center><a href=\"https://syncplay.pl\">syncplay.pl</a></center>")
|
||||||
linkLabel.setOpenExternalLinks(True)
|
linkLabel.setOpenExternalLinks(True)
|
||||||
versionExtString = version + revision
|
versionExtString = version + revision
|
||||||
versionLabel = QtWidgets.QLabel(
|
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>")
|
||||||
"<p><center>" + getMessage("about-dialog-release").format(versionExtString, release_number) +
|
#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>")
|
||||||
"<br />Python " + python_version() + " - " + __binding__ + " " + __binding_version__ +
|
licenseLabel = QtWidgets.QLabel("<center><p>Copyright © 2012–2018 Syncplay</p><p>" + getMessage("about-dialog-license-text") + "</p></center>")
|
||||||
" - Qt " + __qt_version__ + "</center></p>")
|
|
||||||
licenseLabel = QtWidgets.QLabel(
|
|
||||||
"<center><p>Copyright © 2012–2018 Syncplay</p><p>" +
|
|
||||||
getMessage("about-dialog-license-text") + "</p></center>")
|
|
||||||
aboutIconPixmap = QtGui.QPixmap(resourcespath + "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))
|
||||||
@ -166,7 +154,6 @@ class AboutDialog(QtWidgets.QDialog):
|
|||||||
else:
|
else:
|
||||||
QtGui.QDesktopServices.openUrl(QUrl("file://" + resourcespath + "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
|
||||||
playlistState = []
|
playlistState = []
|
||||||
@ -360,6 +347,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
else:
|
else:
|
||||||
super(MainWindow.PlaylistWidget, self).dropEvent(event)
|
super(MainWindow.PlaylistWidget, self).dropEvent(event)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class topSplitter(QtWidgets.QSplitter):
|
class topSplitter(QtWidgets.QSplitter):
|
||||||
def createHandle(self):
|
def createHandle(self):
|
||||||
return self.topSplitterHandle(self.orientation(), self)
|
return self.topSplitterHandle(self.orientation(), self)
|
||||||
@ -481,16 +470,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
def showUserList(self, currentUser, rooms):
|
def showUserList(self, currentUser, rooms):
|
||||||
self._usertreebuffer = QtGui.QStandardItemModel()
|
self._usertreebuffer = QtGui.QStandardItemModel()
|
||||||
self._usertreebuffer.setHorizontalHeaderLabels(
|
self._usertreebuffer.setHorizontalHeaderLabels(
|
||||||
(
|
(getMessage("roomuser-heading-label"), getMessage("size-heading-label"), getMessage("duration-heading-label"), getMessage("filename-heading-label") ))
|
||||||
getMessage("roomuser-heading-label"), getMessage("size-heading-label"),
|
|
||||||
getMessage("duration-heading-label"), getMessage("filename-heading-label")
|
|
||||||
))
|
|
||||||
usertreeRoot = self._usertreebuffer.invisibleRootItem()
|
usertreeRoot = self._usertreebuffer.invisibleRootItem()
|
||||||
if (
|
if self._syncplayClient.userlist.currentUser.file and self._syncplayClient.userlist.currentUser.file and os.path.isfile(self._syncplayClient.userlist.currentUser.file["path"]):
|
||||||
self._syncplayClient.userlist.currentUser.file and
|
|
||||||
self._syncplayClient.userlist.currentUser.file and
|
|
||||||
os.path.isfile(self._syncplayClient.userlist.currentUser.file["path"])
|
|
||||||
):
|
|
||||||
self._syncplayClient.fileSwitch.setCurrentDirectory(os.path.dirname(self._syncplayClient.userlist.currentUser.file["path"]))
|
self._syncplayClient.fileSwitch.setCurrentDirectory(os.path.dirname(self._syncplayClient.userlist.currentUser.file["path"]))
|
||||||
|
|
||||||
for room in rooms:
|
for room in rooms:
|
||||||
@ -631,6 +613,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
menu.addAction(QtGui.QPixmap(resourcespath + "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))
|
||||||
|
|
||||||
|
|
||||||
def openRoomMenu(self, position):
|
def openRoomMenu(self, position):
|
||||||
# TODO: Deselect items after right click
|
# TODO: Deselect items after right click
|
||||||
indexes = self.listTreeView.selectedIndexes()
|
indexes = self.listTreeView.selectedIndexes()
|
||||||
@ -711,7 +694,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
def updateReadyState(self, newState):
|
def updateReadyState(self, newState):
|
||||||
oldState = self.readyPushButton.isChecked()
|
oldState = self.readyPushButton.isChecked()
|
||||||
if newState != oldState and newState is not None:
|
if newState != oldState and newState != None:
|
||||||
self.readyPushButton.blockSignals(True)
|
self.readyPushButton.blockSignals(True)
|
||||||
self.readyPushButton.setChecked(newState)
|
self.readyPushButton.setChecked(newState)
|
||||||
self.readyPushButton.blockSignals(False)
|
self.readyPushButton.blockSignals(False)
|
||||||
@ -785,7 +768,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
@needsClient
|
@needsClient
|
||||||
def joinRoom(self, room=None):
|
def joinRoom(self, room=None):
|
||||||
if room is None:
|
if room == None:
|
||||||
room = self.roomInput.text()
|
room = self.roomInput.text()
|
||||||
if room == "":
|
if room == "":
|
||||||
if self._syncplayClient.userlist.currentUser.file:
|
if self._syncplayClient.userlist.currentUser.file:
|
||||||
@ -798,13 +781,14 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
self._syncplayClient.sendRoom()
|
self._syncplayClient.sendRoom()
|
||||||
|
|
||||||
def seekPositionDialog(self):
|
def seekPositionDialog(self):
|
||||||
seekTime, ok = QtWidgets.QInputDialog.getText(
|
seekTime, ok = QtWidgets.QInputDialog.getText(self, getMessage("seektime-menu-label"),
|
||||||
self, getMessage("seektime-menu-label"),
|
|
||||||
getMessage("seektime-msgbox-label"), QtWidgets.QLineEdit.Normal,
|
getMessage("seektime-msgbox-label"), QtWidgets.QLineEdit.Normal,
|
||||||
"0:00")
|
"0:00")
|
||||||
if ok and seekTime != '':
|
if ok and seekTime != '':
|
||||||
self.seekPosition(seekTime)
|
self.seekPosition(seekTime)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def seekFromButton(self):
|
def seekFromButton(self):
|
||||||
self.seekPosition(self.seekInput.text())
|
self.seekPosition(self.seekInput.text())
|
||||||
|
|
||||||
@ -887,7 +871,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
@needsClient
|
@needsClient
|
||||||
def browseMediapath(self):
|
def browseMediapath(self):
|
||||||
if self._syncplayClient._player.customOpenDialog:
|
if self._syncplayClient._player.customOpenDialog == True:
|
||||||
self._syncplayClient._player.openCustomOpenDialog()
|
self._syncplayClient._player.openCustomOpenDialog()
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -903,8 +887,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
else:
|
else:
|
||||||
defaultdirectory = self.getInitialMediaDirectory()
|
defaultdirectory = self.getInitialMediaDirectory()
|
||||||
browserfilter = "All files (*)"
|
browserfilter = "All files (*)"
|
||||||
fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(
|
fileName, filtr = QtWidgets.QFileDialog.getOpenFileName(self, getMessage("browseformedia-label"), defaultdirectory,
|
||||||
self, getMessage("browseformedia-label"), defaultdirectory,
|
|
||||||
browserfilter, "", options)
|
browserfilter, "", options)
|
||||||
if fileName:
|
if fileName:
|
||||||
if isWindows():
|
if isWindows():
|
||||||
@ -916,7 +899,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
@needsClient
|
@needsClient
|
||||||
def OpenAddFilesToPlaylistDialog(self):
|
def OpenAddFilesToPlaylistDialog(self):
|
||||||
if self._syncplayClient._player.customOpenDialog:
|
if self._syncplayClient._player.customOpenDialog == True:
|
||||||
self._syncplayClient._player.openCustomOpenDialog()
|
self._syncplayClient._player.openCustomOpenDialog()
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -932,8 +915,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
else:
|
else:
|
||||||
defaultdirectory = self.getInitialMediaDirectory()
|
defaultdirectory = self.getInitialMediaDirectory()
|
||||||
browserfilter = "All files (*)"
|
browserfilter = "All files (*)"
|
||||||
fileNames, filtr = QtWidgets.QFileDialog.getOpenFileNames(
|
fileNames, filtr = QtWidgets.QFileDialog.getOpenFileNames(self, getMessage("browseformedia-label"), defaultdirectory,
|
||||||
self, getMessage("browseformedia-label"), defaultdirectory,
|
|
||||||
browserfilter, "", options)
|
browserfilter, "", options)
|
||||||
self.updatingPlaylist = True
|
self.updatingPlaylist = True
|
||||||
if fileNames:
|
if fileNames:
|
||||||
@ -1064,7 +1046,6 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
if result == QtWidgets.QDialog.Accepted:
|
if result == QtWidgets.QDialog.Accepted:
|
||||||
newTrustedDomains = utils.convertMultilineStringToList(TrustedDomainsTextbox.toPlainText())
|
newTrustedDomains = utils.convertMultilineStringToList(TrustedDomainsTextbox.toPlainText())
|
||||||
self._syncplayClient.setTrustedDomains(newTrustedDomains)
|
self._syncplayClient.setTrustedDomains(newTrustedDomains)
|
||||||
|
|
||||||
@needsClient
|
@needsClient
|
||||||
def addTrustedDomain(self, newDomain):
|
def addTrustedDomain(self, newDomain):
|
||||||
trustedDomains = self.config["trustedDomains"][:]
|
trustedDomains = self.config["trustedDomains"][:]
|
||||||
@ -1078,8 +1059,7 @@ 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 = str(QtWidgets.QFileDialog.getExistingDirectory(
|
folderName = str(QtWidgets.QFileDialog.getExistingDirectory(self,None,self.getInitialMediaDirectory(includeUserSpecifiedDirectories=False),options))
|
||||||
self, None, self.getInitialMediaDirectory(includeUserSpecifiedDirectories=False), options))
|
|
||||||
|
|
||||||
if folderName:
|
if folderName:
|
||||||
existingMediaDirs = MediaDirectoriesTextbox.toPlainText()
|
existingMediaDirs = MediaDirectoriesTextbox.toPlainText()
|
||||||
@ -1093,16 +1073,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
@needsClient
|
@needsClient
|
||||||
def promptForStreamURL(self):
|
def promptForStreamURL(self):
|
||||||
streamURL, ok = QtWidgets.QInputDialog.getText(
|
streamURL, ok = QtWidgets.QInputDialog.getText(self, getMessage("promptforstreamurl-msgbox-label"),
|
||||||
self, getMessage("promptforstreamurl-msgbox-label"),
|
getMessage("promptforstreamurlinfo-msgbox-label"), QtWidgets.QLineEdit.Normal,
|
||||||
getMessage("promptforstreamurlinfo-msgbox-label"), QtWidgets.QLineEdit.Normal, "")
|
"")
|
||||||
if ok and streamURL != '':
|
if ok and streamURL != '':
|
||||||
self._syncplayClient._player.openFile(streamURL)
|
self._syncplayClient._player.openFile(streamURL)
|
||||||
|
|
||||||
@needsClient
|
@needsClient
|
||||||
def createControlledRoom(self):
|
def createControlledRoom(self):
|
||||||
controlroom, ok = QtWidgets.QInputDialog.getText(
|
controlroom, ok = QtWidgets.QInputDialog.getText(self, getMessage("createcontrolledroom-msgbox-label"),
|
||||||
self, getMessage("createcontrolledroom-msgbox-label"),
|
|
||||||
getMessage("controlledroominfo-msgbox-label"), QtWidgets.QLineEdit.Normal,
|
getMessage("controlledroominfo-msgbox-label"), QtWidgets.QLineEdit.Normal,
|
||||||
utils.stripRoomName(self._syncplayClient.getRoom()))
|
utils.stripRoomName(self._syncplayClient.getRoom()))
|
||||||
if ok and controlroom != '':
|
if ok and controlroom != '':
|
||||||
@ -1127,9 +1106,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
@needsClient
|
@needsClient
|
||||||
def setOffset(self):
|
def setOffset(self):
|
||||||
newoffset, ok = QtWidgets.QInputDialog.getText(
|
newoffset, ok = QtWidgets.QInputDialog.getText(self, getMessage("setoffset-msgbox-label"),
|
||||||
self, getMessage("setoffset-msgbox-label"),
|
getMessage("offsetinfo-msgbox-label"), QtWidgets.QLineEdit.Normal,
|
||||||
getMessage("offsetinfo-msgbox-label"), QtWidgets.QLineEdit.Normal, "")
|
"")
|
||||||
if ok and newoffset != '':
|
if ok and newoffset != '':
|
||||||
o = re.match(constants.UI_OFFSET_REGEX, "o " + newoffset)
|
o = re.match(constants.UI_OFFSET_REGEX, "o " + newoffset)
|
||||||
if o:
|
if o:
|
||||||
@ -1208,8 +1187,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
window.chatInput = QtWidgets.QLineEdit()
|
window.chatInput = QtWidgets.QLineEdit()
|
||||||
window.chatInput.setMaxLength(constants.MAX_CHAT_MESSAGE_LENGTH)
|
window.chatInput.setMaxLength(constants.MAX_CHAT_MESSAGE_LENGTH)
|
||||||
window.chatInput.returnPressed.connect(self.sendChatMessage)
|
window.chatInput.returnPressed.connect(self.sendChatMessage)
|
||||||
window.chatButton = QtWidgets.QPushButton(
|
window.chatButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + 'email_go.png'),
|
||||||
QtGui.QPixmap(resourcespath + 'email_go.png'),
|
|
||||||
getMessage("sendmessage-label"))
|
getMessage("sendmessage-label"))
|
||||||
window.chatButton.pressed.connect(self.sendChatMessage)
|
window.chatButton.pressed.connect(self.sendChatMessage)
|
||||||
window.chatLayout = QtWidgets.QHBoxLayout()
|
window.chatLayout = QtWidgets.QHBoxLayout()
|
||||||
@ -1264,8 +1242,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
window.roomInput = QtWidgets.QLineEdit()
|
window.roomInput = QtWidgets.QLineEdit()
|
||||||
window.roomInput.setMaxLength(constants.MAX_ROOM_NAME_LENGTH)
|
window.roomInput.setMaxLength(constants.MAX_ROOM_NAME_LENGTH)
|
||||||
window.roomInput.returnPressed.connect(self.joinRoom)
|
window.roomInput.returnPressed.connect(self.joinRoom)
|
||||||
window.roomButton = QtWidgets.QPushButton(
|
window.roomButton = QtWidgets.QPushButton(QtGui.QPixmap(resourcespath + 'door_in.png'),
|
||||||
QtGui.QPixmap(resourcespath + 'door_in.png'),
|
|
||||||
getMessage("joinroom-label"))
|
getMessage("joinroom-label"))
|
||||||
window.roomButton.pressed.connect(self.joinRoom)
|
window.roomButton.pressed.connect(self.joinRoom)
|
||||||
window.roomLayout = QtWidgets.QHBoxLayout()
|
window.roomLayout = QtWidgets.QHBoxLayout()
|
||||||
@ -1428,6 +1405,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
getMessage("setmediadirectories-menu-label"))
|
getMessage("setmediadirectories-menu-label"))
|
||||||
window.openAction.triggered.connect(self.openSetMediaDirectoriesDialog)
|
window.openAction.triggered.connect(self.openSetMediaDirectoriesDialog)
|
||||||
|
|
||||||
|
|
||||||
window.exitAction = window.fileMenu.addAction(QtGui.QPixmap(resourcespath + 'cross.png'),
|
window.exitAction = window.fileMenu.addAction(QtGui.QPixmap(resourcespath + 'cross.png'),
|
||||||
getMessage("exit-menu-label"))
|
getMessage("exit-menu-label"))
|
||||||
window.exitAction.triggered.connect(self.exitSyncplay)
|
window.exitAction.triggered.connect(self.exitSyncplay)
|
||||||
@ -1436,21 +1414,13 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
# Playback menu
|
# Playback menu
|
||||||
|
|
||||||
window.playbackMenu = QtWidgets.QMenu(getMessage("playback-menu-label"), self)
|
window.playbackMenu = QtWidgets.QMenu(getMessage("playback-menu-label"), self)
|
||||||
window.playAction = window.playbackMenu.addAction(
|
window.playAction = window.playbackMenu.addAction(QtGui.QPixmap(resourcespath + 'control_play_blue.png'), getMessage("play-menu-label"))
|
||||||
QtGui.QPixmap(resourcespath + 'control_play_blue.png'),
|
|
||||||
getMessage("play-menu-label"))
|
|
||||||
window.playAction.triggered.connect(self.play)
|
window.playAction.triggered.connect(self.play)
|
||||||
window.pauseAction = window.playbackMenu.addAction(
|
window.pauseAction = window.playbackMenu.addAction(QtGui.QPixmap(resourcespath + 'control_pause_blue.png'), getMessage("pause-menu-label"))
|
||||||
QtGui.QPixmap(resourcespath + 'control_pause_blue.png'),
|
|
||||||
getMessage("pause-menu-label"))
|
|
||||||
window.pauseAction.triggered.connect(self.pause)
|
window.pauseAction.triggered.connect(self.pause)
|
||||||
window.seekAction = window.playbackMenu.addAction(
|
window.seekAction = window.playbackMenu.addAction(QtGui.QPixmap(resourcespath + 'clock_go.png'), getMessage("seektime-menu-label"))
|
||||||
QtGui.QPixmap(resourcespath + 'clock_go.png'),
|
|
||||||
getMessage("seektime-menu-label"))
|
|
||||||
window.seekAction.triggered.connect(self.seekPositionDialog)
|
window.seekAction.triggered.connect(self.seekPositionDialog)
|
||||||
window.unseekAction = window.playbackMenu.addAction(
|
window.unseekAction = window.playbackMenu.addAction(QtGui.QPixmap(resourcespath + 'arrow_undo.png'), getMessage("undoseek-menu-label"))
|
||||||
QtGui.QPixmap(resourcespath + 'arrow_undo.png'),
|
|
||||||
getMessage("undoseek-menu-label"))
|
|
||||||
window.unseekAction.triggered.connect(self.undoSeek)
|
window.unseekAction.triggered.connect(self.undoSeek)
|
||||||
|
|
||||||
window.menuBar.addMenu(window.playbackMenu)
|
window.menuBar.addMenu(window.playbackMenu)
|
||||||
@ -1458,12 +1428,10 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
# Advanced menu
|
# Advanced menu
|
||||||
|
|
||||||
window.advancedMenu = QtWidgets.QMenu(getMessage("advanced-menu-label"), self)
|
window.advancedMenu = QtWidgets.QMenu(getMessage("advanced-menu-label"), self)
|
||||||
window.setoffsetAction = window.advancedMenu.addAction(
|
window.setoffsetAction = window.advancedMenu.addAction(QtGui.QPixmap(resourcespath + 'timeline_marker.png'),
|
||||||
QtGui.QPixmap(resourcespath + 'timeline_marker.png'),
|
|
||||||
getMessage("setoffset-menu-label"))
|
getMessage("setoffset-menu-label"))
|
||||||
window.setoffsetAction.triggered.connect(self.setOffset)
|
window.setoffsetAction.triggered.connect(self.setOffset)
|
||||||
window.setTrustedDomainsAction = window.advancedMenu.addAction(
|
window.setTrustedDomainsAction = window.advancedMenu.addAction(QtGui.QPixmap(resourcespath + 'shield_edit.png'),
|
||||||
QtGui.QPixmap(resourcespath + 'shield_edit.png'),
|
|
||||||
getMessage("settrusteddomains-menu-label"))
|
getMessage("settrusteddomains-menu-label"))
|
||||||
window.setTrustedDomainsAction.triggered.connect(self.openSetTrustedDomainsDialog)
|
window.setTrustedDomainsAction.triggered.connect(self.openSetTrustedDomainsDialog)
|
||||||
window.createcontrolledroomAction = window.advancedMenu.addAction(
|
window.createcontrolledroomAction = window.advancedMenu.addAction(
|
||||||
@ -1488,23 +1456,21 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
window.autoplayAction.triggered.connect(self.updateAutoplayVisibility)
|
window.autoplayAction.triggered.connect(self.updateAutoplayVisibility)
|
||||||
window.menuBar.addMenu(window.windowMenu)
|
window.menuBar.addMenu(window.windowMenu)
|
||||||
|
|
||||||
|
|
||||||
# Help menu
|
# Help menu
|
||||||
|
|
||||||
window.helpMenu = QtWidgets.QMenu(getMessage("help-menu-label"), self)
|
window.helpMenu = QtWidgets.QMenu(getMessage("help-menu-label"), self)
|
||||||
|
|
||||||
window.userguideAction = window.helpMenu.addAction(
|
window.userguideAction = window.helpMenu.addAction(QtGui.QPixmap(resourcespath + 'help.png'),
|
||||||
QtGui.QPixmap(resourcespath + 'help.png'),
|
|
||||||
getMessage("userguide-menu-label"))
|
getMessage("userguide-menu-label"))
|
||||||
window.userguideAction.triggered.connect(self.openUserGuide)
|
window.userguideAction.triggered.connect(self.openUserGuide)
|
||||||
window.updateAction = window.helpMenu.addAction(
|
window.updateAction = window.helpMenu.addAction(QtGui.QPixmap(resourcespath + 'application_get.png'),
|
||||||
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(
|
window.about = window.helpMenu.addAction(QtGui.QPixmap(resourcespath + 'syncplay.png'),
|
||||||
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")
|
||||||
@ -1562,7 +1528,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
def updateAutoPlayState(self, newState):
|
def updateAutoPlayState(self, newState):
|
||||||
oldState = self.autoplayPushButton.isChecked()
|
oldState = self.autoplayPushButton.isChecked()
|
||||||
if newState != oldState and newState is not None:
|
if newState != oldState and newState != None:
|
||||||
self.autoplayPushButton.blockSignals(True)
|
self.autoplayPushButton.blockSignals(True)
|
||||||
self.autoplayPushButton.setChecked(newState)
|
self.autoplayPushButton.setChecked(newState)
|
||||||
self.autoplayPushButton.blockSignals(False)
|
self.autoplayPushButton.blockSignals(False)
|
||||||
@ -1625,11 +1591,10 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
else:
|
else:
|
||||||
import syncplay
|
import syncplay
|
||||||
updateMessage = getMessage("update-check-failed-notification").format(syncplay.version)
|
updateMessage = getMessage("update-check-failed-notification").format(syncplay.version)
|
||||||
if userInitiated:
|
if userInitiated == True:
|
||||||
updateURL = constants.SYNCPLAY_DOWNLOAD_URL
|
updateURL = constants.SYNCPLAY_DOWNLOAD_URL
|
||||||
if updateURL is not None:
|
if updateURL is not None:
|
||||||
reply = QtWidgets.QMessageBox.question(
|
reply = QtWidgets.QMessageBox.question(self, "Syncplay",
|
||||||
self, "Syncplay",
|
|
||||||
updateMessage, QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No)
|
updateMessage, QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No)
|
||||||
if reply == QtWidgets.QMessageBox.Yes:
|
if reply == QtWidgets.QMessageBox.Yes:
|
||||||
self.QtGui.QDesktopServices.openUrl(QUrl(updateURL))
|
self.QtGui.QDesktopServices.openUrl(QUrl(updateURL))
|
||||||
@ -1659,7 +1624,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|||||||
dropfilepath = os.path.abspath(NSURL.URLWithString_(pathString).filePathURL().path())
|
dropfilepath = os.path.abspath(NSURL.URLWithString_(pathString).filePathURL().path())
|
||||||
else:
|
else:
|
||||||
dropfilepath = os.path.abspath(str(url.toLocalFile()))
|
dropfilepath = os.path.abspath(str(url.toLocalFile()))
|
||||||
if not rewindFile:
|
if rewindFile == False:
|
||||||
self._syncplayClient._player.openFile(dropfilepath)
|
self._syncplayClient._player.openFile(dropfilepath)
|
||||||
else:
|
else:
|
||||||
self._syncplayClient.setPosition(0)
|
self._syncplayClient.setPosition(0)
|
||||||
|
|||||||
@ -1,44 +1,35 @@
|
|||||||
|
|
||||||
import ast
|
|
||||||
import datetime
|
|
||||||
import hashlib
|
|
||||||
import itertools
|
|
||||||
import random
|
|
||||||
import os
|
|
||||||
import platform
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
import traceback
|
import re
|
||||||
import unicodedata
|
import datetime
|
||||||
import urllib.error
|
|
||||||
import urllib.parse
|
|
||||||
import urllib.request
|
|
||||||
|
|
||||||
from syncplay import constants
|
from syncplay import constants
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import itertools
|
||||||
|
import hashlib
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import urllib.request, urllib.parse, urllib.error
|
||||||
|
import ast
|
||||||
|
import unicodedata
|
||||||
|
import platform
|
||||||
|
import subprocess
|
||||||
|
import traceback
|
||||||
|
|
||||||
folderSearchEnabled = True
|
folderSearchEnabled = True
|
||||||
|
|
||||||
|
|
||||||
def isWindows():
|
def isWindows():
|
||||||
return sys.platform.startswith(constants.OS_WINDOWS)
|
return sys.platform.startswith(constants.OS_WINDOWS)
|
||||||
|
|
||||||
|
|
||||||
def isLinux():
|
def isLinux():
|
||||||
return sys.platform.startswith(constants.OS_LINUX)
|
return sys.platform.startswith(constants.OS_LINUX)
|
||||||
|
|
||||||
|
|
||||||
def isMacOS():
|
def isMacOS():
|
||||||
return sys.platform.startswith(constants.OS_MACOS)
|
return sys.platform.startswith(constants.OS_MACOS)
|
||||||
|
|
||||||
|
|
||||||
def isBSD():
|
def isBSD():
|
||||||
return constants.OS_BSD in sys.platform or sys.platform.startswith(constants.OS_DRAGONFLY)
|
return constants.OS_BSD in sys.platform or sys.platform.startswith(constants.OS_DRAGONFLY)
|
||||||
|
|
||||||
|
|
||||||
def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
|
def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
|
||||||
"""Retry calling the decorated function using an exponential backoff.
|
"""Retry calling the decorated function using an exponential backoff.
|
||||||
|
|
||||||
@ -80,7 +71,6 @@ def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None):
|
|||||||
return f_retry # true decorator
|
return f_retry # true decorator
|
||||||
return deco_retry
|
return deco_retry
|
||||||
|
|
||||||
|
|
||||||
def parseTime(timeStr):
|
def parseTime(timeStr):
|
||||||
regex = re.compile(constants.PARSE_TIME_REGEX)
|
regex = re.compile(constants.PARSE_TIME_REGEX)
|
||||||
parts = regex.match(timeStr)
|
parts = regex.match(timeStr)
|
||||||
@ -96,7 +86,6 @@ def parseTime(timeStr):
|
|||||||
time_params[name] = int(param)
|
time_params[name] = int(param)
|
||||||
return datetime.timedelta(**time_params).total_seconds()
|
return datetime.timedelta(**time_params).total_seconds()
|
||||||
|
|
||||||
|
|
||||||
def formatTime(timeInSeconds, weeksAsTitles=True):
|
def formatTime(timeInSeconds, weeksAsTitles=True):
|
||||||
if timeInSeconds < 0:
|
if timeInSeconds < 0:
|
||||||
timeInSeconds = -timeInSeconds
|
timeInSeconds = -timeInSeconds
|
||||||
@ -126,8 +115,7 @@ def formatTime(timeInSeconds, weeksAsTitles=True):
|
|||||||
formattedTime = "{0:} (Title {1:.0f})".format(formattedTime, title)
|
formattedTime = "{0:} (Title {1:.0f})".format(formattedTime, title)
|
||||||
return formattedTime
|
return formattedTime
|
||||||
|
|
||||||
|
def formatSize (bytes, precise=False):
|
||||||
def formatSize(num_of_bytes, precise=False):
|
|
||||||
if bytes == 0: # E.g. when file size privacy is enabled
|
if bytes == 0: # E.g. when file size privacy is enabled
|
||||||
return "???"
|
return "???"
|
||||||
try:
|
try:
|
||||||
@ -140,11 +128,9 @@ def formatSize(num_of_bytes, precise=False):
|
|||||||
except: # E.g. when filesize is hashed
|
except: # E.g. when filesize is hashed
|
||||||
return "???"
|
return "???"
|
||||||
|
|
||||||
|
|
||||||
def isASCII(s):
|
def isASCII(s):
|
||||||
return all(ord(c) < 128 for c in s)
|
return all(ord(c) < 128 for c in s)
|
||||||
|
|
||||||
|
|
||||||
def findResourcePath(resourceName):
|
def findResourcePath(resourceName):
|
||||||
if resourceName == "syncplay.lua":
|
if resourceName == "syncplay.lua":
|
||||||
resourcePath = os.path.join(findWorkingDir(), "lua", "intf" , "resources", resourceName)
|
resourcePath = os.path.join(findWorkingDir(), "lua", "intf" , "resources", resourceName)
|
||||||
@ -152,7 +138,6 @@ def findResourcePath(resourceName):
|
|||||||
resourcePath = os.path.join(findWorkingDir(),"resources", resourceName)
|
resourcePath = os.path.join(findWorkingDir(),"resources", resourceName)
|
||||||
return resourcePath
|
return resourcePath
|
||||||
|
|
||||||
|
|
||||||
def findWorkingDir():
|
def findWorkingDir():
|
||||||
frozen = getattr(sys, 'frozen', '')
|
frozen = getattr(sys, 'frozen', '')
|
||||||
if not frozen:
|
if not frozen:
|
||||||
@ -168,18 +153,15 @@ def findWorkingDir():
|
|||||||
path = ""
|
path = ""
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
||||||
def getResourcesPath():
|
def getResourcesPath():
|
||||||
if isWindows():
|
if isWindows():
|
||||||
return findWorkingDir() + "\\resources\\"
|
return findWorkingDir() + "\\resources\\"
|
||||||
else:
|
else:
|
||||||
return findWorkingDir() + "/resources/"
|
return findWorkingDir() + "/resources/"
|
||||||
|
|
||||||
|
|
||||||
resourcespath = getResourcesPath()
|
resourcespath = getResourcesPath()
|
||||||
posixresourcespath = findWorkingDir().replace("\\","/") + "/resources/"
|
posixresourcespath = findWorkingDir().replace("\\","/") + "/resources/"
|
||||||
|
|
||||||
|
|
||||||
def getDefaultMonospaceFont():
|
def getDefaultMonospaceFont():
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
return constants.DEFAULT_WINDOWS_MONOSPACE_FONT
|
return constants.DEFAULT_WINDOWS_MONOSPACE_FONT
|
||||||
@ -188,18 +170,15 @@ def getDefaultMonospaceFont():
|
|||||||
else:
|
else:
|
||||||
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 range(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":
|
||||||
class Stderr(object):
|
class Stderr(object):
|
||||||
softspace = 0
|
softspace = 0
|
||||||
_file = None
|
_file = None
|
||||||
_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':
|
||||||
@ -211,27 +190,21 @@ def blackholeStdoutForFrozenWindow():
|
|||||||
if self._file is not None:
|
if self._file is not None:
|
||||||
self._file.write(text)
|
self._file.write(text)
|
||||||
self._file.flush()
|
self._file.flush()
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
if self._file is not None:
|
if self._file is not None:
|
||||||
self._file.flush()
|
self._file.flush()
|
||||||
|
|
||||||
sys.stderr = Stderr()
|
sys.stderr = Stderr()
|
||||||
del Stderr
|
del Stderr
|
||||||
|
|
||||||
class Blackhole(object):
|
class Blackhole(object):
|
||||||
softspace = 0
|
softspace = 0
|
||||||
|
|
||||||
def write(self, text):
|
def write(self, text):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
sys.stdout = Blackhole()
|
sys.stdout = Blackhole()
|
||||||
del Blackhole
|
del Blackhole
|
||||||
|
|
||||||
|
|
||||||
def truncateText(unicodeText, maxLength):
|
def truncateText(unicodeText, maxLength):
|
||||||
try:
|
try:
|
||||||
unicodeText = unicodeText.decode('utf-8')
|
unicodeText = unicodeText.decode('utf-8')
|
||||||
@ -243,7 +216,6 @@ def truncateText(unicodeText, maxLength):
|
|||||||
pass
|
pass
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def splitText(unicodeText, maxLength):
|
def splitText(unicodeText, maxLength):
|
||||||
try:
|
try:
|
||||||
unicodeText = unicodeText.decode('utf-8')
|
unicodeText = unicodeText.decode('utf-8')
|
||||||
@ -259,7 +231,6 @@ def splitText(unicodeText, maxLength):
|
|||||||
|
|
||||||
# Relate to file hashing / difference checking:
|
# Relate to file hashing / difference checking:
|
||||||
|
|
||||||
|
|
||||||
def stripfilename(filename, stripURL):
|
def stripfilename(filename, stripURL):
|
||||||
if filename:
|
if filename:
|
||||||
try:
|
try:
|
||||||
@ -276,7 +247,6 @@ def stripfilename(filename, stripURL):
|
|||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def stripRoomName(RoomName):
|
def stripRoomName(RoomName):
|
||||||
if RoomName:
|
if RoomName:
|
||||||
try:
|
try:
|
||||||
@ -286,7 +256,6 @@ def stripRoomName(RoomName):
|
|||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def hashFilename(filename, stripURL = False):
|
def hashFilename(filename, stripURL = False):
|
||||||
if isURL(filename):
|
if isURL(filename):
|
||||||
stripURL = True
|
stripURL = True
|
||||||
@ -298,11 +267,9 @@ def hashFilename(filename, stripURL=False):
|
|||||||
filenameHash = hashlib.sha256(strippedFilename).hexdigest()[:12]
|
filenameHash = hashlib.sha256(strippedFilename).hexdigest()[:12]
|
||||||
return filenameHash
|
return filenameHash
|
||||||
|
|
||||||
|
|
||||||
def hashFilesize(size):
|
def hashFilesize(size):
|
||||||
return hashlib.sha256(str(size).encode('utf-8')).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:
|
||||||
if string1raw.lower() == string2raw.lower():
|
if string1raw.lower() == string2raw.lower():
|
||||||
@ -318,7 +285,6 @@ def sameHashed(string1raw, string1hashed, string2raw, string2hashed):
|
|||||||
elif string1hashed == string2hashed:
|
elif string1hashed == string2hashed:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def sameFilename (filename1, filename2):
|
def sameFilename (filename1, filename2):
|
||||||
try:
|
try:
|
||||||
filename1 = filename1
|
filename1 = filename1
|
||||||
@ -336,7 +302,6 @@ def sameFilename(filename1, filename2):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def sameFilesize (filesize1, filesize2):
|
def sameFilesize (filesize1, filesize2):
|
||||||
if filesize1 == 0 or filesize2 == 0:
|
if filesize1 == 0 or filesize2 == 0:
|
||||||
return True
|
return True
|
||||||
@ -345,7 +310,6 @@ def sameFilesize(filesize1, filesize2):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def sameFileduration (duration1, duration2):
|
def sameFileduration (duration1, duration2):
|
||||||
if not constants.SHOW_DURATION_NOTIFICATION:
|
if not constants.SHOW_DURATION_NOTIFICATION:
|
||||||
return True
|
return True
|
||||||
@ -354,13 +318,11 @@ def sameFileduration(duration1, duration2):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def meetsMinVersion(version, minVersion):
|
def meetsMinVersion(version, minVersion):
|
||||||
def versiontotuple(ver):
|
def versiontotuple(ver):
|
||||||
return tuple(map(int, ver.split(".")))
|
return tuple(map(int, ver.split(".")))
|
||||||
return versiontotuple(version) >= versiontotuple(minVersion)
|
return versiontotuple(version) >= versiontotuple(minVersion)
|
||||||
|
|
||||||
|
|
||||||
def isURL(path):
|
def isURL(path):
|
||||||
if path is None:
|
if path is None:
|
||||||
return False
|
return False
|
||||||
@ -369,27 +331,22 @@ def isURL(path):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def getPlayerArgumentsByPathAsArray(arguments, path):
|
def getPlayerArgumentsByPathAsArray(arguments, path):
|
||||||
if arguments and not isinstance(arguments, str) and path in arguments:
|
if arguments and not isinstance(arguments, str) and path in arguments:
|
||||||
return arguments[path]
|
return arguments[path]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def getPlayerArgumentsByPathAsText(arguments, path):
|
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 getListAsMultilineString(pathArray):
|
def getListAsMultilineString(pathArray):
|
||||||
return "\n".join(pathArray) if pathArray else ""
|
return "\n".join(pathArray) if pathArray else ""
|
||||||
|
|
||||||
|
|
||||||
def convertMultilineStringToList(multilineString):
|
def convertMultilineStringToList(multilineString):
|
||||||
return str.split(multilineString,"\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:
|
||||||
return False
|
return False
|
||||||
@ -397,7 +354,6 @@ def playlistIsValid(files):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def getDomainFromURL(URL):
|
def getDomainFromURL(URL):
|
||||||
try:
|
try:
|
||||||
URL = URL.split("//")[-1].split("/")[0]
|
URL = URL.split("//")[-1].split("/")[0]
|
||||||
@ -407,7 +363,6 @@ def getDomainFromURL(URL):
|
|||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def open_system_file_browser(path):
|
def open_system_file_browser(path):
|
||||||
if isURL(path):
|
if isURL(path):
|
||||||
return
|
return
|
||||||
@ -419,7 +374,6 @@ def open_system_file_browser(path):
|
|||||||
else:
|
else:
|
||||||
subprocess.Popen(["xdg-open", path])
|
subprocess.Popen(["xdg-open", path])
|
||||||
|
|
||||||
|
|
||||||
def getListOfPublicServers():
|
def getListOfPublicServers():
|
||||||
try:
|
try:
|
||||||
import urllib.request, urllib.parse, urllib.error, syncplay, sys
|
import urllib.request, urllib.parse, urllib.error, syncplay, sys
|
||||||
@ -440,13 +394,12 @@ def getListOfPublicServers():
|
|||||||
else:
|
else:
|
||||||
raise IOError
|
raise IOError
|
||||||
except:
|
except:
|
||||||
if constants.DEBUG_MODE:
|
if constants.DEBUG_MODE == True:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
raise IOError(getMessage("failed-to-load-server-list-error"))
|
raise IOError(getMessage("failed-to-load-server-list-error"))
|
||||||
|
|
||||||
|
|
||||||
class RoomPasswordProvider(object):
|
class RoomPasswordProvider(object):
|
||||||
CONTROLLED_ROOM_REGEX = re.compile("^\+(.*):(\w{12})$")
|
CONTROLLED_ROOM_REGEX = re.compile("^\+(.*):(\w{12})$")
|
||||||
PASSWORD_REGEX = re.compile("[A-Z]{2}-\d{3}-\d{3}")
|
PASSWORD_REGEX = re.compile("[A-Z]{2}-\d{3}-\d{3}")
|
||||||
@ -480,7 +433,6 @@ class RoomPasswordProvider(object):
|
|||||||
provisionalHash = hashlib.sha256(roomName + salt).hexdigest()
|
provisionalHash = hashlib.sha256(roomName + salt).hexdigest()
|
||||||
return hashlib.sha1(provisionalHash + salt + password).hexdigest()[:12].upper()
|
return hashlib.sha1(provisionalHash + salt + password).hexdigest()[:12].upper()
|
||||||
|
|
||||||
|
|
||||||
class RandomStringGenerator(object):
|
class RandomStringGenerator(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_room_password():
|
def generate_room_password():
|
||||||
@ -506,6 +458,6 @@ class RandomStringGenerator(object):
|
|||||||
def _get_random_numbers(quantity):
|
def _get_random_numbers(quantity):
|
||||||
return ''.join(random.choice(string.digits) for _ in range(quantity))
|
return ''.join(random.choice(string.digits) for _ in range(quantity))
|
||||||
|
|
||||||
|
|
||||||
class NotControlledRoom(Exception):
|
class NotControlledRoom(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@ -17,3 +17,4 @@ from syncplay.utils import blackholeStdoutForFrozenWindow
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
blackholeStdoutForFrozenWindow()
|
blackholeStdoutForFrozenWindow()
|
||||||
SyncplayClientManager().run()
|
SyncplayClientManager().run()
|
||||||
|
|
||||||
|
|||||||
@ -19,14 +19,5 @@ from syncplay.server import SyncFactory, ConfigurationGetter
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
argsGetter = ConfigurationGetter()
|
argsGetter = ConfigurationGetter()
|
||||||
args = argsGetter.getConfiguration()
|
args = argsGetter.getConfiguration()
|
||||||
reactor.listenTCP(
|
reactor.listenTCP(int(args.port), SyncFactory(args.password, args.motd_file, args.isolate_rooms, args.salt, args.disable_ready,args.disable_chat, args.max_chat_message_length))
|
||||||
int(args.port),
|
|
||||||
SyncFactory(
|
|
||||||
args.password,
|
|
||||||
args.motd_file,
|
|
||||||
args.isolate_rooms,
|
|
||||||
args.salt,
|
|
||||||
args.disable_ready,
|
|
||||||
args.disable_chat,
|
|
||||||
args.max_chat_message_length))
|
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user