From 42817b90879ba5e825861b7dde30a387d68169ca Mon Sep 17 00:00:00 2001 From: Et0h Date: Sun, 31 Jan 2016 15:11:01 +0000 Subject: [PATCH] Move FileSwitchManager to Client and use in PlaylistManager --- syncplay/client.py | 145 ++++++++++++++++++++++++++++++++---- syncplay/ui/gui.py | 180 +++++---------------------------------------- 2 files changed, 151 insertions(+), 174 deletions(-) diff --git a/syncplay/client.py b/syncplay/client.py index 6c2c618..5b62d21 100644 --- a/syncplay/client.py +++ b/syncplay/client.py @@ -5,8 +5,9 @@ import re import sys import ast import random +import threading from twisted.internet.protocol import ClientFactory -from twisted.internet import reactor, task, defer +from twisted.internet import reactor, task, defer, threads from functools import wraps from copy import deepcopy from syncplay.protocols import SyncClientProtocol @@ -119,7 +120,9 @@ class SyncplayClient(object): self.__playerReady = defer.Deferred() self._warnings = self._WarningManager(self._player, self.userlist, self.ui, self) + self.fileSwitch = FileSwitchManager(self) self.playlist = SyncplayPlaylist(self) + if constants.LIST_RELATIVE_CONFIGS and self._config.has_key('loadedRelativePaths') and self._config['loadedRelativePaths']: paths = "; ".join(self._config['loadedRelativePaths']) self.ui.showMessage(getMessage("relative-config-notification").format(paths), noPlayer=True, noTimestamp=True) @@ -460,16 +463,6 @@ class SyncplayClient(object): self.sendFile() self.playlist.changeToPlaylistIndexFromFilename(filename) - def findFilenameInDirectories(self, filename): - # TODO: Replace this with the code in gui.py - directoryList = self._config["mediaSearchDirectories"] - if filename and directoryList: - for directory in directoryList: - for root, dirs, files in os.walk(directory): - if filename in files: - return os.path.join(root,filename) - return None - def openFile(self, filePath, resetPosition=False): self._player.openFile(filePath, resetPosition) @@ -1397,8 +1390,7 @@ class SyncplayPlaylist(): self._ui.showErrorMessage(getMessage("cannot-add-unsafe-path-error").format(filename)) return else: - path = self._client.findFilenameInDirectories(filename) - # TODO: Find Path properly + path = self._client.fileSwitch.findFilepath(filename) if path: self._client.openFile(path, resetPosition) else: @@ -1536,4 +1528,129 @@ class SyncplayPlaylist(): self._previousPlaylistRoom = currentRoom def _playlistBufferNeedsUpdating(self, newPlaylist): - return self._previousPlaylist <> self._playlist and self._playlist <> newPlaylist \ No newline at end of file + return self._previousPlaylist <> self._playlist and self._playlist <> newPlaylist + +class FileSwitchManager(object): + def __init__(self, client): + self._client = client + self.fileSwitchTimer = task.LoopingCall(self.updateInfo) + self.mediaFilesCache = {} + self.filenameWatchlist = [] + self.currentDirectory = None + self.mediaDirectories = None + self.lock = threading.Lock() + self.folderSearchEnabled = True + self.disabledDir = None + self.newInfo = False + self.currentlyUpdating = False + self.newInfo = False + self.newWatchlist = [] + self.fileSwitchTimer.start(constants.FOLDER_SEARCH_DOUBLE_CHECK_INTERVAL, True) + + def setClient(self, newClient): + self.client = newClient + + def setCurrentDirectory(self, curDir): + self.currentDirectory = curDir + self.updateInfo() + + def setMediaDirectories(self, mediaDirs): + self.mediaDirectories = mediaDirs + self.updateInfo() + + def checkForFileSwitchUpdate(self, bob=None): + if bob is not None: + print bob + if self.newInfo: + self.newInfo = False + self.infoUpdated() + + def updateInfo(self): + if len(self.filenameWatchlist) > 0 or len(self.mediaFilesCache) == 0 and self.currentlyUpdating == False: + threads.deferToThread(self._updateInfoThread).addCallback(self.checkForFileSwitchUpdate) + + def setFilenameWatchlist(self, unfoundFilenames): + self.filenameWatchlist = unfoundFilenames + + def _updateInfoThread(self): + if not self.folderSearchEnabled: + if self.areWatchedFilenamesInCurrentDir(): + self.newInfo = True + return + + with self.lock: + try: + self.currentlyUpdating = True + dirsToSearch = self.mediaDirectories + + if dirsToSearch: + newMediaFilesCache = {} + startTime = time.time() + for directory in dirsToSearch: + for root, dirs, files in os.walk(directory): + newMediaFilesCache[root] = files + if time.time() - startTime > constants.FOLDER_SEARCH_TIMEOUT: + self.disabledDir = directory + self.folderSearchEnabled = False + if self.areWatchedFilenamesInCurrentDir(): + self.newInfo = True + return + + if self.mediaFilesCache <> newMediaFilesCache: + self.mediaFilesCache = newMediaFilesCache + self.newInfo = True + elif self.areWatchedFilenamesInCurrentDir(): + self.newInfo = True + finally: + self.currentlyUpdating = False + + def infoUpdated(self): + if self.areWatchedFilenamesInCache() or self.areWatchedFilenamesInCurrentDir(): + self.updateListOfWhoIsPlayingWhat() + + def updateListOfWhoIsPlayingWhat(self): + self._client.showUserList() + + def findFilepath(self, filename): + if filename is None: + return + + if self.currentDirectory is not None: + candidatePath = os.path.join(self.currentDirectory,filename) + if os.path.isfile(candidatePath): + return candidatePath + + if self.mediaFilesCache is not None: + for directory in self.mediaFilesCache: + files = self.mediaFilesCache[directory] + + if len(files) > 0 and filename in files: + filepath = os.path.join(directory, filename) + if os.path.isfile(filepath): + return filepath + + def areWatchedFilenamesInCurrentDir(self): + if self.filenameWatchlist is not None and self.currentDirectory is not None: + for filename in self.filenameWatchlist: + potentialPath = os.path.join(self.currentDirectory,filename) + if os.path.isfile(potentialPath): + return True + + def areWatchedFilenamesInCache(self): + if self.filenameWatchlist is not None: + for filename in self.filenameWatchlist: + if self.isFilenameInCache(filename): + return True + + def isFilenameInCurrentDir(self, filename): + if filename is not None and self.currentDirectory is not None: + potentialPath = os.path.join(self.currentDirectory,filename) + if os.path.isfile(potentialPath): + return True + + def isFilenameInCache(self, filename): + if filename is not None and self.mediaFilesCache is not None: + for directory in self.mediaFilesCache: + files = self.mediaFilesCache[directory] + if filename in files: + return True \ No newline at end of file diff --git a/syncplay/ui/gui.py b/syncplay/ui/gui.py index 33150d4..d5c5d9e 100644 --- a/syncplay/ui/gui.py +++ b/syncplay/ui/gui.py @@ -10,8 +10,7 @@ import re import os from syncplay.utils import formatTime, sameFilename, sameFilesize, sameFileduration, RoomPasswordProvider, formatSize, isURL from functools import wraps -from twisted.internet import task, threads -import threading +from twisted.internet import task lastCheckedForUpdates = None class UserlistItemDelegate(QtGui.QStyledItemDelegate): @@ -260,148 +259,7 @@ class MainWindow(QtGui.QMainWindow): else: super(MainWindow.PlaylistWidget, self).dropEvent(event) - class FileSwitchManager(object): - def __init__(self): - self.fileSwitchTimer = task.LoopingCall(self.updateInfo) - self.fileSwitchTimer.start(constants.FOLDER_SEARCH_DOUBLE_CHECK_INTERVAL, True) - mediaFilesCache = {} - filenameWatchlist = [] - currentDirectory = None - mediaDirectories = None - lock = threading.Lock() - client = None - currentWindow = None - folderSearchEnabled = True - disabledDir = None - newInfo = False - currentlyUpdating = False - - @staticmethod - def setWindow(window): - MainWindow.FileSwitchManager.currentWindow = window - - @staticmethod - def setClient(newClient): - MainWindow.FileSwitchManager.client = newClient - - @staticmethod - def setCurrentDirectory(curDir): - MainWindow.FileSwitchManager.currentDirectory = curDir - MainWindow.FileSwitchManager.updateInfo() - - @staticmethod - def setMediaDirectories(mediaDirs): - MainWindow.FileSwitchManager.mediaDirectories = mediaDirs - MainWindow.FileSwitchManager.updateInfo() - - @staticmethod - def checkForUpdate(self=None): - if MainWindow.FileSwitchManager.newInfo: - MainWindow.FileSwitchManager.newInfo = False - MainWindow.FileSwitchManager.infoUpdated() - - @staticmethod - def updateInfo(): - if len(MainWindow.FileSwitchManager.filenameWatchlist) > 0 or len(MainWindow.FileSwitchManager.mediaFilesCache) == 0 and MainWindow.FileSwitchManager.currentlyUpdating == False: - threads.deferToThread(MainWindow.FileSwitchManager._updateInfoThread).addCallback(MainWindow.FileSwitchManager.checkForUpdate) - - @staticmethod - def setFilenameWatchlist(unfoundFilenames): - MainWindow.FileSwitchManager.filenameWatchlist = unfoundFilenames - - @staticmethod - def _updateInfoThread(): - if not MainWindow.FileSwitchManager.folderSearchEnabled: - if MainWindow.FileSwitchManager.areWatchedFilenamesInCurrentDir(): - MainWindow.FileSwitchManager.newInfo = True - return - - with MainWindow.FileSwitchManager.lock: - try: - MainWindow.FileSwitchManager.currentlyUpdating = True - dirsToSearch = MainWindow.FileSwitchManager.mediaDirectories - - if dirsToSearch: - newMediaFilesCache = {} - startTime = time.time() - for directory in dirsToSearch: - for root, dirs, files in os.walk(directory): - newMediaFilesCache[root] = files - if time.time() - startTime > constants.FOLDER_SEARCH_TIMEOUT: - if MainWindow.FileSwitchManager.client is not None and MainWindow.FileSwitchManager.currentWindow is not None: - MainWindow.FileSwitchManager.disabledDir = directory - MainWindow.FileSwitchManager.folderSearchEnabled = False - if MainWindow.FileSwitchManager.areWatchedFilenamesInCurrentDir(): - MainWindow.FileSwitchManager.newInfo = True - return - - if MainWindow.FileSwitchManager.mediaFilesCache <> newMediaFilesCache: - MainWindow.FileSwitchManager.mediaFilesCache = newMediaFilesCache - MainWindow.FileSwitchManager.newInfo = True - elif MainWindow.FileSwitchManager.areWatchedFilenamesInCurrentDir(): - MainWindow.FileSwitchManager.newInfo = True - finally: - MainWindow.FileSwitchManager.currentlyUpdating = False - - @staticmethod - def infoUpdated(): - if MainWindow.FileSwitchManager.areWatchedFilenamesInCache() or MainWindow.FileSwitchManager.areWatchedFilenamesInCurrentDir(): - MainWindow.FileSwitchManager.updateListOfWhoIsPlayingWhat() - - @staticmethod - def updateListOfWhoIsPlayingWhat(): - if MainWindow.FileSwitchManager.client is not None: - MainWindow.FileSwitchManager.client.showUserList() - - @staticmethod - def findFilepath(filename): - if filename is None: - return - - if MainWindow.FileSwitchManager.currentDirectory is not None: - candidatePath = os.path.join(MainWindow.FileSwitchManager.currentDirectory,filename) - if os.path.isfile(candidatePath): - return candidatePath - - if MainWindow.FileSwitchManager.mediaFilesCache is not None: - for directory in MainWindow.FileSwitchManager.mediaFilesCache: - files = MainWindow.FileSwitchManager.mediaFilesCache[directory] - - if len(files) > 0 and filename in files: - filepath = os.path.join(directory, filename) - if os.path.isfile(filepath): - return filepath - - @staticmethod - def areWatchedFilenamesInCurrentDir(): - if MainWindow.FileSwitchManager.filenameWatchlist is not None and MainWindow.FileSwitchManager.currentDirectory is not None: - for filename in MainWindow.FileSwitchManager.filenameWatchlist: - potentialPath = os.path.join(MainWindow.FileSwitchManager.currentDirectory,filename) - if os.path.isfile(potentialPath): - return True - - @staticmethod - def areWatchedFilenamesInCache(): - if MainWindow.FileSwitchManager.filenameWatchlist is not None: - for filename in MainWindow.FileSwitchManager.filenameWatchlist: - if MainWindow.FileSwitchManager.isFilenameInCache(filename): - return True - - @staticmethod - def isFilenameInCurrentDir(filename): - if filename is not None and MainWindow.FileSwitchManager.currentDirectory is not None: - potentialPath = os.path.join(MainWindow.FileSwitchManager.currentDirectory,filename) - if os.path.isfile(potentialPath): - return True - - @staticmethod - def isFilenameInCache(filename): - if filename is not None and MainWindow.FileSwitchManager.mediaFilesCache is not None: - for directory in MainWindow.FileSwitchManager.mediaFilesCache: - files = MainWindow.FileSwitchManager.mediaFilesCache[directory] - if filename in files: - return True class topSplitter(QtGui.QSplitter): def createHandle(self): @@ -427,14 +285,13 @@ class MainWindow(QtGui.QMainWindow): def addClient(self, client): self._syncplayClient = client - MainWindow.FileSwitchManager.setClient(client) self.roomInput.setText(self._syncplayClient.getRoom()) self.config = self._syncplayClient.getConfig() try: self.playlistGroup.blockSignals(True) self.playlistGroup.setChecked(self.config['sharedPlaylistEnabled']) self.playlistGroup.blockSignals(False) - self.FileSwitchManager.setMediaDirectories(self.config["mediaSearchDirectories"]) + self._syncplayClient.fileSwitch.setMediaDirectories(self.config["mediaSearchDirectories"]) self.updateReadyState(self.config['readyAtStart']) autoplayInitialState = self.config['autoplayInitialState'] if autoplayInitialState is not None: @@ -467,6 +324,7 @@ class MainWindow(QtGui.QMainWindow): else: self.newMessage(time.strftime(constants.UI_TIME_FORMAT, time.localtime()) + message + "
") + @needsClient def getFileSwitchState(self, filename): if filename: if filename == getMessage("nofile-note"): @@ -476,19 +334,20 @@ class MainWindow(QtGui.QMainWindow): if isURL(filename): return constants.FILEITEM_SWITCH_STREAM_SWITCH elif filename not in self.newWatchlist: - if MainWindow.FileSwitchManager.findFilepath(filename): + if self._syncplayClient.fileSwitch.findFilepath(filename): return constants.FILEITEM_SWITCH_FILE_SWITCH else: self.newWatchlist.extend([filename]) return constants.FILEITEM_SWITCH_NO_SWITCH + @needsClient def showUserList(self, currentUser, rooms): self._usertreebuffer = QtGui.QStandardItemModel() self._usertreebuffer.setHorizontalHeaderLabels( (getMessage("roomuser-heading-label"), getMessage("size-heading-label"), getMessage("duration-heading-label"), getMessage("filename-heading-label") )) usertreeRoot = self._usertreebuffer.invisibleRootItem() if self._syncplayClient.userlist.currentUser.file and self._syncplayClient.userlist.currentUser.file and os.path.isfile(self._syncplayClient.userlist.currentUser.file["path"]): - MainWindow.FileSwitchManager.setCurrentDirectory(os.path.dirname(self._syncplayClient.userlist.currentUser.file["path"])) + self._syncplayClient.fileSwitch.setCurrentDirectory(os.path.dirname(self._syncplayClient.userlist.currentUser.file["path"])) for room in rooms: self.newWatchlist = [] @@ -577,7 +436,7 @@ class MainWindow(QtGui.QMainWindow): self.listTreeView.setRootIsDecorated(False) self.listTreeView.expandAll() self.updateListGeometry() - MainWindow.FileSwitchManager.setFilenameWatchlist(self.newWatchlist) + self._syncplayClient.fileSwitch.setFilenameWatchlist(self.newWatchlist) self.checkForDisabledDir() @needsClient @@ -588,6 +447,7 @@ class MainWindow(QtGui.QMainWindow): def shufflePlaylist(self): self._syncplayClient.playlist.shufflePlaylist() + @needsClient def openPlaylistMenu(self, position): indexes = self.playlist.selectedIndexes() if sys.platform.startswith('win'): @@ -606,7 +466,7 @@ class MainWindow(QtGui.QMainWindow): if isURL(firstFile): menu.addAction(QtGui.QPixmap(resourcespath + "world_go.png"), getMessage("openstreamurl-menu-label"), lambda: self.openFile(firstFile)) else: - pathFound = MainWindow.FileSwitchManager.findFilepath(firstFile) + pathFound = self._syncplayClient.fileSwitch.findFilepath(firstFile) if pathFound: menu.addAction(QtGui.QPixmap(resourcespath + "film_go.png"), getMessage("openmedia-menu-label"), lambda: self.openFile(pathFound)) menu.addAction(QtGui.QPixmap(resourcespath + "delete.png"), getMessage("removefromplaylist-menu-label"), lambda: self.deleteSelectedPlaylistItems()) @@ -656,7 +516,7 @@ class MainWindow(QtGui.QMainWindow): if isURL(filename): menu.addAction(QtGui.QPixmap(resourcespath + "world_go.png"), getMessage("openusersstream-menu-label").format(shortUsername), lambda: self.openFile(filename)) else: - pathFound = MainWindow.FileSwitchManager.findFilepath(filename) + pathFound = self._syncplayClient.fileSwitch.findFilepath(filename) if pathFound: menu.addAction(QtGui.QPixmap(resourcespath + "film_go.png"), getMessage("openusersfile-menu-label").format(shortUsername), lambda: self.openFile(pathFound)) else: @@ -664,10 +524,11 @@ class MainWindow(QtGui.QMainWindow): menu.exec_(self.listTreeView.viewport().mapToGlobal(position)) + @needsClient def checkForDisabledDir(self): - if MainWindow.FileSwitchManager.disabledDir is not None and MainWindow.FileSwitchManager.currentWindow is not None: - self.showErrorMessage(getMessage("folder-search-timeout-error").format(MainWindow.FileSwitchManager.disabledDir)) - MainWindow.FileSwitchManager.disabledDir = None + if self._syncplayClient.fileSwitch.disabledDir is not None and self._syncplayClient.fileSwitch.currentWindow is not None: + self.showErrorMessage(getMessage("folder-search-timeout-error").format(self._syncplayClient.fileSwitch.disabledDir)) + self._syncplayClient.fileSwitch.disabledDir = None def updateListGeometry(self): try: @@ -697,13 +558,14 @@ class MainWindow(QtGui.QMainWindow): self.readyPushButton.blockSignals(False) self.updateReadyIcon() + @needsClient def playlistItemClicked(self, item): # TODO: Integrate into client.py code filename = item.data() if isURL(filename): self._syncplayClient._player.openFile(filename) else: - pathFound = MainWindow.FileSwitchManager.findFilepath(filename) + pathFound = self._syncplayClient.fileSwitch.findFilepath(filename) if pathFound: self._syncplayClient._player.openFile(pathFound) else: @@ -723,11 +585,11 @@ class MainWindow(QtGui.QMainWindow): if isURL(filename): self._syncplayClient._player.openFile(filename) else: - pathFound = MainWindow.FileSwitchManager.findFilepath(filename) + pathFound = self._syncplayClient.fileSwitch.findFilepath(filename) if pathFound: self._syncplayClient._player.openFile(pathFound) else: - MainWindow.FileSwitchManager.updateInfo() + self._syncplayClient.fileSwitch.updateInfo() self.showErrorMessage(getMessage("switch-file-not-found-error").format(filename)) @needsClient @@ -861,7 +723,7 @@ class MainWindow(QtGui.QMainWindow): if sys.platform.startswith('win'): fileName = fileName.replace("/", "\\") self.mediadirectory = os.path.dirname(fileName) - self.FileSwitchManager.setCurrentDirectory(self.mediadirectory) + self._syncplayClient.fileSwitch.setCurrentDirectory(self.mediadirectory) self.saveMediaBrowseSettings() self._syncplayClient._player.openFile(fileName) @@ -888,7 +750,7 @@ class MainWindow(QtGui.QMainWindow): if sys.platform.startswith('win'): fileName = fileName.replace("/", "\\") self.mediadirectory = os.path.dirname(fileName) - self.FileSwitchManager.setCurrentDirectory(self.mediadirectory) + self._syncplayClient.fileSwitch.setCurrentDirectory(self.mediadirectory) self.saveMediaBrowseSettings() self.addFileToPlaylist(fileName) self.updatingPlaylist = False @@ -1529,8 +1391,6 @@ class MainWindow(QtGui.QMainWindow): def __init__(self): super(MainWindow, self).__init__() - FileSwitchManager = self.FileSwitchManager() - FileSwitchManager.setWindow(self) self.newWatchlist = [] self.publicServerList = [] self.lastCheckedForUpdates = None