Refactor: Move playlist into its own class
This commit is contained in:
parent
a77d3146de
commit
5ce752cbef
@ -114,12 +114,10 @@ class SyncplayClient(object):
|
||||
self.autoplayTimer = task.LoopingCall(self.autoplayCountdown)
|
||||
self.autoplayTimeLeft = constants.AUTOPLAY_DELAY
|
||||
|
||||
self._playlist = []
|
||||
self._playlistIndex = None
|
||||
self.__playerReady = defer.Deferred()
|
||||
|
||||
self._warnings = self._WarningManager(self._player, self.userlist, self.ui, self)
|
||||
self._undoPlaylist = self._UndoPlaylistManager()
|
||||
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)
|
||||
@ -129,15 +127,6 @@ class SyncplayClient(object):
|
||||
if missingStrings is not None and missingStrings is not "":
|
||||
self.ui.showDebugMessage("MISSING/UNUSED STRINGS DETECTED:\n{}".format(missingStrings))
|
||||
|
||||
def needsSharedPlaylistsEnabled(f): # @NoSelf
|
||||
@wraps(f)
|
||||
def wrapper(self, *args, **kwds):
|
||||
if not self._config['sharedPlaylistEnabled']:
|
||||
self.ui.showDebugMessage("Tried to use shared playlists when it was disabled!")
|
||||
return
|
||||
return f(self, *args, **kwds)
|
||||
return wrapper
|
||||
|
||||
def initProtocol(self, protocol):
|
||||
self._protocol = protocol
|
||||
|
||||
@ -153,6 +142,12 @@ class SyncplayClient(object):
|
||||
self.scheduleAskPlayer()
|
||||
self.__playerReady.callback(player)
|
||||
|
||||
def addPlayerReadyCallback(self, lambdaToCall):
|
||||
self.__playerReady.addCallback(lambdaToCall)
|
||||
|
||||
def playerIsNotReady(self):
|
||||
return self._player is None
|
||||
|
||||
def scheduleAskPlayer(self, when=constants.PLAYER_ASK_DELAY):
|
||||
self._askPlayerTimer = task.LoopingCall(self.askPlayer)
|
||||
self._askPlayerTimer.start(when)
|
||||
@ -179,43 +174,6 @@ class SyncplayClient(object):
|
||||
seeked = _playerDiff > constants.SEEK_THRESHOLD and _globalDiff > constants.SEEK_THRESHOLD
|
||||
return pauseChange, seeked
|
||||
|
||||
@needsSharedPlaylistsEnabled
|
||||
def loadNextFileInPlaylist(self):
|
||||
if self._notPlayingCurrentIndex():
|
||||
return
|
||||
if self._thereIsNextPlaylistIndex():
|
||||
self.switchToNewPlaylistIndex(self._nextPlaylistIndex(), resetPosition=True)
|
||||
else:
|
||||
self.rewindFile()
|
||||
|
||||
def _notPlayingCurrentIndex(self):
|
||||
if self._playlistIndex is None or self._playlist is None or len(self._playlist) <= self._playlistIndex:
|
||||
self.ui.showDebugMessage(u"Not playing current index - Index none or length issue")
|
||||
return True
|
||||
currentPlaylistFilename = self._playlist[self._playlistIndex]
|
||||
if self.userlist.currentUser.file and currentPlaylistFilename == self.userlist.currentUser.file['name']:
|
||||
return False
|
||||
else:
|
||||
self.ui.showDebugMessage(u"Not playing current index - Filename mismatch or no file")
|
||||
return True
|
||||
|
||||
def _thereIsNextPlaylistIndex(self):
|
||||
if self._playlistIndex is None:
|
||||
return False
|
||||
elif len(self._playlist) == 1:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def _nextPlaylistIndex(self):
|
||||
if self.playlistIsAtEnd():
|
||||
return 0
|
||||
else:
|
||||
return self._playlistIndex+1
|
||||
|
||||
def playlistIsAtEnd(self):
|
||||
return len(self._playlist) <= self._playlistIndex+1
|
||||
|
||||
def rewindFile(self):
|
||||
self.setPosition(0)
|
||||
|
||||
@ -227,7 +185,7 @@ class SyncplayClient(object):
|
||||
currentLength = self.userlist.currentUser.file["duration"] if self.userlist.currentUser.file else 0
|
||||
if pauseChange and paused and currentLength > constants.PLAYLIST_LOAD_NEXT_FILE_MINIMUM_LENGTH\
|
||||
and abs(position - currentLength ) < constants.PLAYLIST_LOAD_NEXT_FILE_TIME_FROM_END_THRESHOLD:
|
||||
self.loadNextFileInPlaylist()
|
||||
self.playlist.loadNextFileInPlaylist()
|
||||
elif pauseChange and utils.meetsMinVersion(self.serverVersion, constants.USER_READY_MIN_VERSION):
|
||||
pauseChange = self._toggleReady(pauseChange, paused)
|
||||
|
||||
@ -472,13 +430,7 @@ class SyncplayClient(object):
|
||||
filename, size = self.__executePrivacySettings(filename, size)
|
||||
self.userlist.currentUser.setFile(filename, duration, size, path)
|
||||
self.sendFile()
|
||||
|
||||
try:
|
||||
index = self._playlist.index(filename)
|
||||
self.changeToPlaylistIndex(index)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
self.playlist.changeToPlaylistIndexFromFilename(filename)
|
||||
|
||||
def findFilenameInDirectories(self, filename):
|
||||
# TODO: Replace this with the code in gui.py
|
||||
@ -490,117 +442,14 @@ class SyncplayClient(object):
|
||||
return os.path.join(root,filename)
|
||||
return None
|
||||
|
||||
def changeToPlaylistIndex(self, index, username = None):
|
||||
if not self._playlist or len(self._playlist) == 0:
|
||||
return
|
||||
path = None
|
||||
if index is None:
|
||||
return
|
||||
if username is None and not self._config['sharedPlaylistEnabled']:
|
||||
return
|
||||
try:
|
||||
filename = self._playlist[index]
|
||||
self.ui.setPlaylistIndexFilename(filename)
|
||||
if not self._config['sharedPlaylistEnabled']:
|
||||
self._playlistIndex = index
|
||||
if username is not None and self.userlist.currentUser.file and filename == self.userlist.currentUser.file['name']:
|
||||
return
|
||||
except IndexError:
|
||||
pass
|
||||
def openFile(self, filePath, resetPosition=False):
|
||||
self._player.openFile(filePath, resetPosition)
|
||||
|
||||
if self._player is None:
|
||||
self.__playerReady.addCallback(lambda x: self.changeToPlaylistIndex(index, username))
|
||||
return
|
||||
self._playlistIndex = index
|
||||
if username is None and self._protocol and self._protocol.logged and self._config["sharedPlaylistEnabled"]:
|
||||
self._protocol.setPlaylistIndex(index)
|
||||
else:
|
||||
self.ui.showMessage(getMessage("playlist-selection-changed-notification").format(username))
|
||||
self.switchToNewPlaylistIndex(index)
|
||||
def setPlaylistIndex(self, index):
|
||||
self._protocol.setPlaylistIndex(index)
|
||||
|
||||
|
||||
@needsSharedPlaylistsEnabled
|
||||
def switchToNewPlaylistIndex(self, index, resetPosition=False):
|
||||
try:
|
||||
filename = self._playlist[index]
|
||||
if utils.isURL(filename):
|
||||
for URI in constants.SAFE_URIS:
|
||||
if filename.startswith(URI):
|
||||
self._player.openFile(filename, resetPosition=resetPosition)
|
||||
return
|
||||
self.ui.showErrorMessage(getMessage("cannot-add-unsafe-path-error").format(filename))
|
||||
return
|
||||
else:
|
||||
path = self.findFilenameInDirectories(filename)
|
||||
# TODO: Find Path properly
|
||||
if path:
|
||||
self._player.openFile(path, resetPosition)
|
||||
else:
|
||||
self.ui.showErrorMessage(getMessage("cannot-find-file-for-playlist-switch-error").format(filename))
|
||||
return
|
||||
except IndexError:
|
||||
self.ui.showDebugMessage("Could not change playlist index due to IndexError")
|
||||
|
||||
def changePlaylist(self, files, username = None):
|
||||
try:
|
||||
filename = self._playlist[self._playlistIndex]
|
||||
newIndex = files.index(filename)
|
||||
except:
|
||||
newIndex = 0
|
||||
|
||||
self._undoPlaylist.updateUndoPlaylistBuffer(currentPlaylist=self._playlist, newPlaylist=files, newRoom=self.userlist.currentUser.room)
|
||||
self._playlist = files
|
||||
|
||||
if username is None and self._protocol and self._protocol.logged:
|
||||
if self._config['sharedPlaylistEnabled']:
|
||||
self._protocol.setPlaylist(files)
|
||||
self.changeToPlaylistIndex(newIndex)
|
||||
else:
|
||||
self.ui.setPlaylist(self._playlist)
|
||||
self.changeToPlaylistIndex(newIndex, username)
|
||||
self.ui.showMessage(getMessage("playlist-contents-changed-notification").format(username))
|
||||
|
||||
@needsSharedPlaylistsEnabled
|
||||
def undoPlaylistChange(self):
|
||||
if self._undoPlaylist.canUndoPlaylist(self._playlist):
|
||||
newPlaylist = self._undoPlaylist.getPreviousPlaylist()
|
||||
self.ui.setPlaylist(newPlaylist)
|
||||
self.changePlaylist(newPlaylist)
|
||||
|
||||
@needsSharedPlaylistsEnabled
|
||||
def shufflePlaylist(self):
|
||||
if self._playlist and len(self._playlist) > 0:
|
||||
shuffledPlaylist = deepcopy(self._playlist)
|
||||
random.shuffle(shuffledPlaylist)
|
||||
self.ui.setPlaylist(shuffledPlaylist)
|
||||
self.changePlaylist(shuffledPlaylist)
|
||||
|
||||
class _UndoPlaylistManager():
|
||||
def __init__(self):
|
||||
self._previousPlaylist = None
|
||||
self._previousPlaylistRoom = None
|
||||
|
||||
def updateUndoPlaylistBuffer(self, currentPlaylist, newPlaylist, newRoom):
|
||||
if self._playlistBufferIsFromOldRoom(newRoom):
|
||||
self._movePlaylistBufferToNewRoom(newRoom)
|
||||
elif self._playlistBufferNeedsUpdating(currentPlaylist, newPlaylist):
|
||||
self._previousPlaylist = currentPlaylist
|
||||
|
||||
def canUndoPlaylist(self, currentPlaylist):
|
||||
return self._previousPlaylist is not None and currentPlaylist <> self._previousPlaylist
|
||||
|
||||
def getPreviousPlaylist(self):
|
||||
return self._previousPlaylist
|
||||
|
||||
def _playlistBufferIsFromOldRoom(self, newRoom):
|
||||
return self._previousPlaylistRoom <> newRoom
|
||||
|
||||
def _movePlaylistBufferToNewRoom(self, currentRoom):
|
||||
self._previousPlaylist = None
|
||||
self._previousPlaylistRoom = currentRoom
|
||||
|
||||
def _playlistBufferNeedsUpdating(self, currentPlaylist, newPlaylist):
|
||||
return self._previousPlaylist <> currentPlaylist and currentPlaylist <> newPlaylist
|
||||
def changeToPlaylistIndex(self, *args, **kwargs):
|
||||
self.playlist.changeToPlaylistIndex(*args, **kwargs)
|
||||
|
||||
def __executePrivacySettings(self, filename, size):
|
||||
if self._config['filenamePrivacyMode'] == PRIVACY_SENDHASHED_MODE:
|
||||
@ -662,6 +511,12 @@ class SyncplayClient(object):
|
||||
if storedRoomPassword:
|
||||
self.identifyAsController(storedRoomPassword)
|
||||
|
||||
def isConnectedAndInARoom(self):
|
||||
return self._protocol and self._protocol.logged and self.userlist.currentUser.room
|
||||
|
||||
def sharedPlaylistIsEnabled(self):
|
||||
return self._config['sharedPlaylistEnabled']
|
||||
|
||||
def connected(self):
|
||||
readyState = self._config['readyAtStart'] if self.userlist.currentUser.isReady() is None else self.userlist.currentUser.isReady()
|
||||
self._protocol.setReady(readyState, manuallyInitiated=False)
|
||||
@ -744,12 +599,12 @@ class SyncplayClient(object):
|
||||
return requireMinVersionDecorator
|
||||
|
||||
def changePlaylistEnabledState(self, newState):
|
||||
oldState = self._config["sharedPlaylistEnabled"]
|
||||
oldState = self.sharedPlaylistIsEnabled()
|
||||
from syncplay.ui.ConfigurationGetter import ConfigurationGetter
|
||||
ConfigurationGetter().setConfigOption("sharedPlaylistEnabled", newState)
|
||||
self._config["sharedPlaylistEnabled"] = newState
|
||||
if oldState == False and newState == True:
|
||||
self.changeToPlaylistIndex(self._playlistIndex)
|
||||
self.playlist.loadCurrentPlaylistIndex()
|
||||
|
||||
def changeAutoplayState(self, newState):
|
||||
self.autoPlay = newState
|
||||
@ -1437,4 +1292,179 @@ class UiManager(object):
|
||||
def drop(self):
|
||||
self.__ui.drop()
|
||||
|
||||
class SyncplayPlaylist():
|
||||
def __init__(self, client):
|
||||
self._client = client
|
||||
self._ui = self._client.ui
|
||||
self._previousPlaylist = None
|
||||
self._previousPlaylistRoom = None
|
||||
self._playlist = []
|
||||
self._playlistIndex = None
|
||||
|
||||
def needsSharedPlaylistsEnabled(f): # @NoSelf
|
||||
@wraps(f)
|
||||
def wrapper(self, *args, **kwds):
|
||||
if not self._client.sharedPlaylistIsEnabled():
|
||||
self._ui.showDebugMessage("Tried to use shared playlists when it was disabled!")
|
||||
return
|
||||
return f(self, *args, **kwds)
|
||||
return wrapper
|
||||
|
||||
def changeToPlaylistIndexFromFilename(self, filename):
|
||||
try:
|
||||
index = self._playlist.index(filename)
|
||||
self.changeToPlaylistIndex(index)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def changeToPlaylistIndex(self, index, username = None):
|
||||
if not self._playlist or len(self._playlist) == 0:
|
||||
return
|
||||
path = None
|
||||
if index is None:
|
||||
return
|
||||
if username is None and not self._client.sharedPlaylistIsEnabled():
|
||||
return
|
||||
try:
|
||||
filename = self._playlist[index]
|
||||
self._ui.setPlaylistIndexFilename(filename)
|
||||
if not self._client.sharedPlaylistIsEnabled():
|
||||
self._playlistIndex = index
|
||||
if username is not None and self._client.userlist.currentUser.file and filename == self._client.userlist.currentUser.file['name']:
|
||||
return
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
if self._client.playerIsNotReady():
|
||||
self._client.addPlayerReadyCallback(lambda x: self.changeToPlaylistIndex(index, username))
|
||||
return
|
||||
|
||||
self._playlistIndex = index
|
||||
if username is None and self._client.isConnectedAndInARoom() and self._client.sharedPlaylistIsEnabled():
|
||||
self._client.setPlaylistIndex(index)
|
||||
else:
|
||||
self._ui.showMessage(getMessage("playlist-selection-changed-notification").format(username))
|
||||
self.switchToNewPlaylistIndex(index)
|
||||
|
||||
@needsSharedPlaylistsEnabled
|
||||
def switchToNewPlaylistIndex(self, index, resetPosition=False):
|
||||
if self._client.playerIsNotReady():
|
||||
self._client.addPlayerReadyCallback(lambda x: self.switchToNewPlaylistIndex(index, resetPosition))
|
||||
return
|
||||
|
||||
try:
|
||||
filename = self._playlist[index]
|
||||
if utils.isURL(filename):
|
||||
for URI in constants.SAFE_URIS:
|
||||
if filename.startswith(URI):
|
||||
self._client.openFile(filename, resetPosition=resetPosition)
|
||||
return
|
||||
self._ui.showErrorMessage(getMessage("cannot-add-unsafe-path-error").format(filename))
|
||||
return
|
||||
else:
|
||||
path = self._client.findFilenameInDirectories(filename)
|
||||
# TODO: Find Path properly
|
||||
if path:
|
||||
self._client.openFile(path, resetPosition)
|
||||
else:
|
||||
self._ui.showErrorMessage(getMessage("cannot-find-file-for-playlist-switch-error").format(filename))
|
||||
return
|
||||
except IndexError:
|
||||
self._ui.showDebugMessage("Could not change playlist index due to IndexError")
|
||||
|
||||
def changePlaylist(self, files, username = None):
|
||||
try:
|
||||
filename = self._playlist[self._playlistIndex]
|
||||
newIndex = files.index(filename)
|
||||
except:
|
||||
newIndex = 0
|
||||
|
||||
self._updateUndoPlaylistBuffer(newPlaylist=files, newRoom=self._client.userlist.currentUser.room)
|
||||
self._playlist = files
|
||||
|
||||
if username is None and self._client.isConnectedAndInARoom():
|
||||
if self._client.sharedPlaylistIsEnabled():
|
||||
self._client._protocol.setPlaylist(files)
|
||||
self.changeToPlaylistIndex(newIndex)
|
||||
else:
|
||||
self._ui.setPlaylist(self._playlist)
|
||||
self.changeToPlaylistIndex(newIndex, username)
|
||||
self._ui.showMessage(getMessage("playlist-contents-changed-notification").format(username))
|
||||
|
||||
@needsSharedPlaylistsEnabled
|
||||
def undoPlaylistChange(self):
|
||||
if self.canUndoPlaylist(self._playlist):
|
||||
newPlaylist = self._getPreviousPlaylist()
|
||||
self._ui.setPlaylist(newPlaylist)
|
||||
self.changePlaylist(newPlaylist)
|
||||
|
||||
@needsSharedPlaylistsEnabled
|
||||
def shufflePlaylist(self):
|
||||
if self._playlist and len(self._playlist) > 0:
|
||||
shuffledPlaylist = deepcopy(self._playlist)
|
||||
random.shuffle(shuffledPlaylist)
|
||||
self._ui.setPlaylist(shuffledPlaylist)
|
||||
self.changePlaylist(shuffledPlaylist)
|
||||
|
||||
def canUndoPlaylist(self, currentPlaylist):
|
||||
return self._previousPlaylist is not None and currentPlaylist <> self._previousPlaylist
|
||||
|
||||
def loadCurrentPlaylistIndex(self):
|
||||
if self._notPlayingCurrentIndex():
|
||||
self.switchToNewPlaylistIndex(self._playlistIndex)
|
||||
|
||||
@needsSharedPlaylistsEnabled
|
||||
def loadNextFileInPlaylist(self):
|
||||
if self._notPlayingCurrentIndex():
|
||||
return
|
||||
if self._thereIsNextPlaylistIndex():
|
||||
self.switchToNewPlaylistIndex(self._nextPlaylistIndex(), resetPosition=True)
|
||||
else:
|
||||
self._client.rewindFile()
|
||||
|
||||
def _updateUndoPlaylistBuffer(self, newPlaylist, newRoom):
|
||||
if self._playlistBufferIsFromOldRoom(newRoom):
|
||||
self._movePlaylistBufferToNewRoom(newRoom)
|
||||
elif self._playlistBufferNeedsUpdating(newPlaylist):
|
||||
self._previousPlaylist = self._playlist
|
||||
|
||||
def _getPreviousPlaylist(self):
|
||||
return self._previousPlaylist
|
||||
|
||||
def _notPlayingCurrentIndex(self):
|
||||
if self._playlistIndex is None or self._playlist is None or len(self._playlist) <= self._playlistIndex:
|
||||
self._ui.showDebugMessage(u"Not playing current index - Index none or length issue")
|
||||
return True
|
||||
currentPlaylistFilename = self._playlist[self._playlistIndex]
|
||||
if self._client.userlist.currentUser.file and currentPlaylistFilename == self._client.userlist.currentUser.file['name']:
|
||||
return False
|
||||
else:
|
||||
self._ui.showDebugMessage(u"Not playing current index - Filename mismatch or no file")
|
||||
return True
|
||||
|
||||
def _thereIsNextPlaylistIndex(self):
|
||||
if self._playlistIndex is None:
|
||||
return False
|
||||
elif len(self._playlist) == 1:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def _nextPlaylistIndex(self):
|
||||
if self._playlistIsAtEnd():
|
||||
return 0
|
||||
else:
|
||||
return self._playlistIndex+1
|
||||
|
||||
def _playlistIsAtEnd(self):
|
||||
return len(self._playlist) <= self._playlistIndex+1
|
||||
|
||||
def _playlistBufferIsFromOldRoom(self, newRoom):
|
||||
return self._previousPlaylistRoom <> newRoom
|
||||
|
||||
def _movePlaylistBufferToNewRoom(self, currentRoom):
|
||||
self._previousPlaylist = None
|
||||
self._previousPlaylistRoom = currentRoom
|
||||
|
||||
def _playlistBufferNeedsUpdating(self, newPlaylist):
|
||||
return self._previousPlaylist <> self._playlist and self._playlist <> newPlaylist
|
||||
|
||||
@ -141,9 +141,9 @@ class SyncClientProtocol(JSONCommandProtocol):
|
||||
manuallyInitiated = values["manuallyInitiated"] if values.has_key("manuallyInitiated") else True
|
||||
self._client.setReady(user, isReady, manuallyInitiated)
|
||||
elif command == "playlistIndex":
|
||||
self._client.changeToPlaylistIndex(values['index'], values['user'])
|
||||
self._client.playlist.changeToPlaylistIndex(values['index'], values['user'])
|
||||
elif command == "playlistChange":
|
||||
self._client.changePlaylist(values['files'], values['user'])
|
||||
self._client.playlist.changePlaylist(values['files'], values['user'])
|
||||
|
||||
def sendSet(self, setting):
|
||||
self.sendMessage({"Set": setting})
|
||||
|
||||
@ -582,11 +582,11 @@ class MainWindow(QtGui.QMainWindow):
|
||||
|
||||
@needsClient
|
||||
def undoPlaylistChange(self):
|
||||
self._syncplayClient.undoPlaylistChange()
|
||||
self._syncplayClient.playlist.undoPlaylistChange()
|
||||
|
||||
@needsClient
|
||||
def shufflePlaylist(self):
|
||||
self._syncplayClient.shufflePlaylist()
|
||||
self._syncplayClient.playlist.shufflePlaylist()
|
||||
|
||||
def openPlaylistMenu(self, position):
|
||||
indexes = self.playlist.selectedIndexes()
|
||||
@ -996,7 +996,7 @@ class MainWindow(QtGui.QMainWindow):
|
||||
newPlaylist = self.getPlaylistState()
|
||||
if newPlaylist <> self.playlistState and self._syncplayClient and not self.updatingPlaylist:
|
||||
self.playlistState = newPlaylist
|
||||
self._syncplayClient.changePlaylist(newPlaylist)
|
||||
self._syncplayClient.playlist.changePlaylist(newPlaylist)
|
||||
|
||||
def addTopLayout(self, window):
|
||||
window.topSplit = self.topSplitter(Qt.Horizontal, self)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user