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

middleware.js 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /* @flow */
  2. import {
  3. createRecordingEvent,
  4. sendAnalytics
  5. } from '../analytics';
  6. import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
  7. import { CONFERENCE_WILL_JOIN, getCurrentConference } from '../base/conference';
  8. import JitsiMeetJS, {
  9. JitsiConferenceEvents,
  10. JitsiRecordingConstants
  11. } from '../base/lib-jitsi-meet';
  12. import { getParticipantDisplayName } from '../base/participants';
  13. import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
  14. import {
  15. playSound,
  16. registerSound,
  17. stopSound,
  18. unregisterSound
  19. } from '../base/sounds';
  20. import {
  21. clearRecordingSessions,
  22. hidePendingRecordingNotification,
  23. showPendingRecordingNotification,
  24. showRecordingError,
  25. showStartedRecordingNotification,
  26. showStoppedRecordingNotification,
  27. updateRecordingSessionData
  28. } from './actions';
  29. import { RECORDING_SESSION_UPDATED } from './actionTypes';
  30. import {
  31. LIVE_STREAMING_OFF_SOUND_ID,
  32. LIVE_STREAMING_ON_SOUND_ID,
  33. RECORDING_OFF_SOUND_ID,
  34. RECORDING_ON_SOUND_ID
  35. } from './constants';
  36. import { getSessionById } from './functions';
  37. import {
  38. LIVE_STREAMING_OFF_SOUND_FILE,
  39. LIVE_STREAMING_ON_SOUND_FILE,
  40. RECORDING_OFF_SOUND_FILE,
  41. RECORDING_ON_SOUND_FILE
  42. } from './sounds';
  43. /**
  44. * StateListenerRegistry provides a reliable way to detect the leaving of a
  45. * conference, where we need to clean up the recording sessions.
  46. */
  47. StateListenerRegistry.register(
  48. /* selector */ state => getCurrentConference(state),
  49. /* listener */ (conference, { dispatch }) => {
  50. if (!conference) {
  51. dispatch(clearRecordingSessions());
  52. }
  53. }
  54. );
  55. /**
  56. * The redux middleware to handle the recorder updates in a React way.
  57. *
  58. * @param {Store} store - The redux store.
  59. * @returns {Function}
  60. */
  61. MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
  62. let oldSessionData;
  63. if (action.type === RECORDING_SESSION_UPDATED) {
  64. oldSessionData
  65. = getSessionById(getState(), action.sessionData.id);
  66. }
  67. const result = next(action);
  68. switch (action.type) {
  69. case APP_WILL_MOUNT:
  70. dispatch(registerSound(
  71. LIVE_STREAMING_OFF_SOUND_ID,
  72. LIVE_STREAMING_OFF_SOUND_FILE));
  73. dispatch(registerSound(
  74. LIVE_STREAMING_ON_SOUND_ID,
  75. LIVE_STREAMING_ON_SOUND_FILE));
  76. dispatch(registerSound(
  77. RECORDING_OFF_SOUND_ID,
  78. RECORDING_OFF_SOUND_FILE));
  79. dispatch(registerSound(
  80. RECORDING_ON_SOUND_ID,
  81. RECORDING_ON_SOUND_FILE));
  82. break;
  83. case APP_WILL_UNMOUNT:
  84. dispatch(unregisterSound(LIVE_STREAMING_OFF_SOUND_ID));
  85. dispatch(unregisterSound(LIVE_STREAMING_ON_SOUND_ID));
  86. dispatch(unregisterSound(RECORDING_OFF_SOUND_ID));
  87. dispatch(unregisterSound(RECORDING_ON_SOUND_ID));
  88. break;
  89. case CONFERENCE_WILL_JOIN: {
  90. const { conference } = action;
  91. conference.on(
  92. JitsiConferenceEvents.RECORDER_STATE_CHANGED,
  93. recorderSession => {
  94. if (recorderSession) {
  95. recorderSession.getID()
  96. && dispatch(
  97. updateRecordingSessionData(recorderSession));
  98. recorderSession.getError()
  99. && _showRecordingErrorNotification(
  100. recorderSession, dispatch);
  101. }
  102. return;
  103. });
  104. break;
  105. }
  106. case RECORDING_SESSION_UPDATED: {
  107. // When in recorder mode no notifications are shown
  108. // or extra sounds are also not desired
  109. if (getState()['features/base/config'].iAmRecorder) {
  110. break;
  111. }
  112. const updatedSessionData
  113. = getSessionById(getState(), action.sessionData.id);
  114. const { initiator, mode, terminator } = updatedSessionData;
  115. const { PENDING, OFF, ON } = JitsiRecordingConstants.status;
  116. if (updatedSessionData.status === PENDING
  117. && (!oldSessionData || oldSessionData.status !== PENDING)) {
  118. dispatch(showPendingRecordingNotification(mode));
  119. } else if (updatedSessionData.status !== PENDING) {
  120. dispatch(hidePendingRecordingNotification(mode));
  121. if (updatedSessionData.status === ON
  122. && (!oldSessionData || oldSessionData.status !== ON)) {
  123. const initiatorName = initiator && getParticipantDisplayName(getState, initiator.getId());
  124. initiatorName && dispatch(showStartedRecordingNotification(mode, initiatorName));
  125. let soundID;
  126. if (mode === JitsiRecordingConstants.mode.FILE) {
  127. soundID = RECORDING_ON_SOUND_ID;
  128. } else if (mode === JitsiRecordingConstants.mode.STREAM) {
  129. soundID = LIVE_STREAMING_ON_SOUND_ID;
  130. }
  131. if (soundID) {
  132. sendAnalytics(createRecordingEvent('start', mode));
  133. dispatch(playSound(soundID));
  134. }
  135. } else if (updatedSessionData.status === OFF
  136. && (!oldSessionData || oldSessionData.status !== OFF)) {
  137. dispatch(showStoppedRecordingNotification(
  138. mode, terminator && getParticipantDisplayName(getState, terminator.getId())));
  139. let duration = 0, soundOff, soundOn;
  140. if (oldSessionData && oldSessionData.timestamp) {
  141. duration
  142. = (Date.now() / 1000) - oldSessionData.timestamp;
  143. }
  144. if (mode === JitsiRecordingConstants.mode.FILE) {
  145. soundOff = RECORDING_OFF_SOUND_ID;
  146. soundOn = RECORDING_ON_SOUND_ID;
  147. } else if (mode === JitsiRecordingConstants.mode.STREAM) {
  148. soundOff = LIVE_STREAMING_OFF_SOUND_ID;
  149. soundOn = LIVE_STREAMING_ON_SOUND_ID;
  150. }
  151. if (soundOff && soundOn) {
  152. sendAnalytics(createRecordingEvent('stop', mode, duration));
  153. dispatch(stopSound(soundOn));
  154. dispatch(playSound(soundOff));
  155. }
  156. }
  157. }
  158. break;
  159. }
  160. }
  161. return result;
  162. });
  163. /**
  164. * Shows a notification about an error in the recording session. A
  165. * default notification will display if no error is specified in the passed
  166. * in recording session.
  167. *
  168. * @private
  169. * @param {Object} recorderSession - The recorder session model from the
  170. * lib.
  171. * @param {Dispatch} dispatch - The Redux Dispatch function.
  172. * @returns {void}
  173. */
  174. function _showRecordingErrorNotification(recorderSession, dispatch) {
  175. const isStreamMode
  176. = recorderSession.getMode()
  177. === JitsiMeetJS.constants.recording.mode.STREAM;
  178. switch (recorderSession.getError()) {
  179. case JitsiMeetJS.constants.recording.error.SERVICE_UNAVAILABLE:
  180. dispatch(showRecordingError({
  181. descriptionKey: 'recording.unavailable',
  182. descriptionArguments: {
  183. serviceName: isStreamMode
  184. ? '$t(liveStreaming.serviceName)'
  185. : '$t(recording.serviceName)'
  186. },
  187. titleKey: isStreamMode
  188. ? 'liveStreaming.unavailableTitle'
  189. : 'recording.unavailableTitle'
  190. }));
  191. break;
  192. case JitsiMeetJS.constants.recording.error.RESOURCE_CONSTRAINT:
  193. dispatch(showRecordingError({
  194. descriptionKey: isStreamMode
  195. ? 'liveStreaming.busy'
  196. : 'recording.busy',
  197. titleKey: isStreamMode
  198. ? 'liveStreaming.busyTitle'
  199. : 'recording.busyTitle'
  200. }));
  201. break;
  202. default:
  203. dispatch(showRecordingError({
  204. descriptionKey: isStreamMode
  205. ? 'liveStreaming.error'
  206. : 'recording.error',
  207. titleKey: isStreamMode
  208. ? 'liveStreaming.failedToStart'
  209. : 'recording.failedToStart'
  210. }));
  211. break;
  212. }
  213. }