Переглянути джерело

Add media buttons and fix massive bug.

niels 4 роки тому
батько
коміт
4ed2b8e53e
3 змінених файлів з 118 додано та 15 видалено
  1. 50 5
      chube.py
  2. 44 1
      static/js/main.js
  3. 24 9
      static/player.html

+ 50 - 5
chube.py

@@ -3,7 +3,6 @@ from typing import Optional, Iterator, Dict, List
 
 import sys
 from itertools import cycle
-from websockets import WebSocketServerProtocol
 
 import chube_search
 from channel import Channel, Subscriber
@@ -46,7 +45,7 @@ class Chueue:
     def pop(self):
         with self:
             if len(self._queue) > 0:
-                song_id = self._queue.pop()
+                song_id = self._queue.pop(0)
                 code = self._codes.pop(song_id)
                 return self.as_song(song_id, code)
             else:
@@ -164,6 +163,45 @@ async def request_list_operation_processor(ws, data, path):
         await room.channel.send(message)
 
 
+async def media_action_processor(ws, data, path):
+    room = rooms[path]
+    action = data["action"]
+    send_next = False
+    if action == "NEXT":
+        current_id = data["current_id"]
+        with room.playback.lock, room.chueue:
+            old_song_id = room.playback.get_song_id()
+            if old_song_id == current_id:
+                send_next = True
+                new_song = play_next_song(room)
+                if new_song is None:
+                    new_song_id = None
+                else:
+                    new_song_id = new_song["id"]
+        if send_next:
+            await room.channel.send(make_message(
+                Message.MEDIA_ACTION,
+                {"action": MediaAction.NEXT.name, "ended_id": old_song_id, "current_id": new_song_id}))
+
+    if action == "PLAY" or send_next:
+        send_play = False
+        with room.playback.lock:
+            if room.playback.get_state() == PlayerState.PAUSED:
+                send_play = True
+                room.playback.set_state(PlayerState.PLAYING)
+        if send_play:
+            await room.channel.send(make_message(Message.MEDIA_ACTION, {"action": MediaAction.PLAY.name}))
+
+    if action == "PAUSE":
+        send_pause = False
+        with room.playback.lock:
+            if room.playback.get_state() == PlayerState.PLAYING:
+                send_pause = True
+                room.playback.set_state(PlayerState.PAUSED)
+        if send_pause:
+            await room.channel.send(make_message(Message.MEDIA_ACTION, {"action": MediaAction.PAUSE.name}))
+
+
 async def obtain_control_processor(ws, data, path):
     room = rooms[path]
     await obtain_control(ws, room)
@@ -178,15 +216,21 @@ async def release_control_processor(ws, data, path):
         # TODO error here
 
 
+def play_next_song(room):
+    new_song = room.chueue.pop()
+    room.playback.set_song(new_song)
+    if new_song is None:
+        room.playback.set_state(PlayerState.LIST_END)
+    return new_song
+
+
 async def song_end_processor(ws, data, path):
     room = rooms[path]
     old_song_id = data["id"]
     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():
-            new_song = room.chueue.pop()
-            room.playback.set_song(new_song)
+            new_song = play_next_song(room)
             if new_song is None:
-                room.playback.set_state(PlayerState.LIST_END)
                 new_song_id = None
             else:
                 new_song_id = new_song["id"]
@@ -249,6 +293,7 @@ def make_resolver():
     resolver = Resolver()
     resolver.register(Message.STATE, request_state_processor)
     resolver.register(Message.LIST_OPERATION, request_list_operation_processor)
+    resolver.register(Message.MEDIA_ACTION, media_action_processor)
     resolver.register(Message.PLAYER_ENABLED, player_enabled_processor)
     resolver.register(Message.OBTAIN_CONTROL, obtain_control_processor)
     resolver.register(Message.RELEASE_CONTROL, release_control_processor)

+ 44 - 1
static/js/main.js

@@ -1,5 +1,5 @@
 import { makeMessage, Resolver } from './websocketResolver.js';
-import { ListOperationTypes, MessageTypes, PlayerState } from "./enums.js";
+import { ListOperationTypes, MessageTypes, PlayerState, MediaAction } from "./enums.js";
 
 window.onYouTubeIframeAPIReady = onYouTubeIframeAPIReady
 
@@ -353,6 +353,24 @@ function showPlayerPlaceholder(event) {
     showPlaceholderButton.toggleAttribute("hidden")
 }
 
+function onPlayButton(event) {
+    event.preventDefault();
+    socket.send(makeMessage(MessageTypes.MEDIA_ACTION, {action: MediaAction.PLAY}))
+}
+
+function onPauseButton(event) {
+    event.preventDefault();
+    socket.send(makeMessage(MessageTypes.MEDIA_ACTION, {action: MediaAction.PAUSE}))
+
+}
+
+function onNextButton(event) {
+    event.preventDefault();
+    if (videoPlaying !== null) {
+        socket.send(makeMessage(MessageTypes.MEDIA_ACTION, { action: MediaAction.NEXT, current_id: videoPlaying.id }))
+    }
+}
+
 function stateProcessor(ws, data) {
     const { playing, state: newState, list } = data;
 
@@ -400,6 +418,27 @@ function listOperationProcessor(ws, data) {
     }
 }
 
+function mediaActionProcessor(ws, data) {
+    const {action, ended_id, current_id} = data;
+    if (action === MediaAction.PLAY && state === PlayerState.PAUSED) {
+        state = PlayerState.PLAYING
+        player.playVideo();
+    } else if (action === MediaAction.PAUSE && state === PlayerState.PLAYING) {
+        state = PlayerState.PAUSED
+        player.pauseVideo();
+    } else if (action === MediaAction.NEXT) {
+        if (videoPlaying !== null && videoPlaying.id === ended_id) {
+            const vid = popVideo()
+            if (vid !== undefined) {
+                playVideo(vid)
+            } else {
+                videoPlaying = null;
+                state = PlayerState.LIST_END;
+            }
+        }
+    }
+}
+
 function songEndProcessor(ws, data) {
     const { ended_id, current_id } = data;
     console.log(ended_id, current_id)
@@ -494,6 +533,7 @@ function onYTDone() {
     const resolver = new Resolver()
     resolver.register(MessageTypes.STATE, stateProcessor)
     resolver.register(MessageTypes.LIST_OPERATION, listOperationProcessor)
+    resolver.register(MessageTypes.MEDIA_ACTION, mediaActionProcessor)
     resolver.register(MessageTypes.OBTAIN_CONTROL, () => setLeader(true))
     resolver.register(MessageTypes.RELEASE_CONTROL, () => setLeader(false))
     resolver.register(MessageTypes.SONG_END, songEndProcessor)
@@ -513,4 +553,7 @@ function afterStateInit() {
     document.getElementById('closePlayer').addEventListener('click', onPlayerClose)
     document.getElementById('hidePlayerPlaceholder').addEventListener('click', hidePlayerPlaceholder)
     document.getElementById('showPlayerPlaceholder').addEventListener('click', showPlayerPlaceholder)
+    document.getElementById('play-button').addEventListener('click', onPlayButton)
+    document.getElementById('pause-button').addEventListener('click', onPauseButton)
+    document.getElementById('next-button').addEventListener('click', onNextButton)
 }

+ 24 - 9
static/player.html

@@ -31,7 +31,7 @@
 <div class="container">
     <div class="row">
         <div class="col-xl-6 col-sm-12">
-            <div class="row" >
+            <div class="row">
                 <form hidden id="addVideoForm" class="form-inline my-4">
                     <div class="form-group">
                         <label for="addVideo">Add Video</label>
@@ -66,21 +66,34 @@
                     <button class="btn btn-link btn-sm text-secondary" id="showPlayerPlaceholder" hidden>Show</button>
                     <div id="playerPlaceholder" class="d-flex justify-content-center my-4">
                         <div>
-                            <button class="btn btn-outline-secondary" id="startPlayerButton">Start Player</button><br/>
-                            <button class="btn btn-link btn-sm small text-secondary" id="hidePlayerPlaceholder" style="width:100%">Hide</button>
+                            <button class="btn btn-outline-secondary" id="startPlayerButton">Start Player</button>
+                            <br/>
+                            <button class="btn btn-link btn-sm small text-secondary" id="hidePlayerPlaceholder"
+                                    style="width:100%">Hide
+                            </button>
                         </div>
                     </div>
                     <div id="playerContainer" class="py-4" hidden>
-                        <div class="row justify-content-between">
-                            <span class="col-2"><button id="leader-button"
-                                      class="btn btn-outline-secondary disabled">No connection</button></span>
+                        <div class="row">
+                            <div class="btn-toolbar col-11">
+                                <div class="btn btn-group">
+                                    <button id="leader-button" class="btn btn-outline-secondary disabled">
+                                        No connection
+                                    </button>
+                                </div>
+                                <div class="btn btn-group">
+                                    <button id="play-button" class="btn btn-outline-secondary"><i class="fa fa-play"></i></button>
+                                    <button id="pause-button" class="btn btn-outline-secondary"><i class="fa fa-pause"></i></button>
+                                    <button id="next-button" class="btn btn-outline-secondary"><i class="fa fa-forward"></i></button>
+                                </div>
+                            </div>
                             <span class="col-1">
                                 <a href="#" id="closePlayer">
                                     <i class="fa fa-times"></i>
                                 </a>
                             </span>
                         </div>
-                        <div id="player" class="pt-4"></div>
+                        <div id="player" class="pt-2"></div>
                     </div>
                 </div>
             </div>
@@ -100,7 +113,8 @@
                                     <span class="videoListCardDescription"></span>
                                 </div>
                                 <div class="col-1">
-                                    <button class="videoListCardDelete btn btn-outline-danger"><i class="fa fa-trash-alt"></i></button>
+                                    <button class="videoListCardDelete btn btn-outline-danger"><i
+                                        class="fa fa-trash-alt"></i></button>
                                 </div>
                             </div>
                         </div>
@@ -110,7 +124,8 @@
         </div>
     </div>
 </div>
-<footer class="footer mb-4"><a href="https://github.com/NielsOverkamp/ChuChube">Made by Niels Overkamp</a>&nbsp·&nbsp<a href="http://joetoep.student.utwente.nl">Based on JoeToep</a></footer>
+<footer class="footer mb-4"><a href="https://github.com/NielsOverkamp/ChuChube">Made by Niels Overkamp</a>&nbsp·&nbsp<a
+    href="http://joetoep.student.utwente.nl">Based on JoeToep</a></footer>
 <script src="js/main.js" type="module"></script>
 </body>