|
@@ -54,7 +54,7 @@ class Chueue:
|
|
self._played_queue = []
|
|
self._played_queue = []
|
|
else:
|
|
else:
|
|
return None
|
|
return None
|
|
-
|
|
|
|
|
|
+
|
|
song_id = self._queue.pop(0)
|
|
song_id = self._queue.pop(0)
|
|
if self._repeat_enabled:
|
|
if self._repeat_enabled:
|
|
code = self._codes[song_id]
|
|
code = self._codes[song_id]
|
|
@@ -137,7 +137,7 @@ class Playback:
|
|
class Room:
|
|
class Room:
|
|
chueue: Chueue
|
|
chueue: Chueue
|
|
channel: Channel
|
|
channel: Channel
|
|
- controller: Optional[Subscriber]
|
|
|
|
|
|
+ _controller: Optional[Subscriber]
|
|
controller_lock: RLock
|
|
controller_lock: RLock
|
|
playback: Playback
|
|
playback: Playback
|
|
|
|
|
|
@@ -146,7 +146,13 @@ class Room:
|
|
self.channel = Channel()
|
|
self.channel = Channel()
|
|
self.controller_lock = RLock()
|
|
self.controller_lock = RLock()
|
|
self.playback = Playback()
|
|
self.playback = Playback()
|
|
- self.controller = None
|
|
|
|
|
|
+ self._controller = None
|
|
|
|
+
|
|
|
|
+ def get_controller(self):
|
|
|
|
+ return self._controller
|
|
|
|
+
|
|
|
|
+ def set_controller(self, controller):
|
|
|
|
+ self._controller = controller
|
|
|
|
|
|
|
|
|
|
rooms: Dict[str, Room] = dict()
|
|
rooms: Dict[str, Room] = dict()
|
|
@@ -249,7 +255,8 @@ async def media_action_processor(ws, data, path):
|
|
if room.chueue.is_repeat_enabled() != enable:
|
|
if room.chueue.is_repeat_enabled() != enable:
|
|
with room.chueue:
|
|
with room.chueue:
|
|
room.chueue.set_repeat_enabled(enable, room.playback.get_song())
|
|
room.chueue.set_repeat_enabled(enable, room.playback.get_song())
|
|
- await room.channel.send(make_message(Message.MEDIA_ACTION, {"action": MediaAction.REPEAT.value, "enable": enable}))
|
|
|
|
|
|
+ await room.channel.send(
|
|
|
|
+ make_message(Message.MEDIA_ACTION, {"action": MediaAction.REPEAT.value, "enable": enable}))
|
|
|
|
|
|
|
|
|
|
async def obtain_control_processor(ws, data, path):
|
|
async def obtain_control_processor(ws, data, path):
|
|
@@ -278,7 +285,8 @@ async def song_end_processor(ws, data, path):
|
|
room = rooms[path]
|
|
room = rooms[path]
|
|
old_song_id = data["id"]
|
|
old_song_id = data["id"]
|
|
with room.controller_lock, room.playback.lock:
|
|
with room.controller_lock, room.playback.lock:
|
|
- if room.controller is not None and ws is room.controller.ws and old_song_id == room.playback.get_song_id():
|
|
|
|
|
|
+ controller = room.get_controller()
|
|
|
|
+ if controller is not None and controller.ws is ws and old_song_id == room.playback.get_song_id():
|
|
new_song = play_next_song(room)
|
|
new_song = play_next_song(room)
|
|
if new_song is None:
|
|
if new_song is None:
|
|
new_song_id = None
|
|
new_song_id = None
|
|
@@ -293,7 +301,7 @@ async def player_enabled_processor(ws, data, path):
|
|
room.channel.subscribers[ws].player_enabled = data["enabled"]
|
|
room.channel.subscribers[ws].player_enabled = data["enabled"]
|
|
if data["enabled"]:
|
|
if data["enabled"]:
|
|
with room.controller_lock:
|
|
with room.controller_lock:
|
|
- if room.controller is None:
|
|
|
|
|
|
+ if room.get_controller() is None:
|
|
await obtain_control(ws, room)
|
|
await obtain_control(ws, room)
|
|
else:
|
|
else:
|
|
await release_control(ws, room)
|
|
await release_control(ws, room)
|
|
@@ -302,21 +310,24 @@ async def player_enabled_processor(ws, data, path):
|
|
# TODO There is some potential concurrent bug here, when the controller loses/releases control right before a song end.
|
|
# TODO There is some potential concurrent bug here, when the controller loses/releases control right before a song end.
|
|
async def obtain_control(ws, room: Room):
|
|
async def obtain_control(ws, room: Room):
|
|
with room.controller_lock:
|
|
with room.controller_lock:
|
|
- if room.controller is None or room.controller.ws is not ws:
|
|
|
|
- prev_controller = room.controller
|
|
|
|
- room.controller = room.channel.subscribers[ws]
|
|
|
|
|
|
+ controller = room.get_controller()
|
|
|
|
+ if controller is None or controller.ws is not ws:
|
|
|
|
+ room.set_controller(room.channel.subscribers[ws])
|
|
await ws.send(make_message(Message.OBTAIN_CONTROL))
|
|
await ws.send(make_message(Message.OBTAIN_CONTROL))
|
|
- if prev_controller is not None:
|
|
|
|
- await prev_controller.ws.send(make_message(Message.RELEASE_CONTROL))
|
|
|
|
|
|
+ if controller is not None:
|
|
|
|
+ await controller.ws.send(make_message(Message.RELEASE_CONTROL))
|
|
|
|
|
|
|
|
|
|
async def release_control(ws, room: Room):
|
|
async def release_control(ws, room: Room):
|
|
with room.controller_lock:
|
|
with room.controller_lock:
|
|
- if room.controller is not None and room.controller.ws is ws:
|
|
|
|
- room.controller = next(room.channel.get_player_enabled_subscribers(), None)
|
|
|
|
- if room.controller is not None:
|
|
|
|
- await room.controller.ws.send(make_message(Message.OBTAIN_CONTROL))
|
|
|
|
- await ws.send(make_message(Message.RELEASE_CONTROL))
|
|
|
|
|
|
+ controller = room.get_controller()
|
|
|
|
+ if controller is not None and controller.ws is ws:
|
|
|
|
+ controller = next(room.channel.get_player_enabled_subscribers(), None)
|
|
|
|
+ room.set_controller(controller)
|
|
|
|
+ if controller is not None:
|
|
|
|
+ await controller.ws.send(make_message(Message.OBTAIN_CONTROL))
|
|
|
|
+ if ws.open:
|
|
|
|
+ await ws.send(make_message(Message.RELEASE_CONTROL))
|
|
|
|
|
|
|
|
|
|
async def on_connect(ws, path):
|
|
async def on_connect(ws, path):
|
|
@@ -330,9 +341,6 @@ async def on_disconnect(ws, path):
|
|
room = rooms[path]
|
|
room = rooms[path]
|
|
room.channel.unsubscribe(ws)
|
|
room.channel.unsubscribe(ws)
|
|
await release_control(ws, room)
|
|
await release_control(ws, room)
|
|
- # with room.controller_lock:
|
|
|
|
- # if room.controller is None:
|
|
|
|
- # room.playback.
|
|
|
|
|
|
|
|
|
|
|
|
def make_resolver():
|
|
def make_resolver():
|
|
@@ -352,14 +360,6 @@ def make_resolver():
|
|
return resolver
|
|
return resolver
|
|
|
|
|
|
|
|
|
|
-def init_rooms():
|
|
|
|
- # rooms["main"] = Room()
|
|
|
|
- pass
|
|
|
|
-
|
|
|
|
-
|
|
|
|
if __name__ == "__main__":
|
|
if __name__ == "__main__":
|
|
player_resolver = make_resolver()
|
|
player_resolver = make_resolver()
|
|
-
|
|
|
|
- init_rooms()
|
|
|
|
-
|
|
|
|
start_server(player_resolver, on_connect, on_disconnect)
|
|
start_server(player_resolver, on_connect, on_disconnect)
|