您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

functions.js 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /* global APP */
  2. import JitsiMeetJS, { JitsiTrackErrors, JitsiTrackEvents }
  3. from '../lib-jitsi-meet';
  4. import { MEDIA_TYPE } from '../media';
  5. const logger = require('jitsi-meet-logger').getLogger(__filename);
  6. /**
  7. * Create local tracks of specific types.
  8. *
  9. * @param {Object} options - The options with which the local tracks are to be
  10. * created.
  11. * @param {string|null} [options.cameraDeviceId] - Camera device id or
  12. * {@code undefined} to use app's settings.
  13. * @param {string[]} options.devices - Required track types such as 'audio'
  14. * and/or 'video'.
  15. * @param {string|null} [options.micDeviceId] - Microphone device id or
  16. * {@code undefined} to use app's settings.
  17. * @param {boolean} [firePermissionPromptIsShownEvent] - Whether lib-jitsi-meet
  18. * should check for a {@code getUserMedia} permission prompt and fire a
  19. * corresponding event.
  20. * @param {Object} store - The redux store in the context of which the function
  21. * is to execute and from which state such as {@code config} is to be retrieved.
  22. * @returns {Promise<JitsiLocalTrack[]>}
  23. */
  24. export function createLocalTracksF(
  25. options,
  26. firePermissionPromptIsShownEvent,
  27. store) {
  28. options || (options = {}); // eslint-disable-line no-param-reassign
  29. let { cameraDeviceId, micDeviceId } = options;
  30. if (typeof APP !== 'undefined') {
  31. // TODO The app's settings should go in the redux store and then the
  32. // reliance on the global variable APP will go away.
  33. if (typeof cameraDeviceId === 'undefined' || cameraDeviceId === null) {
  34. cameraDeviceId = APP.settings.getCameraDeviceId();
  35. }
  36. if (typeof micDeviceId === 'undefined' || micDeviceId === null) {
  37. micDeviceId = APP.settings.getMicDeviceId();
  38. }
  39. store || (store = APP.store); // eslint-disable-line no-param-reassign
  40. }
  41. const {
  42. constraints,
  43. firefox_fake_device, // eslint-disable-line camelcase
  44. resolution
  45. } = store.getState()['features/base/config'];
  46. return (
  47. JitsiMeetJS.createLocalTracks(
  48. {
  49. cameraDeviceId,
  50. constraints,
  51. desktopSharingExtensionExternalInstallation:
  52. options.desktopSharingExtensionExternalInstallation,
  53. desktopSharingSources: options.desktopSharingSources,
  54. // Copy array to avoid mutations inside library.
  55. devices: options.devices.slice(0),
  56. firefox_fake_device, // eslint-disable-line camelcase
  57. micDeviceId,
  58. resolution
  59. },
  60. firePermissionPromptIsShownEvent)
  61. .then(tracks => {
  62. // TODO JitsiTrackEvents.NO_DATA_FROM_SOURCE should probably be
  63. // dispatched in the redux store here and then
  64. // APP.UI.showTrackNotWorkingDialog should be in a middleware
  65. // somewhere else.
  66. if (typeof APP !== 'undefined') {
  67. tracks.forEach(track =>
  68. track.on(
  69. JitsiTrackEvents.NO_DATA_FROM_SOURCE,
  70. APP.UI.showTrackNotWorkingDialog.bind(
  71. null, track.isAudioTrack())));
  72. }
  73. return tracks;
  74. })
  75. .catch(err => {
  76. logger.error('Failed to create local tracks', options.devices, err);
  77. return Promise.reject(err);
  78. }));
  79. }
  80. /**
  81. * Returns local audio track.
  82. *
  83. * @param {Track[]} tracks - List of all tracks.
  84. * @returns {(Track|undefined)}
  85. */
  86. export function getLocalAudioTrack(tracks) {
  87. return getLocalTrack(tracks, MEDIA_TYPE.AUDIO);
  88. }
  89. /**
  90. * Returns local track by media type.
  91. *
  92. * @param {Track[]} tracks - List of all tracks.
  93. * @param {MEDIA_TYPE} mediaType - Media type.
  94. * @returns {(Track|undefined)}
  95. */
  96. export function getLocalTrack(tracks, mediaType) {
  97. return getLocalTracks(tracks).find(t => t.mediaType === mediaType);
  98. }
  99. /**
  100. * Returns an array containing the local tracks with a (valid)
  101. * {@code JitsiTrack}.
  102. *
  103. * @param {Track[]} tracks - An array containing all local tracks.
  104. * @returns {Track[]}
  105. */
  106. export function getLocalTracks(tracks) {
  107. // XXX A local track is considered ready only once it has its `jitsiTrack`
  108. // property set by the `TRACK_ADDED` action. Until then there is a stub
  109. // added just before the `getUserMedia` call with a cancellable
  110. // `gumInProgress` property which then can be used to destroy the track that
  111. // has not yet been added to the redux store. Once GUM is cancelled, it will
  112. // never make it to the store nor there will be any
  113. // `TRACK_ADDED`/`TRACK_REMOVED` actions dispatched for it.
  114. return tracks.filter(t => t.local && t.jitsiTrack);
  115. }
  116. /**
  117. * Returns local video track.
  118. *
  119. * @param {Track[]} tracks - List of all tracks.
  120. * @returns {(Track|undefined)}
  121. */
  122. export function getLocalVideoTrack(tracks) {
  123. return getLocalTrack(tracks, MEDIA_TYPE.VIDEO);
  124. }
  125. /**
  126. * Returns track of specified media type for specified participant id.
  127. *
  128. * @param {Track[]} tracks - List of all tracks.
  129. * @param {MEDIA_TYPE} mediaType - Media type.
  130. * @param {string} participantId - Participant ID.
  131. * @returns {(Track|undefined)}
  132. */
  133. export function getTrackByMediaTypeAndParticipant(
  134. tracks,
  135. mediaType,
  136. participantId) {
  137. return tracks.find(
  138. t => t.participantId === participantId && t.mediaType === mediaType
  139. );
  140. }
  141. /**
  142. * Returns the track if any which corresponds to a specific instance
  143. * of JitsiLocalTrack or JitsiRemoteTrack.
  144. *
  145. * @param {Track[]} tracks - List of all tracks.
  146. * @param {(JitsiLocalTrack|JitsiRemoteTrack)} jitsiTrack - JitsiTrack instance.
  147. * @returns {(Track|undefined)}
  148. */
  149. export function getTrackByJitsiTrack(tracks, jitsiTrack) {
  150. return tracks.find(t => t.jitsiTrack === jitsiTrack);
  151. }
  152. /**
  153. * Returns tracks of specified media type.
  154. *
  155. * @param {Track[]} tracks - List of all tracks.
  156. * @param {MEDIA_TYPE} mediaType - Media type.
  157. * @returns {Track[]}
  158. */
  159. export function getTracksByMediaType(tracks, mediaType) {
  160. return tracks.filter(t => t.mediaType === mediaType);
  161. }
  162. /**
  163. * Checks if the first local track in the given tracks set is muted.
  164. *
  165. * @param {Track[]} tracks - List of all tracks.
  166. * @param {MEDIA_TYPE} mediaType - The media type of tracks to be checked.
  167. * @returns {boolean} True if local track is muted or false if the track is
  168. * unmuted or if there are no local tracks of the given media type in the given
  169. * set of tracks.
  170. */
  171. export function isLocalTrackMuted(tracks, mediaType) {
  172. const track = getLocalTrack(tracks, mediaType);
  173. return !track || track.muted;
  174. }
  175. /**
  176. * Mutes or unmutes a specific {@code JitsiLocalTrack}. If the muted state of
  177. * the specified {@code track} is already in accord with the specified
  178. * {@code muted} value, then does nothing.
  179. *
  180. * @param {JitsiLocalTrack} track - The {@code JitsiLocalTrack} to mute or
  181. * unmute.
  182. * @param {boolean} muted - If the specified {@code track} is to be muted, then
  183. * {@code true}; otherwise, {@code false}.
  184. * @returns {Promise}
  185. */
  186. export function setTrackMuted(track, muted) {
  187. muted = Boolean(muted); // eslint-disable-line no-param-reassign
  188. if (track.isMuted() === muted) {
  189. return Promise.resolve();
  190. }
  191. const f = muted ? 'mute' : 'unmute';
  192. return track[f]().catch(error => {
  193. // Track might be already disposed so ignore such an error.
  194. if (error.name !== JitsiTrackErrors.TRACK_IS_DISPOSED) {
  195. // FIXME Emit mute failed, so that the app can show error dialog.
  196. console.error(`set track ${f} failed`, error);
  197. }
  198. });
  199. }