2021-02-02 02:47:05 +08:00
|
|
|
import Storage from '/imports/ui/services/storage/session';
|
|
|
|
import getFromUserSettings from '/imports/ui/services/users-settings';
|
2021-04-03 11:06:39 +08:00
|
|
|
import MediaStreamUtils from '/imports/utils/media-stream-utils';
|
|
|
|
|
|
|
|
// VIDEO_STREAM_STORAGE: Map<deviceId, MediaStream>. Registers WEBCAM streams.
|
|
|
|
// Easier to keep track of them. Easier to centralize their referencing.
|
|
|
|
// Easier to shuffle them around.
|
|
|
|
const VIDEO_STREAM_STORAGE = new Map();
|
|
|
|
|
|
|
|
const storeStream = (deviceId, stream) => {
|
|
|
|
// Check if there's a dangling stream. If there's one and it's active, cool,
|
|
|
|
// return false as it's already stored. Otherwised, clean the derelict stream
|
|
|
|
// and store the new one
|
|
|
|
if (hasStream(deviceId)) {
|
|
|
|
const existingStream = getStream(deviceId);
|
|
|
|
if (existingStream.active) return false;
|
|
|
|
deleteStream(deviceId);
|
|
|
|
}
|
|
|
|
|
|
|
|
VIDEO_STREAM_STORAGE.set(deviceId, stream);
|
|
|
|
|
|
|
|
// Stream insurance: clean it up if it ends (see the events being listened to below)
|
|
|
|
const cleanup = () => {
|
|
|
|
deleteStream(deviceId)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dirty, but effective way of checking whether the browser supports the 'inactive'
|
|
|
|
// event. If the oninactive interface is null, it can be overridden === supported.
|
|
|
|
// If undefined, it's not; so we fallback to the track 'ended' event.
|
|
|
|
if (stream.oninactive === null) {
|
|
|
|
stream.addEventListener('inactive', cleanup, { once: true });
|
|
|
|
} else {
|
|
|
|
const track = MediaStreamUtils.getVideoTracks(stream)[0];
|
|
|
|
if (track) {
|
|
|
|
track.addEventListener('ended', cleanup, { once: true });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const getStream = (deviceId) => {
|
|
|
|
return VIDEO_STREAM_STORAGE.get(deviceId);
|
|
|
|
}
|
|
|
|
|
|
|
|
const hasStream = (deviceId) => {
|
|
|
|
return VIDEO_STREAM_STORAGE.has(deviceId);
|
|
|
|
}
|
|
|
|
|
|
|
|
const deleteStream = (deviceId) => {
|
|
|
|
const stream = getStream(deviceId);
|
|
|
|
if (stream == null) return false;
|
|
|
|
MediaStreamUtils.stopMediaStreamTracks(stream);
|
|
|
|
return VIDEO_STREAM_STORAGE.delete(deviceId);
|
|
|
|
}
|
2021-02-02 02:47:05 +08:00
|
|
|
|
2020-12-22 03:47:00 +08:00
|
|
|
const promiseTimeout = (ms, promise) => {
|
|
|
|
const timeout = new Promise((resolve, reject) => {
|
|
|
|
const id = setTimeout(() => {
|
|
|
|
clearTimeout(id);
|
|
|
|
|
|
|
|
const error = {
|
|
|
|
name: 'TimeoutError',
|
|
|
|
message: 'Promise did not return',
|
|
|
|
};
|
|
|
|
|
|
|
|
reject(error);
|
|
|
|
}, ms);
|
|
|
|
});
|
|
|
|
|
|
|
|
return Promise.race([
|
|
|
|
promise,
|
|
|
|
timeout,
|
|
|
|
]);
|
|
|
|
};
|
|
|
|
|
2021-02-02 02:47:05 +08:00
|
|
|
const getSkipVideoPreview = () => {
|
|
|
|
const KURENTO_CONFIG = Meteor.settings.public.kurento;
|
|
|
|
|
|
|
|
const skipVideoPreviewOnFirstJoin = getFromUserSettings(
|
|
|
|
'bbb_skip_video_preview_on_first_join',
|
|
|
|
KURENTO_CONFIG.skipVideoPreviewOnFirstJoin,
|
|
|
|
);
|
|
|
|
const skipVideoPreview = getFromUserSettings(
|
|
|
|
'bbb_skip_video_preview',
|
|
|
|
KURENTO_CONFIG.skipVideoPreview,
|
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
(Storage.getItem('isFirstJoin') !== false && skipVideoPreviewOnFirstJoin)
|
|
|
|
|| skipVideoPreview
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2021-04-03 11:06:39 +08:00
|
|
|
const digestVideoDevices = (devices, priorityDevice) => {
|
|
|
|
const webcams = [];
|
|
|
|
let areLabelled = true;
|
|
|
|
let areIdentified = true;
|
|
|
|
|
|
|
|
devices.forEach((device) => {
|
|
|
|
if (device.kind === 'videoinput') {
|
|
|
|
// Avoid duplicated devices
|
|
|
|
if (!webcams.some(d => d.deviceId === device.deviceId)) {
|
|
|
|
// We found a priority device. Push it to the beginning of the array so we
|
|
|
|
// can use it as the "initial device"
|
|
|
|
if (priorityDevice && priorityDevice === device.deviceId) {
|
|
|
|
webcams.unshift(device);
|
|
|
|
} else {
|
|
|
|
webcams.push(device);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!device.label) { areLabelled = false };
|
|
|
|
if (!device.deviceId) { areIdentified = false};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Returns the list of devices and whether they are labelled and identified with deviceId
|
|
|
|
return {
|
|
|
|
webcams,
|
|
|
|
areLabelled,
|
|
|
|
areIdentified,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-11-07 07:10:56 +08:00
|
|
|
export default {
|
2020-12-22 03:47:00 +08:00
|
|
|
promiseTimeout,
|
2018-11-07 07:10:56 +08:00
|
|
|
changeWebcam: (deviceId) => {
|
|
|
|
Session.set('WebcamDeviceId', deviceId);
|
|
|
|
},
|
2018-11-17 02:56:39 +08:00
|
|
|
webcamDeviceId: () => Session.get('WebcamDeviceId'),
|
2019-04-09 06:07:26 +08:00
|
|
|
changeProfile: (profileId) => {
|
|
|
|
Session.set('WebcamProfileId', profileId);
|
|
|
|
},
|
2021-02-02 02:47:05 +08:00
|
|
|
getSkipVideoPreview,
|
2021-04-03 11:06:39 +08:00
|
|
|
storeStream,
|
|
|
|
getStream,
|
|
|
|
hasStream,
|
|
|
|
deleteStream,
|
|
|
|
digestVideoDevices,
|
2018-11-07 07:10:56 +08:00
|
|
|
};
|