147 lines
3.9 KiB
JavaScript
147 lines
3.9 KiB
JavaScript
/**
|
|
* Track state & reducer
|
|
* ---
|
|
* All (participant & screen) video and audio tracks indexed on participant ID
|
|
* If using manual track subscriptions, we'll also keep a record of those
|
|
* and their playing / paused state
|
|
*/
|
|
|
|
import { getId, getScreenId } from './participantsState';
|
|
|
|
export const initialTracksState = {
|
|
audioTracks: {},
|
|
videoTracks: {},
|
|
};
|
|
|
|
// --- Actions ---
|
|
|
|
export const TRACK_STARTED = 'TRACK_STARTED';
|
|
export const TRACK_STOPPED = 'TRACK_STOPPED';
|
|
export const TRACK_VIDEO_UPDATED = 'TRACK_VIDEO_UPDATED';
|
|
export const TRACK_AUDIO_UPDATED = 'TRACK_AUDIO_UPDATED';
|
|
export const REMOVE_TRACKS = 'REMOVE_TRACKS';
|
|
|
|
// --- Reducer and helpers --
|
|
|
|
export function tracksReducer(prevState, action) {
|
|
switch (action.type) {
|
|
case TRACK_STARTED: {
|
|
const id = getId(action.participant);
|
|
const screenId = getScreenId(id);
|
|
|
|
if (action.track.kind === 'audio') {
|
|
if (action.participant?.local) {
|
|
// Ignore local audio from mic and screen share
|
|
return prevState;
|
|
}
|
|
const newAudioTracks = {
|
|
[id]: action.participant.tracks.audio,
|
|
};
|
|
if (action.participant.screen) {
|
|
newAudioTracks[screenId] = action.participant.tracks.screenAudio;
|
|
}
|
|
return {
|
|
...prevState,
|
|
audioTracks: {
|
|
...prevState.audioTracks,
|
|
...newAudioTracks,
|
|
},
|
|
};
|
|
}
|
|
|
|
const newVideoTracks = {
|
|
[id]: action.participant.tracks.video,
|
|
};
|
|
if (action.participant.screen) {
|
|
newVideoTracks[screenId] = action.participant.tracks.screenVideo;
|
|
}
|
|
return {
|
|
...prevState,
|
|
videoTracks: {
|
|
...prevState.videoTracks,
|
|
...newVideoTracks,
|
|
},
|
|
};
|
|
}
|
|
|
|
case TRACK_STOPPED: {
|
|
const { audioTracks, videoTracks } = prevState;
|
|
|
|
const newAudioTracks = { ...audioTracks };
|
|
const newVideoTracks = { ...videoTracks };
|
|
|
|
action.items.forEach(([participant, track]) => {
|
|
const id = participant ? getId(participant) : null;
|
|
const screenId = participant ? getScreenId(id) : null;
|
|
|
|
if (track.kind === 'audio') {
|
|
if (!participant?.local) {
|
|
// Ignore local audio from mic and screen share
|
|
newAudioTracks[id] = participant.tracks.audio;
|
|
if (participant.screen) {
|
|
newAudioTracks[screenId] = participant.tracks.screenAudio;
|
|
}
|
|
}
|
|
} else if (track.kind === 'video') {
|
|
newVideoTracks[id] = participant.tracks.video;
|
|
if (participant.screen) {
|
|
newVideoTracks[screenId] = participant.tracks.screenVideo;
|
|
}
|
|
}
|
|
});
|
|
|
|
return {
|
|
audioTracks: newAudioTracks,
|
|
videoTracks: newVideoTracks,
|
|
};
|
|
}
|
|
|
|
case TRACK_AUDIO_UPDATED: {
|
|
const id = getId(action.participant);
|
|
if (action.participant?.local) {
|
|
// Ignore local audio from mic and screen share
|
|
return prevState;
|
|
}
|
|
const newAudioTracks = {
|
|
...prevState.audioTracks,
|
|
[id]: action.participant.tracks.audio,
|
|
};
|
|
return {
|
|
...prevState,
|
|
audioTracks: newAudioTracks,
|
|
};
|
|
}
|
|
|
|
case TRACK_VIDEO_UPDATED: {
|
|
const id = getId(action.participant);
|
|
const newVideoTracks = {
|
|
...prevState.videoTracks,
|
|
[id]: action.participant.tracks.video,
|
|
};
|
|
return {
|
|
...prevState,
|
|
videoTracks: newVideoTracks,
|
|
};
|
|
}
|
|
|
|
case REMOVE_TRACKS: {
|
|
const { audioTracks, videoTracks } = prevState;
|
|
const id = getId(action.participant);
|
|
const screenId = getScreenId(id);
|
|
|
|
delete audioTracks[id];
|
|
delete audioTracks[screenId];
|
|
delete videoTracks[id];
|
|
delete videoTracks[screenId];
|
|
|
|
return {
|
|
audioTracks,
|
|
videoTracks,
|
|
};
|
|
}
|
|
|
|
default:
|
|
throw new Error();
|
|
}
|
|
}
|