Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

actions.js 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. import { API_ID } from '../../../modules/API/constants';
  2. import {
  3. PostMessageTransportBackend,
  4. Transport
  5. } from '../../../modules/transport';
  6. import { createDeviceChangedEvent, sendAnalytics } from '../analytics';
  7. import {
  8. getAudioOutputDeviceId,
  9. setAudioInputDevice,
  10. setAudioOutputDeviceId,
  11. setVideoInputDevice
  12. } from '../base/devices';
  13. import { i18next } from '../base/i18n';
  14. import JitsiMeetJS from '../base/lib-jitsi-meet';
  15. import { updateSettings } from '../base/settings';
  16. import { SET_DEVICE_SELECTION_POPUP_DATA } from './actionTypes';
  17. import { getDeviceSelectionDialogProps } from './functions';
  18. const logger = require('jitsi-meet-logger').getLogger(__filename);
  19. /**
  20. * Opens a popup window with the device selection dialog in it.
  21. *
  22. * @returns {Function}
  23. */
  24. export function openDeviceSelectionPopup() {
  25. return (dispatch, getState) => {
  26. const { popupDialogData } = getState()['features/device-selection'];
  27. if (popupDialogData) {
  28. popupDialogData.popup.focus();
  29. return;
  30. }
  31. // API_ID will always be defined because the iframe api is enabled
  32. const scope = `dialog_${API_ID}`;
  33. const url = `${
  34. window.location.origin}/static/deviceSelectionPopup.html#scope=${
  35. encodeURIComponent(JSON.stringify(scope))}`;
  36. const popup
  37. = window.open(
  38. url,
  39. 'device-selection-popup',
  40. 'toolbar=no,scrollbars=no,resizable=no,width=720,height=458');
  41. popup.addEventListener('DOMContentLoaded', () => {
  42. popup.init(i18next);
  43. });
  44. const transport = new Transport({
  45. backend: new PostMessageTransportBackend({
  46. postisOptions: {
  47. scope,
  48. window: popup
  49. }
  50. })
  51. });
  52. transport.on('request',
  53. _processRequest.bind(undefined, dispatch, getState));
  54. transport.on('event', event => {
  55. if (event.type === 'devices-dialog' && event.name === 'close') {
  56. popup.close();
  57. transport.dispose();
  58. dispatch(_setDeviceSelectionPopupData());
  59. return true;
  60. }
  61. return false;
  62. });
  63. dispatch(_setDeviceSelectionPopupData({
  64. popup,
  65. transport
  66. }));
  67. };
  68. }
  69. /**
  70. * Processes device requests from external applications.
  71. *
  72. * @param {Dispatch} dispatch - The redux {@code dispatch} function.
  73. * @param {Function} getState - The redux function that gets/retrieves the redux
  74. * state.
  75. * @param {Object} request - The request to be processed.
  76. * @param {Function} responseCallback - The callback that will send the
  77. * response.
  78. * @returns {boolean}
  79. */
  80. function _processRequest(dispatch, getState, request, responseCallback) { // eslint-disable-line max-len, max-params
  81. if (request.type === 'devices') {
  82. const state = getState();
  83. const settings = state['features/base/settings'];
  84. switch (request.name) {
  85. case 'isDeviceListAvailable':
  86. responseCallback(JitsiMeetJS.mediaDevices.isDeviceListAvailable());
  87. break;
  88. case 'isDeviceChangeAvailable':
  89. responseCallback(
  90. JitsiMeetJS.mediaDevices.isDeviceChangeAvailable(
  91. request.deviceType));
  92. break;
  93. case 'isMultipleAudioInputSupported':
  94. responseCallback(JitsiMeetJS.isMultipleAudioInputSupported());
  95. break;
  96. case 'getCurrentDevices':
  97. responseCallback({
  98. audioInput: settings.micDeviceId,
  99. audioOutput: getAudioOutputDeviceId(),
  100. videoInput: settings.cameraDeviceId
  101. });
  102. break;
  103. case 'getAvailableDevices':
  104. responseCallback(getState()['features/base/devices']);
  105. break;
  106. case 'setDevice': {
  107. const { device } = request;
  108. switch (device.kind) {
  109. case 'audioinput':
  110. dispatch(setAudioInputDevice(device.id));
  111. break;
  112. case 'audiooutput':
  113. setAudioOutputDeviceId(device.id, dispatch);
  114. break;
  115. case 'videoinput':
  116. dispatch(setVideoInputDevice(device.id));
  117. break;
  118. default:
  119. }
  120. responseCallback(true);
  121. break;
  122. }
  123. default:
  124. return false;
  125. }
  126. return true;
  127. }
  128. return false;
  129. }
  130. /**
  131. * Sets information about device selection popup in the store.
  132. *
  133. * @param {Object} popupDialogData - Information about the popup.
  134. * @param {Object} popupDialog.popup - The popup object returned from
  135. * window.open.
  136. * @param {Object} popupDialogData.transport - The transport instance used for
  137. * communication with the popup window.
  138. * @returns {{
  139. * type: SET_DEVICE_SELECTION_POPUP_DATA,
  140. * popupDialogData: Object
  141. * }}
  142. */
  143. function _setDeviceSelectionPopupData(popupDialogData) {
  144. return {
  145. type: SET_DEVICE_SELECTION_POPUP_DATA,
  146. popupDialogData
  147. };
  148. }
  149. /**
  150. * Submits the settings related to device selection.
  151. *
  152. * @param {Object} newState - The new settings.
  153. * @returns {Function}
  154. */
  155. export function submitDeviceSelectionTab(newState) {
  156. return (dispatch, getState) => {
  157. const currentState = getDeviceSelectionDialogProps(getState());
  158. if (newState.selectedVideoInputId
  159. && newState.selectedVideoInputId
  160. !== currentState.selectedVideoInputId) {
  161. dispatch(updateSettings({
  162. cameraDeviceId: newState.selectedVideoInputId
  163. }));
  164. dispatch(
  165. setVideoInputDevice(newState.selectedVideoInputId));
  166. }
  167. if (newState.selectedAudioInputId
  168. && newState.selectedAudioInputId
  169. !== currentState.selectedAudioInputId) {
  170. dispatch(updateSettings({
  171. micDeviceId: newState.selectedAudioInputId
  172. }));
  173. dispatch(
  174. setAudioInputDevice(newState.selectedAudioInputId));
  175. }
  176. if (newState.selectedAudioOutputId
  177. && newState.selectedAudioOutputId
  178. !== currentState.selectedAudioOutputId) {
  179. sendAnalytics(createDeviceChangedEvent('audio', 'output'));
  180. setAudioOutputDeviceId(
  181. newState.selectedAudioOutputId,
  182. dispatch)
  183. .then(() => logger.log('changed audio output device'))
  184. .catch(err => {
  185. logger.warn(
  186. 'Failed to change audio output device.',
  187. 'Default or previously set audio output device will',
  188. ' be used instead.',
  189. err);
  190. });
  191. }
  192. };
  193. }