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

AudioOutputPreview.js 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /* @flow */
  2. import React, { Component } from 'react';
  3. import { translate } from '../../base/i18n/functions';
  4. import Audio from '../../base/media/components/Audio';
  5. const TEST_SOUND_PATH = 'sounds/ring.wav';
  6. /**
  7. * The type of the React {@code Component} props of {@link AudioOutputPreview}.
  8. */
  9. type Props = {
  10. /**
  11. * The device id of the audio output device to use.
  12. */
  13. deviceId: string,
  14. /**
  15. * Invoked to obtain translated strings.
  16. */
  17. t: Function
  18. };
  19. /**
  20. * React component for playing a test sound through a specified audio device.
  21. *
  22. * @extends Component
  23. */
  24. class AudioOutputPreview extends Component<Props> {
  25. _audioElement: ?Object;
  26. /**
  27. * Initializes a new AudioOutputPreview instance.
  28. *
  29. * @param {Object} props - The read-only React Component props with which
  30. * the new instance is to be initialized.
  31. */
  32. constructor(props: Props) {
  33. super(props);
  34. this._audioElement = null;
  35. this._audioElementReady = this._audioElementReady.bind(this);
  36. this._onClick = this._onClick.bind(this);
  37. this._onKeyPress = this._onKeyPress.bind(this);
  38. }
  39. /**
  40. * Updates the audio element when the target output device changes and the
  41. * audio element has re-rendered.
  42. *
  43. * @inheritdoc
  44. * @returns {void}
  45. */
  46. componentDidUpdate() {
  47. this._setAudioSink();
  48. }
  49. /**
  50. * Implements React's {@link Component#render()}.
  51. *
  52. * @inheritdoc
  53. * @returns {ReactElement}
  54. */
  55. render() {
  56. return (
  57. <div className = 'audio-output-preview'>
  58. <a
  59. aria-label = { this.props.t('deviceSelection.testAudio') }
  60. onClick = { this._onClick }
  61. onKeyPress = { this._onKeyPress }
  62. role = 'button'
  63. tabIndex = { 0 }>
  64. { this.props.t('deviceSelection.testAudio') }
  65. </a>
  66. <Audio
  67. setRef = { this._audioElementReady }
  68. src = { TEST_SOUND_PATH } />
  69. </div>
  70. );
  71. }
  72. _audioElementReady: (Object) => void;
  73. /**
  74. * Sets the instance variable for the component's audio element so it can be
  75. * accessed directly.
  76. *
  77. * @param {Object} element - The DOM element for the component's audio.
  78. * @private
  79. * @returns {void}
  80. */
  81. _audioElementReady(element: Object) {
  82. this._audioElement = element;
  83. this._setAudioSink();
  84. }
  85. _onClick: () => void;
  86. /**
  87. * Plays a test sound.
  88. *
  89. * @private
  90. * @returns {void}
  91. */
  92. _onClick() {
  93. this._audioElement
  94. && this._audioElement.play();
  95. }
  96. _onKeyPress: (Object) => void;
  97. /**
  98. * KeyPress handler for accessibility.
  99. *
  100. * @param {Object} e - The key event to handle.
  101. *
  102. * @returns {void}
  103. */
  104. _onKeyPress(e) {
  105. if (e.key === ' ' || e.key === 'Enter') {
  106. e.preventDefault();
  107. this._onClick();
  108. }
  109. }
  110. /**
  111. * Updates the target output device for playing the test sound.
  112. *
  113. * @private
  114. * @returns {void}
  115. */
  116. _setAudioSink() {
  117. this._audioElement
  118. && this.props.deviceId
  119. && this._audioElement.setSinkId(this.props.deviceId);
  120. }
  121. }
  122. export default translate(AudioOutputPreview);