You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

actions.js 6.7KB

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