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.

functions.js 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // @flow
  2. import type { Dispatch } from 'redux';
  3. import {
  4. addPendingDeviceRequest,
  5. areDeviceLabelsInitialized,
  6. getAudioOutputDeviceId,
  7. getAvailableDevices,
  8. getDeviceIdByLabel,
  9. groupDevicesByKind,
  10. setAudioInputDevice,
  11. setAudioOutputDeviceId,
  12. setVideoInputDevice
  13. } from '../base/devices';
  14. import JitsiMeetJS from '../base/lib-jitsi-meet';
  15. import { toState } from '../base/redux';
  16. /**
  17. * Returns the properties for the device selection dialog from Redux state.
  18. *
  19. * @param {(Function|Object)} stateful -The (whole) redux state, or redux's
  20. * {@code getState} function to be used to retrieve the state.
  21. * @returns {Object} - The properties for the device selection dialog.
  22. */
  23. export function getDeviceSelectionDialogProps(stateful: Object | Function) {
  24. const state = toState(stateful);
  25. const settings = state['features/base/settings'];
  26. return {
  27. availableDevices: state['features/base/devices'],
  28. disableAudioInputChange:
  29. !JitsiMeetJS.isMultipleAudioInputSupported(),
  30. disableDeviceChange:
  31. !JitsiMeetJS.mediaDevices.isDeviceChangeAvailable(),
  32. hideAudioInputPreview:
  33. !JitsiMeetJS.isCollectingLocalStats(),
  34. hideAudioOutputSelect: !JitsiMeetJS.mediaDevices
  35. .isDeviceChangeAvailable('output'),
  36. selectedAudioInputId: settings.micDeviceId,
  37. selectedAudioOutputId: getAudioOutputDeviceId(),
  38. selectedVideoInputId: settings.cameraDeviceId
  39. };
  40. }
  41. /**
  42. * Processes device requests from external applications.
  43. *
  44. * @param {Dispatch} dispatch - The redux {@code dispatch} function.
  45. * @param {Function} getState - The redux function that gets/retrieves the redux
  46. * state.
  47. * @param {Object} request - The request to be processed.
  48. * @param {Function} responseCallback - The callback that will send the
  49. * response.
  50. * @returns {boolean}
  51. */
  52. export function processRequest( // eslint-disable-line max-params
  53. dispatch: Dispatch<any>,
  54. getState: Function,
  55. request: Object,
  56. responseCallback: Function) {
  57. if (request.type === 'devices') {
  58. const state = getState();
  59. const settings = state['features/base/settings'];
  60. const { conference } = state['features/base/conference'];
  61. let result = true;
  62. switch (request.name) {
  63. case 'isDeviceListAvailable':
  64. responseCallback(JitsiMeetJS.mediaDevices.isDeviceListAvailable());
  65. break;
  66. case 'isDeviceChangeAvailable':
  67. responseCallback(
  68. JitsiMeetJS.mediaDevices.isDeviceChangeAvailable(
  69. request.deviceType));
  70. break;
  71. case 'isMultipleAudioInputSupported':
  72. responseCallback(JitsiMeetJS.isMultipleAudioInputSupported());
  73. break;
  74. case 'getCurrentDevices':
  75. dispatch(getAvailableDevices()).then(devices => {
  76. if (areDeviceLabelsInitialized(state)) {
  77. let audioInput, audioOutput, videoInput;
  78. const audioOutputDeviceId = getAudioOutputDeviceId();
  79. const { cameraDeviceId, micDeviceId } = settings;
  80. devices.forEach(({ deviceId, label }) => {
  81. switch (deviceId) {
  82. case micDeviceId:
  83. audioInput = label;
  84. break;
  85. case audioOutputDeviceId:
  86. audioOutput = label;
  87. break;
  88. case cameraDeviceId:
  89. videoInput = label;
  90. break;
  91. }
  92. });
  93. responseCallback({
  94. audioInput,
  95. audioOutput,
  96. videoInput
  97. });
  98. } else {
  99. // The labels are not available if the A/V permissions are
  100. // not yet granted.
  101. dispatch(addPendingDeviceRequest({
  102. type: 'devices',
  103. name: 'getCurrentDevices',
  104. responseCallback
  105. }));
  106. }
  107. });
  108. break;
  109. case 'getAvailableDevices':
  110. dispatch(getAvailableDevices()).then(devices => {
  111. if (areDeviceLabelsInitialized(state)) {
  112. responseCallback(groupDevicesByKind(devices));
  113. } else {
  114. // The labels are not available if the A/V permissions are
  115. // not yet granted.
  116. dispatch(addPendingDeviceRequest({
  117. type: 'devices',
  118. name: 'getAvailableDevices',
  119. responseCallback
  120. }));
  121. }
  122. });
  123. break;
  124. case 'setDevice': {
  125. const { device } = request;
  126. if (!conference) {
  127. dispatch(addPendingDeviceRequest({
  128. type: 'devices',
  129. name: 'setDevice',
  130. device,
  131. responseCallback
  132. }));
  133. return true;
  134. }
  135. const deviceId = getDeviceIdByLabel(state, device.label);
  136. if (deviceId) {
  137. switch (device.kind) {
  138. case 'audioinput': {
  139. dispatch(setAudioInputDevice(deviceId));
  140. break;
  141. }
  142. case 'audiooutput':
  143. setAudioOutputDeviceId(deviceId, dispatch);
  144. break;
  145. case 'videoinput':
  146. dispatch(setVideoInputDevice(deviceId));
  147. break;
  148. default:
  149. result = false;
  150. }
  151. } else {
  152. result = false;
  153. }
  154. responseCallback(result);
  155. break;
  156. }
  157. default:
  158. return false;
  159. }
  160. return true;
  161. }
  162. return false;
  163. }