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

middleware.js 7.5KB

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