fix formattings
This commit is contained in:
parent
759f1e1457
commit
f01de206d8
15
appdmg.py
15
appdmg.py
@ -7,6 +7,7 @@ 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)
|
||||||
@ -17,6 +18,7 @@ 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')
|
||||||
|
|
||||||
@ -27,10 +29,19 @@ compression_level = 9
|
|||||||
size = defines.get('size', None)
|
size = defines.get('size', None)
|
||||||
|
|
||||||
# Files to include
|
# 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 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
|
# 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, 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!")
|
||||||
@ -14,18 +14,20 @@ import sys, codecs
|
|||||||
# 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
|
||||||
@ -39,9 +41,11 @@ 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 = "dist\Syncplay"
|
OUT_DIR = r"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
|
||||||
@ -608,6 +612,7 @@ 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)
|
||||||
@ -664,7 +669,9 @@ 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',
|
||||||
@ -686,7 +693,13 @@ guiIcons = ['resources/accept.png', 'resources/arrow_undo.png', 'resources/clock
|
|||||||
'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/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)
|
resources.extend(guiIcons)
|
||||||
intf_resources = ["resources/lua/intf/syncplay.lua"]
|
intf_resources = ["resources/lua/intf/syncplay.lua"]
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,12 @@ 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': ['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': {
|
'plist': {
|
||||||
'CFBundleName': 'Syncplay',
|
'CFBundleName': 'Syncplay',
|
||||||
'CFBundleShortVersionString': syncplay.version,
|
'CFBundleShortVersionString': syncplay.version,
|
||||||
|
|||||||
@ -12,5 +12,6 @@ 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,4 +1,6 @@
|
|||||||
from syncplay import constants
|
from syncplay import constants
|
||||||
|
|
||||||
|
|
||||||
class BasePlayer(object):
|
class BasePlayer(object):
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -12,7 +14,9 @@ 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(self, message, duration = (constants.OSD_DURATION*1000), secondaryOSD=False, mood=constants.MESSAGE_NEUTRAL):
|
def displayMessage(
|
||||||
|
self, message, duration=(constants.OSD_DURATION*1000), secondaryOSD=False, mood=constants.MESSAGE_NEUTRAL
|
||||||
|
):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -58,7 +62,6 @@ 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
|
||||||
'''
|
'''
|
||||||
@ -107,6 +110,7 @@ class BasePlayer(object):
|
|||||||
def getPlayerPathErrors(playerPath, filePath):
|
def getPlayerPathErrors(playerPath, filePath):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class DummyPlayer(BasePlayer):
|
class DummyPlayer(BasePlayer):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@ -1,15 +1,18 @@
|
|||||||
#coding:utf8
|
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
import _thread
|
import _thread
|
||||||
import win32con, win32api, win32gui, ctypes, ctypes.wintypes #@UnresolvedImport @UnusedImport
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from syncplay.players.basePlayer import BasePlayer
|
|
||||||
import re
|
import win32con, win32api, win32gui, ctypes, ctypes.wintypes #@UnresolvedImport @UnusedImport
|
||||||
from syncplay.utils import retry
|
|
||||||
from syncplay import constants
|
from syncplay import constants
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
import os.path
|
from syncplay.players.basePlayer import BasePlayer
|
||||||
|
from syncplay.utils import retry
|
||||||
|
|
||||||
|
|
||||||
class MpcHcApi:
|
class MpcHcApi:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -49,7 +52,7 @@ class MpcHcApi:
|
|||||||
self.__listener.SendCommand(self.CMD_OPENFILE, filePath)
|
self.__listener.SendCommand(self.CMD_OPENFILE, filePath)
|
||||||
|
|
||||||
def isPaused(self):
|
def isPaused(self):
|
||||||
return self.playState != self.__MPC_PLAYSTATE.PS_PLAY and self.playState != None
|
return self.playState != self.__MPC_PLAYSTATE.PS_PLAY and self.playState is not None
|
||||||
|
|
||||||
def askForVersion(self):
|
def askForVersion(self):
|
||||||
self.__listener.SendCommand(self.CMD_GETVERSION)
|
self.__listener.SendCommand(self.CMD_GETVERSION)
|
||||||
@ -103,7 +106,11 @@ class MpcHcApi:
|
|||||||
|
|
||||||
elif cmd == self.CMD_STATE:
|
elif cmd == self.CMD_STATE:
|
||||||
self.loadState = int(value)
|
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:
|
if fileNotReady:
|
||||||
self.playState = None
|
self.playState = None
|
||||||
self.__locks.fileReady.clear()
|
self.__locks.fileReady.clear()
|
||||||
@ -272,7 +279,6 @@ 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)
|
||||||
@ -304,6 +310,7 @@ 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
|
||||||
@ -400,7 +407,10 @@ 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(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)
|
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)
|
||||||
@ -412,6 +422,7 @@ 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
|
||||||
|
|
||||||
@ -482,7 +493,10 @@ class MPCHCAPIPlayer(BasePlayer):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getIconPath(path):
|
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
|
return constants.MPC64_ICONPATH
|
||||||
else:
|
else:
|
||||||
return constants.MPC_ICONPATH
|
return constants.MPC_ICONPATH
|
||||||
@ -496,7 +510,11 @@ class MPCHCAPIPlayer(BasePlayer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def getExpandedPath(path):
|
def getExpandedPath(path):
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
if path.lower().endswith('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
|
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"
|
||||||
@ -528,4 +546,3 @@ 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,8 +1,11 @@
|
|||||||
from syncplay import constants
|
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
|
from syncplay import constants
|
||||||
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):
|
||||||
@ -30,7 +33,11 @@ class MpcBePlayer(MPCHCAPIPlayer):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def getExpandedPath(path):
|
def getExpandedPath(path):
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
if path.lower().endswith('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
|
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,14 +1,18 @@
|
|||||||
# coding:utf8
|
# coding:utf8
|
||||||
import subprocess
|
import os
|
||||||
import re
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from syncplay.players.basePlayer import BasePlayer
|
|
||||||
|
|
||||||
from syncplay import constants, utils
|
from syncplay import constants, utils
|
||||||
|
from syncplay.players.basePlayer import BasePlayer
|
||||||
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
|
||||||
@ -90,15 +94,20 @@ 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(self, message, duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL):
|
def displayMessage(
|
||||||
|
self, message,
|
||||||
|
duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION, mood=constants.MESSAGE_NEUTRAL
|
||||||
|
):
|
||||||
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
|
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
|
||||||
self._listener.sendLine('{} "{!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):
|
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.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):
|
def setSpeed(self, value):
|
||||||
self._setProperty('speed', "{:.2f}".format(value))
|
self._setProperty('speed', "{:.2f}".format(value))
|
||||||
@ -181,7 +190,13 @@ 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 "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:
|
if "filename" in line:
|
||||||
self._getFilename()
|
self._getFilename()
|
||||||
elif "length" in line:
|
elif "length" in line:
|
||||||
@ -250,7 +265,7 @@ class MplayerPlayer(BasePlayer):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def isValidPlayerPath(path):
|
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 True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -324,12 +339,15 @@ class MplayerPlayer(BasePlayer):
|
|||||||
if 'TERM' in env:
|
if 'TERM' in env:
|
||||||
del env['TERM']
|
del env['TERM']
|
||||||
if filePath:
|
if filePath:
|
||||||
self.__process = subprocess.Popen(call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=self.__getCwd(filePath, env), env=env, 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:
|
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")
|
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
|
||||||
@ -365,8 +383,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._client.ui.executeCommand,
|
self.__playerController.reactor.callFromThread(
|
||||||
command)
|
self.__playerController._client.ui.executeCommand, command)
|
||||||
return
|
return
|
||||||
self.__playerController.reactor.callFromThread(self.__playerController._client.sendChat, message)
|
self.__playerController.reactor.callFromThread(self.__playerController._client.sendChat, message)
|
||||||
|
|
||||||
@ -377,12 +395,12 @@ class MplayerPlayer(BasePlayer):
|
|||||||
def setReadyToSend(self, newReadyState):
|
def setReadyToSend(self, newReadyState):
|
||||||
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 not newReadyState else None
|
||||||
if self.readyToSend == True:
|
if self.readyToSend:
|
||||||
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 == True and oldState == False:
|
if self.readyToSend and not oldState:
|
||||||
self.processSendQueue()
|
self.processSendQueue()
|
||||||
|
|
||||||
def checkForReadinessOverride(self):
|
def checkForReadinessOverride(self):
|
||||||
@ -391,7 +409,7 @@ class MplayerPlayer(BasePlayer):
|
|||||||
|
|
||||||
def sendLine(self, line, notReadyAfterThis=None):
|
def sendLine(self, line, notReadyAfterThis=None):
|
||||||
self.checkForReadinessOverride()
|
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")
|
self.__playerController._client.ui.showDebugMessage("<mpv> Not ready to get status update, so skipping")
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -401,11 +419,13 @@ 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("<mpv> Remove duplicate (supersede): {}".format(self.sendQueue[itemID]))
|
self.__playerController._client.ui.showDebugMessage(
|
||||||
|
"<mpv> Remove duplicate (supersede): {}".format(self.sendQueue[itemID]))
|
||||||
try:
|
try:
|
||||||
self.sendQueue.remove(self.sendQueue[itemID])
|
self.sendQueue.remove(self.sendQueue[itemID])
|
||||||
except UnicodeWarning:
|
except UnicodeWarning:
|
||||||
self.__playerController._client.ui.showDebugMessage("<mpv> Unicode mismatch occured when trying to remove duplicate")
|
self.__playerController._client.ui.showDebugMessage(
|
||||||
|
"<mpv> Unicode mismatch occured when trying to remove duplicate")
|
||||||
# TODO: Prevent this from being triggered
|
# TODO: Prevent this from being triggered
|
||||||
pass
|
pass
|
||||||
break
|
break
|
||||||
@ -415,7 +435,8 @@ 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("<mpv> Remove duplicate (delete both): {}".format(self.sendQueue[itemID]))
|
self.__playerController._client.ui.showDebugMessage(
|
||||||
|
"<mpv> Remove duplicate (delete both): {}".format(self.sendQueue[itemID]))
|
||||||
self.__playerController._client.ui.showDebugMessage(self.sendQueue[itemID])
|
self.__playerController._client.ui.showDebugMessage(self.sendQueue[itemID])
|
||||||
return
|
return
|
||||||
except:
|
except:
|
||||||
@ -428,7 +449,9 @@ 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("<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)
|
time.sleep(constants.MPV_SENDMESSAGE_COOLDOWN_TIME)
|
||||||
try:
|
try:
|
||||||
lineToSend = self.sendQueue.pop()
|
lineToSend = self.sendQueue.pop()
|
||||||
|
|||||||
@ -1,14 +1,18 @@
|
|||||||
# coding:utf8
|
# coding:utf8x
|
||||||
|
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('.*mpv (\d+)\.(\d+)\.\d+.*')
|
RE_VERSION = re.compile(r'.*mpv (\d+)\.(\d+)\.\d+.*')
|
||||||
osdMessageSeparator = "\\n"
|
osdMessageSeparator = "\\n"
|
||||||
osdMessageSeparator = "; " # TODO: Make conditional
|
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_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("This version of mpv is not known to be compatible with changing the OSC visibility. Please use mpv >=0.28.0.")
|
client.ui.showDebugMessage(
|
||||||
|
"This version of mpv is not known to be compatible with changing the OSC visibility. "
|
||||||
|
"Please use mpv >=0.28.0.")
|
||||||
if constants.MPV_NEW_VERSION:
|
if constants.MPV_NEW_VERSION:
|
||||||
return NewMpvPlayer(client, MpvPlayer.getExpandedPath(playerPath), filePath, args)
|
return NewMpvPlayer(client, MpvPlayer.getExpandedPath(playerPath), filePath, args)
|
||||||
else:
|
else:
|
||||||
@ -77,6 +83,7 @@ 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'
|
||||||
@ -111,6 +118,7 @@ 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
|
||||||
@ -122,14 +130,15 @@ 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("\\\\",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))
|
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("\\",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))
|
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))
|
||||||
@ -141,7 +150,7 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
pauseValue = "yes" if value else "no"
|
pauseValue = "yes" if value else "no"
|
||||||
self._setProperty("pause", pauseValue)
|
self._setProperty("pause", pauseValue)
|
||||||
self._paused = value
|
self._paused = value
|
||||||
if value == False:
|
if not value:
|
||||||
self.lastMPVPositionUpdate = time.time()
|
self.lastMPVPositionUpdate = time.time()
|
||||||
|
|
||||||
def _getProperty(self, property_):
|
def _getProperty(self, property_):
|
||||||
@ -155,25 +164,34 @@ 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 self.fileLoaded == False:
|
if not self.fileLoaded:
|
||||||
self._client.ui.showDebugMessage("File not loaded so using GlobalPosition for getCalculatedPosition({})".format(self._client.getGlobalPosition()))
|
self._client.ui.showDebugMessage(
|
||||||
|
"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("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()
|
return self._client.getGlobalPosition()
|
||||||
|
|
||||||
if self._recentlyReset():
|
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
|
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._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()
|
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("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
|
return self._position + diff
|
||||||
else:
|
else:
|
||||||
return self._position
|
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)):
|
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("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()
|
self._position = self._client.getGlobalPosition()
|
||||||
|
|
||||||
def _storePauseState(self, value):
|
def _storePauseState(self, value):
|
||||||
@ -205,7 +224,8 @@ 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._paused if self.fileLoaded else self._client.getGlobalPaused(), self.getCalculatedPosition())
|
self._client.updatePlayerStatus(
|
||||||
|
self._paused if self.fileLoaded else self._client.getGlobalPaused(), self.getCalculatedPosition())
|
||||||
|
|
||||||
def _getPausedAndPosition(self):
|
def _getPausedAndPosition(self):
|
||||||
self._listener.sendLine("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}")
|
||||||
@ -229,7 +249,8 @@ 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("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
|
return
|
||||||
super(self.__class__, self).setPosition(value)
|
super(self.__class__, self).setPosition(value)
|
||||||
self.lastMPVPositionUpdate = time.time()
|
self.lastMPVPositionUpdate = time.time()
|
||||||
@ -245,7 +266,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 resetPosition == False:
|
if not resetPosition:
|
||||||
self.setPosition(self._client.getGlobalPosition())
|
self.setPosition(self._client.getGlobalPosition())
|
||||||
else:
|
else:
|
||||||
self._storePosition(0)
|
self._storePosition(0)
|
||||||
@ -285,7 +306,14 @@ class NewMpvPlayer(OldMpvPlayer):
|
|||||||
self._listener.setReadyToSend(True)
|
self._listener.setReadyToSend(True)
|
||||||
|
|
||||||
def _setOSDPosition(self):
|
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-align-y", "bottom")
|
||||||
self._setProperty("osd-margin-y", int(self._client._config['chatOSDMargin']))
|
self._setProperty("osd-margin-y", int(self._client._config['chatOSDMargin']))
|
||||||
|
|
||||||
@ -309,9 +337,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 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 (
|
||||||
return True
|
self.fileLoaded and self.lastLoadedTime is not None and
|
||||||
else:
|
time.time() > (self.lastLoadedTime + constants.MPV_NEWFILE_IGNORE_TIME)
|
||||||
return False
|
)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
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,18 +1,24 @@
|
|||||||
import subprocess
|
|
||||||
import re
|
import asynchat
|
||||||
import threading
|
import asyncore
|
||||||
from syncplay.players.basePlayer import BasePlayer
|
|
||||||
from syncplay import constants, utils
|
|
||||||
import os
|
import os
|
||||||
import sys
|
|
||||||
import random
|
import random
|
||||||
|
import re
|
||||||
import socket
|
import socket
|
||||||
import asynchat, asyncore
|
import subprocess
|
||||||
import urllib.request, urllib.parse, urllib.error
|
import sys
|
||||||
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import urllib.error
|
||||||
|
import urllib.parse
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
from syncplay import constants, utils
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
|
from syncplay.players.basePlayer import BasePlayer
|
||||||
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
|
||||||
@ -47,7 +53,8 @@ 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("Failed to determine locale. As a fallback Syncplay is using the following radix character: \".\".")
|
self._client.ui.showErrorMessage(
|
||||||
|
"Failed to determine locale. As a fallback Syncplay is using the following radix character: \".\".")
|
||||||
self.radixChar = "."
|
self.radixChar = "."
|
||||||
|
|
||||||
self._durationAsk = threading.Event()
|
self._durationAsk = threading.Event()
|
||||||
@ -110,7 +117,8 @@ 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._position + diff, self._position, diff))
|
self._client.ui.showDebugMessage("VLC did not response in time, so assuming position is {} ({}+{})".format(
|
||||||
|
self._position + diff, self._position, diff))
|
||||||
if diff > constants.VLC_LATENCY_ERROR_THRESHOLD:
|
if diff > constants.VLC_LATENCY_ERROR_THRESHOLD:
|
||||||
if not self.shownVLCLatencyError or constants.DEBUG_MODE:
|
if not self.shownVLCLatencyError or constants.DEBUG_MODE:
|
||||||
self._client.ui.showErrorMessage(getMessage("media-player-latency-warning").format(int(diff)))
|
self._client.ui.showErrorMessage(getMessage("media-player-latency-warning").format(int(diff)))
|
||||||
@ -119,7 +127,10 @@ class VlcPlayer(BasePlayer):
|
|||||||
else:
|
else:
|
||||||
return self._position
|
return self._position
|
||||||
|
|
||||||
def displayMessage(self, message, duration=constants.OSD_DURATION * 1000, OSDType=constants.OSD_DURATION, mood=constants.MESSAGE_NEUTRAL):
|
def displayMessage(
|
||||||
|
self, message,
|
||||||
|
duration=constants.OSD_DURATION * 1000, OSDType=constants.OSD_DURATION, mood=constants.MESSAGE_NEUTRAL
|
||||||
|
):
|
||||||
duration /= 1000
|
duration /= 1000
|
||||||
if OSDType != constants.OSD_ALERT:
|
if OSDType != constants.OSD_ALERT:
|
||||||
self._listener.sendLine('display-osd: {}, {}, {}'.format('top-right', duration, message))
|
self._listener.sendLine('display-osd: {}, {}, {}'.format('top-right', duration, message))
|
||||||
@ -212,21 +223,25 @@ 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 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
|
diff = time.time() - self._lastVLCPositionUpdate if self._lastVLCPositionUpdate else 0
|
||||||
if self._paused == False \
|
if (
|
||||||
and self._position == self._previousPreviousPosition \
|
not self._paused and
|
||||||
and self._previousPosition == self._position \
|
self._position == self._previousPreviousPosition and
|
||||||
and self._duration > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH \
|
self._previousPosition == self._position and
|
||||||
and (self._duration - self._position) < constants.VLC_EOF_DURATION_THRESHOLD \
|
self._duration > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH and
|
||||||
and diff > constants.VLC_LATENCY_ERROR_THRESHOLD:
|
(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._client.ui.showDebugMessage("Treating 'playing' response as 'paused' due to VLC EOF bug")
|
||||||
self.setPaused(True)
|
self.setPaused(True)
|
||||||
self._pausedAsk.set()
|
self._pausedAsk.set()
|
||||||
elif name == "position":
|
elif name == "position":
|
||||||
newPosition = float(value.replace(",", ".")) if (value != "no-input" and self._filechanged == False) else self._client.getGlobalPosition()
|
newPosition = float(value.replace(",", ".")) if (value != "no-input" and not self._filechanged) else self._client.getGlobalPosition()
|
||||||
if newPosition == self._previousPosition and newPosition != self._duration and not self._paused:
|
if newPosition == self._previousPosition and newPosition != self._duration and not self._paused:
|
||||||
self._client.ui.showDebugMessage("Not considering position {} duplicate as new time because of VLC time precision bug".format(newPosition))
|
self._client.ui.showDebugMessage(
|
||||||
|
"Not considering position {} duplicate as new time because of VLC time precision bug".format(
|
||||||
|
newPosition))
|
||||||
self._previousPreviousPosition = self._previousPosition
|
self._previousPreviousPosition = self._previousPosition
|
||||||
self._previousPosition = self._position
|
self._previousPosition = self._position
|
||||||
self._positionAsk.set()
|
self._positionAsk.set()
|
||||||
@ -347,7 +362,8 @@ 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(os.getenv('HOME', '.'), "Library/Application Support/org.videolan.vlc/lua/intf/")
|
playerController.vlcIntfUserPath = os.path.join(
|
||||||
|
os.getenv('HOME', '.'), "Library/Application Support/org.videolan.vlc/lua/intf/")
|
||||||
elif isBSD():
|
elif isBSD():
|
||||||
# *BSD ports/pkgs install to /usr/local by default.
|
# *BSD ports/pkgs install to /usr/local by default.
|
||||||
# This should also work for all the other BSDs, such as OpenBSD or DragonFly.
|
# This should also work for all the other BSDs, such as OpenBSD or DragonFly.
|
||||||
@ -358,14 +374,17 @@ 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('--lua-config=syncplay={{port=\"{}\"}}'.format(str(playerController.vlcport)))
|
playerController.SLAVE_ARGS.append(
|
||||||
|
'--lua-config=syncplay={{port=\"{}\"}}'.format(str(playerController.vlcport)))
|
||||||
else:
|
else:
|
||||||
if isLinux():
|
if isLinux():
|
||||||
playerController.vlcDataPath = "/usr/lib/syncplay/resources"
|
playerController.vlcDataPath = "/usr/lib/syncplay/resources"
|
||||||
else:
|
else:
|
||||||
playerController.vlcDataPath = utils.findWorkingDir() + "\\resources"
|
playerController.vlcDataPath = utils.findWorkingDir() + "\\resources"
|
||||||
playerController.SLAVE_ARGS.append('--data-path={}'.format(playerController.vlcDataPath))
|
playerController.SLAVE_ARGS.append('--data-path={}'.format(playerController.vlcDataPath))
|
||||||
playerController.SLAVE_ARGS.append('--lua-config=syncplay={{modulepath=\"{}\",port=\"{}\"}}'.format(playerController.vlcModulePath, str(playerController.vlcport)))
|
playerController.SLAVE_ARGS.append(
|
||||||
|
'--lua-config=syncplay={{modulepath=\"{}\",port=\"{}\"}}'.format(
|
||||||
|
playerController.vlcModulePath, str(playerController.vlcport)))
|
||||||
|
|
||||||
call.extend(playerController.SLAVE_ARGS)
|
call.extend(playerController.SLAVE_ARGS)
|
||||||
if args:
|
if args:
|
||||||
@ -376,11 +395,15 @@ class VlcPlayer(BasePlayer):
|
|||||||
self._vlcVersion = None
|
self._vlcVersion = None
|
||||||
|
|
||||||
if self.oldIntfVersion:
|
if self.oldIntfVersion:
|
||||||
self.__playerController.drop(getMessage("vlc-interface-version-mismatch").format(self.oldIntfVersion,constants.VLC_INTERFACE_MIN_VERSION))
|
self.__playerController.drop(
|
||||||
|
getMessage("vlc-interface-version-mismatch").format(
|
||||||
|
self.oldIntfVersion, constants.VLC_INTERFACE_MIN_VERSION))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
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(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:
|
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()
|
||||||
@ -416,10 +439,7 @@ class VlcPlayer(BasePlayer):
|
|||||||
self._sendingData = threading.Lock()
|
self._sendingData = threading.Lock()
|
||||||
|
|
||||||
def _shouldListenForSTDOUT(self):
|
def _shouldListenForSTDOUT(self):
|
||||||
if isWindows():
|
return not 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:
|
||||||
@ -462,7 +482,6 @@ 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))
|
||||||
|
|||||||
@ -17,4 +17,3 @@ from syncplay.utils import blackholeStdoutForFrozenWindow
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
blackholeStdoutForFrozenWindow()
|
blackholeStdoutForFrozenWindow()
|
||||||
SyncplayClientManager().run()
|
SyncplayClientManager().run()
|
||||||
|
|
||||||
|
|||||||
@ -19,5 +19,14 @@ from syncplay.server import SyncFactory, ConfigurationGetter
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
argsGetter = ConfigurationGetter()
|
argsGetter = ConfigurationGetter()
|
||||||
args = argsGetter.getConfiguration()
|
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()
|
reactor.run()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user