Trying to make the distinction between a video element ('source')
and its parent div ('stream') less confusing
This commit is contained in:
parent
3d8d2b44e8
commit
1a661ac4e9
123
multiplayer.js
123
multiplayer.js
@ -243,14 +243,18 @@
|
||||
// raw presentation json is stored here
|
||||
this._presentation = null;
|
||||
|
||||
// all streams to be played back
|
||||
this._streams = [];
|
||||
// all sources to be played back
|
||||
this._sources = [];
|
||||
|
||||
// the main playback stream at any given time
|
||||
this._mainStream = null;
|
||||
// the controlling video element
|
||||
// other video elements will sync with this source
|
||||
this._controlSource = null;
|
||||
|
||||
// the stream that plays the audio
|
||||
this._audioStream = null;
|
||||
// the source that plays the audio
|
||||
this._audioSource = null;
|
||||
|
||||
// the main playback source at any given time
|
||||
this._mainSource = null;
|
||||
|
||||
// list of elements to show/hide based on playlist presence
|
||||
this._playlistUI = [];
|
||||
@ -431,8 +435,8 @@
|
||||
button.addEventListener('click', (event) => {
|
||||
const speed = event.currentTarget.textContent;
|
||||
currentSpeed.textContent = speed;
|
||||
this._streams.forEach((stream) => {
|
||||
stream.querySelector('video').playbackRate = speed;
|
||||
this._sources.forEach((source) => {
|
||||
source.playbackRate = speed;
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -495,8 +499,7 @@
|
||||
[createIcon(['subtitles-off',
|
||||
'subtitles-on'])]);
|
||||
this._subtitlesButton.addEventListener('click', (event) => {
|
||||
const track = this._mainStream.querySelector('video')
|
||||
.textTracks[0];
|
||||
const track = this._mainSource.textTracks[0];
|
||||
if(track.mode === 'disabled') {
|
||||
track.mode = 'showing';
|
||||
} else {
|
||||
@ -539,7 +542,7 @@
|
||||
while(parent.hasChildNodes()) {
|
||||
parent.removeChild(parent.firstChild());
|
||||
}
|
||||
this._streams = [];
|
||||
this._sources = [];
|
||||
this._overlayPlayIcons = [];
|
||||
|
||||
// initialize UI elements
|
||||
@ -593,15 +596,11 @@
|
||||
'src': `${presentation.subtitles}?token=${token}`});
|
||||
}
|
||||
|
||||
// keep a reference to the stream that plays audio
|
||||
if(stream.playAudio) {
|
||||
this._audioSource = video;
|
||||
}
|
||||
|
||||
//misc details
|
||||
video.muted = !stream.playAudio;
|
||||
video.poster = stream.poster;
|
||||
video.load();
|
||||
this._sources.push(video);
|
||||
|
||||
// set up overlay icons
|
||||
const switchIcon = streamRoot.appendChild(
|
||||
@ -612,25 +611,28 @@
|
||||
streamRoot.classList.add('main');
|
||||
switchIcon.classList.add('hidden');
|
||||
|
||||
// keep a reference to the main stream around
|
||||
this._mainStream = streamRoot;
|
||||
// kepp a reference to the control source around
|
||||
this._controlSource = video;
|
||||
// keep a reference to the main source around
|
||||
this._mainSource = video;
|
||||
// keep a reference to the source that plays audio
|
||||
this._audioSource = video;
|
||||
} else {
|
||||
playIcon.classList.add('hidden');
|
||||
}
|
||||
|
||||
// set up stream listeners
|
||||
streamRoot.addEventListener('click', (event) => {
|
||||
const stream = event.currentTarget;
|
||||
if(stream.classList.contains('main')) {
|
||||
// this is the main stream, toggle playback
|
||||
if(event.currentTarget.classList.contains('main')) {
|
||||
// this is the main source, toggle playback
|
||||
this.togglePlayback();
|
||||
} else {
|
||||
// this is a secondary stream, switch it to main
|
||||
this.switchMainStream(stream);
|
||||
// this is a secondary source, switch it to main
|
||||
this.switchMainSource(
|
||||
event.currentTarget.querySelector('video'));
|
||||
}
|
||||
});
|
||||
|
||||
this._streams.push(streamRoot);
|
||||
}
|
||||
|
||||
this.setActivePlaylistItem();
|
||||
@ -732,9 +734,8 @@
|
||||
}
|
||||
button.addEventListener('click', (event) => {
|
||||
const res = event.currentTarget.textContent;
|
||||
const time = this._mainStream.querySelector('video')
|
||||
.currentTime;
|
||||
const paused = this._mainStream.paused;
|
||||
const time = this._mainSource.currentTime;
|
||||
const paused = this._mainSource.paused;
|
||||
// temporarily pause playback for the switch
|
||||
if(!paused) {
|
||||
this.togglePlayback();
|
||||
@ -743,10 +744,9 @@
|
||||
return;
|
||||
}
|
||||
current.textContent = res;
|
||||
this._streams.forEach((stream) => {
|
||||
const video = stream.querySelector('video');
|
||||
video.src = video.dataset[res];
|
||||
video.currentTime = time;
|
||||
this._sources.forEach((source) => {
|
||||
source.src = source.dataset[res];
|
||||
source.currentTime = time;
|
||||
});
|
||||
this.togglePlayback();
|
||||
});
|
||||
@ -778,11 +778,11 @@
|
||||
* Jump in the presentation.
|
||||
*
|
||||
* The arg 'time' gives the time to jump to as a number of seconds
|
||||
* since start. Syncronizes any secondary streams via a custom event.
|
||||
* since start. Syncronizes any secondary sources via a custom event.
|
||||
*/
|
||||
setTime(time) {
|
||||
this._mainstream.currentTime = time;
|
||||
this._mainstream.dispatchEvent(new CustomEvent('sync'));
|
||||
this._mainSource.currentTime = time;
|
||||
this._mainSource.dispatchEvent(new CustomEvent('sync'));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -837,73 +837,70 @@
|
||||
/*
|
||||
* Start or stop playback.
|
||||
*
|
||||
* Toggles Playback button states and synchronizes streams.
|
||||
* Toggles Playback button states and synchronizes sources.
|
||||
*/
|
||||
togglePlayback() {
|
||||
this.toggleButtonState(this._playButton);
|
||||
const paused = this._mainStream.querySelector('video').paused;
|
||||
this._streams.forEach((stream) => {
|
||||
const videoElem = stream.querySelector('video');
|
||||
const paused = this._controlSource.paused;
|
||||
this._sources.forEach((source) => {
|
||||
if(paused) {
|
||||
videoElem.play();
|
||||
source.play();
|
||||
} else {
|
||||
videoElem.pause();
|
||||
source.pause();
|
||||
}
|
||||
this.toggleIconState(stream.querySelector('.play'));
|
||||
this.toggleIconState(
|
||||
source.parentNode.querySelector('.play'));
|
||||
});
|
||||
this.syncStreams();
|
||||
this.syncSources();
|
||||
}
|
||||
|
||||
/*
|
||||
* Synchronize all secondary streams to the current main stream.
|
||||
* Synchronize all secondary sources to the current main source.
|
||||
*/
|
||||
syncStreams() {
|
||||
const mainVideo = this._mainStream.querySelector('video');
|
||||
this._streams.forEach((stream) => {
|
||||
const video = stream.querySelector('video');
|
||||
if(stream.classList.contains('main')) {
|
||||
syncSources() {
|
||||
this._sources.forEach((source) => {
|
||||
if(source == this._controlSource) {
|
||||
return;
|
||||
}
|
||||
video.currentTime = mainVideo.currentTime;
|
||||
source.currentTime = this._controlSource.currentTime;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch the main playback stream to the one passed in newMain.
|
||||
* Switch the main playback source to the one passed in newMain.
|
||||
*/
|
||||
switchMainStream(newMain) {
|
||||
switchMainSource(newMain) {
|
||||
function switchIcons(elem) {
|
||||
elem.querySelectorAll('svg').forEach((icon) => {
|
||||
icon.classList.toggle('hidden');
|
||||
});
|
||||
}
|
||||
this._mainStream.classList.remove('main');
|
||||
switchIcons(this._mainStream);
|
||||
const oldMainParent = this._mainSource.parentNode;
|
||||
oldMainParent.classList.remove('main');
|
||||
switchIcons(oldMainParent);
|
||||
|
||||
newMain.classList.add('main');
|
||||
switchIcons(newMain);
|
||||
const newMainParent = newMain.parentNode;
|
||||
newMainParent.classList.add('main');
|
||||
switchIcons(newMainParent);
|
||||
|
||||
const oldTrack = this._mainStream.querySelector('video')
|
||||
.textTracks[0];
|
||||
const newTrack = newMain.querySelector('video')
|
||||
.textTracks[0];
|
||||
const oldTrack = this._mainSource.textTracks[0];
|
||||
const newTrack = newMain.textTracks[0];
|
||||
const oldState = oldTrack.mode;
|
||||
oldTrack.mode = newTrack.mode;
|
||||
newTrack.mode = oldState;
|
||||
|
||||
this._mainStream = newMain;
|
||||
this.syncStreams();
|
||||
this._mainSource = newMain;
|
||||
this.syncSources();
|
||||
}
|
||||
|
||||
updateProgress() {
|
||||
if(this._progressInterval != null) {
|
||||
window.clearInterval(this._progressInterval)
|
||||
}
|
||||
const trackedVideo = this._mainStream.querySelector('video');
|
||||
this._progressInterval = window.setInterval(
|
||||
() => {
|
||||
this._elapsed.textContent = this.formatTime(
|
||||
trackedVideo.currentTime);
|
||||
this._controlSource.currentTime);
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user