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.

Audio.ts 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import Sound from 'react-native-sound';
  2. import logger from '../../logger';
  3. import AbstractAudio, { IProps } from '../AbstractAudio';
  4. /**
  5. * The React Native/mobile {@link Component} which is similar to Web's
  6. * {@code HTMLAudioElement} and wraps around react-native-webrtc's
  7. * {@link RTCView}.
  8. */
  9. export default class Audio extends AbstractAudio {
  10. /**
  11. * Reference to 'react-native-sound} {@link Sound} instance.
  12. */
  13. _sound: Sound | undefined | null;
  14. /**
  15. * A callback passed to the 'react-native-sound''s {@link Sound} instance,
  16. * called when loading sound is finished.
  17. *
  18. * @param {Object} error - The error object passed by
  19. * the 'react-native-sound' library.
  20. * @returns {void}
  21. * @private
  22. */
  23. _soundLoadedCallback(error: Error) {
  24. if (error) {
  25. logger.error('Failed to load sound', error);
  26. } else {
  27. this.setAudioElementImpl(this._sound);
  28. }
  29. }
  30. /**
  31. * Implements React's {@link Component#componentDidUpdate()}.
  32. *
  33. * @inheritdoc
  34. */
  35. async componentDidUpdate(prevProps: IProps): Promise<void> {
  36. // source is different !! call didunmount and call didmount
  37. if (prevProps.src !== this.props.src) {
  38. await this.componentWillUnmount();
  39. await this.componentDidMount();
  40. }
  41. }
  42. /**
  43. * Will load the sound, after the component did mount.
  44. *
  45. * @returns {void}
  46. */
  47. async componentDidMount() {
  48. this._sound
  49. = this.props.src
  50. ? new Sound(
  51. this.props.src, undefined,
  52. this._soundLoadedCallback.bind(this))
  53. : null;
  54. }
  55. /**
  56. * Will dispose sound resources (if any) when component is about to unmount.
  57. *
  58. * @returns {void}
  59. */
  60. async componentWillUnmount() {
  61. if (this._sound) {
  62. this._sound.release();
  63. this._sound = null;
  64. this.setAudioElementImpl(null);
  65. }
  66. }
  67. /**
  68. * Attempts to begin the playback of the media.
  69. *
  70. * @inheritdoc
  71. * @override
  72. */
  73. play() {
  74. if (this._sound) {
  75. this._sound.setNumberOfLoops(this.props.loop ? -1 : 0);
  76. this._sound.play(success => {
  77. if (!success) {
  78. logger.warn(`Failed to play ${this.props.src}`);
  79. }
  80. });
  81. }
  82. }
  83. /**
  84. * Implements React's {@link Component#render()}.
  85. *
  86. * @inheritdoc
  87. * @returns {null}
  88. */
  89. render() {
  90. // TODO react-native-webrtc's RTCView doesn't do anything with the audio
  91. // MediaStream specified to it so it's easier at the time of this
  92. // writing to not render anything.
  93. return null;
  94. }
  95. /**
  96. * Stops the sound if it's currently playing.
  97. *
  98. * @returns {void}
  99. */
  100. stop() {
  101. if (this._sound) {
  102. this._sound.stop();
  103. }
  104. }
  105. }