fix formattings

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

View File

@ -7,16 +7,18 @@ 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)
icon_name = plist['CFBundleIconFile'] 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: if not icon_ext:
icon_ext = '.icns' icon_ext = '.icns'
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
# #
@ -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 # 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 # 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) badge_icon = icon_from_app(application)
# Where to put the icons # Where to put the icons
icon_locations = { icon_locations = {
appname: (150, 110), appname: (150, 110),
'Applications': (450, 110), 'Applications': (450, 110),
'Read Me': (100, 285), 'Read Me': (100, 285),
'Install for VLC': (500, 285) 'Install for VLC': (500, 285)
@ -106,7 +117,7 @@ arrange_by = None
grid_offset = (0, 0) grid_offset = (0, 0)
grid_spacing = 20 grid_spacing = 20
scroll_position = (0, 0) scroll_position = (0, 0)
label_pos = 'bottom' # or 'right' label_pos = 'bottom' # or 'right'
text_size = 12 text_size = 12
icon_size = 80 icon_size = 80

View File

@ -1,12 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
#coding:utf8 # coding:utf8
#*** 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
@ -241,11 +245,11 @@ NSIS_SCRIPT_TEMPLATE = r"""
Push English Push English
Push $${LANG_POLISH} Push $${LANG_POLISH}
Push Polski Push Polski
Push $${LANG_RUSSIAN} Push $${LANG_RUSSIAN}
Push Русский Push Русский
Push $${LANG_GERMAN} Push $${LANG_GERMAN}
Push Deutsch Push Deutsch
Push $${LANG_ITALIAN} Push $${LANG_ITALIAN}
Push Italiano Push Italiano
Push A ; A means auto count languages Push A ; A means auto count languages
LangDLL::LangDialog "Language Selection" "Please select the language of Syncplay and the installer" LangDLL::LangDialog "Language Selection" "Please select the language of Syncplay and the installer"
@ -317,25 +321,25 @@ NSIS_SCRIPT_TEMPLATE = r"""
;$${EndIf} ;$${EndIf}
$${If} $$CheckBox_VLC_State == $${BST_CHECKED} $${If} $$CheckBox_VLC_State == $${BST_CHECKED}
$${NSD_Check} $$CheckBox_VLC $${NSD_Check} $$CheckBox_VLC
$${EndIf} $${EndIf}
Call UpdateVLCCheckbox Call UpdateVLCCheckbox
$${If} $$CheckBox_StartMenuShortcut_State == $${BST_CHECKED} $${If} $$CheckBox_StartMenuShortcut_State == $${BST_CHECKED}
$${NSD_Check} $$CheckBox_StartMenuShortcut $${NSD_Check} $$CheckBox_StartMenuShortcut
$${EndIf} $${EndIf}
$${If} $$CheckBox_DesktopShortcut_State == $${BST_CHECKED} $${If} $$CheckBox_DesktopShortcut_State == $${BST_CHECKED}
$${NSD_Check} $$CheckBox_DesktopShortcut $${NSD_Check} $$CheckBox_DesktopShortcut
$${EndIf} $${EndIf}
$${If} $$CheckBox_QuickLaunchShortcut_State == $${BST_CHECKED} $${If} $$CheckBox_QuickLaunchShortcut_State == $${BST_CHECKED}
$${NSD_Check} $$CheckBox_QuickLaunchShortcut $${NSD_Check} $$CheckBox_QuickLaunchShortcut
$${EndIf} $${EndIf}
$${If} $$CheckBox_AutomaticUpdates_State == $${BST_CHECKED} $${If} $$CheckBox_AutomaticUpdates_State == $${BST_CHECKED}
$${NSD_Check} $$CheckBox_AutomaticUpdates $${NSD_Check} $$CheckBox_AutomaticUpdates
$${EndIf} $${EndIf}
nsDialogs::Show nsDialogs::Show
@ -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)
@ -617,12 +622,12 @@ class NSISScript(object):
if os.path.isfile(SETUP_SCRIPT_PATH): if os.path.isfile(SETUP_SCRIPT_PATH):
raise RuntimeError("Cannot create setup script, file exists at {}".format(SETUP_SCRIPT_PATH)) raise RuntimeError("Cannot create setup script, file exists at {}".format(SETUP_SCRIPT_PATH))
contents = Template(NSIS_SCRIPT_TEMPLATE).substitute( contents = Template(NSIS_SCRIPT_TEMPLATE).substitute(
version = syncplay.version, version=syncplay.version,
uninstallFiles = uninstallFiles, uninstallFiles=uninstallFiles,
installFiles = installFiles, installFiles=installFiles,
totalSize = totalSize, totalSize=totalSize,
) )
with codecs.open(SETUP_SCRIPT_PATH, "w", "utf-8-sig") as outfile: with codecs.open(SETUP_SCRIPT_PATH, "w", "utf-8-sig") as outfile:
outfile.write(contents) outfile.write(contents)
@ -664,29 +669,37 @@ 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',
'resources/control_pause_blue.png', 'resources/cross.png', 'resources/door_in.png', guiIcons = [
'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png', 'resources/accept.png', 'resources/arrow_undo.png', 'resources/clock_go.png',
'resources/timeline_marker.png','resources/control_play_blue.png', 'resources/control_pause_blue.png', 'resources/cross.png', 'resources/door_in.png',
'resources/mpc-hc.png','resources/mpc-hc64.png','resources/mplayer.png', 'resources/folder_explore.png', 'resources/help.png', 'resources/table_refresh.png',
'resources/mpc-be.png', 'resources/timeline_marker.png', 'resources/control_play_blue.png',
'resources/mpv.png','resources/vlc.png', 'resources/house.png', 'resources/film_link.png', 'resources/mpc-hc.png', 'resources/mpc-hc64.png', 'resources/mplayer.png',
'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/chevrons_right.png', 'resources/mpc-be.png',
'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png', 'resources/mpv.png', 'resources/vlc.png', 'resources/house.png', 'resources/film_link.png',
'resources/tick.png', 'resources/lock_open.png', 'resources/empty_checkbox.png', 'resources/tick_checkbox.png', 'resources/eye.png', 'resources/comments.png', 'resources/cog_delete.png', 'resources/chevrons_right.png',
'resources/world_explore.png', 'resources/application_get.png', 'resources/cog.png', 'resources/arrow_switch.png', 'resources/user_key.png', 'resources/lock.png', 'resources/key_go.png', 'resources/page_white_key.png',
'resources/film_go.png', 'resources/world_go.png', 'resources/arrow_refresh.png', 'resources/bullet_right_grey.png', 'resources/tick.png', 'resources/lock_open.png', 'resources/empty_checkbox.png', 'resources/tick_checkbox.png',
'resources/user_comment.png', 'resources/world_explore.png', 'resources/application_get.png', 'resources/cog.png', 'resources/arrow_switch.png',
'resources/error.png', 'resources/film_go.png', 'resources/world_go.png', 'resources/arrow_refresh.png', 'resources/bullet_right_grey.png',
'resources/film_folder_edit.png', 'resources/user_comment.png',
'resources/film_edit.png', 'resources/error.png',
'resources/folder_film.png', 'resources/film_folder_edit.png',
'resources/shield_edit.png', 'resources/film_edit.png',
'resources/shield_add.png', 'resources/folder_film.png',
'resources/email_go.png', 'resources/shield_edit.png',
'resources/world_add.png', 'resources/film_add.png', 'resources/delete.png', 'resources/spinner.mng' 'resources/shield_add.png',
] 'resources/email_go.png',
resources = ["resources/icon.ico", "resources/syncplay.png", "resources/syncplayintf.lua", "resources/license.rtf", "resources/third-party-notices.rtf"] '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) resources.extend(guiIcons)
intf_resources = ["resources/lua/intf/syncplay.lua"] intf_resources = ["resources/lua/intf/syncplay.lua"]

View File

@ -14,16 +14,21 @@ DATA_FILES = [
('resources', glob('resources/*.png') + glob('resources/*.rtf') + glob('resources/*.lua')), ('resources', glob('resources/*.png') + glob('resources/*.rtf') + glob('resources/*.lua')),
] ]
OPTIONS = { OPTIONS = {
'iconfile':'resources/icon.icns', 'iconfile': 'resources/icon.icns',
'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,
'CFBundleIdentifier':'pl.syncplay.Syncplay', 'CFBundleIdentifier': 'pl.syncplay.Syncplay',
'LSMinimumSystemVersion':'10.11.0', 'LSMinimumSystemVersion': '10.11.0',
'NSHumanReadableCopyright': '@ 2018 Syncplay All Rights Reserved' 'NSHumanReadableCopyright': '@ 2018 Syncplay All Rights Reserved'
} }
} }

View File

@ -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]

View File

@ -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

View File

@ -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):
@ -30,7 +33,7 @@ class MpcHcApi:
self.__listener.start() self.__listener.start()
self.__locks.listenerStart.wait() self.__locks.listenerStart.wait()
def waitForFileStateReady(f): #@NoSelf def waitForFileStateReady(f): #@NoSelf
@wraps(f) @wraps(f)
def wrapper(self, *args, **kwds): def wrapper(self, *args, **kwds):
if not self.__locks.fileReady.wait(constants.MPC_LOCK_WAIT_TIME): if not self.__locks.fileReady.wait(constants.MPC_LOCK_WAIT_TIME):
@ -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)
@ -99,18 +102,22 @@ class MpcHcApi:
self.__listener.mpcHandle = int(value) self.__listener.mpcHandle = int(value)
self.__locks.mpcStart.set() self.__locks.mpcStart.set()
if self.callbacks.onConnected: if self.callbacks.onConnected:
_thread.start_new_thread(self.callbacks.onConnected, ()) _thread.start_new_thread(self.callbacks.onConnected, ())
elif cmd == self.CMD_STATE: elif cmd == self.CMD_STATE:
self.loadState = int(value) self.loadState = int(value)
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()
else: else:
self.__locks.fileReady.set() self.__locks.fileReady.set()
if self.callbacks.onFileStateChange: if self.callbacks.onFileStateChange:
_thread.start_new_thread(self.callbacks.onFileStateChange, (self.loadState,)) _thread.start_new_thread(self.callbacks.onFileStateChange, (self.loadState,))
elif cmd == self.CMD_PLAYMODE: elif cmd == self.CMD_PLAYMODE:
self.playState = int(value) self.playState = int(value)
@ -125,31 +132,31 @@ class MpcHcApi:
self.filePlaying = value[3].split('\\').pop() self.filePlaying = value[3].split('\\').pop()
self.fileDuration = float(value[4]) self.fileDuration = float(value[4])
if self.callbacks.onUpdatePath: if self.callbacks.onUpdatePath:
_thread.start_new_thread(self.callbacks.onUpdatePath, (self.onUpdatePath,)) _thread.start_new_thread(self.callbacks.onUpdatePath, (self.onUpdatePath,))
if self.callbacks.onUpdateFilename: if self.callbacks.onUpdateFilename:
_thread.start_new_thread(self.callbacks.onUpdateFilename, (self.filePlaying,)) _thread.start_new_thread(self.callbacks.onUpdateFilename, (self.filePlaying,))
if self.callbacks.onUpdateFileDuration: if self.callbacks.onUpdateFileDuration:
_thread.start_new_thread(self.callbacks.onUpdateFileDuration, (self.fileDuration,)) _thread.start_new_thread(self.callbacks.onUpdateFileDuration, (self.fileDuration,))
elif cmd == self.CMD_CURRENTPOSITION: elif cmd == self.CMD_CURRENTPOSITION:
self.lastFilePosition = float(value) self.lastFilePosition = float(value)
if self.callbacks.onGetCurrentPosition: if self.callbacks.onGetCurrentPosition:
_thread.start_new_thread(self.callbacks.onGetCurrentPosition, (self.lastFilePosition,)) _thread.start_new_thread(self.callbacks.onGetCurrentPosition, (self.lastFilePosition,))
elif cmd == self.CMD_NOTIFYSEEK: elif cmd == self.CMD_NOTIFYSEEK:
if self.lastFilePosition != float(value): #Notify seek is sometimes sent twice if self.lastFilePosition != float(value): # Notify seek is sometimes sent twice
self.lastFilePosition = float(value) self.lastFilePosition = float(value)
if self.callbacks.onSeek: if self.callbacks.onSeek:
_thread.start_new_thread(self.callbacks.onSeek, (self.lastFilePosition,)) _thread.start_new_thread(self.callbacks.onSeek, (self.lastFilePosition,))
elif cmd == self.CMD_DISCONNECT: elif cmd == self.CMD_DISCONNECT:
if self.callbacks.onMpcClosed: if self.callbacks.onMpcClosed:
_thread.start_new_thread(self.callbacks.onMpcClosed, (None,)) _thread.start_new_thread(self.callbacks.onMpcClosed, (None,))
elif cmd == self.CMD_VERSION: elif cmd == self.CMD_VERSION:
if self.callbacks.onVersion: if self.callbacks.onVersion:
self.version = value self.version = value
_thread.start_new_thread(self.callbacks.onVersion, (value,)) _thread.start_new_thread(self.callbacks.onVersion, (value,))
class PlayerNotReadyException(Exception): class PlayerNotReadyException(Exception):
pass pass
@ -198,11 +205,11 @@ class MpcHcApi:
CMD_ADDTOPLAYLIST = 0xA0001000 CMD_ADDTOPLAYLIST = 0xA0001000
CMD_CLEARPLAYLIST = 0xA0001001 CMD_CLEARPLAYLIST = 0xA0001001
CMD_STARTPLAYLIST = 0xA0001002 CMD_STARTPLAYLIST = 0xA0001002
CMD_REMOVEFROMPLAYLIST = 0xA0001003 # TODO CMD_REMOVEFROMPLAYLIST = 0xA0001003 # TODO
CMD_SETPOSITION = 0xA0002000 CMD_SETPOSITION = 0xA0002000
CMD_SETAUDIODELAY = 0xA0002001 CMD_SETAUDIODELAY = 0xA0002001
CMD_SETSUBTITLEDELAY = 0xA0002002 CMD_SETSUBTITLEDELAY = 0xA0002002
CMD_SETINDEXPLAYLIST = 0xA0002003 # DOESNT WORK CMD_SETINDEXPLAYLIST = 0xA0002003 # DOESNT WORK
CMD_SETAUDIOTRACK = 0xA0002004 CMD_SETAUDIOTRACK = 0xA0002004
CMD_SETSUBTITLETRACK = 0xA0002005 CMD_SETSUBTITLETRACK = 0xA0002005
CMD_GETSUBTITLETRACKS = 0xA0003000 CMD_GETSUBTITLETRACKS = 0xA0003000
@ -256,7 +263,7 @@ class MpcHcApi:
wc.lpszClassName = 'MPCApiListener' wc.lpszClassName = 'MPCApiListener'
hinst = wc.hInstance = win32api.GetModuleHandle(None) hinst = wc.hInstance = win32api.GetModuleHandle(None)
classAtom = win32gui.RegisterClass(wc) classAtom = win32gui.RegisterClass(wc)
self.hwnd = win32gui.CreateWindow ( self.hwnd = win32gui.CreateWindow(
classAtom, classAtom,
"ListenerGUI", "ListenerGUI",
0, 0,
@ -272,14 +279,13 @@ 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)
self.__mpcApi.handleCommand(pCDS.contents.dwData, ctypes.wstring_at(pCDS.contents.lpData)) self.__mpcApi.handleCommand(pCDS.contents.dwData, ctypes.wstring_at(pCDS.contents.lpData))
def SendCommand(self, cmd, message=''): def SendCommand(self, cmd, message=''):
#print "API:\t<out\t 0x%X\t" % int(cmd), message # print "API:\t<out\t 0x%X\t" % int(cmd), message
if not win32gui.IsWindow(self.mpcHandle): if not win32gui.IsWindow(self.mpcHandle):
if self.__mpcApi.callbacks.onMpcClosed: if self.__mpcApi.callbacks.onMpcClosed:
self.__mpcApi.callbacks.onMpcClosed(None) self.__mpcApi.callbacks.onMpcClosed(None)
@ -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

View File

@ -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"

View File

@ -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))
@ -118,7 +127,7 @@ class MplayerPlayer(BasePlayer):
pass pass
def setPosition(self, value): def setPosition(self, value):
self._position = max(value,0) self._position = max(value, 0)
self._setProperty(self.POSITION_QUERY, "{}".format(value)) self._setProperty(self.POSITION_QUERY, "{}".format(value))
time.sleep(0.03) time.sleep(0.03)
@ -151,7 +160,7 @@ class MplayerPlayer(BasePlayer):
text = text.replace("\\", "\\\\") text = text.replace("\\", "\\\\")
text = text.replace("{", "\\\\{") text = text.replace("{", "\\\\{")
text = text.replace("}", "\\\\}") text = text.replace("}", "\\\\}")
text = text.replace("<SYNCPLAY_QUOTE>","\\\"") text = text.replace("<SYNCPLAY_QUOTE>", "\\\"")
return text return text
def _quoteArg(self, arg): def _quoteArg(self, arg):
@ -169,7 +178,7 @@ class MplayerPlayer(BasePlayer):
pass pass
def _storePosition(self, value): def _storePosition(self, value):
self._position = max(value,0) self._position = max(value, 0)
def _storePauseState(self, value): def _storePauseState(self, value):
self._paused = value self._paused = value
@ -179,9 +188,15 @@ class MplayerPlayer(BasePlayer):
self._client.ui.showDebugMessage("player << {}".format(line)) self._client.ui.showDebugMessage("player << {}".format(line))
line = line.replace("[cplayer] ", "") # -v workaround line = line.replace("[cplayer] ", "") # -v workaround
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:
@ -194,7 +209,7 @@ class MplayerPlayer(BasePlayer):
self._handleUnknownLine(line) self._handleUnknownLine(line)
return return
name, value =[m for m in match.groups() if m] name, value = [m for m in match.groups() if m]
name = name.lower() name = name.lower()
if name == self.POSITION_QUERY: if name == self.POSITION_QUERY:
@ -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
@ -301,7 +316,7 @@ class MplayerPlayer(BasePlayer):
if not self.__playerController._client._config["chatOutputEnabled"]: if not self.__playerController._client._config["chatOutputEnabled"]:
self.__playerController.alertOSDSupported = False self.__playerController.alertOSDSupported = False
self.__playerController.chatOSDSupported = False self.__playerController.chatOSDSupported = False
if self.__playerController.getPlayerPathErrors(playerPath,filePath): if self.__playerController.getPlayerPathErrors(playerPath, filePath):
raise ValueError() raise ValueError()
if filePath and '://' not in filePath: if filePath and '://' not in filePath:
if not os.path.isfile(filePath) and 'PWD' in os.environ: if not os.path.isfile(filePath) and 'PWD' in os.environ:
@ -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()
@ -440,8 +463,8 @@ class MplayerPlayer(BasePlayer):
def actuallySendLine(self, line): def actuallySendLine(self, line):
try: try:
#if not isinstance(line, str): # if not isinstance(line, str):
#line = line.decode('utf8') # line = line.decode('utf8')
line = line + "\n" line = line + "\n"
self.__playerController._client.ui.showDebugMessage("player >> {}".format(line)) self.__playerController._client.ui.showDebugMessage("player >> {}".format(line))
line = line.encode('utf-8') line = line.encode('utf-8')

View File

@ -1,16 +1,20 @@
# 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
@staticmethod @staticmethod
def run(client, playerPath, filePath, args): def run(client, playerPath, filePath, args):
@ -19,9 +23,11 @@ class MpvPlayer(MplayerPlayer):
except: except:
ver = None ver = None
constants.MPV_NEW_VERSION = ver is None or int(ver.group(1)) > 0 or int(ver.group(2)) >= 6 constants.MPV_NEW_VERSION = ver is None or int(ver.group(1)) > 0 or int(ver.group(2)) >= 6
constants.MPV_OSC_VISIBILITY_CHANGE_VERSION = False if ver is None else int(ver.group(1)) > 0 or int(ver.group(2)) >= 28 constants.MPV_OSC_VISIBILITY_CHANGE_VERSION = False if ver is None else int(ver.group(1)) > 0 or int(ver.group(2)) >= 28
if not constants.MPV_OSC_VISIBILITY_CHANGE_VERSION: if not constants.MPV_OSC_VISIBILITY_CHANGE_VERSION:
client.ui.showDebugMessage("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
@ -120,17 +128,18 @@ class NewMpvPlayer(OldMpvPlayer):
def displayMessage(self, message, duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION, def displayMessage(self, message, duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION,
mood=constants.MESSAGE_NEUTRAL): mood=constants.MESSAGE_NEUTRAL):
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
@ -184,9 +202,10 @@ class NewMpvPlayer(OldMpvPlayer):
self._client.ui.showDebugMessage("Recently reset, so storing position as 0") self._client.ui.showDebugMessage("Recently reset, so storing position as 0")
self._position = 0 self._position = 0
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 )

View File

@ -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()

View File

@ -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
@ -42,12 +48,13 @@ class VlcPlayer(BasePlayer):
self._previousPreviousPosition = -2 self._previousPreviousPosition = -2
self._previousPosition = -1 self._previousPosition = -1
self._position = 0 self._position = 0
try: # Hack to fix locale issue without importing locale library try: # Hack to fix locale issue without importing locale library
self.radixChar = "{:n}".format(1.5)[1:2] self.radixChar = "{:n}".format(1.5)[1:2]
if self.radixChar == "" or self.radixChar == "1" or self.radixChar == "5": if self.radixChar == "" or self.radixChar == "1" or self.radixChar == "5":
raise ValueError raise ValueError
except: except:
self._client.ui.showErrorMessage("Failed to determine locale. As a fallback Syncplay is using the following radix character: \".\".") self._client.ui.showErrorMessage(
"Failed to determine locale. As a fallback Syncplay is using the following radix character: \".\".")
self.radixChar = "." self.radixChar = "."
self._durationAsk = threading.Event() self._durationAsk = threading.Event()
@ -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()
@ -405,7 +428,7 @@ class VlcPlayer(BasePlayer):
if not isMacOS(): if not isMacOS():
self.__process.stderr = None self.__process.stderr = None
else: else:
vlcoutputthread = threading.Thread(target = self.handle_vlcoutput, args=()) vlcoutputthread = threading.Thread(target=self.handle_vlcoutput, args=())
vlcoutputthread.setDaemon(True) vlcoutputthread.setDaemon(True)
vlcoutputthread.start() vlcoutputthread.start()
threading.Thread.__init__(self, name="VLC Listener") threading.Thread.__init__(self, name="VLC Listener")
@ -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))

View File

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

View File

@ -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()