Initial Client Features support

This commit is contained in:
Etoh 2017-04-18 10:37:32 +01:00
parent 06f6eb183b
commit 7307fb4eb5
3 changed files with 74 additions and 9 deletions

View File

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

View File

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

View File

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