Source: lib/ads/client_side_ad.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.ads.ClientSideAd');
  7. goog.require('shaka.util.EventManager');
  8. /**
  9. * @implements {shaka.extern.IAd}
  10. * @export
  11. */
  12. shaka.ads.ClientSideAd = class {
  13. /**
  14. * @param {!google.ima.Ad} imaAd
  15. * @param {!google.ima.AdsManager} imaAdManager
  16. * @param {HTMLMediaElement} video
  17. */
  18. constructor(imaAd, imaAdManager, video) {
  19. /** @private {google.ima.Ad} */
  20. this.ad_ = imaAd;
  21. /** @private {google.ima.AdsManager} */
  22. this.manager_ = imaAdManager;
  23. /** @private {HTMLMediaElement} */
  24. this.video_ = video;
  25. /** @private {boolean} */
  26. this.isPaused_ = false;
  27. /** @private {number} */
  28. this.volume_ = this.manager_.getVolume();
  29. /** @private {shaka.util.EventManager} */
  30. this.eventManager_ = new shaka.util.EventManager();
  31. this.eventManager_.listen(this.manager_,
  32. google.ima.AdEvent.Type.PAUSED, () => {
  33. this.isPaused_ = true;
  34. });
  35. this.eventManager_.listen(this.manager_,
  36. google.ima.AdEvent.Type.RESUMED, () => {
  37. this.isPaused_ = false;
  38. });
  39. }
  40. /**
  41. * @override
  42. * @export
  43. */
  44. getDuration() {
  45. return this.ad_.getDuration();
  46. }
  47. /**
  48. * @override
  49. * @export
  50. */
  51. getMinSuggestedDuration() {
  52. return this.ad_.getMinSuggestedDuration();
  53. }
  54. /**
  55. * @override
  56. * @export
  57. */
  58. getRemainingTime() {
  59. return this.manager_.getRemainingTime();
  60. }
  61. /**
  62. * @override
  63. * @export
  64. */
  65. isPaused() {
  66. return this.isPaused_;
  67. }
  68. /**
  69. * @override
  70. * @export
  71. */
  72. isSkippable() {
  73. // IMA returns -1 for non-skippable ads. Any positive number is a genuine
  74. // skip offset, meaning the ad is skippable.
  75. return this.ad_.getSkipTimeOffset() >= 0;
  76. }
  77. /**
  78. * @override
  79. * @export
  80. */
  81. getTimeUntilSkippable() {
  82. const skipOffset = this.ad_.getSkipTimeOffset();
  83. const canSkipIn = this.getRemainingTime() - skipOffset;
  84. return Math.max(canSkipIn, 0);
  85. }
  86. /**
  87. * @override
  88. * @export
  89. */
  90. canSkipNow() {
  91. return this.manager_.getAdSkippableState();
  92. }
  93. /**
  94. * @override
  95. * @export
  96. */
  97. skip() {
  98. return this.manager_.skip();
  99. }
  100. /**
  101. * @param {boolean} paused
  102. */
  103. setPaused(paused) {
  104. this.isPaused_ = paused;
  105. }
  106. /**
  107. * @override
  108. * @export
  109. */
  110. pause() {
  111. return this.manager_.pause();
  112. }
  113. /**
  114. * @override
  115. * @export
  116. */
  117. play() {
  118. return this.manager_.resume();
  119. }
  120. /**
  121. * @override
  122. * @export
  123. */
  124. getVolume() {
  125. return this.manager_.getVolume();
  126. }
  127. /**
  128. * @override
  129. * @export
  130. */
  131. setVolume(volume) {
  132. return this.manager_.setVolume(volume);
  133. }
  134. /**
  135. * @override
  136. * @export
  137. */
  138. isMuted() {
  139. return this.manager_.getVolume() == 0;
  140. }
  141. /**
  142. * @override
  143. * @export
  144. */
  145. isLinear() {
  146. return this.ad_.isLinear();
  147. }
  148. /**
  149. * @override
  150. * @export
  151. */
  152. resize(width, height) {
  153. let isInFullscreen = false;
  154. const video = /** @type {HTMLVideoElement} */(this.video_);
  155. if (document.fullscreenEnabled) {
  156. isInFullscreen = !!document.fullscreenElement;
  157. } else if (video.webkitSupportsFullscreen) {
  158. isInFullscreen = video.webkitDisplayingFullscreen;
  159. }
  160. const viewMode = isInFullscreen ?
  161. google.ima.ViewMode.FULLSCREEN : google.ima.ViewMode.NORMAL;
  162. this.manager_.resize(width, height, viewMode);
  163. }
  164. /**
  165. * @override
  166. * @export
  167. */
  168. setMuted(muted) {
  169. // Emulate the "mute" functionality, where current, pre-mute
  170. // volume is saved and can be restored on unmute.
  171. if (muted) {
  172. this.volume_ = this.getVolume();
  173. this.setVolume(0);
  174. } else {
  175. this.setVolume(this.volume_);
  176. }
  177. }
  178. /**
  179. * @override
  180. * @export
  181. */
  182. getSequenceLength() {
  183. const podInfo = this.ad_.getAdPodInfo();
  184. if (podInfo == null) {
  185. // No pod, just one ad.
  186. return 1;
  187. }
  188. return podInfo.getTotalAds();
  189. }
  190. /**
  191. * @override
  192. * @export
  193. */
  194. getPositionInSequence() {
  195. const podInfo = this.ad_.getAdPodInfo();
  196. if (podInfo == null) {
  197. // No pod, just one ad.
  198. return 1;
  199. }
  200. return podInfo.getAdPosition();
  201. }
  202. /**
  203. * @override
  204. * @export
  205. */
  206. release() {
  207. this.ad_ = null;
  208. this.manager_ = null;
  209. }
  210. };