diff --git a/appdmg.py b/appdmg.py index 705ff7b..45a3f9d 100755 --- a/appdmg.py +++ b/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 diff --git a/buildInstaller.py b/buildInstaller.py index 73560ce..50181c0 100644 --- a/buildInstaller.py +++ b/buildInstaller.py @@ -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 @@ -79,7 +83,7 @@ NSIS_SCRIPT_TEMPLATE = r""" VIAddVersionKey /LANG=$${LANG_RUSSIAN} "FileVersion" "$version.0" VIAddVersionKey /LANG=$${LANG_RUSSIAN} "LegalCopyright" "Syncplay" VIAddVersionKey /LANG=$${LANG_RUSSIAN} "FileDescription" "Syncplay" - + VIAddVersionKey /LANG=$${LANG_ITALIAN} "ProductName" "Syncplay" VIAddVersionKey /LANG=$${LANG_ITALIAN} "FileVersion" "$version.0" VIAddVersionKey /LANG=$${LANG_ITALIAN} "LegalCopyright" "Syncplay" @@ -127,7 +131,7 @@ NSIS_SCRIPT_TEMPLATE = r""" LangString ^QuickLaunchBar $${LANG_GERMAN} "Schnellstartleiste" LangString ^AutomaticUpdates $${LANG_GERMAN} "Automatisch nach Updates suchen"; LangString ^UninstConfig $${LANG_GERMAN} "Konfigurationsdatei löschen." - + LangString ^SyncplayLanguage $${LANG_ITALIAN} "it" LangString ^Associate $${LANG_ITALIAN} "Associa Syncplay con i file multimediali." LangString ^VLC $${LANG_ITALIAN} "Installa l'interfaccia di Syncplay per VLC 2+" @@ -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,24 +612,25 @@ NSIS_SCRIPT_TEMPLATE = r""" SectionEnd """ + class NSISScript(object): def create(self): fileList, totalSize = self.getBuildDirContents(OUT_DIR) print("Total size eq: {}".format(totalSize)) - installFiles = self.prepareInstallListTemplate(fileList) + installFiles = self.prepareInstallListTemplate(fileList) uninstallFiles = self.prepareDeleteListTemplate(fileList) - + 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) - + def compile(self): if not os.path.isfile(NSIS_COMPILE): return "makensis.exe not found, won't create the installer" @@ -635,7 +640,7 @@ class NSISScript(object): os.remove(SETUP_SCRIPT_PATH) if retcode: raise RuntimeError("NSIS compilation return code: %d" % retcode) - + def getBuildDirContents(self, path): fileList = {} totalSize = 0 @@ -646,8 +651,8 @@ class NSISScript(object): if new_root not in fileList: fileList[new_root] = [] fileList[new_root].append(file_) - return fileList, totalSize - + return fileList, totalSize + def prepareInstallListTemplate(self, fileList): create = [] for dir_ in fileList.keys(): @@ -655,38 +660,46 @@ class NSISScript(object): for file_ in fileList[dir_]: create.append('FILE "{}\\{}\\{}"'.format(OUT_DIR, dir_, file_)) return "\n".join(create) - + def prepareDeleteListTemplate(self, fileList): delete = [] for dir_ in fileList.keys(): for file_ in fileList[dir_]: delete.append('DELETE "$INSTDIR\\{}\\{}"'.format(dir_, file_)) - delete.append('RMdir "$INSTDIR\\{}"'.format(file_)) + 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"] @@ -697,7 +710,7 @@ common_info = dict( author_email='dev@syncplay.pl', description='Syncplay', ) - + script = NSISScript() script.create() print("*** compiling the NSIS setup script***") diff --git a/buildPy2app.py b/buildPy2app.py index 8e4d14a..aa1e0dc 100755 --- a/buildPy2app.py +++ b/buildPy2app.py @@ -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' } } diff --git a/syncplay/players/__init__.py b/syncplay/players/__init__.py index a2a888b..6ba79d3 100755 --- a/syncplay/players/__init__.py +++ b/syncplay/players/__init__.py @@ -4,13 +4,14 @@ from syncplay.players.vlc import VlcPlayer try: from syncplay.players.mpc import MPCHCAPIPlayer except ImportError: - from syncplay.players.basePlayer import DummyPlayer + from syncplay.players.basePlayer import DummyPlayer MPCHCAPIPlayer = DummyPlayer try: from syncplay.players.mpcbe import MpcBePlayer except ImportError: from syncplay.players.basePlayer import DummyPlayer MpcBePlayer = DummyPlayer - + + def getAvailablePlayers(): return [MPCHCAPIPlayer, MplayerPlayer, MpvPlayer, VlcPlayer, MpcBePlayer] diff --git a/syncplay/players/basePlayer.py b/syncplay/players/basePlayer.py index 96069d9..eb5e0d5 100755 --- a/syncplay/players/basePlayer.py +++ b/syncplay/players/basePlayer.py @@ -1,10 +1,12 @@ from syncplay import constants + + class BasePlayer(object): - + ''' - This method is supposed to + This method is supposed to execute updatePlayerStatus(paused, position) on client - Given the arguments: boolean paused and float position in seconds + Given the arguments: boolean paused and float position in seconds ''' def askForStatus(self): raise NotImplementedError() @@ -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() ''' @@ -29,62 +33,61 @@ class BasePlayer(object): raise NotImplementedError() ''' - @type value: boolean + @type value: boolean ''' def setPaused(self, value): raise NotImplementedError() ''' - @type value: list + @type value: list ''' def setFeatures(self, featureList): raise NotImplementedError() ''' - @type value: float + @type value: float ''' def setPosition(self, value): raise NotImplementedError() ''' - @type value: float + @type value: float ''' def setSpeed(self, value): raise NotImplementedError() - + ''' - @type filePath: string + @type filePath: string ''' def openFile(self, filePath, resetPosition=False): raise NotImplementedError() - - + ''' @return: list of strings ''' @staticmethod def getDefaultPlayerPathsList(): raise NotImplementedError() - + ''' @type path: string ''' @staticmethod def isValidPlayerPath(path): raise NotImplementedError() - + ''' @type path: string @return: string - ''' + ''' @staticmethod def getIconPath(path): raise NotImplementedError() - + ''' @type path: string @return: string - ''' + ''' @staticmethod def getExpandedPath(path): raise NotImplementedError() @@ -107,24 +110,25 @@ class BasePlayer(object): def getPlayerPathErrors(playerPath, filePath): raise NotImplementedError() + class DummyPlayer(BasePlayer): @staticmethod def getDefaultPlayerPathsList(): return [] - + @staticmethod def isValidPlayerPath(path): return False - + @staticmethod def getIconPath(path): return None - + @staticmethod def getExpandedPath(path): return path @staticmethod def getPlayerPathErrors(playerPath, filePath): - return None \ No newline at end of file + return None diff --git a/syncplay/players/mpc.py b/syncplay/players/mpc.py index 32eda91..88d684c 100755 --- a/syncplay/players/mpc.py +++ b/syncplay/players/mpc.py @@ -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")).replace("", "\\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", "")).replace("", "\\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("","\\\"") + text = text.replace("", "\\\"") 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(" Ready to send: True") else: self.__playerController._client.ui.showDebugMessage(" 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(" 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(" Remove duplicate (supersede): {}".format(self.sendQueue[itemID])) + self.__playerController._client.ui.showDebugMessage( + " Remove duplicate (supersede): {}".format(self.sendQueue[itemID])) try: self.sendQueue.remove(self.sendQueue[itemID]) except UnicodeWarning: - self.__playerController._client.ui.showDebugMessage(" Unicode mismatch occured when trying to remove duplicate") + self.__playerController._client.ui.showDebugMessage( + " 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(" Remove duplicate (delete both): {}".format(self.sendQueue[itemID])) + self.__playerController._client.ui.showDebugMessage( + " 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(" Throttling message send, so sleeping for {}".format(constants.MPV_SENDMESSAGE_COOLDOWN_TIME)) + self.__playerController._client.ui.showDebugMessage( + " 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') diff --git a/syncplay/players/mpv.py b/syncplay/players/mpv.py index 26da661..5ccf6e8 100755 --- a/syncplay/players/mpv.py +++ b/syncplay/players/mpv.py @@ -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", "")).replace("\\\\",constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER).replace("", "\\n") + messageString = self._sanitizeText(message.replace("\\n", "")).replace( + "\\\\", constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER).replace("", "\\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) + ) diff --git a/syncplay/players/playerFactory.py b/syncplay/players/playerFactory.py index cb2c2a1..2171d4e 100755 --- a/syncplay/players/playerFactory.py +++ b/syncplay/players/playerFactory.py @@ -1,26 +1,27 @@ import syncplay.players + class PlayerFactory(object): def __init__(self): self._players = syncplay.players.getAvailablePlayers() - + def getAvailablePlayerPaths(self): l = [] for player in self._players: l.extend(player.getDefaultPlayerPathsList()) return l - + def getPlayerByPath(self, path): for player in self._players: if player.isValidPlayerPath(path): return player - + def getPlayerIconByPath(self, path): for player in self._players: if player.isValidPlayerPath(path): return player.getIconPath(path) return None - + def getExpandedPlayerPathByPath(self, path): for player in self._players: if player.isValidPlayerPath(path): diff --git a/syncplay/players/vlc.py b/syncplay/players/vlc.py index 7908ddf..59b5f39 100755 --- a/syncplay/players/vlc.py +++ b/syncplay/players/vlc.py @@ -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 @@ -23,8 +29,8 @@ class VlcPlayer(BasePlayer): RE_ANSWER = re.compile(constants.VLC_ANSWER_REGEX) SLAVE_ARGS = constants.VLC_SLAVE_ARGS if isMacOS(): - SLAVE_ARGS.extend(constants.VLC_SLAVE_MACOS_ARGS) - else: + SLAVE_ARGS.extend(constants.VLC_SLAVE_MACOS_ARGS) + else: SLAVE_ARGS.extend(constants.VLC_SLAVE_NONMACOS_ARGS) vlcport = random.randrange(constants.VLC_MIN_PORT, constants.VLC_MAX_PORT) if (constants.VLC_MIN_PORT < constants.VLC_MAX_PORT) else constants.VLC_MIN_PORT @@ -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,13 +395,17 @@ 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.__process = subprocess.Popen(call, stderr=subprocess.PIPE, stdout=subprocess.PIPE) self.timeVLCLaunched = time.time() if self._shouldListenForSTDOUT(): for line in iter(self.__process.stderr.readline, ''): @@ -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: @@ -461,7 +481,6 @@ class VlcPlayer(BasePlayer): self.__playerController.drop() break out.close() - def found_terminator(self): self.vlcHasResponded = True diff --git a/syncplayClient.py b/syncplayClient.py index 917849e..dad7ac3 100755 --- a/syncplayClient.py +++ b/syncplayClient.py @@ -17,4 +17,3 @@ from syncplay.utils import blackholeStdoutForFrozenWindow if __name__ == '__main__': blackholeStdoutForFrozenWindow() SyncplayClientManager().run() - diff --git a/syncplayServer.py b/syncplayServer.py index 148deba..3aa9866 100755 --- a/syncplayServer.py +++ b/syncplayServer.py @@ -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()