123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- // @flow
-
- import JitsiMeetJS from '../lib-jitsi-meet';
- import { updateSettings } from '../settings';
- import { parseURLParams } from '../util';
-
- import logger from './logger';
-
- declare var APP: Object;
-
- /**
- * Detects the use case when the labels are not available if the A/V permissions
- * are not yet granted.
- *
- * @param {Object} state - The redux state.
- * @returns {boolean} - True if the labels are already initialized and false
- * otherwise.
- */
- export function areDeviceLabelsInitialized(state: Object) {
- // TODO: Replace with something that doesn't use APP when the conference.js logic is reactified.
- if (APP.conference._localTracksInitialized) {
- return true;
- }
-
- for (const type of [ 'audioInput', 'audioOutput', 'videoInput' ]) {
- if ((state['features/base/devices'].availableDevices[type] || []).find(d => Boolean(d.label))) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Get device id of the audio output device which is currently in use.
- * Empty string stands for default device.
- *
- * @returns {string}
- */
- export function getAudioOutputDeviceId() {
- return JitsiMeetJS.mediaDevices.getAudioOutputDevice();
- }
-
- /**
- * Finds a device with a label that matches the passed label and returns its id.
- *
- * @param {Object} state - The redux state.
- * @param {string} label - The label.
- * @param {string} kind - The type of the device. One of "audioInput",
- * "audioOutput", and "videoInput". Also supported is all lowercase versions
- * of the preceding types.
- * @returns {string|undefined}
- */
- export function getDeviceIdByLabel(state: Object, label: string, kind: string) {
- const webrtcKindToJitsiKindTranslator = {
- audioinput: 'audioInput',
- audiooutput: 'audioOutput',
- videoinput: 'videoInput'
- };
-
- const kindToSearch = webrtcKindToJitsiKindTranslator[kind] || kind;
-
- const device
- = (state['features/base/devices'].availableDevices[kindToSearch] || [])
- .find(d => d.label === label);
-
- if (device) {
- return device.deviceId;
- }
- }
-
- /**
- * Finds a device with a label that matches the passed id and returns its label.
- *
- * @param {Object} state - The redux state.
- * @param {string} id - The device id.
- * @param {string} kind - The type of the device. One of "audioInput",
- * "audioOutput", and "videoInput". Also supported is all lowercase versions
- * of the preceding types.
- * @returns {string|undefined}
- */
- export function getDeviceLabelById(state: Object, id: string, kind: string) {
- const webrtcKindToJitsiKindTranslator = {
- audioinput: 'audioInput',
- audiooutput: 'audioOutput',
- videoinput: 'videoInput'
- };
-
- const kindToSearch = webrtcKindToJitsiKindTranslator[kind] || kind;
-
- const device
- = (state['features/base/devices'].availableDevices[kindToSearch] || [])
- .find(d => d.deviceId === id);
-
- if (device) {
- return device.label;
- }
- }
-
- /**
- * Returns the devices set in the URL.
- *
- * @param {Object} state - The redux state.
- * @returns {Object|undefined}
- */
- export function getDevicesFromURL(state: Object) {
- const urlParams
- = parseURLParams(state['features/base/connection'].locationURL);
-
- const audioOutput = urlParams['devices.audioOutput'];
- const videoInput = urlParams['devices.videoInput'];
- const audioInput = urlParams['devices.audioInput'];
-
- if (!audioOutput && !videoInput && !audioInput) {
- return undefined;
- }
-
- const devices = {};
-
- audioOutput && (devices.audioOutput = audioOutput);
- videoInput && (devices.videoInput = videoInput);
- audioInput && (devices.audioInput = audioInput);
-
- return devices;
- }
-
- /**
- * Converts an array of media devices into an object organized by device kind.
- *
- * @param {Array<MediaDeviceInfo>} devices - Available media devices.
- * @private
- * @returns {Object} An object with the media devices split by type. The keys
- * are device type and the values are arrays with devices matching the device
- * type.
- */
- export function groupDevicesByKind(devices: Object[]): Object {
- return {
- audioInput: devices.filter(device => device.kind === 'audioinput'),
- audioOutput: devices.filter(device => device.kind === 'audiooutput'),
- videoInput: devices.filter(device => device.kind === 'videoinput')
- };
- }
-
- /**
- * Filters audio devices from a list of MediaDeviceInfo objects.
- *
- * @param {Array<MediaDeviceInfo>} devices - Unfiltered media devices.
- * @private
- * @returns {Array<MediaDeviceInfo>} Filtered audio devices.
- */
- export function filterAudioDevices(devices: Object[]): Object {
- return devices.filter(device => device.kind === 'audioinput');
- }
-
- /**
- * We want to strip any device details that are not very user friendly, like usb ids put in brackets at the end.
- *
- * @param {string} label - Device label to format.
- *
- * @returns {string} - Formatted string.
- */
- export function formatDeviceLabel(label: string) {
-
- let formattedLabel = label;
-
- // Remove braked description at the end as it contains non user friendly strings i.e.
- // Microsoft® LifeCam HD-3000 (045e:0779:31dg:d1231)
- const ix = formattedLabel.lastIndexOf('(');
-
- if (ix !== -1) {
- formattedLabel = formattedLabel.substr(0, ix);
- }
-
- return formattedLabel;
- }
-
- /**
- * Returns a list of objects containing all the microphone device ids and labels.
- *
- * @param {Object} state - The state of the application.
- * @returns {Object[]}
- */
- export function getAudioInputDeviceData(state: Object) {
- return state['features/base/devices'].availableDevices.audioInput.map(
- ({ deviceId, label }) => {
- return {
- deviceId,
- label
- };
- });
- }
-
- /**
- * Returns a list of objectes containing all the output device ids and labels.
- *
- * @param {Object} state - The state of the application.
- * @returns {Object[]}
- */
- export function getAudioOutputDeviceData(state: Object) {
- return state['features/base/devices'].availableDevices.audioOutput.map(
- ({ deviceId, label }) => {
- return {
- deviceId,
- label
- };
- });
- }
-
- /**
- * Returns a list of all the camera device ids.
- *
- * @param {Object} state - The state of the application.
- * @returns {string[]}
- */
- export function getVideoDeviceIds(state: Object) {
- return state['features/base/devices'].availableDevices.videoInput.map(({ deviceId }) => deviceId);
- }
-
- /**
- * Returns true if there are devices of a specific type.
- *
- * @param {Object} state - The state of the application.
- * @param {string} type - The type of device: VideoOutput | audioOutput | audioInput.
- *
- * @returns {boolean}
- */
- export function hasAvailableDevices(state: Object, type: string) {
- return state['features/base/devices'].availableDevices[type].length > 0;
- }
-
- /**
- * Set device id of the audio output device which is currently in use.
- * Empty string stands for default device.
- *
- * @param {string} newId - New audio output device id.
- * @param {Function} dispatch - The Redux dispatch function.
- * @param {boolean} userSelection - Whether this is a user selection update.
- * @param {?string} newLabel - New audio output device label to store.
- * @returns {Promise}
- */
- export function setAudioOutputDeviceId(
- newId: string = 'default',
- dispatch: Function,
- userSelection: boolean = false,
- newLabel: ?string): Promise<*> {
-
- logger.debug(`setAudioOutputDevice: ${String(newLabel)}[${newId}]`);
-
- return JitsiMeetJS.mediaDevices.setAudioOutputDevice(newId)
- .then(() => {
- const newSettings = {
- audioOutputDeviceId: newId,
- userSelectedAudioOutputDeviceId: undefined,
- userSelectedAudioOutputDeviceLabel: undefined
- };
-
- if (userSelection) {
- newSettings.userSelectedAudioOutputDeviceId = newId;
- newSettings.userSelectedAudioOutputDeviceLabel = newLabel;
- } else {
- // a flow workaround, I needed to add 'userSelectedAudioOutputDeviceId: undefined'
- delete newSettings.userSelectedAudioOutputDeviceId;
- delete newSettings.userSelectedAudioOutputDeviceLabel;
- }
-
- return dispatch(updateSettings(newSettings));
- });
- }
|