videojs-contrib-quality-levels.es.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*! @name videojs-contrib-quality-levels @version 3.0.0 @license Apache-2.0 */
  2. import videojs from 'video.js';
  3. /**
  4. * A single QualityLevel.
  5. *
  6. * interface QualityLevel {
  7. * readonly attribute DOMString id;
  8. * attribute DOMString label;
  9. * readonly attribute long width;
  10. * readonly attribute long height;
  11. * readonly attribute long bitrate;
  12. * attribute boolean enabled;
  13. * };
  14. *
  15. * @class QualityLevel
  16. */
  17. class QualityLevel {
  18. /**
  19. * Creates a QualityLevel
  20. *
  21. * @param {Representation|Object} representation The representation of the quality level
  22. * @param {string} representation.id Unique id of the QualityLevel
  23. * @param {number=} representation.width Resolution width of the QualityLevel
  24. * @param {number=} representation.height Resolution height of the QualityLevel
  25. * @param {number} representation.bandwidth Bitrate of the QualityLevel
  26. * @param {number=} representation.frameRate Frame-rate of the QualityLevel
  27. * @param {Function} representation.enabled Callback to enable/disable QualityLevel
  28. */
  29. constructor(representation) {
  30. let level = this; // eslint-disable-line
  31. level.id = representation.id;
  32. level.label = level.id;
  33. level.width = representation.width;
  34. level.height = representation.height;
  35. level.bitrate = representation.bandwidth;
  36. level.frameRate = representation.frameRate;
  37. level.enabled_ = representation.enabled;
  38. Object.defineProperty(level, 'enabled', {
  39. /**
  40. * Get whether the QualityLevel is enabled.
  41. *
  42. * @return {boolean} True if the QualityLevel is enabled.
  43. */
  44. get() {
  45. return level.enabled_();
  46. },
  47. /**
  48. * Enable or disable the QualityLevel.
  49. *
  50. * @param {boolean} enable true to enable QualityLevel, false to disable.
  51. */
  52. set(enable) {
  53. level.enabled_(enable);
  54. }
  55. });
  56. return level;
  57. }
  58. }
  59. /**
  60. * A list of QualityLevels.
  61. *
  62. * interface QualityLevelList : EventTarget {
  63. * getter QualityLevel (unsigned long index);
  64. * readonly attribute unsigned long length;
  65. * readonly attribute long selectedIndex;
  66. *
  67. * void addQualityLevel(QualityLevel qualityLevel)
  68. * void removeQualityLevel(QualityLevel remove)
  69. * QualityLevel? getQualityLevelById(DOMString id);
  70. *
  71. * attribute EventHandler onchange;
  72. * attribute EventHandler onaddqualitylevel;
  73. * attribute EventHandler onremovequalitylevel;
  74. * };
  75. *
  76. * @extends videojs.EventTarget
  77. * @class QualityLevelList
  78. */
  79. class QualityLevelList extends videojs.EventTarget {
  80. constructor() {
  81. super();
  82. let list = this; // eslint-disable-line
  83. list.levels_ = [];
  84. list.selectedIndex_ = -1;
  85. /**
  86. * Get the index of the currently selected QualityLevel.
  87. *
  88. * @returns {number} The index of the selected QualityLevel. -1 if none selected.
  89. * @readonly
  90. */
  91. Object.defineProperty(list, 'selectedIndex', {
  92. get() {
  93. return list.selectedIndex_;
  94. }
  95. });
  96. /**
  97. * Get the length of the list of QualityLevels.
  98. *
  99. * @returns {number} The length of the list.
  100. * @readonly
  101. */
  102. Object.defineProperty(list, 'length', {
  103. get() {
  104. return list.levels_.length;
  105. }
  106. });
  107. return list;
  108. }
  109. /**
  110. * Adds a quality level to the list.
  111. *
  112. * @param {Representation|Object} representation The representation of the quality level
  113. * @param {string} representation.id Unique id of the QualityLevel
  114. * @param {number=} representation.width Resolution width of the QualityLevel
  115. * @param {number=} representation.height Resolution height of the QualityLevel
  116. * @param {number} representation.bandwidth Bitrate of the QualityLevel
  117. * @param {number=} representation.frameRate Frame-rate of the QualityLevel
  118. * @param {Function} representation.enabled Callback to enable/disable QualityLevel
  119. * @return {QualityLevel} the QualityLevel added to the list
  120. * @method addQualityLevel
  121. */
  122. addQualityLevel(representation) {
  123. let qualityLevel = this.getQualityLevelById(representation.id); // Do not add duplicate quality levels
  124. if (qualityLevel) {
  125. return qualityLevel;
  126. }
  127. const index = this.levels_.length;
  128. qualityLevel = new QualityLevel(representation);
  129. if (!('' + index in this)) {
  130. Object.defineProperty(this, index, {
  131. get() {
  132. return this.levels_[index];
  133. }
  134. });
  135. }
  136. this.levels_.push(qualityLevel);
  137. this.trigger({
  138. qualityLevel,
  139. type: 'addqualitylevel'
  140. });
  141. return qualityLevel;
  142. }
  143. /**
  144. * Removes a quality level from the list.
  145. *
  146. * @param {QualityLevel} remove QualityLevel to remove to the list.
  147. * @return {QualityLevel|null} the QualityLevel removed or null if nothing removed
  148. * @method removeQualityLevel
  149. */
  150. removeQualityLevel(qualityLevel) {
  151. let removed = null;
  152. for (let i = 0, l = this.length; i < l; i++) {
  153. if (this[i] === qualityLevel) {
  154. removed = this.levels_.splice(i, 1)[0];
  155. if (this.selectedIndex_ === i) {
  156. this.selectedIndex_ = -1;
  157. } else if (this.selectedIndex_ > i) {
  158. this.selectedIndex_--;
  159. }
  160. break;
  161. }
  162. }
  163. if (removed) {
  164. this.trigger({
  165. qualityLevel,
  166. type: 'removequalitylevel'
  167. });
  168. }
  169. return removed;
  170. }
  171. /**
  172. * Searches for a QualityLevel with the given id.
  173. *
  174. * @param {string} id The id of the QualityLevel to find.
  175. * @return {QualityLevel|null} The QualityLevel with id, or null if not found.
  176. * @method getQualityLevelById
  177. */
  178. getQualityLevelById(id) {
  179. for (let i = 0, l = this.length; i < l; i++) {
  180. const level = this[i];
  181. if (level.id === id) {
  182. return level;
  183. }
  184. }
  185. return null;
  186. }
  187. /**
  188. * Resets the list of QualityLevels to empty
  189. *
  190. * @method dispose
  191. */
  192. dispose() {
  193. this.selectedIndex_ = -1;
  194. this.levels_.length = 0;
  195. }
  196. }
  197. /**
  198. * change - The selected QualityLevel has changed.
  199. * addqualitylevel - A QualityLevel has been added to the QualityLevelList.
  200. * removequalitylevel - A QualityLevel has been removed from the QualityLevelList.
  201. */
  202. QualityLevelList.prototype.allowedEvents_ = {
  203. change: 'change',
  204. addqualitylevel: 'addqualitylevel',
  205. removequalitylevel: 'removequalitylevel'
  206. }; // emulate attribute EventHandler support to allow for feature detection
  207. for (const event in QualityLevelList.prototype.allowedEvents_) {
  208. QualityLevelList.prototype['on' + event] = null;
  209. }
  210. var version = "3.0.0";
  211. const registerPlugin = videojs.registerPlugin || videojs.plugin;
  212. /**
  213. * Initialization function for the qualityLevels plugin. Sets up the QualityLevelList and
  214. * event handlers.
  215. *
  216. * @param {Player} player Player object.
  217. * @param {Object} options Plugin options object.
  218. * @function initPlugin
  219. */
  220. const initPlugin = function (player, options) {
  221. const originalPluginFn = player.qualityLevels;
  222. const qualityLevelList = new QualityLevelList();
  223. const disposeHandler = function () {
  224. qualityLevelList.dispose();
  225. player.qualityLevels = originalPluginFn;
  226. player.off('dispose', disposeHandler);
  227. };
  228. player.on('dispose', disposeHandler);
  229. player.qualityLevels = () => qualityLevelList;
  230. player.qualityLevels.VERSION = version;
  231. return qualityLevelList;
  232. };
  233. /**
  234. * A video.js plugin.
  235. *
  236. * In the plugin function, the value of `this` is a video.js `Player`
  237. * instance. You cannot rely on the player being in a "ready" state here,
  238. * depending on how the plugin is invoked. This may or may not be important
  239. * to you; if not, remove the wait for "ready"!
  240. *
  241. * @param {Object} options Plugin options object
  242. * @function qualityLevels
  243. */
  244. const qualityLevels = function (options) {
  245. return initPlugin(this, videojs.mergeOptions({}, options));
  246. }; // Register the plugin with video.js.
  247. registerPlugin('qualityLevels', qualityLevels); // Include the version number.
  248. qualityLevels.VERSION = version;
  249. export default qualityLevels;