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.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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'].availableDevices,
  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} - True if the request has been processed and false otherwise.
  51. */
  52. export function processExternalDeviceRequest( // eslint-disable-line max-params
  53. dispatch: Dispatch<any>,
  54. getState: Function,
  55. request: Object,
  56. responseCallback: Function) {
  57. if (request.type !== 'devices') {
  58. return false;
  59. }
  60. const state = getState();
  61. const settings = state['features/base/settings'];
  62. const { conference } = state['features/base/conference'];
  63. let result = true;
  64. switch (request.name) {
  65. case 'isDeviceListAvailable':
  66. responseCallback(JitsiMeetJS.mediaDevices.isDeviceListAvailable());
  67. break;
  68. case 'isDeviceChangeAvailable':
  69. responseCallback(
  70. JitsiMeetJS.mediaDevices.isDeviceChangeAvailable(
  71. request.deviceType));
  72. break;
  73. case 'isMultipleAudioInputSupported':
  74. responseCallback(JitsiMeetJS.isMultipleAudioInputSupported());
  75. break;
  76. case 'getCurrentDevices':
  77. dispatch(getAvailableDevices()).then(devices => {
  78. if (areDeviceLabelsInitialized(state)) {
  79. const deviceDescriptions = {
  80. audioInput: undefined,
  81. audioOutput: undefined,
  82. videoInput: undefined
  83. };
  84. const currentlyUsedDeviceIds = new Set([
  85. getAudioOutputDeviceId(),
  86. settings.micDeviceId,
  87. settings.cameraDeviceId
  88. ]);
  89. devices.forEach(device => {
  90. const { deviceId, kind } = device;
  91. if (currentlyUsedDeviceIds.has(deviceId)) {
  92. switch (kind) {
  93. case 'audioinput':
  94. deviceDescriptions.audioInput = device;
  95. break;
  96. case 'audiooutput':
  97. deviceDescriptions.audioOutput = device;
  98. break;
  99. case 'videoinput':
  100. deviceDescriptions.videoInput = device;
  101. break;
  102. }
  103. }
  104. });
  105. responseCallback(deviceDescriptions);
  106. } else {
  107. // The labels are not available if the A/V permissions are
  108. // not yet granted.
  109. dispatch(addPendingDeviceRequest({
  110. type: 'devices',
  111. name: 'getCurrentDevices',
  112. responseCallback
  113. }));
  114. }
  115. });
  116. break;
  117. case 'getAvailableDevices':
  118. dispatch(getAvailableDevices()).then(devices => {
  119. if (areDeviceLabelsInitialized(state)) {
  120. responseCallback(groupDevicesByKind(devices));
  121. } else {
  122. // The labels are not available if the A/V permissions are
  123. // not yet granted.
  124. dispatch(addPendingDeviceRequest({
  125. type: 'devices',
  126. name: 'getAvailableDevices',
  127. responseCallback
  128. }));
  129. }
  130. });
  131. break;
  132. case 'setDevice': {
  133. const { device } = request;
  134. if (!conference) {
  135. dispatch(addPendingDeviceRequest({
  136. type: 'devices',
  137. name: 'setDevice',
  138. device,
  139. responseCallback
  140. }));
  141. return true;
  142. }
  143. const { label, id } = device;
  144. const deviceId = label
  145. ? getDeviceIdByLabel(state, device.label, device.kind)
  146. : id;
  147. if (deviceId) {
  148. switch (device.kind) {
  149. case 'audioinput': {
  150. dispatch(setAudioInputDevice(deviceId));
  151. break;
  152. }
  153. case 'audiooutput':
  154. setAudioOutputDeviceId(deviceId, dispatch);
  155. break;
  156. case 'videoinput':
  157. dispatch(setVideoInputDevice(deviceId));
  158. break;
  159. default:
  160. result = false;
  161. }
  162. } else {
  163. result = false;
  164. }
  165. responseCallback(result);
  166. break;
  167. }
  168. default:
  169. return false;
  170. }
  171. return true;
  172. }