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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // @flow
  2. import type { AudioElement } from '../media';
  3. import { assign, ReducerRegistry } from '../redux';
  4. import {
  5. _ADD_AUDIO_ELEMENT,
  6. _REMOVE_AUDIO_ELEMENT,
  7. REGISTER_SOUND,
  8. UNREGISTER_SOUND
  9. } from './actionTypes';
  10. const logger = require('jitsi-meet-logger').getLogger(__filename);
  11. /**
  12. * The structure use by this reducer to describe a sound.
  13. */
  14. export type Sound = {
  15. /**
  16. * The HTMLAudioElement which implements the audio playback functionality.
  17. * Becomes available once the sound resource gets loaded and the sound can
  18. * not be played until that happens.
  19. */
  20. audioElement?: AudioElement,
  21. /**
  22. * This field describes the source of the audio resource to be played. It
  23. * can be either a path to the file or an object depending on the platform
  24. * (native vs web).
  25. */
  26. src: Object | string
  27. }
  28. /**
  29. * Initial/default state of the feature {@code base/sounds}. It is a {@code Map}
  30. * of globally stored sounds.
  31. *
  32. * @type {Map<string, Sound>}
  33. */
  34. const DEFAULT_STATE = new Map();
  35. /**
  36. * The base/sounds feature's reducer.
  37. */
  38. ReducerRegistry.register(
  39. 'features/base/sounds',
  40. (state = DEFAULT_STATE, action) => {
  41. switch (action.type) {
  42. case _ADD_AUDIO_ELEMENT:
  43. case _REMOVE_AUDIO_ELEMENT:
  44. return _addOrRemoveAudioElement(state, action);
  45. case REGISTER_SOUND:
  46. return _registerSound(state, action);
  47. case UNREGISTER_SOUND:
  48. return _unregisterSound(state, action);
  49. default:
  50. return state;
  51. }
  52. });
  53. /**
  54. * Adds or removes {@link AudioElement} associated with a {@link Sound}.
  55. *
  56. * @param {Map<string, Sound>} state - The current Redux state of this feature.
  57. * @param {_ADD_AUDIO_ELEMENT | _REMOVE_AUDIO_ELEMENT} action - The action to be
  58. * handled.
  59. * @private
  60. * @returns {Map<string, Sound>}
  61. */
  62. function _addOrRemoveAudioElement(state, action) {
  63. const isAddAction = action.type === _ADD_AUDIO_ELEMENT;
  64. const nextState = new Map(state);
  65. const { soundId } = action;
  66. const sound = nextState.get(soundId);
  67. if (sound) {
  68. if (isAddAction) {
  69. nextState.set(soundId,
  70. assign(sound, {
  71. audioElement: action.audioElement
  72. }));
  73. } else {
  74. nextState.set(soundId,
  75. assign(sound, {
  76. audioElement: undefined
  77. }));
  78. }
  79. } else {
  80. const actionName
  81. = isAddAction ? '_ADD_AUDIO_ELEMENT' : '_REMOVE_AUDIO_ELEMENT';
  82. logger.error(`${actionName}: no sound for id: ${soundId}`);
  83. }
  84. return nextState;
  85. }
  86. /**
  87. * Registers a new {@link Sound} for given id and source. It will make
  88. * the {@link SoundCollection} component render HTMLAudioElement for given
  89. * source making it available for playback through the redux actions.
  90. *
  91. * @param {Map<string, Sound>} state - The current Redux state of the sounds
  92. * features.
  93. * @param {REGISTER_SOUND} action - The register sound action.
  94. * @private
  95. * @returns {Map<string, Sound>}
  96. */
  97. function _registerSound(state, action) {
  98. const nextState = new Map(state);
  99. nextState.set(action.soundId, {
  100. src: action.src
  101. });
  102. return nextState;
  103. }
  104. /**
  105. * Unregisters a {@link Sound} which will make the {@link SoundCollection}
  106. * component stop rendering the corresponding HTMLAudioElement. This will
  107. * result further in the audio resource disposal.
  108. *
  109. * @param {Map<string, Sound>} state - The current Redux state of this feature.
  110. * @param {UNREGISTER_SOUND} action - The unregister sound action.
  111. * @private
  112. * @returns {Map<string, Sound>}
  113. */
  114. function _unregisterSound(state, action) {
  115. const nextState = new Map(state);
  116. nextState.delete(action.soundId);
  117. return nextState;
  118. }