Initial Client Features support
This commit is contained in:
parent
06f6eb183b
commit
7307fb4eb5
@ -552,6 +552,7 @@ class SyncplayClient(object):
|
||||
self.ui.showErrorMessage(getMessage("shared-playlists-not-supported-by-server-error").format(constants.SHARED_PLAYLIST_MIN_VERSION, self.serverVersion))
|
||||
elif not self.serverFeatures["sharedPlaylists"]:
|
||||
self.ui.showErrorMessage(getMessage("shared-playlists-disabled-by-server-error"))
|
||||
# TODO: Have messages for all unsupported & disabled features
|
||||
self.ui.setFeatures(self.serverFeatures)
|
||||
|
||||
def getSanitizedCurrentUserFile(self):
|
||||
@ -581,6 +582,24 @@ class SyncplayClient(object):
|
||||
def getUsername(self):
|
||||
return self.userlist.currentUser.username
|
||||
|
||||
def chatIsEnabled(self):
|
||||
return True
|
||||
# TODO: Allow chat to be disabled
|
||||
|
||||
def getFeatures(self):
|
||||
features = dict()
|
||||
|
||||
# Can change during runtime:
|
||||
features["sharedPlaylists"] = self.sharedPlaylistIsEnabled() # Can change during runtime
|
||||
features["chat"] = self.chatIsEnabled() # Can change during runtime
|
||||
|
||||
# Static for this version/release of Syncplay:
|
||||
features["featureList"] = True
|
||||
features["readiness"] = True
|
||||
features["managedRooms"] = True
|
||||
|
||||
return features
|
||||
|
||||
def setRoom(self, roomName, resetAutoplay=False):
|
||||
self.userlist.currentUser.room = roomName
|
||||
if resetAutoplay:
|
||||
@ -702,6 +721,9 @@ class SyncplayClient(object):
|
||||
message = utils.truncateText(message,constants.MAX_CHAT_MESSAGE_LENGTH)
|
||||
self._protocol.sendChatMessage(message)
|
||||
|
||||
def sendFeaturesUpdate(self, features):
|
||||
self._protocol.sendFeaturesUpdate(features)
|
||||
|
||||
def changePlaylistEnabledState(self, newState):
|
||||
oldState = self.sharedPlaylistIsEnabled()
|
||||
from syncplay.ui.ConfigurationGetter import ConfigurationGetter
|
||||
@ -799,6 +821,11 @@ class SyncplayClient(object):
|
||||
if oldReadyState != isReady:
|
||||
self._warnings.checkReadyStates()
|
||||
|
||||
@requireServerFeature("managedRooms")
|
||||
def setUserFeatures(self, username, features):
|
||||
self.userlist.setFeatures(username, features)
|
||||
self.ui.userListChange()
|
||||
|
||||
@requireServerFeature("managedRooms")
|
||||
def createControlledRoom(self, roomName):
|
||||
controlPassword = utils.RandomStringGenerator.generate_room_password()
|
||||
@ -989,6 +1016,7 @@ class SyncplayUser(object):
|
||||
self.room = room
|
||||
self.file = file_
|
||||
self._controller = False
|
||||
self._features = {}
|
||||
|
||||
def setFile(self, filename, duration, size, path=None):
|
||||
file_ = {
|
||||
@ -1042,6 +1070,9 @@ class SyncplayUser(object):
|
||||
def setReady(self, ready):
|
||||
self.ready = ready
|
||||
|
||||
def setFeatures(self, features):
|
||||
self._features = features
|
||||
|
||||
class SyncplayUserlist(object):
|
||||
def __init__(self, ui, client):
|
||||
self.currentUser = SyncplayUser()
|
||||
@ -1120,7 +1151,7 @@ class SyncplayUserlist(object):
|
||||
if differentDuration: differences.append(getMessage("file-difference-duration"))
|
||||
return ", ".join(differences)
|
||||
|
||||
def addUser(self, username, room, file_, noMessage=False, isController=None, isReady=None):
|
||||
def addUser(self, username, room, file_, noMessage=False, isController=None, isReady=None, features={}):
|
||||
if username == self.currentUser.username:
|
||||
if isController is not None:
|
||||
self.currentUser.setControllerStatus(isController)
|
||||
@ -1131,7 +1162,7 @@ class SyncplayUserlist(object):
|
||||
user.setControllerStatus(isController)
|
||||
self._users[username] = user
|
||||
user.setReady(isReady)
|
||||
|
||||
user.setFeatures(features)
|
||||
if not noMessage:
|
||||
self.__showUserChangeMessage(username, room, file_)
|
||||
self.userListChange(room)
|
||||
|
||||
@ -5,8 +5,7 @@ import syncplay
|
||||
from functools import wraps
|
||||
import time
|
||||
from syncplay.messages import getMessage
|
||||
from syncplay.constants import PING_MOVING_AVERAGE_WEIGHT
|
||||
|
||||
from syncplay.constants import PING_MOVING_AVERAGE_WEIGHT, CONTROLLED_ROOMS_MIN_VERSION, USER_READY_MIN_VERSION, SHARED_PLAYLIST_MIN_VERSION, CHAT_MIN_VERSION
|
||||
|
||||
class JSONCommandProtocol(LineReceiver):
|
||||
def handleMessages(self, messages):
|
||||
@ -107,6 +106,7 @@ class SyncClientProtocol(JSONCommandProtocol):
|
||||
if room: hello["room"] = {"name" :room}
|
||||
hello["version"] = "1.2.255" # Used so newer clients work on 1.2.X server
|
||||
hello["realversion"] = syncplay.version
|
||||
hello["features"] = self._client.getFeatures()
|
||||
self.sendMessage({"Hello": hello})
|
||||
|
||||
def _SetUser(self, users):
|
||||
@ -147,6 +147,11 @@ class SyncClientProtocol(JSONCommandProtocol):
|
||||
self._client.playlist.changeToPlaylistIndex(values['index'], values['user'])
|
||||
elif command == "playlistChange":
|
||||
self._client.playlist.changePlaylist(values['files'], values['user'])
|
||||
elif command == "features":
|
||||
self._client.setUserFeatures(values["username"],values['features'])
|
||||
|
||||
def sendFeaturesUpdate(self, features):
|
||||
self.sendSet({"features": features})
|
||||
|
||||
def sendSet(self, setting):
|
||||
self.sendMessage({"Set": setting})
|
||||
@ -173,7 +178,8 @@ class SyncClientProtocol(JSONCommandProtocol):
|
||||
file_ = user[1]['file'] if user[1]['file'] <> {} else None
|
||||
isController = user[1]['controller'] if 'controller' in user[1] else False
|
||||
isReady = user[1]['isReady'] if 'isReady' in user[1] else None
|
||||
self._client.userlist.addUser(userName, roomName, file_, noMessage=True, isController=isController, isReady=isReady)
|
||||
features = user[1]['features'] if 'features' in user[1] else None
|
||||
self._client.userlist.addUser(userName, roomName, file_, noMessage=True, isController=isController, isReady=isReady, features=features)
|
||||
self._client.userlist.showUserList()
|
||||
|
||||
def sendList(self):
|
||||
@ -286,6 +292,7 @@ class SyncServerProtocol(JSONCommandProtocol):
|
||||
def __init__(self, factory):
|
||||
self._factory = factory
|
||||
self._version = None
|
||||
self._features = None
|
||||
self._logged = False
|
||||
self.clientIgnoringOnTheFly = 0
|
||||
self.serverIgnoringOnTheFly = 0
|
||||
@ -319,6 +326,16 @@ class SyncServerProtocol(JSONCommandProtocol):
|
||||
def connectionLost(self, reason):
|
||||
self._factory.removeWatcher(self._watcher)
|
||||
|
||||
def getFeatures(self):
|
||||
if not self._features:
|
||||
self._features = {}
|
||||
self._features["sharedPlaylists"] = self._version >= SHARED_PLAYLIST_MIN_VERSION
|
||||
self._features["chat"] = self._version >= CHAT_MIN_VERSION
|
||||
self._features["featureList"] = False
|
||||
self._features["readiness"] = self._version >= USER_READY_MIN_VERSION
|
||||
self._features["managedRooms"] = self._version >= CONTROLLED_ROOMS_MIN_VERSION
|
||||
return self._features
|
||||
|
||||
def isLogged(self):
|
||||
return self._logged
|
||||
|
||||
@ -339,7 +356,8 @@ class SyncServerProtocol(JSONCommandProtocol):
|
||||
roomName = roomName.strip()
|
||||
version = hello["version"] if hello.has_key("version") else None
|
||||
version = hello["realversion"] if hello.has_key("realversion") else version
|
||||
return username, serverPassword, roomName, version
|
||||
features = hello["features"] if hello.has_key("features") else None
|
||||
return username, serverPassword, roomName, version, features
|
||||
|
||||
def _checkPassword(self, serverPassword):
|
||||
if self._factory.password:
|
||||
@ -352,7 +370,7 @@ class SyncServerProtocol(JSONCommandProtocol):
|
||||
return True
|
||||
|
||||
def handleHello(self, hello):
|
||||
username, serverPassword, roomName, version = self._extractHelloArguments(hello)
|
||||
username, serverPassword, roomName, version, features = self._extractHelloArguments(hello)
|
||||
if not username or not roomName or not version:
|
||||
self.dropWithError(getMessage("hello-server-error"))
|
||||
return
|
||||
@ -360,14 +378,22 @@ class SyncServerProtocol(JSONCommandProtocol):
|
||||
if not self._checkPassword(serverPassword):
|
||||
return
|
||||
self._version = version
|
||||
self.setFeatures(features)
|
||||
self._factory.addWatcher(self, username, roomName)
|
||||
self._logged = True
|
||||
self.sendHello(version)
|
||||
|
||||
@requireLogged
|
||||
def handleChat(self,chatMessage):
|
||||
if not self._factory.disableChat:
|
||||
self._factory.sendChat(self._watcher,chatMessage)
|
||||
|
||||
def setFeatures(self, features):
|
||||
self._features = features
|
||||
|
||||
def sendFeaturesUpdate(self):
|
||||
self.sendSet({"features": self.getFeatures()})
|
||||
|
||||
def setWatcher(self, watcher):
|
||||
self._watcher = watcher
|
||||
|
||||
@ -404,6 +430,9 @@ class SyncServerProtocol(JSONCommandProtocol):
|
||||
self._factory.setPlaylist(self._watcher, set_[1]['files'])
|
||||
elif command == "playlistIndex":
|
||||
self._factory.setPlaylistIndex(self._watcher, set_[1]['index'])
|
||||
elif command == "features":
|
||||
#TODO: Check
|
||||
self._watcher.setFeatures(set_[1])
|
||||
|
||||
def sendSet(self, setting):
|
||||
self.sendMessage({"Set": setting})
|
||||
@ -470,7 +499,8 @@ class SyncServerProtocol(JSONCommandProtocol):
|
||||
"position": 0,
|
||||
"file": watcher.getFile() if watcher.getFile() else {},
|
||||
"controller": watcher.isController(),
|
||||
"isReady": watcher.isReady()
|
||||
"isReady": watcher.isReady(),
|
||||
"features": watcher.getFeatures()
|
||||
}
|
||||
userlist[room.getName()][watcher.getName()] = userFile
|
||||
|
||||
|
||||
@ -108,7 +108,7 @@ class SyncFactory(Factory):
|
||||
self._roomManager.broadcast(watcher, l)
|
||||
|
||||
def sendJoinMessage(self, watcher):
|
||||
l = lambda w: w.sendSetting(watcher.getName(), watcher.getRoom(), None, {"joined": True, "version": watcher.getVersion()}) if w != watcher else None
|
||||
l = lambda w: w.sendSetting(watcher.getName(), watcher.getRoom(), None, {"joined": True, "version": watcher.getVersion(), "features": watcher.getFeatures()}) if w != watcher else None
|
||||
self._roomManager.broadcast(watcher, l)
|
||||
self._roomManager.broadcastRoom(watcher, lambda w: w.sendSetReady(watcher.getName(), watcher.isReady(), False))
|
||||
|
||||
@ -414,6 +414,10 @@ class Watcher(object):
|
||||
def setReady(self, ready):
|
||||
self._ready = ready
|
||||
|
||||
def getFeatures(self):
|
||||
features = self._connector.getFeatures()
|
||||
return features
|
||||
|
||||
def isReady(self):
|
||||
if self._server.disableReady:
|
||||
return None
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user