Skip to content

Commit

Permalink
Bugfixes: advance time by interval / 2000 (ugh); no currentTime -> pl…
Browse files Browse the repository at this point in the history
…ay()
  • Loading branch information
JoshuaKGoldberg committed Aug 30, 2020
1 parent 4c42a65 commit ae0b71a
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 15 deletions.
5 changes: 5 additions & 0 deletions src/components/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@ export const controlIds = {
volumeHighButton: "volume-high-button",
volumeLowButton: "volume-low-button",
};

/**
* How often to emit currentTime updates.
*/
export const videoSyncInterval = 500;
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { controls, videoElement } from "@components/elements";
import { useRoomContext } from "@connection/RoomContext";

import { useEmitOnClick } from "../useEmitOnClick";
import { videoSyncInterval } from "@components/constants";

export const usePlayPauseControl = () => {
const { originalRoomData, roomData } = useRoomContext();
const { currentTime, playing } = roomData.get();
const { playing } = roomData.get();

useEmitOnClick(controls.playPauseButton, (oldRoomData) => ({
currentTime: videoElement.currentTime,
Expand All @@ -22,10 +23,13 @@ export const usePlayPauseControl = () => {
} else {
videoElement.pause();
}
}, [currentTime, playing]);
}, [playing]);

useEffect(() => {
videoElement.currentTime = originalRoomData.currentTime;
// Video timing is, on average, behind by half of the sync interval.
// currentTime is also measured in seconds instead of milliseconds for some reason.
videoElement.currentTime =
originalRoomData.currentTime + videoSyncInterval / 2000;

if (originalRoomData.playing) {
videoElement.play();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,20 @@ import { useInterval } from "react-use";

import { videoElement } from "@components/elements";
import { useRoomContext } from "@connection/RoomContext";

/**
* How often to emit currentTime updates.
*/
const videoElementSyncInterval = 1000;
import { videoSyncInterval } from "@components/constants";

export const useTimeSynchronization = () => {
const { emitRoomData, roomData } = useRoomContext();
const { currentTime, playing } = roomData.get();

// Constantly update the server on the current time of the video
// Constantly update the server on the current time of the video if playing
useInterval(() => {
emitRoomData({
currentTime: videoElement.currentTime,
});
}, videoElementSyncInterval);
if (playing) {
emitRoomData({
currentTime: videoElement.currentTime,
});
}
}, videoSyncInterval);

// If the video is paused, we can safely match its time to currentTime
useEffect(() => {
Expand Down
28 changes: 26 additions & 2 deletions src/server/events/karaoke.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { isEqual } from "lodash";

import { KaraokeEvent } from "@shared/events";
import { RoomDataUpdatedData, SetUsernameData } from "@shared/types";

Expand Down Expand Up @@ -29,7 +31,29 @@ export const karaokeEvents = ({
socket.on(KaraokeEvent.RoomDataUpdated, (data: RoomDataUpdatedData) => {
log(`Updated jukebox: ${JSON.stringify(data)}`);

room.data = { ...room.data, ...data };
io.in(room.name).emit(KaraokeEvent.RoomDataUpdated, room.data);
// We declare a new "player" for the room if they're saying to play while paused.
const newPlayer =
data.playing && !room.data.playing ? person.id : room.data.player;

const newData = {
...room.data,
...data,

// Ignore currentTime updates from any client who didn't click the play button.
// This is a somewhat arbitrary measure to stop "currentTime battles", wherein
// two clients go back and forth sending vastly different times to each other.
currentTime:
newPlayer === person.id
? data.currentTime ?? room.data.currentTime
: room.data.currentTime,
player: newPlayer,
};

if (isEqual(room.data, newData)) {
return;
}

room.data = newData;
io.in(room.name).emit(KaraokeEvent.RoomDataUpdated, newData);
});
};
5 changes: 5 additions & 0 deletions src/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ export type RoomData = {
*/
environment: string;

/**
* Client ID of the last person to trigger the play button.
*/
player?: PersonId;

/**
* Whether the current song is playing.
*/
Expand Down

0 comments on commit ae0b71a

Please sign in to comment.