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 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import { _handleParticipantError } from '../base/conference';
  2. import { MEDIA_TYPE, VIDEO_TYPE } from '../base/media';
  3. import {
  4. getLocalVideoTrack,
  5. getTrackByMediaTypeAndParticipant
  6. } from '../base/tracks';
  7. import {
  8. SELECT_LARGE_VIDEO_PARTICIPANT,
  9. UPDATE_KNOWN_LARGE_VIDEO_RESOLUTION
  10. } from './actionTypes';
  11. /**
  12. * Signals conference to select a participant.
  13. *
  14. * @returns {Function}
  15. */
  16. export function selectParticipant() {
  17. return (dispatch, getState) => {
  18. const state = getState();
  19. const conference = state['features/base/conference'].conference;
  20. if (conference) {
  21. const largeVideo = state['features/large-video'];
  22. const tracks = state['features/base/tracks'];
  23. const id = largeVideo.participantId;
  24. const videoTrack
  25. = getTrackByMediaTypeAndParticipant(
  26. tracks,
  27. MEDIA_TYPE.VIDEO,
  28. id);
  29. try {
  30. conference.selectParticipant(
  31. videoTrack && videoTrack.videoType === VIDEO_TYPE.CAMERA
  32. ? id
  33. : null);
  34. } catch (err) {
  35. _handleParticipantError(err);
  36. }
  37. }
  38. };
  39. }
  40. /**
  41. * Action to select the participant to be displayed in LargeVideo based on a
  42. * variety of factors: if there is a dominant or pinned speaker, or if there are
  43. * remote tracks, etc.
  44. *
  45. * @returns {Function}
  46. */
  47. export function selectParticipantInLargeVideo() {
  48. return (dispatch, getState) => {
  49. const state = getState();
  50. const participantId = _electParticipantInLargeVideo(state);
  51. const largeVideo = state['features/large-video'];
  52. if (participantId !== largeVideo.participantId) {
  53. dispatch({
  54. type: SELECT_LARGE_VIDEO_PARTICIPANT,
  55. participantId
  56. });
  57. dispatch(selectParticipant());
  58. }
  59. };
  60. }
  61. /**
  62. * Updates the currently seen resolution of the video displayed on large video.
  63. *
  64. * @param {number} resolution - The current resolution (height) of the video.
  65. * @returns {{
  66. * type: UPDATE_KNOWN_LARGE_VIDEO_RESOLUTION,
  67. * resolution: number
  68. * }}
  69. */
  70. export function updateKnownLargeVideoResolution(resolution) {
  71. return {
  72. type: UPDATE_KNOWN_LARGE_VIDEO_RESOLUTION,
  73. resolution
  74. };
  75. }
  76. /**
  77. * Returns the most recent existing video track. It can be local or remote
  78. * video.
  79. *
  80. * @param {Track[]} tracks - All current tracks.
  81. * @private
  82. * @returns {(Track|undefined)}
  83. */
  84. function _electLastVisibleVideo(tracks) {
  85. // First we try to get most recent remote video track.
  86. for (let i = tracks.length - 1; i >= 0; --i) {
  87. const track = tracks[i];
  88. if (!track.local && track.mediaType === MEDIA_TYPE.VIDEO) {
  89. return track;
  90. }
  91. }
  92. // And if no remote video tracks are available, we select the local one.
  93. return getLocalVideoTrack(tracks);
  94. }
  95. /**
  96. * Returns the identifier of the participant who is to be on the stage i.e.
  97. * should be displayed in {@code LargeVideo}.
  98. *
  99. * @param {Object} state - The Redux state from which the participant to be
  100. * displayed in {@code LargeVideo} is to be elected.
  101. * @private
  102. * @returns {(string|undefined)}
  103. */
  104. function _electParticipantInLargeVideo(state) {
  105. // First get the pinned participant. If the local participant is pinned,
  106. // he/she will be shown in LargeVideo.
  107. const participants = state['features/base/participants'];
  108. let participant = participants.find(p => p.pinned);
  109. let id = participant ? participant.id : undefined;
  110. if (!id) {
  111. // No participant is pinned so get the dominant speaker. But the local
  112. // participant won't be displayed in LargeVideo even if he/she is the
  113. // dominant speaker.
  114. participant = participants.find(p => p.dominantSpeaker && !p.local);
  115. if (participant) {
  116. id = participant.id;
  117. }
  118. if (!id) {
  119. // There is no dominant speaker so get the participant with the last
  120. // visible video track. This may turn out to be the local
  121. // participant.
  122. const tracks = state['features/base/tracks'];
  123. const videoTrack = _electLastVisibleVideo(tracks);
  124. id = videoTrack && videoTrack.participantId;
  125. }
  126. }
  127. return id;
  128. }