Completed "backend" for controlled rooms

This commit is contained in:
Uriziel 2014-10-11 22:06:54 +02:00
parent ec74daf963
commit 51e2e42293
3 changed files with 67 additions and 15 deletions

View File

@ -225,7 +225,7 @@ class SyncplayClient(object):
def _changePlayerStateAccordingToGlobalState(self, position, paused, doSeek, setBy): def _changePlayerStateAccordingToGlobalState(self, position, paused, doSeek, setBy):
madeChangeOnPlayer = False madeChangeOnPlayer = False
pauseChanged = paused != self.getGlobalPaused() pauseChanged = paused != self.getGlobalPaused() or paused != self.getPlayerPaused()
diff = self.getPlayerPosition() - position diff = self.getPlayerPosition() - position
if self._lastGlobalUpdate is None: if self._lastGlobalUpdate is None:
madeChangeOnPlayer = self._initPlayerState(position, paused) madeChangeOnPlayer = self._initPlayerState(position, paused)

View File

@ -386,7 +386,7 @@ class SyncServerProtocol(JSONCommandProtocol):
"position": position if position else 0, "position": position if position else 0,
"paused": paused, "paused": paused,
"doSeek": doSeek, "doSeek": doSeek,
"setBy": setBy.getName() "setBy": setBy.getName() if setBy else None
} }
ping = { ping = {
"latencyCalculation": self._pingService.newTimestamp(), "latencyCalculation": self._pingService.newTimestamp(),

View File

@ -13,10 +13,6 @@ import os
from string import Template from string import Template
import argparse import argparse
# TODO: Check if room should have status of "Controlled room"
# TODO: Make only controllers able to control a room
# TODO: Send list of controllers
# TODO: Broadcast information about controller auth
class SyncFactory(Factory): class SyncFactory(Factory):
def __init__(self, password='', motdFilePath=None, isolateRooms=False): def __init__(self, password='', motdFilePath=None, isolateRooms=False):
print getMessage("welcome-server-notification").format(syncplay.version) print getMessage("welcome-server-notification").format(syncplay.version)
@ -73,6 +69,9 @@ class SyncFactory(Factory):
self.sendJoinMessage(watcher) self.sendJoinMessage(watcher)
else: else:
self.sendRoomSwitchMessage(watcher) self.sendRoomSwitchMessage(watcher)
if RoomPasswordProvider.isControlledRoom(roomName):
for controller in watcher.getRoom().getControllers():
watcher.sendControlledRoomAuthStatus(True, controller)
def sendRoomSwitchMessage(self, watcher): def sendRoomSwitchMessage(self, watcher):
l = lambda w: w.sendSetting(watcher.getName(), watcher.getRoom(), None, None) l = lambda w: w.sendSetting(watcher.getName(), watcher.getRoom(), None, None)
@ -97,11 +96,14 @@ class SyncFactory(Factory):
def forcePositionUpdate(self, watcher, doSeek): def forcePositionUpdate(self, watcher, doSeek):
room = watcher.getRoom() room = watcher.getRoom()
paused, position = room.isPaused(), watcher.getPosition() if room.canControl(watcher):
setBy = watcher paused, position = room.isPaused(), watcher.getPosition()
room.setPosition(watcher.getPosition(), setBy) setBy = watcher
l = lambda w: w.sendState(position, paused, doSeek, setBy, True) l = lambda w: w.sendState(position, paused, doSeek, setBy, True)
self._roomManager.broadcastRoom(watcher, l) room.setPosition(watcher.getPosition(), setBy)
self._roomManager.broadcastRoom(watcher, l)
else:
watcher.sendState(room.getPosition(), room.isPaused(), doSeek, room.getSetBy(), True)
def getAllWatchersForUser(self, forUser): def getAllWatchersForUser(self, forUser):
return self._roomManager.getAllWatchersForUser(forUser) return self._roomManager.getAllWatchersForUser(forUser)
@ -110,6 +112,8 @@ class SyncFactory(Factory):
room = watcher.getRoom() room = watcher.getRoom()
try: try:
success = RoomPasswordProvider.check(room.getName(), password, self._salt) success = RoomPasswordProvider.check(room.getName(), password, self._salt)
if success:
watcher.getRoom().addController(watcher)
self._roomManager.broadcastRoom(watcher, lambda w: w.sendControlledRoomAuthStatus(success, watcher.getName())) self._roomManager.broadcastRoom(watcher, lambda w: w.sendControlledRoomAuthStatus(success, watcher.getName()))
except NotControlledRoom: except NotControlledRoom:
newName = RoomPasswordProvider.getControlledRoomName(room.getName(), password, self._salt) newName = RoomPasswordProvider.getControlledRoomName(room.getName(), password, self._salt)
@ -155,7 +159,10 @@ class RoomManager(object):
if roomName in self._rooms: if roomName in self._rooms:
return self._rooms[roomName] return self._rooms[roomName]
else: else:
room = Room(roomName) if RoomPasswordProvider.isControlledRoom(roomName):
room = ControlledRoom(roomName)
else:
room = Room(roomName)
self._rooms[roomName] = room self._rooms[roomName] = room
return room return room
@ -248,6 +255,44 @@ class Room(object):
def getSetBy(self): def getSetBy(self):
return self._setBy return self._setBy
def canControl(self, watcher):
return True
class ControlledRoom(Room):
def __init__(self, name):
Room.__init__(self, name)
self._controllers = {}
def getPosition(self):
if self._controllers:
watcher = min(self._controllers.values())
self._setBy = watcher
return watcher.getPosition()
else:
return 0
def addController(self, watcher):
self._controllers[watcher.getName()] = watcher
def removeWatcher(self, watcher):
Room.removeWatcher(self, watcher)
if watcher.getName() in self._controllers:
del self._controllers[watcher.getName()]
def setPaused(self, paused=Room.STATE_PAUSED, setBy=None):
if self.canControl(setBy):
Room.setPaused(self, paused, setBy)
def setPosition(self, position, setBy=None):
if self.canControl(setBy):
Room.setPosition(self, position, setBy)
def canControl(self, watcher):
return watcher.getName() in self._controllers
def getControllers(self):
return self._controllers
class Watcher(object): class Watcher(object):
def __init__(self, server, connector, name): def __init__(self, server, connector, name):
self._server = server self._server = server
@ -339,14 +384,18 @@ class Watcher(object):
return False return False
return self._room.isPaused() and not paused or not self._room.isPaused() and paused return self._room.isPaused() and not paused or not self._room.isPaused() and paused
def _updatePositionByAge(self, messageAge, paused, position):
if not paused:
position += messageAge
return position
def updateState(self, position, paused, doSeek, messageAge): def updateState(self, position, paused, doSeek, messageAge):
pauseChanged = self.__hasPauseChanged(paused) pauseChanged = self.__hasPauseChanged(paused)
self._lastUpdatedOn = time.time() self._lastUpdatedOn = time.time()
if pauseChanged: if pauseChanged:
self.getRoom().setPaused(Room.STATE_PAUSED if paused else Room.STATE_PLAYING, self) self.getRoom().setPaused(Room.STATE_PAUSED if paused else Room.STATE_PLAYING, self)
if position is not None: if position is not None:
if not paused: position = self._updatePositionByAge(messageAge, paused, position)
position += messageAge
self.setPosition(position) self.setPosition(position)
if doSeek or pauseChanged: if doSeek or pauseChanged:
self._server.forcePositionUpdate(self, doSeek) self._server.forcePositionUpdate(self, doSeek)
@ -368,11 +417,14 @@ class ConfigurationGetter(object):
self._argparser.add_argument('--isolate-rooms', action='store_true', help=getMessage("server-isolate-room-argument")) self._argparser.add_argument('--isolate-rooms', action='store_true', help=getMessage("server-isolate-room-argument"))
self._argparser.add_argument('--motd-file', metavar='file', type=str, nargs='?', help=getMessage("server-motd-argument")) self._argparser.add_argument('--motd-file', metavar='file', type=str, nargs='?', help=getMessage("server-motd-argument"))
class RoomPasswordProvider(object): class RoomPasswordProvider(object):
CONTROLLED_ROOM_REGEX = re.compile("^\+(.*):(\w{12})$") CONTROLLED_ROOM_REGEX = re.compile("^\+(.*):(\w{12})$")
PASSWORD_REGEX = re.compile("[A-Z]{2}-\d{3}-\d{3}") PASSWORD_REGEX = re.compile("[A-Z]{2}-\d{3}-\d{3}")
@staticmethod
def isControlledRoom(roomName):
return bool(re.match(RoomPasswordProvider.CONTROLLED_ROOM_REGEX, roomName))
@staticmethod @staticmethod
def check(roomName, password, salt): def check(roomName, password, salt):
if not re.match(RoomPasswordProvider.PASSWORD_REGEX, password): if not re.match(RoomPasswordProvider.PASSWORD_REGEX, password):