fix formattings

This commit is contained in:
Daniel Ahn 2018-07-20 12:12:55 -07:00
parent 759f1e1457
commit f01de206d8
13 changed files with 362 additions and 225 deletions

View File

@ -7,6 +7,7 @@ import os.path
application = defines.get('app', 'dist/Syncplay.app')
appname = os.path.basename(application)
def icon_from_app(app_path):
plist_path = os.path.join(app_path, 'Contents', 'Info.plist')
plist = biplist.readPlist(plist_path)
@ -17,6 +18,7 @@ def icon_from_app(app_path):
icon_name = icon_root + icon_ext
return os.path.join(app_path, 'Contents', 'Resources', icon_name)
# Volume format (see hdiutil create -help)
format = defines.get('format', 'UDZO')
@ -27,10 +29,19 @@ compression_level = 9
size = defines.get('size', None)
# Files to include
files = [ application, 'resources/lua/intf/.syncplay.lua', 'resources/.macos_vlc_install.command', 'resources/.macOS_readme.pdf' ]
files = [
application,
'resources/lua/intf/.syncplay.lua',
'resources/.macos_vlc_install.command',
'resources/.macOS_readme.pdf'
]
# Symlinks to create
symlinks = { 'Applications': '/Applications', 'Install for VLC': '.macos_vlc_install.command', 'Read Me': '.macOS_readme.pdf' }
symlinks = {
'Applications': '/Applications',
'Install for VLC': '.macos_vlc_install.command',
'Read Me': '.macOS_readme.pdf'
}
# Volume icon
#

View File

@ -5,8 +5,8 @@
# *** TROUBLESHOOTING ***
# 1) If you get the error "ImportError: No module named zope.interface" then add an empty __init__.py file to the PYTHONDIR/Lib/site-packages/zope directory
# 2) It is expected that you will have NSIS 3 NSIS from http://nsis.sourceforge.net installed.
import sys, codecs
import codecs
import sys
# try:
# if (sys.version_info.major != 2) or (sys.version_info.minor < 7):
# raise Exception("You must build Syncplay with Python 2.7!")
@ -14,18 +14,20 @@ import sys, codecs
# import warnings
# warnings.warn("You must build Syncplay with Python 2.7!")
import os
import subprocess
from string import Template
import syncplay
import os
import subprocess
from syncplay.messages import getMissingStrings
missingStrings = getMissingStrings()
if missingStrings is not None and missingStrings is not "":
import warnings
warnings.warn("MISSING/UNUSED STRINGS DETECTED:\n{}".format(missingStrings))
def get_nsis_path():
bin_name = "makensis.exe"
from winreg import HKEY_LOCAL_MACHINE as HKLM
@ -39,9 +41,11 @@ def get_nsis_path():
raise Exception("You must install NSIS 3 or later.")
except WindowsError:
return bin_name
NSIS_COMPILE = get_nsis_path()
OUT_DIR = "dist\Syncplay"
OUT_DIR = r"dist\Syncplay"
SETUP_SCRIPT_PATH = "syncplay_setup.nsi"
NSIS_SCRIPT_TEMPLATE = r"""
!include LogicLib.nsh
@ -608,6 +612,7 @@ NSIS_SCRIPT_TEMPLATE = r"""
SectionEnd
"""
class NSISScript(object):
def create(self):
fileList, totalSize = self.getBuildDirContents(OUT_DIR)
@ -664,7 +669,9 @@ class NSISScript(object):
delete.append('RMdir "$INSTDIR\\{}"'.format(file_))
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/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png',
'resources/timeline_marker.png', 'resources/control_play_blue.png',
@ -686,7 +693,13 @@ guiIcons = ['resources/accept.png', 'resources/arrow_undo.png', 'resources/clock
'resources/email_go.png',
'resources/world_add.png', 'resources/film_add.png', 'resources/delete.png', 'resources/spinner.mng'
]
resources = ["resources/icon.ico", "resources/syncplay.png", "resources/syncplayintf.lua", "resources/license.rtf", "resources/third-party-notices.rtf"]
resources = [
"resources/icon.ico",
"resources/syncplay.png",
"resources/syncplayintf.lua",
"resources/license.rtf",
"resources/third-party-notices.rtf"
]
resources.extend(guiIcons)
intf_resources = ["resources/lua/intf/syncplay.lua"]

View File

@ -18,7 +18,12 @@ OPTIONS = {
'extra_scripts': 'syncplayServer.py',
'includes': {'PySide2.QtCore', 'PySide2.QtUiTools', 'PySide2.QtGui', 'PySide2.QtWidgets', 'certifi'},
'excludes': {'PySide', 'PySide.QtCore', 'PySide.QtUiTools', 'PySide.QtGui'},
'qt_plugins': ['platforms/libqcocoa.dylib', 'platforms/libqminimal.dylib','platforms/libqoffscreen.dylib', 'styles/libqmacstyle.dylib'],
'qt_plugins': [
'platforms/libqcocoa.dylib',
'platforms/libqminimal.dylib',
'platforms/libqoffscreen.dylib',
'styles/libqmacstyle.dylib'
],
'plist': {
'CFBundleName': 'Syncplay',
'CFBundleShortVersionString': syncplay.version,

View File

@ -12,5 +12,6 @@ except ImportError:
from syncplay.players.basePlayer import DummyPlayer
MpcBePlayer = DummyPlayer
def getAvailablePlayers():
return [MPCHCAPIPlayer, MplayerPlayer, MpvPlayer, VlcPlayer, MpcBePlayer]

View File

@ -1,4 +1,6 @@
from syncplay import constants
class BasePlayer(object):
'''
@ -12,7 +14,9 @@ class BasePlayer(object):
'''
Display given message on player's OSD or similar means
'''
def displayMessage(self, message, duration = (constants.OSD_DURATION*1000), secondaryOSD=False, mood=constants.MESSAGE_NEUTRAL):
def displayMessage(
self, message, duration=(constants.OSD_DURATION*1000), secondaryOSD=False, mood=constants.MESSAGE_NEUTRAL
):
raise NotImplementedError()
'''
@ -58,7 +62,6 @@ class BasePlayer(object):
def openFile(self, filePath, resetPosition=False):
raise NotImplementedError()
'''
@return: list of strings
'''
@ -107,6 +110,7 @@ class BasePlayer(object):
def getPlayerPathErrors(playerPath, filePath):
raise NotImplementedError()
class DummyPlayer(BasePlayer):
@staticmethod

View File

@ -1,15 +1,18 @@
#coding:utf8
import os.path
import re
import time
import threading
import _thread
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
import win32con, win32api, win32gui, ctypes, ctypes.wintypes #@UnresolvedImport @UnusedImport
from syncplay import constants
from syncplay.messages import getMessage
import os.path
from syncplay.players.basePlayer import BasePlayer
from syncplay.utils import retry
class MpcHcApi:
def __init__(self):
@ -49,7 +52,7 @@ class MpcHcApi:
self.__listener.SendCommand(self.CMD_OPENFILE, filePath)
def isPaused(self):
return self.playState != self.__MPC_PLAYSTATE.PS_PLAY and self.playState != None
return self.playState != self.__MPC_PLAYSTATE.PS_PLAY and self.playState is not None
def askForVersion(self):
self.__listener.SendCommand(self.CMD_GETVERSION)
@ -103,7 +106,11 @@ class MpcHcApi:
elif cmd == self.CMD_STATE:
self.loadState = int(value)
fileNotReady = self.loadState == self.__MPC_LOADSTATE.MLS_CLOSING or self.loadState == self.__MPC_LOADSTATE.MLS_LOADING or self.loadState == self.__MPC_LOADSTATE.MLS_CLOSED
fileNotReady = (
self.loadState == self.__MPC_LOADSTATE.MLS_CLOSING or
self.loadState == self.__MPC_LOADSTATE.MLS_LOADING or
self.loadState == self.__MPC_LOADSTATE.MLS_CLOSED
)
if fileNotReady:
self.playState = None
self.__locks.fileReady.clear()
@ -272,7 +279,6 @@ class MpcHcApi:
self.locks.listenerStart.set()
win32gui.PumpMessages()
def OnCopyData(self, hwnd, msg, wparam, lparam):
pCDS = ctypes.cast(lparam, self.__PCOPYDATASTRUCT)
# print "API:\tin>\t 0x%X\t" % int(pCDS.contents.dwData), ctypes.wstring_at(pCDS.contents.lpData)
@ -304,6 +310,7 @@ class MpcHcApi:
('lpData', ctypes.c_void_p)
]
class MPCHCAPIPlayer(BasePlayer):
speedSupported = False
alertOSDSupported = False
@ -400,7 +407,10 @@ class MPCHCAPIPlayer(BasePlayer):
def openFile(self, filePath, resetPosition=False):
self._mpcApi.openFile(filePath)
def displayMessage(self, message, duration = (constants.OSD_DURATION*1000), OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL):
def displayMessage(
self, message,
duration=(constants.OSD_DURATION*1000), OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL
):
self._mpcApi.sendOsd(message, constants.MPC_OSD_POSITION, duration)
@retry(MpcHcApi.PlayerNotReadyException, constants.MPC_MAX_RETRIES, constants.MPC_RETRY_WAIT_TIME, 1)
@ -412,6 +422,7 @@ class MPCHCAPIPlayer(BasePlayer):
self._mpcApi.pause()
else:
self._mpcApi.unpause()
def setFeatures(self, featureList):
pass
@ -482,7 +493,10 @@ class MPCHCAPIPlayer(BasePlayer):
@staticmethod
def getIconPath(path):
if MPCHCAPIPlayer.getExpandedPath(path).lower().endswith('mpc-hc64.exe'.lower()) or MPCHCAPIPlayer.getExpandedPath(path).lower().endswith('mpc-hc64_nvo.exe'.lower()):
if (
MPCHCAPIPlayer.getExpandedPath(path).lower().endswith('mpc-hc64.exe'.lower()) or
MPCHCAPIPlayer.getExpandedPath(path).lower().endswith('mpc-hc64_nvo.exe'.lower())
):
return constants.MPC64_ICONPATH
else:
return constants.MPC_ICONPATH
@ -496,7 +510,11 @@ class MPCHCAPIPlayer(BasePlayer):
@staticmethod
def getExpandedPath(path):
if os.path.isfile(path):
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()):
if (
path.lower().endswith('mpc-hc.exe'.lower()) or path.lower().endswith('mpc-hcportable.exe'.lower()) or
path.lower().endswith('mpc-hc64.exe'.lower()) or path.lower().endswith('mpc-hc64_nvo.exe'.lower()) or
path.lower().endswith('mpc-hc_nvo.exe'.lower())
):
return path
if os.path.isfile(path + "mpc-hc.exe"):
path += "mpc-hc.exe"
@ -528,4 +546,3 @@ class MPCHCAPIPlayer(BasePlayer):
if os.path.isfile(path + "\\mpc-hc64_nvo.exe"):
path += "\\mpc-hc64_nvo.exe"
return path

View File

@ -1,8 +1,11 @@
from syncplay import constants
import os.path
from syncplay import constants
from syncplay.messages import getMessage
from syncplay.players.mpc import MPCHCAPIPlayer
class MpcBePlayer(MPCHCAPIPlayer):
@staticmethod
def run(client, playerPath, filePath, args):
@ -30,7 +33,11 @@ class MpcBePlayer(MPCHCAPIPlayer):
@staticmethod
def getExpandedPath(path):
if os.path.isfile(path):
if path.lower().endswith('mpc-be.exe'.lower()) or path.lower().endswith('mpc-be64.exe'.lower() or path.lower().endswith('mpc-beportable.exe'.lower())):
if (
path.lower().endswith('mpc-be.exe'.lower()) or
path.lower().endswith('mpc-be64.exe'.lower()) or
path.lower().endswith('mpc-beportable.exe'.lower())
):
return path
if os.path.isfile(path + "mpc-be.exe"):
path += "mpc-be.exe"

View File

@ -1,14 +1,18 @@
# coding:utf8
import subprocess
import os
import re
import subprocess
import sys
import threading
import time
from syncplay.players.basePlayer import BasePlayer
from syncplay import constants, utils
from syncplay.players.basePlayer import BasePlayer
from syncplay.messages import getMessage
import os, sys
from syncplay.utils import isWindows
class MplayerPlayer(BasePlayer):
speedSupported = True
customOpenDialog = False
@ -90,15 +94,20 @@ class MplayerPlayer(BasePlayer):
def _getProperty(self, property_):
self._listener.sendLine("get_property {}".format(property_))
def displayMessage(self, message, duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL):
def displayMessage(
self, message,
duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL
):
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
self._listener.sendLine('{} "{!s}" {} {}'.format(self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL))
self._listener.sendLine('{} "{!s}" {} {}'.format(
self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL))
def displayChatMessage(self, username, message):
messageString = "<{}> {}".format(username, message)
messageString = self._sanitizeText(messageString.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
duration = int(constants.OSD_DURATION * 1000)
self._listener.sendLine('{} "{!s}" {} {}'.format(self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL))
self._listener.sendLine('{} "{!s}" {} {}'.format(
self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL))
def setSpeed(self, value):
self._setProperty('speed', "{:.2f}".format(value))
@ -181,7 +190,13 @@ class MplayerPlayer(BasePlayer):
line = line.replace("[term-msg] ", "") # -v workaround
line = line.replace(" cplayer: ", "") # --msg-module workaround
line = line.replace(" term-msg: ", "")
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=":
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="
):
if "filename" in line:
self._getFilename()
elif "length" in line:
@ -250,7 +265,7 @@ class MplayerPlayer(BasePlayer):
@staticmethod
def isValidPlayerPath(path):
if "mplayer" in path and MplayerPlayer.getExpandedPath(path) and not "mplayerc.exe" in path: # "mplayerc.exe" is Media Player Classic (not Home Cinema):
if "mplayer" in path and MplayerPlayer.getExpandedPath(path) and "mplayerc.exe" not in path: # "mplayerc.exe" is Media Player Classic (not Home Cinema):
return True
return False
@ -324,12 +339,15 @@ class MplayerPlayer(BasePlayer):
if 'TERM' in env:
del env['TERM']
if filePath:
self.__process = subprocess.Popen(call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.__getCwd(filePath, env), env=env, bufsize=0)
self.__process = subprocess.Popen(
call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT,
cwd=self.__getCwd(filePath, env), env=env, bufsize=0)
else:
self.__process = subprocess.Popen(call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, env=env, bufsize=0)
self.__process = subprocess.Popen(
call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT,
env=env, bufsize=0)
threading.Thread.__init__(self, name="MPlayer Listener")
def __getCwd(self, filePath, env):
if not filePath:
return None
@ -365,8 +383,8 @@ class MplayerPlayer(BasePlayer):
if command and command[:1] == "/":
message = message[1:]
else:
self.__playerController.reactor.callFromThread(self.__playerController._client.ui.executeCommand,
command)
self.__playerController.reactor.callFromThread(
self.__playerController._client.ui.executeCommand, command)
return
self.__playerController.reactor.callFromThread(self.__playerController._client.sendChat, message)
@ -377,12 +395,12 @@ class MplayerPlayer(BasePlayer):
def setReadyToSend(self, newReadyState):
oldState = self.readyToSend
self.readyToSend = newReadyState
self.lastNotReadyTime = time.time() if newReadyState == False else None
if self.readyToSend == True:
self.lastNotReadyTime = time.time() if not newReadyState else None
if self.readyToSend:
self.__playerController._client.ui.showDebugMessage("<mpv> Ready to send: True")
else:
self.__playerController._client.ui.showDebugMessage("<mpv> Ready to send: False")
if self.readyToSend == True and oldState == False:
if self.readyToSend and not oldState:
self.processSendQueue()
def checkForReadinessOverride(self):
@ -391,7 +409,7 @@ class MplayerPlayer(BasePlayer):
def sendLine(self, line, notReadyAfterThis=None):
self.checkForReadinessOverride()
if self.readyToSend == False and "print_text ANS_pause" in line:
if not self.readyToSend and "print_text ANS_pause" in line:
self.__playerController._client.ui.showDebugMessage("<mpv> Not ready to get status update, so skipping")
return
try:
@ -401,11 +419,13 @@ class MplayerPlayer(BasePlayer):
if line.startswith(command):
for itemID, deletionCandidate in enumerate(self.sendQueue):
if deletionCandidate.startswith(command):
self.__playerController._client.ui.showDebugMessage("<mpv> Remove duplicate (supersede): {}".format(self.sendQueue[itemID]))
self.__playerController._client.ui.showDebugMessage(
"<mpv> Remove duplicate (supersede): {}".format(self.sendQueue[itemID]))
try:
self.sendQueue.remove(self.sendQueue[itemID])
except UnicodeWarning:
self.__playerController._client.ui.showDebugMessage("<mpv> Unicode mismatch occured when trying to remove duplicate")
self.__playerController._client.ui.showDebugMessage(
"<mpv> Unicode mismatch occured when trying to remove duplicate")
# TODO: Prevent this from being triggered
pass
break
@ -415,7 +435,8 @@ class MplayerPlayer(BasePlayer):
if line == command:
for itemID, deletionCandidate in enumerate(self.sendQueue):
if deletionCandidate == command:
self.__playerController._client.ui.showDebugMessage("<mpv> Remove duplicate (delete both): {}".format(self.sendQueue[itemID]))
self.__playerController._client.ui.showDebugMessage(
"<mpv> Remove duplicate (delete both): {}".format(self.sendQueue[itemID]))
self.__playerController._client.ui.showDebugMessage(self.sendQueue[itemID])
return
except:
@ -428,7 +449,9 @@ class MplayerPlayer(BasePlayer):
def processSendQueue(self):
while self.sendQueue and self.readyToSend:
if self.lastSendTime and time.time() - self.lastSendTime < constants.MPV_SENDMESSAGE_COOLDOWN_TIME:
self.__playerController._client.ui.showDebugMessage("<mpv> Throttling message send, so sleeping for {}".format(constants.MPV_SENDMESSAGE_COOLDOWN_TIME))
self.__playerController._client.ui.showDebugMessage(
"<mpv> Throttling message send, so sleeping for {}".format(
constants.MPV_SENDMESSAGE_COOLDOWN_TIME))
time.sleep(constants.MPV_SENDMESSAGE_COOLDOWN_TIME)
try:
lineToSend = self.sendQueue.pop()

View File

@ -1,14 +1,18 @@
# coding:utf8
# coding:utf8x
import os
import re
import sys
import time
import subprocess
from syncplay import constants
from syncplay.players.mplayer import MplayerPlayer
from syncplay.messages import getMessage
from syncplay import constants
from syncplay.utils import isURL, findResourcePath
import os, sys, time
class MpvPlayer(MplayerPlayer):
RE_VERSION = re.compile('.*mpv (\d+)\.(\d+)\.\d+.*')
RE_VERSION = re.compile(r'.*mpv (\d+)\.(\d+)\.\d+.*')
osdMessageSeparator = "\\n"
osdMessageSeparator = "; " # TODO: Make conditional
@ -21,7 +25,9 @@ class MpvPlayer(MplayerPlayer):
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
if not constants.MPV_OSC_VISIBILITY_CHANGE_VERSION:
client.ui.showDebugMessage("This version of mpv is not known to be compatible with changing the OSC visibility. Please use mpv >=0.28.0.")
client.ui.showDebugMessage(
"This version of mpv is not known to be compatible with changing the OSC visibility. "
"Please use mpv >=0.28.0.")
if constants.MPV_NEW_VERSION:
return NewMpvPlayer(client, MpvPlayer.getExpandedPath(playerPath), filePath, args)
else:
@ -77,6 +83,7 @@ class MpvPlayer(MplayerPlayer):
def getPlayerPathErrors(playerPath, filePath):
return None
class OldMpvPlayer(MpvPlayer):
POSITION_QUERY = 'time-pos'
OSD_QUERY = 'show_text'
@ -111,6 +118,7 @@ class OldMpvPlayer(MpvPlayer):
self.setPaused(self._client.getGlobalPaused())
self.setPosition(self._client.getGlobalPosition())
class NewMpvPlayer(OldMpvPlayer):
lastResetTime = None
lastMPVPositionUpdate = None
@ -122,14 +130,15 @@ class NewMpvPlayer(OldMpvPlayer):
if not self._client._config["chatOutputEnabled"]:
super(self.__class__, self).displayMessage(message=message, duration=duration, OSDType=OSDType, mood=mood)
return
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace("\\\\",constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER).replace("<NEWLINE>", "\\n")
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace(
"\\\\", constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER).replace("<NEWLINE>", "\\n")
self._listener.sendLine('script-message-to syncplayintf {}-osd-{} "{}"'.format(OSDType, mood, messageString))
def displayChatMessage(self, username, message):
if not self._client._config["chatOutputEnabled"]:
super(self.__class__, self).displayChatMessage(username, message)
return
username = self._sanitizeText(username.replace("\\",constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
username = self._sanitizeText(username.replace("\\", sconstants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
message = self._sanitizeText(message.replace("\\", constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
messageString = "<{}> {}".format(username, message)
self._listener.sendLine('script-message-to syncplayintf chat "{}"'.format(messageString))
@ -141,7 +150,7 @@ class NewMpvPlayer(OldMpvPlayer):
pauseValue = "yes" if value else "no"
self._setProperty("pause", pauseValue)
self._paused = value
if value == False:
if not value:
self.lastMPVPositionUpdate = time.time()
def _getProperty(self, property_):
@ -155,25 +164,34 @@ class NewMpvPlayer(OldMpvPlayer):
self._listener.sendLine("print_text ""ANS_{}=${{{}}}""".format(property_, propertyID))
def getCalculatedPosition(self):
if self.fileLoaded == False:
self._client.ui.showDebugMessage("File not loaded so using GlobalPosition for getCalculatedPosition({})".format(self._client.getGlobalPosition()))
if not self.fileLoaded:
self._client.ui.showDebugMessage(
"File not loaded so using GlobalPosition for getCalculatedPosition({})".format(
self._client.getGlobalPosition()))
return self._client.getGlobalPosition()
if self.lastMPVPositionUpdate is None:
self._client.ui.showDebugMessage("MPV not updated position so using GlobalPosition for getCalculatedPosition ({})".format(self._client.getGlobalPosition()))
self._client.ui.showDebugMessage(
"MPV not updated position so using GlobalPosition for getCalculatedPosition ({})".format(
self._client.getGlobalPosition()))
return self._client.getGlobalPosition()
if self._recentlyReset():
self._client.ui.showDebugMessage("Recently reset so using self.position for getCalculatedPosition ({})".format(self._position))
self._client.ui.showDebugMessage(
"Recently reset so using self.position for getCalculatedPosition ({})".format(
self._position))
return self._position
diff = time.time() - self.lastMPVPositionUpdate
if diff > constants.MPV_UNRESPONSIVE_THRESHOLD:
self.reactor.callFromThread(self._client.ui.showErrorMessage, getMessage("mpv-unresponsive-error").format(int(diff)), True)
self.reactor.callFromThread(
self._client.ui.showErrorMessage, getMessage("mpv-unresponsive-error").format(int(diff)), True)
self.drop()
if diff > constants.PLAYER_ASK_DELAY and not self._paused:
self._client.ui.showDebugMessage("mpv did not response in time, so assuming position is {} ({}+{})".format(self._position + diff, self._position, diff))
self._client.ui.showDebugMessage(
"mpv did not response in time, so assuming position is {} ({}+{})".format(
self._position + diff, self._position, diff))
return self._position + diff
else:
return self._position
@ -186,7 +204,8 @@ class NewMpvPlayer(OldMpvPlayer):
elif self._fileIsLoaded() or (value < constants.MPV_NEWFILE_IGNORE_TIME and self._fileIsLoaded(ignoreDelay=True)):
self._position = max(value, 0)
else:
self._client.ui.showDebugMessage("No file loaded so storing position as GlobalPosition ({})".format(self._client.getGlobalPosition()))
self._client.ui.showDebugMessage(
"No file loaded so storing position as GlobalPosition ({})".format(self._client.getGlobalPosition()))
self._position = self._client.getGlobalPosition()
def _storePauseState(self, value):
@ -205,7 +224,8 @@ class NewMpvPlayer(OldMpvPlayer):
self._getPausedAndPosition()
self._positionAsk.wait(constants.MPV_LOCK_WAIT_TIME)
self._pausedAsk.wait(constants.MPV_LOCK_WAIT_TIME)
self._client.updatePlayerStatus(self._paused if self.fileLoaded else self._client.getGlobalPaused(), self.getCalculatedPosition())
self._client.updatePlayerStatus(
self._paused if self.fileLoaded else self._client.getGlobalPaused(), self.getCalculatedPosition())
def _getPausedAndPosition(self):
self._listener.sendLine("print_text ANS_pause=${pause}\r\nprint_text ANS_time-pos=${=time-pos}")
@ -229,7 +249,8 @@ class NewMpvPlayer(OldMpvPlayer):
def setPosition(self, value):
if value < constants.DO_NOT_RESET_POSITION_THRESHOLD and self._recentlyReset():
self._client.ui.showDebugMessage("Did not seek as recently reset and {} below 'do not reset position' threshold".format(value))
self._client.ui.showDebugMessage(
"Did not seek as recently reset and {} below 'do not reset position' threshold".format(value))
return
super(self.__class__, self).setPosition(value)
self.lastMPVPositionUpdate = time.time()
@ -245,7 +266,7 @@ class NewMpvPlayer(OldMpvPlayer):
self._client.ui.showDebugMessage("Want to set paused to {}".format(self._client.getGlobalPaused()))
else:
self._client.ui.showDebugMessage("Don't want to set paused to {}".format(self._client.getGlobalPaused()))
if resetPosition == False:
if not resetPosition:
self.setPosition(self._client.getGlobalPosition())
else:
self._storePosition(0)
@ -285,7 +306,14 @@ class NewMpvPlayer(OldMpvPlayer):
self._listener.setReadyToSend(True)
def _setOSDPosition(self):
if self._client._config['chatMoveOSD'] and (self._client._config['chatOutputEnabled'] or (self._client._config['chatInputEnabled'] and self._client._config['chatInputPosition'] == constants.INPUT_POSITION_TOP)):
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._setProperty("osd-align-y", "bottom")
self._setProperty("osd-margin-y", int(self._client._config['chatOSDMargin']))
@ -309,9 +337,9 @@ class NewMpvPlayer(OldMpvPlayer):
def _fileIsLoaded(self, ignoreDelay=False):
if ignoreDelay:
self._client.ui.showDebugMessage("Ignoring _fileIsLoaded MPV_NEWFILE delay")
return True if self.fileLoaded else False
return bool(self.fileLoaded)
if self.fileLoaded == True and self.lastLoadedTime != None and time.time() > (self.lastLoadedTime + constants.MPV_NEWFILE_IGNORE_TIME):
return True
else:
return False
return (
self.fileLoaded and self.lastLoadedTime is not None and
time.time() > (self.lastLoadedTime + constants.MPV_NEWFILE_IGNORE_TIME)
)

View File

@ -1,5 +1,6 @@
import syncplay.players
class PlayerFactory(object):
def __init__(self):
self._players = syncplay.players.getAvailablePlayers()

View File

@ -1,18 +1,24 @@
import subprocess
import re
import threading
from syncplay.players.basePlayer import BasePlayer
from syncplay import constants, utils
import asynchat
import asyncore
import os
import sys
import random
import re
import socket
import asynchat, asyncore
import urllib.request, urllib.parse, urllib.error
import subprocess
import sys
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.utils import isBSD, isLinux, isWindows, isMacOS
class VlcPlayer(BasePlayer):
speedSupported = True
customOpenDialog = False
@ -47,7 +53,8 @@ class VlcPlayer(BasePlayer):
if self.radixChar == "" or self.radixChar == "1" or self.radixChar == "5":
raise ValueError
except:
self._client.ui.showErrorMessage("Failed to determine locale. As a fallback Syncplay is using the following radix character: \".\".")
self._client.ui.showErrorMessage(
"Failed to determine locale. As a fallback Syncplay is using the following radix character: \".\".")
self.radixChar = "."
self._durationAsk = threading.Event()
@ -110,7 +117,8 @@ class VlcPlayer(BasePlayer):
return self._client.getGlobalPosition()
diff = time.time() - self._lastVLCPositionUpdate
if diff > constants.PLAYER_ASK_DELAY and not self._paused:
self._client.ui.showDebugMessage("VLC did not response in time, so assuming position is {} ({}+{})".format(self._position + diff, self._position, diff))
self._client.ui.showDebugMessage("VLC did not response in time, so assuming position is {} ({}+{})".format(
self._position + diff, self._position, diff))
if diff > constants.VLC_LATENCY_ERROR_THRESHOLD:
if not self.shownVLCLatencyError or constants.DEBUG_MODE:
self._client.ui.showErrorMessage(getMessage("media-player-latency-warning").format(int(diff)))
@ -119,7 +127,10 @@ class VlcPlayer(BasePlayer):
else:
return self._position
def displayMessage(self, message, duration=constants.OSD_DURATION * 1000, OSDType=constants.OSD_DURATION, mood=constants.MESSAGE_NEUTRAL):
def displayMessage(
self, message,
duration=constants.OSD_DURATION * 1000, OSDType=constants.OSD_DURATION, mood=constants.MESSAGE_NEUTRAL
):
duration /= 1000
if OSDType != constants.OSD_ALERT:
self._listener.sendLine('display-osd: {}, {}, {}'.format('top-right', duration, message))
@ -212,21 +223,25 @@ class VlcPlayer(BasePlayer):
self._duration = float(value.replace(",", "."))
self._durationAsk.set()
elif name == "playstate":
self._paused = bool(value != 'playing') if(value != "no-input" and self._filechanged == False) else self._client.getGlobalPaused()
self._paused = bool(value != 'playing') if (value != "no-input" and not self._filechanged) else self._client.getGlobalPaused()
diff = time.time() - self._lastVLCPositionUpdate if self._lastVLCPositionUpdate else 0
if self._paused == False \
and self._position == self._previousPreviousPosition \
and self._previousPosition == self._position \
and self._duration > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH \
and (self._duration - self._position) < constants.VLC_EOF_DURATION_THRESHOLD \
and diff > constants.VLC_LATENCY_ERROR_THRESHOLD:
if (
not self._paused and
self._position == self._previousPreviousPosition and
self._previousPosition == self._position and
self._duration > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH and
(self._duration - self._position) < constants.VLC_EOF_DURATION_THRandD and
diff > constants.VLC_LATENCY_ERROR_THRESHOLD
):
self._client.ui.showDebugMessage("Treating 'playing' response as 'paused' due to VLC EOF bug")
self.setPaused(True)
self._pausedAsk.set()
elif name == "position":
newPosition = float(value.replace(",", ".")) if (value != "no-input" and self._filechanged == False) else self._client.getGlobalPosition()
newPosition = float(value.replace(",", ".")) if (value != "no-input" and not self._filechanged) else self._client.getGlobalPosition()
if newPosition == self._previousPosition and newPosition != self._duration and not self._paused:
self._client.ui.showDebugMessage("Not considering position {} duplicate as new time because of VLC time precision bug".format(newPosition))
self._client.ui.showDebugMessage(
"Not considering position {} duplicate as new time because of VLC time precision bug".format(
newPosition))
self._previousPreviousPosition = self._previousPosition
self._previousPosition = self._position
self._positionAsk.set()
@ -347,7 +362,8 @@ class VlcPlayer(BasePlayer):
playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), ".local/share/vlc/lua/intf/")
elif isMacOS():
playerController.vlcIntfPath = "/Applications/VLC.app/Contents/MacOS/share/lua/intf/"
playerController.vlcIntfUserPath = os.path.join(os.getenv('HOME', '.'), "Library/Application Support/org.videolan.vlc/lua/intf/")
playerController.vlcIntfUserPath = os.path.join(
os.getenv('HOME', '.'), "Library/Application Support/org.videolan.vlc/lua/intf/")
elif isBSD():
# *BSD ports/pkgs install to /usr/local by default.
# This should also work for all the other BSDs, such as OpenBSD or DragonFly.
@ -358,14 +374,17 @@ class VlcPlayer(BasePlayer):
playerController.vlcIntfUserPath = os.path.join(os.getenv('APPDATA', '.'), "VLC\\lua\\intf\\")
playerController.vlcModulePath = playerController.vlcIntfPath + "modules/?.luac"
if _usevlcintf(playerController.vlcIntfPath, playerController.vlcIntfUserPath):
playerController.SLAVE_ARGS.append('--lua-config=syncplay={{port=\"{}\"}}'.format(str(playerController.vlcport)))
playerController.SLAVE_ARGS.append(
'--lua-config=syncplay={{port=\"{}\"}}'.format(str(playerController.vlcport)))
else:
if isLinux():
playerController.vlcDataPath = "/usr/lib/syncplay/resources"
else:
playerController.vlcDataPath = utils.findWorkingDir() + "\\resources"
playerController.SLAVE_ARGS.append('--data-path={}'.format(playerController.vlcDataPath))
playerController.SLAVE_ARGS.append('--lua-config=syncplay={{modulepath=\"{}\",port=\"{}\"}}'.format(playerController.vlcModulePath, str(playerController.vlcport)))
playerController.SLAVE_ARGS.append(
'--lua-config=syncplay={{modulepath=\"{}\",port=\"{}\"}}'.format(
playerController.vlcModulePath, str(playerController.vlcport)))
call.extend(playerController.SLAVE_ARGS)
if args:
@ -376,11 +395,15 @@ class VlcPlayer(BasePlayer):
self._vlcVersion = None
if self.oldIntfVersion:
self.__playerController.drop(getMessage("vlc-interface-version-mismatch").format(self.oldIntfVersion,constants.VLC_INTERFACE_MIN_VERSION))
self.__playerController.drop(
getMessage("vlc-interface-version-mismatch").format(
self.oldIntfVersion, constants.VLC_INTERFACE_MIN_VERSION))
else:
if isWindows() and getattr(sys, 'frozen', '') and getattr(sys, '_MEIPASS', '') is not None: # Needed for pyinstaller --onefile bundle
self.__process = subprocess.Popen(call, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=False, creationflags=0x08000000)
self.__process = subprocess.Popen(
call, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE,
shell=False, creationflags=0x08000000)
else:
self.__process = subprocess.Popen(call, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
self.timeVLCLaunched = time.time()
@ -416,10 +439,7 @@ class VlcPlayer(BasePlayer):
self._sendingData = threading.Lock()
def _shouldListenForSTDOUT(self):
if isWindows():
return False # Due to VLC3 not using STDOUT/STDERR
else:
return True
return not isWindows()
def initiate_send(self):
with self._sendingData:
@ -462,7 +482,6 @@ class VlcPlayer(BasePlayer):
break
out.close()
def found_terminator(self):
self.vlcHasResponded = True
self.__playerController.lineReceived(b"".join(self._ibuffer))

View File

@ -17,4 +17,3 @@ from syncplay.utils import blackholeStdoutForFrozenWindow
if __name__ == '__main__':
blackholeStdoutForFrozenWindow()
SyncplayClientManager().run()

View File

@ -19,5 +19,14 @@ from syncplay.server import SyncFactory, ConfigurationGetter
if __name__ == '__main__':
argsGetter = ConfigurationGetter()
args = argsGetter.getConfiguration()
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))
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))
reactor.run()