fix formattings
This commit is contained in:
parent
759f1e1457
commit
f01de206d8
23
appdmg.py
23
appdmg.py
@ -7,16 +7,18 @@ 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)
|
||||
icon_name = plist['CFBundleIconFile']
|
||||
icon_root,icon_ext = os.path.splitext(icon_name)
|
||||
icon_root, icon_ext = os.path.splitext(icon_name)
|
||||
if not icon_ext:
|
||||
icon_ext = '.icns'
|
||||
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
|
||||
#
|
||||
@ -38,12 +49,12 @@ symlinks = { 'Applications': '/Applications', 'Install for VLC': '.macos_vlc_ins
|
||||
# image, *or* you can define badge_icon, in which case the icon file you specify
|
||||
# will be used to badge the system's Removable Disk icon
|
||||
#
|
||||
#icon = '/path/to/icon.icns'
|
||||
# icon = '/path/to/icon.icns'
|
||||
badge_icon = icon_from_app(application)
|
||||
|
||||
# Where to put the icons
|
||||
icon_locations = {
|
||||
appname: (150, 110),
|
||||
appname: (150, 110),
|
||||
'Applications': (450, 110),
|
||||
'Read Me': (100, 285),
|
||||
'Install for VLC': (500, 285)
|
||||
@ -106,7 +117,7 @@ arrange_by = None
|
||||
grid_offset = (0, 0)
|
||||
grid_spacing = 20
|
||||
scroll_position = (0, 0)
|
||||
label_pos = 'bottom' # or 'right'
|
||||
label_pos = 'bottom' # or 'right'
|
||||
text_size = 12
|
||||
icon_size = 80
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
#!/usr/bin/env python
|
||||
#coding:utf8
|
||||
# coding:utf8
|
||||
|
||||
|
||||
#*** TROUBLESHOOTING ***
|
||||
#1) If you get the error "ImportError: No module named zope.interface" then add an empty __init__.py file to the PYTHONDIR/Lib/site-packages/zope directory
|
||||
#2) It is expected that you will have NSIS 3 NSIS from http://nsis.sourceforge.net installed.
|
||||
|
||||
import sys, codecs
|
||||
# *** 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 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
|
||||
@ -241,11 +245,11 @@ NSIS_SCRIPT_TEMPLATE = r"""
|
||||
Push English
|
||||
Push $${LANG_POLISH}
|
||||
Push Polski
|
||||
Push $${LANG_RUSSIAN}
|
||||
Push $${LANG_RUSSIAN}
|
||||
Push Русский
|
||||
Push $${LANG_GERMAN}
|
||||
Push Deutsch
|
||||
Push $${LANG_ITALIAN}
|
||||
Push $${LANG_ITALIAN}
|
||||
Push Italiano
|
||||
Push A ; A means auto count languages
|
||||
LangDLL::LangDialog "Language Selection" "Please select the language of Syncplay and the installer"
|
||||
@ -317,25 +321,25 @@ NSIS_SCRIPT_TEMPLATE = r"""
|
||||
;$${EndIf}
|
||||
|
||||
$${If} $$CheckBox_VLC_State == $${BST_CHECKED}
|
||||
$${NSD_Check} $$CheckBox_VLC
|
||||
$${NSD_Check} $$CheckBox_VLC
|
||||
$${EndIf}
|
||||
|
||||
Call UpdateVLCCheckbox
|
||||
|
||||
$${If} $$CheckBox_StartMenuShortcut_State == $${BST_CHECKED}
|
||||
$${NSD_Check} $$CheckBox_StartMenuShortcut
|
||||
$${NSD_Check} $$CheckBox_StartMenuShortcut
|
||||
$${EndIf}
|
||||
|
||||
$${If} $$CheckBox_DesktopShortcut_State == $${BST_CHECKED}
|
||||
$${NSD_Check} $$CheckBox_DesktopShortcut
|
||||
$${NSD_Check} $$CheckBox_DesktopShortcut
|
||||
$${EndIf}
|
||||
|
||||
$${If} $$CheckBox_QuickLaunchShortcut_State == $${BST_CHECKED}
|
||||
$${NSD_Check} $$CheckBox_QuickLaunchShortcut
|
||||
$${NSD_Check} $$CheckBox_QuickLaunchShortcut
|
||||
$${EndIf}
|
||||
|
||||
$${If} $$CheckBox_AutomaticUpdates_State == $${BST_CHECKED}
|
||||
$${NSD_Check} $$CheckBox_AutomaticUpdates
|
||||
$${NSD_Check} $$CheckBox_AutomaticUpdates
|
||||
$${EndIf}
|
||||
|
||||
nsDialogs::Show
|
||||
@ -608,6 +612,7 @@ NSIS_SCRIPT_TEMPLATE = r"""
|
||||
SectionEnd
|
||||
"""
|
||||
|
||||
|
||||
class NSISScript(object):
|
||||
def create(self):
|
||||
fileList, totalSize = self.getBuildDirContents(OUT_DIR)
|
||||
@ -617,12 +622,12 @@ class NSISScript(object):
|
||||
|
||||
if os.path.isfile(SETUP_SCRIPT_PATH):
|
||||
raise RuntimeError("Cannot create setup script, file exists at {}".format(SETUP_SCRIPT_PATH))
|
||||
contents = Template(NSIS_SCRIPT_TEMPLATE).substitute(
|
||||
version = syncplay.version,
|
||||
uninstallFiles = uninstallFiles,
|
||||
installFiles = installFiles,
|
||||
totalSize = totalSize,
|
||||
)
|
||||
contents = Template(NSIS_SCRIPT_TEMPLATE).substitute(
|
||||
version=syncplay.version,
|
||||
uninstallFiles=uninstallFiles,
|
||||
installFiles=installFiles,
|
||||
totalSize=totalSize,
|
||||
)
|
||||
with codecs.open(SETUP_SCRIPT_PATH, "w", "utf-8-sig") as outfile:
|
||||
outfile.write(contents)
|
||||
|
||||
@ -664,29 +669,37 @@ 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',
|
||||
'resources/control_pause_blue.png', 'resources/cross.png', 'resources/door_in.png',
|
||||
'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png',
|
||||
'resources/timeline_marker.png','resources/control_play_blue.png',
|
||||
'resources/mpc-hc.png','resources/mpc-hc64.png','resources/mplayer.png',
|
||||
'resources/mpc-be.png',
|
||||
'resources/mpv.png','resources/vlc.png', 'resources/house.png', 'resources/film_link.png',
|
||||
'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/chevrons_right.png',
|
||||
'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png',
|
||||
'resources/tick.png', 'resources/lock_open.png', 'resources/empty_checkbox.png', 'resources/tick_checkbox.png',
|
||||
'resources/world_explore.png', 'resources/application_get.png', 'resources/cog.png', 'resources/arrow_switch.png',
|
||||
'resources/film_go.png', 'resources/world_go.png', 'resources/arrow_refresh.png', 'resources/bullet_right_grey.png',
|
||||
'resources/user_comment.png',
|
||||
'resources/error.png',
|
||||
'resources/film_folder_edit.png',
|
||||
'resources/film_edit.png',
|
||||
'resources/folder_film.png',
|
||||
'resources/shield_edit.png',
|
||||
'resources/shield_add.png',
|
||||
'resources/email_go.png',
|
||||
'resources/world_add.png', 'resources/film_add.png', 'resources/delete.png', 'resources/spinner.mng'
|
||||
]
|
||||
resources = ["resources/icon.ico", "resources/syncplay.png", "resources/syncplayintf.lua", "resources/license.rtf", "resources/third-party-notices.rtf"]
|
||||
|
||||
guiIcons = [
|
||||
'resources/accept.png', 'resources/arrow_undo.png', 'resources/clock_go.png',
|
||||
'resources/control_pause_blue.png', 'resources/cross.png', 'resources/door_in.png',
|
||||
'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png',
|
||||
'resources/timeline_marker.png', 'resources/control_play_blue.png',
|
||||
'resources/mpc-hc.png', 'resources/mpc-hc64.png', 'resources/mplayer.png',
|
||||
'resources/mpc-be.png',
|
||||
'resources/mpv.png', 'resources/vlc.png', 'resources/house.png', 'resources/film_link.png',
|
||||
'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/chevrons_right.png',
|
||||
'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png',
|
||||
'resources/tick.png', 'resources/lock_open.png', 'resources/empty_checkbox.png', 'resources/tick_checkbox.png',
|
||||
'resources/world_explore.png', 'resources/application_get.png', 'resources/cog.png', 'resources/arrow_switch.png',
|
||||
'resources/film_go.png', 'resources/world_go.png', 'resources/arrow_refresh.png', 'resources/bullet_right_grey.png',
|
||||
'resources/user_comment.png',
|
||||
'resources/error.png',
|
||||
'resources/film_folder_edit.png',
|
||||
'resources/film_edit.png',
|
||||
'resources/folder_film.png',
|
||||
'resources/shield_edit.png',
|
||||
'resources/shield_add.png',
|
||||
'resources/email_go.png',
|
||||
'resources/world_add.png', 'resources/film_add.png', 'resources/delete.png', 'resources/spinner.mng'
|
||||
]
|
||||
resources = [
|
||||
"resources/icon.ico",
|
||||
"resources/syncplay.png",
|
||||
"resources/syncplayintf.lua",
|
||||
"resources/license.rtf",
|
||||
"resources/third-party-notices.rtf"
|
||||
]
|
||||
resources.extend(guiIcons)
|
||||
intf_resources = ["resources/lua/intf/syncplay.lua"]
|
||||
|
||||
|
||||
@ -14,16 +14,21 @@ DATA_FILES = [
|
||||
('resources', glob('resources/*.png') + glob('resources/*.rtf') + glob('resources/*.lua')),
|
||||
]
|
||||
OPTIONS = {
|
||||
'iconfile':'resources/icon.icns',
|
||||
'iconfile': 'resources/icon.icns',
|
||||
'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'},
|
||||
'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,
|
||||
'CFBundleIdentifier':'pl.syncplay.Syncplay',
|
||||
'LSMinimumSystemVersion':'10.11.0',
|
||||
'CFBundleName': 'Syncplay',
|
||||
'CFBundleShortVersionString': syncplay.version,
|
||||
'CFBundleIdentifier': 'pl.syncplay.Syncplay',
|
||||
'LSMinimumSystemVersion': '10.11.0',
|
||||
'NSHumanReadableCopyright': '@ 2018 Syncplay All Rights Reserved'
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,5 +12,6 @@ except ImportError:
|
||||
from syncplay.players.basePlayer import DummyPlayer
|
||||
MpcBePlayer = DummyPlayer
|
||||
|
||||
|
||||
def getAvailablePlayers():
|
||||
return [MPCHCAPIPlayer, MplayerPlayer, MpvPlayer, VlcPlayer, MpcBePlayer]
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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):
|
||||
@ -30,7 +33,7 @@ class MpcHcApi:
|
||||
self.__listener.start()
|
||||
self.__locks.listenerStart.wait()
|
||||
|
||||
def waitForFileStateReady(f): #@NoSelf
|
||||
def waitForFileStateReady(f): #@NoSelf
|
||||
@wraps(f)
|
||||
def wrapper(self, *args, **kwds):
|
||||
if not self.__locks.fileReady.wait(constants.MPC_LOCK_WAIT_TIME):
|
||||
@ -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)
|
||||
@ -99,18 +102,22 @@ class MpcHcApi:
|
||||
self.__listener.mpcHandle = int(value)
|
||||
self.__locks.mpcStart.set()
|
||||
if self.callbacks.onConnected:
|
||||
_thread.start_new_thread(self.callbacks.onConnected, ())
|
||||
_thread.start_new_thread(self.callbacks.onConnected, ())
|
||||
|
||||
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()
|
||||
else:
|
||||
self.__locks.fileReady.set()
|
||||
if self.callbacks.onFileStateChange:
|
||||
_thread.start_new_thread(self.callbacks.onFileStateChange, (self.loadState,))
|
||||
_thread.start_new_thread(self.callbacks.onFileStateChange, (self.loadState,))
|
||||
|
||||
elif cmd == self.CMD_PLAYMODE:
|
||||
self.playState = int(value)
|
||||
@ -125,31 +132,31 @@ class MpcHcApi:
|
||||
self.filePlaying = value[3].split('\\').pop()
|
||||
self.fileDuration = float(value[4])
|
||||
if self.callbacks.onUpdatePath:
|
||||
_thread.start_new_thread(self.callbacks.onUpdatePath, (self.onUpdatePath,))
|
||||
_thread.start_new_thread(self.callbacks.onUpdatePath, (self.onUpdatePath,))
|
||||
if self.callbacks.onUpdateFilename:
|
||||
_thread.start_new_thread(self.callbacks.onUpdateFilename, (self.filePlaying,))
|
||||
_thread.start_new_thread(self.callbacks.onUpdateFilename, (self.filePlaying,))
|
||||
if self.callbacks.onUpdateFileDuration:
|
||||
_thread.start_new_thread(self.callbacks.onUpdateFileDuration, (self.fileDuration,))
|
||||
_thread.start_new_thread(self.callbacks.onUpdateFileDuration, (self.fileDuration,))
|
||||
|
||||
elif cmd == self.CMD_CURRENTPOSITION:
|
||||
self.lastFilePosition = float(value)
|
||||
if self.callbacks.onGetCurrentPosition:
|
||||
_thread.start_new_thread(self.callbacks.onGetCurrentPosition, (self.lastFilePosition,))
|
||||
_thread.start_new_thread(self.callbacks.onGetCurrentPosition, (self.lastFilePosition,))
|
||||
|
||||
elif cmd == self.CMD_NOTIFYSEEK:
|
||||
if self.lastFilePosition != float(value): #Notify seek is sometimes sent twice
|
||||
if self.lastFilePosition != float(value): # Notify seek is sometimes sent twice
|
||||
self.lastFilePosition = float(value)
|
||||
if self.callbacks.onSeek:
|
||||
_thread.start_new_thread(self.callbacks.onSeek, (self.lastFilePosition,))
|
||||
|
||||
elif cmd == self.CMD_DISCONNECT:
|
||||
if self.callbacks.onMpcClosed:
|
||||
_thread.start_new_thread(self.callbacks.onMpcClosed, (None,))
|
||||
_thread.start_new_thread(self.callbacks.onMpcClosed, (None,))
|
||||
|
||||
elif cmd == self.CMD_VERSION:
|
||||
if self.callbacks.onVersion:
|
||||
self.version = value
|
||||
_thread.start_new_thread(self.callbacks.onVersion, (value,))
|
||||
self.version = value
|
||||
_thread.start_new_thread(self.callbacks.onVersion, (value,))
|
||||
|
||||
class PlayerNotReadyException(Exception):
|
||||
pass
|
||||
@ -198,11 +205,11 @@ class MpcHcApi:
|
||||
CMD_ADDTOPLAYLIST = 0xA0001000
|
||||
CMD_CLEARPLAYLIST = 0xA0001001
|
||||
CMD_STARTPLAYLIST = 0xA0001002
|
||||
CMD_REMOVEFROMPLAYLIST = 0xA0001003 # TODO
|
||||
CMD_REMOVEFROMPLAYLIST = 0xA0001003 # TODO
|
||||
CMD_SETPOSITION = 0xA0002000
|
||||
CMD_SETAUDIODELAY = 0xA0002001
|
||||
CMD_SETSUBTITLEDELAY = 0xA0002002
|
||||
CMD_SETINDEXPLAYLIST = 0xA0002003 # DOESNT WORK
|
||||
CMD_SETINDEXPLAYLIST = 0xA0002003 # DOESNT WORK
|
||||
CMD_SETAUDIOTRACK = 0xA0002004
|
||||
CMD_SETSUBTITLETRACK = 0xA0002005
|
||||
CMD_GETSUBTITLETRACKS = 0xA0003000
|
||||
@ -256,7 +263,7 @@ class MpcHcApi:
|
||||
wc.lpszClassName = 'MPCApiListener'
|
||||
hinst = wc.hInstance = win32api.GetModuleHandle(None)
|
||||
classAtom = win32gui.RegisterClass(wc)
|
||||
self.hwnd = win32gui.CreateWindow (
|
||||
self.hwnd = win32gui.CreateWindow(
|
||||
classAtom,
|
||||
"ListenerGUI",
|
||||
0,
|
||||
@ -272,14 +279,13 @@ 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)
|
||||
# print "API:\tin>\t 0x%X\t" % int(pCDS.contents.dwData), ctypes.wstring_at(pCDS.contents.lpData)
|
||||
self.__mpcApi.handleCommand(pCDS.contents.dwData, ctypes.wstring_at(pCDS.contents.lpData))
|
||||
|
||||
def SendCommand(self, cmd, message=''):
|
||||
#print "API:\t<out\t 0x%X\t" % int(cmd), message
|
||||
# print "API:\t<out\t 0x%X\t" % int(cmd), message
|
||||
if not win32gui.IsWindow(self.mpcHandle):
|
||||
if self.__mpcApi.callbacks.onMpcClosed:
|
||||
self.__mpcApi.callbacks.onMpcClosed(None)
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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))
|
||||
@ -118,7 +127,7 @@ class MplayerPlayer(BasePlayer):
|
||||
pass
|
||||
|
||||
def setPosition(self, value):
|
||||
self._position = max(value,0)
|
||||
self._position = max(value, 0)
|
||||
self._setProperty(self.POSITION_QUERY, "{}".format(value))
|
||||
time.sleep(0.03)
|
||||
|
||||
@ -151,7 +160,7 @@ class MplayerPlayer(BasePlayer):
|
||||
text = text.replace("\\", "\\\\")
|
||||
text = text.replace("{", "\\\\{")
|
||||
text = text.replace("}", "\\\\}")
|
||||
text = text.replace("<SYNCPLAY_QUOTE>","\\\"")
|
||||
text = text.replace("<SYNCPLAY_QUOTE>", "\\\"")
|
||||
return text
|
||||
|
||||
def _quoteArg(self, arg):
|
||||
@ -169,7 +178,7 @@ class MplayerPlayer(BasePlayer):
|
||||
pass
|
||||
|
||||
def _storePosition(self, value):
|
||||
self._position = max(value,0)
|
||||
self._position = max(value, 0)
|
||||
|
||||
def _storePauseState(self, value):
|
||||
self._paused = value
|
||||
@ -179,9 +188,15 @@ class MplayerPlayer(BasePlayer):
|
||||
self._client.ui.showDebugMessage("player << {}".format(line))
|
||||
line = line.replace("[cplayer] ", "") # -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: ", "")
|
||||
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:
|
||||
@ -194,7 +209,7 @@ class MplayerPlayer(BasePlayer):
|
||||
self._handleUnknownLine(line)
|
||||
return
|
||||
|
||||
name, value =[m for m in match.groups() if m]
|
||||
name, value = [m for m in match.groups() if m]
|
||||
name = name.lower()
|
||||
|
||||
if name == self.POSITION_QUERY:
|
||||
@ -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
|
||||
|
||||
@ -301,7 +316,7 @@ class MplayerPlayer(BasePlayer):
|
||||
if not self.__playerController._client._config["chatOutputEnabled"]:
|
||||
self.__playerController.alertOSDSupported = False
|
||||
self.__playerController.chatOSDSupported = False
|
||||
if self.__playerController.getPlayerPathErrors(playerPath,filePath):
|
||||
if self.__playerController.getPlayerPathErrors(playerPath, filePath):
|
||||
raise ValueError()
|
||||
if filePath and '://' not in filePath:
|
||||
if not os.path.isfile(filePath) and 'PWD' in os.environ:
|
||||
@ -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()
|
||||
@ -440,8 +463,8 @@ class MplayerPlayer(BasePlayer):
|
||||
|
||||
def actuallySendLine(self, line):
|
||||
try:
|
||||
#if not isinstance(line, str):
|
||||
#line = line.decode('utf8')
|
||||
# if not isinstance(line, str):
|
||||
# line = line.decode('utf8')
|
||||
line = line + "\n"
|
||||
self.__playerController._client.ui.showDebugMessage("player >> {}".format(line))
|
||||
line = line.encode('utf-8')
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
# 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
|
||||
osdMessageSeparator = "; " # TODO: Make conditional
|
||||
|
||||
@staticmethod
|
||||
def run(client, playerPath, filePath, args):
|
||||
@ -19,9 +23,11 @@ class MpvPlayer(MplayerPlayer):
|
||||
except:
|
||||
ver = None
|
||||
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:
|
||||
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
|
||||
@ -120,17 +128,18 @@ class NewMpvPlayer(OldMpvPlayer):
|
||||
def displayMessage(self, message, duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION,
|
||||
mood=constants.MESSAGE_NEUTRAL):
|
||||
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
|
||||
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)
|
||||
super(self.__class__, self).displayChatMessage(username, message)
|
||||
return
|
||||
username = self._sanitizeText(username.replace("\\",constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
|
||||
message = self._sanitizeText(message.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
|
||||
@ -184,9 +202,10 @@ class NewMpvPlayer(OldMpvPlayer):
|
||||
self._client.ui.showDebugMessage("Recently reset, so storing position as 0")
|
||||
self._position = 0
|
||||
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:
|
||||
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)
|
||||
)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import syncplay.players
|
||||
|
||||
|
||||
class PlayerFactory(object):
|
||||
def __init__(self):
|
||||
self._players = syncplay.players.getAvailablePlayers()
|
||||
|
||||
@ -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
|
||||
@ -42,12 +48,13 @@ class VlcPlayer(BasePlayer):
|
||||
self._previousPreviousPosition = -2
|
||||
self._previousPosition = -1
|
||||
self._position = 0
|
||||
try: # Hack to fix locale issue without importing locale library
|
||||
try: # Hack to fix locale issue without importing locale library
|
||||
self.radixChar = "{:n}".format(1.5)[1:2]
|
||||
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)
|
||||
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)
|
||||
else:
|
||||
self.__process = subprocess.Popen(call, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
self.timeVLCLaunched = time.time()
|
||||
@ -405,7 +428,7 @@ class VlcPlayer(BasePlayer):
|
||||
if not isMacOS():
|
||||
self.__process.stderr = None
|
||||
else:
|
||||
vlcoutputthread = threading.Thread(target = self.handle_vlcoutput, args=())
|
||||
vlcoutputthread = threading.Thread(target=self.handle_vlcoutput, args=())
|
||||
vlcoutputthread.setDaemon(True)
|
||||
vlcoutputthread.start()
|
||||
threading.Thread.__init__(self, name="VLC Listener")
|
||||
@ -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))
|
||||
|
||||
@ -17,4 +17,3 @@ from syncplay.utils import blackholeStdoutForFrozenWindow
|
||||
if __name__ == '__main__':
|
||||
blackholeStdoutForFrozenWindow()
|
||||
SyncplayClientManager().run()
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user