Source: ui/volume_bar.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.ui.VolumeBar');
  7. goog.require('goog.asserts');
  8. goog.require('shaka.ads.Utils');
  9. goog.require('shaka.ui.Controls');
  10. goog.require('shaka.ui.Locales');
  11. goog.require('shaka.ui.Localization');
  12. goog.require('shaka.ui.RangeElement');
  13. goog.require('shaka.ui.Utils');
  14. /**
  15. * @extends {shaka.ui.RangeElement}
  16. * @final
  17. * @export
  18. */
  19. shaka.ui.VolumeBar = class extends shaka.ui.RangeElement {
  20. /**
  21. * @param {!HTMLElement} parent
  22. * @param {!shaka.ui.Controls} controls
  23. */
  24. constructor(parent, controls) {
  25. super(parent, controls,
  26. ['shaka-volume-bar-container'], ['shaka-volume-bar']);
  27. /** @private {!shaka.extern.UIConfiguration} */
  28. this.config_ = this.controls.getConfig();
  29. // We use a range of 100 to avoid problems with Firefox.
  30. // See https://github.com/shaka-project/shaka-player/issues/3987
  31. this.setRange(0, 100);
  32. this.eventManager.listen(this.video,
  33. 'volumechange',
  34. () => this.onPresentationVolumeChange_());
  35. this.eventManager.listen(this.player,
  36. 'loading',
  37. () => this.onPresentationVolumeChange_());
  38. this.eventManager.listen(this.player,
  39. 'loaded',
  40. () => this.checkAvailability_());
  41. this.eventManager.listen(this.player,
  42. 'unloading',
  43. () => this.checkAvailability_());
  44. this.eventManager.listen(this.player,
  45. 'trackschanged',
  46. () => this.checkAvailability_());
  47. this.eventManager.listen(this.controls,
  48. 'caststatuschanged',
  49. () => this.onPresentationVolumeChange_());
  50. this.eventManager.listen(this.adManager,
  51. shaka.ads.Utils.AD_VOLUME_CHANGED,
  52. () => this.onAdVolumeChange_());
  53. this.eventManager.listen(this.adManager,
  54. shaka.ads.Utils.AD_MUTED,
  55. () => this.onAdVolumeChange_());
  56. this.eventManager.listen(this.adManager,
  57. shaka.ads.Utils.AD_STARTED,
  58. () => this.checkAvailability_());
  59. this.eventManager.listen(this.adManager,
  60. shaka.ads.Utils.AD_STOPPED, () => {
  61. this.checkAvailability_();
  62. this.onPresentationVolumeChange_();
  63. });
  64. this.eventManager.listen(this.localization,
  65. shaka.ui.Localization.LOCALE_UPDATED,
  66. () => this.updateAriaLabel_());
  67. this.eventManager.listen(this.localization,
  68. shaka.ui.Localization.LOCALE_CHANGED,
  69. () => this.updateAriaLabel_());
  70. // Initialize volume display and label.
  71. this.onPresentationVolumeChange_();
  72. this.updateAriaLabel_();
  73. if (this.ad) {
  74. // There was already an ad.
  75. this.onChange();
  76. }
  77. this.checkAvailability_();
  78. }
  79. /**
  80. * Update the video element's state to match the input element's state.
  81. * Called by the base class when the input element changes.
  82. *
  83. * @override
  84. */
  85. onChange() {
  86. if (this.ad && this.ad.isLinear()) {
  87. this.ad.setVolume(this.getValue() / 100);
  88. } else {
  89. this.video.volume = this.getValue() / 100;
  90. if (this.video.volume > 0) {
  91. this.video.muted = false;
  92. }
  93. }
  94. }
  95. /** @private */
  96. onPresentationVolumeChange_() {
  97. if (this.video.muted) {
  98. this.setValue(0);
  99. } else {
  100. this.setValue(this.video.volume * 100);
  101. }
  102. this.updateColors_();
  103. }
  104. /** @private */
  105. onAdVolumeChange_() {
  106. goog.asserts.assert(this.ad != null,
  107. 'This.ad should exist at this point!');
  108. const volume = this.ad.getVolume();
  109. this.setValue(volume * 100);
  110. this.updateColors_();
  111. }
  112. /** @private */
  113. updateColors_() {
  114. const colors = this.config_.volumeBarColors;
  115. const gradient = ['to right'];
  116. gradient.push(colors.level + this.getValue() + '%');
  117. gradient.push(colors.base + this.getValue() + '%');
  118. gradient.push(colors.base + '100%');
  119. this.container.style.background =
  120. 'linear-gradient(' + gradient.join(',') + ')';
  121. }
  122. /** @private */
  123. updateAriaLabel_() {
  124. this.bar.ariaLabel = this.localization.resolve(shaka.ui.Locales.Ids.VOLUME);
  125. }
  126. /** @private */
  127. checkAvailability_() {
  128. let available = true;
  129. if (this.ad && this.ad.isLinear()) {
  130. // We can't tell if the Ad has audio or not.
  131. available = true;
  132. } else if (this.player.isVideoOnly()) {
  133. available = false;
  134. }
  135. shaka.ui.Utils.setDisplay(this.container, available);
  136. }
  137. };
  138. /**
  139. * @implements {shaka.extern.IUIElement.Factory}
  140. * @final
  141. */
  142. shaka.ui.VolumeBar.Factory = class {
  143. /** @override */
  144. create(rootElement, controls) {
  145. return new shaka.ui.VolumeBar(rootElement, controls);
  146. }
  147. };
  148. shaka.ui.Controls.registerElement('volume', new shaka.ui.VolumeBar.Factory());