bundle.js 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839
  1. (function (videojs,sinon,QUnit) {
  2. 'use strict';
  3. var videojs__default = 'default' in videojs ? videojs['default'] : videojs;
  4. sinon = sinon && sinon.hasOwnProperty('default') ? sinon['default'] : sinon;
  5. QUnit = QUnit && QUnit.hasOwnProperty('default') ? QUnit['default'] : QUnit;
  6. var version = "5.4.2";
  7. var version$1 = "2.2.1";
  8. /**
  9. * @file flash-rtmp.js
  10. * @module flash-rtmp
  11. */
  12. /**
  13. * Add RTMP properties to the {@link Flash} Tech.
  14. *
  15. * @param {Flash} Flash
  16. * The flash tech class.
  17. *
  18. * @mixin FlashRtmpDecorator
  19. *
  20. * @return {Flash}
  21. * The flash tech with RTMP properties added.
  22. */
  23. function FlashRtmpDecorator(Flash) {
  24. Flash.streamingFormats = {
  25. 'rtmp/mp4': 'MP4',
  26. 'rtmp/flv': 'FLV'
  27. };
  28. /**
  29. * Join connection and stream with an ampersand.
  30. *
  31. * @param {string} connection
  32. * The connection string.
  33. *
  34. * @param {string} stream
  35. * The stream string.
  36. *
  37. * @return {string}
  38. * The connection and stream joined with an `&` character
  39. */
  40. Flash.streamFromParts = function (connection, stream) {
  41. return connection + '&' + stream;
  42. };
  43. /**
  44. * The flash parts object that contains connection and stream info.
  45. *
  46. * @typedef {Object} Flash~PartsObject
  47. *
  48. * @property {string} connection
  49. * The connection string of a source, defaults to an empty string.
  50. *
  51. * @property {string} stream
  52. * The stream string of the source, defaults to an empty string.
  53. */
  54. /**
  55. * Convert a source url into a stream and connection parts.
  56. *
  57. * @param {string} src
  58. * the source url
  59. *
  60. * @return {Flash~PartsObject}
  61. * The parts object that contains a connection and a stream
  62. */
  63. Flash.streamToParts = function (src) {
  64. var parts = {
  65. connection: '',
  66. stream: ''
  67. };
  68. if (!src) {
  69. return parts;
  70. }
  71. // Look for the normal URL separator we expect, '&'.
  72. // If found, we split the URL into two pieces around the
  73. // first '&'.
  74. var connEnd = src.search(/&(?![\w-]+=)/);
  75. var streamBegin = void 0;
  76. if (connEnd !== -1) {
  77. streamBegin = connEnd + 1;
  78. } else {
  79. // If there's not a '&', we use the last '/' as the delimiter.
  80. connEnd = streamBegin = src.lastIndexOf('/') + 1;
  81. if (connEnd === 0) {
  82. // really, there's not a '/'?
  83. connEnd = streamBegin = src.length;
  84. }
  85. }
  86. parts.connection = src.substring(0, connEnd);
  87. parts.stream = src.substring(streamBegin, src.length);
  88. return parts;
  89. };
  90. /**
  91. * Check if the source type is a streaming type.
  92. *
  93. * @param {string} srcType
  94. * The mime type to check.
  95. *
  96. * @return {boolean}
  97. * - True if the source type is a streaming type.
  98. * - False if the source type is not a streaming type.
  99. */
  100. Flash.isStreamingType = function (srcType) {
  101. return srcType in Flash.streamingFormats;
  102. };
  103. // RTMP has four variations, any string starting
  104. // with one of these protocols should be valid
  105. /**
  106. * Regular expression used to check if the source is an rtmp source.
  107. *
  108. * @property {RegExp} Flash.RTMP_RE
  109. */
  110. Flash.RTMP_RE = /^rtmp[set]?:\/\//i;
  111. /**
  112. * Check if the source itself is a streaming type.
  113. *
  114. * @param {string} src
  115. * The url to the source.
  116. *
  117. * @return {boolean}
  118. * - True if the source url indicates that the source is streaming.
  119. * - False if the shource url indicates that the source url is not streaming.
  120. */
  121. Flash.isStreamingSrc = function (src) {
  122. return Flash.RTMP_RE.test(src);
  123. };
  124. /**
  125. * A source handler for RTMP urls
  126. * @type {Object}
  127. */
  128. Flash.rtmpSourceHandler = {};
  129. /**
  130. * Check if Flash can play the given mime type.
  131. *
  132. * @param {string} type
  133. * The mime type to check
  134. *
  135. * @return {string}
  136. * 'maybe', or '' (empty string)
  137. */
  138. Flash.rtmpSourceHandler.canPlayType = function (type) {
  139. if (Flash.isStreamingType(type)) {
  140. return 'maybe';
  141. }
  142. return '';
  143. };
  144. /**
  145. * Check if Flash can handle the source natively
  146. *
  147. * @param {Object} source
  148. * The source object
  149. *
  150. * @param {Object} [options]
  151. * The options passed to the tech
  152. *
  153. * @return {string}
  154. * 'maybe', or '' (empty string)
  155. */
  156. Flash.rtmpSourceHandler.canHandleSource = function (source, options) {
  157. var can = Flash.rtmpSourceHandler.canPlayType(source.type);
  158. if (can) {
  159. return can;
  160. }
  161. if (Flash.isStreamingSrc(source.src)) {
  162. return 'maybe';
  163. }
  164. return '';
  165. };
  166. /**
  167. * Pass the source to the flash object.
  168. *
  169. * @param {Object} source
  170. * The source object
  171. *
  172. * @param {Flash} tech
  173. * The instance of the Flash tech
  174. *
  175. * @param {Object} [options]
  176. * The options to pass to the source
  177. */
  178. Flash.rtmpSourceHandler.handleSource = function (source, tech, options) {
  179. var srcParts = Flash.streamToParts(source.src);
  180. tech.setRtmpConnection(srcParts.connection);
  181. tech.setRtmpStream(srcParts.stream);
  182. };
  183. // Register the native source handler
  184. Flash.registerSourceHandler(Flash.rtmpSourceHandler);
  185. return Flash;
  186. }
  187. var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
  188. var win;
  189. if (typeof window !== "undefined") {
  190. win = window;
  191. } else if (typeof commonjsGlobal !== "undefined") {
  192. win = commonjsGlobal;
  193. } else if (typeof self !== "undefined"){
  194. win = self;
  195. } else {
  196. win = {};
  197. }
  198. var window_1 = win;
  199. var classCallCheck = function (instance, Constructor) {
  200. if (!(instance instanceof Constructor)) {
  201. throw new TypeError("Cannot call a class as a function");
  202. }
  203. };
  204. var inherits = function (subClass, superClass) {
  205. if (typeof superClass !== "function" && superClass !== null) {
  206. throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  207. }
  208. subClass.prototype = Object.create(superClass && superClass.prototype, {
  209. constructor: {
  210. value: subClass,
  211. enumerable: false,
  212. writable: true,
  213. configurable: true
  214. }
  215. });
  216. if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  217. };
  218. var possibleConstructorReturn = function (self, call) {
  219. if (!self) {
  220. throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  221. }
  222. return call && (typeof call === "object" || typeof call === "function") ? call : self;
  223. };
  224. /**
  225. * @file flash.js
  226. * VideoJS-SWF - Custom Flash Player with HTML5-ish API
  227. * https://github.com/zencoder/video-js-swf
  228. * Not using setupTriggers. Using global onEvent func to distribute events
  229. */
  230. var Tech = videojs__default.getComponent('Tech');
  231. var Dom = videojs__default.dom;
  232. var Url = videojs__default.url;
  233. var createTimeRange = videojs__default.createTimeRange;
  234. var mergeOptions = videojs__default.mergeOptions;
  235. var navigator = window_1 && window_1.navigator || {};
  236. /**
  237. * Flash Media Controller - Wrapper for Flash Media API
  238. *
  239. * @mixes FlashRtmpDecorator
  240. * @mixes Tech~SouceHandlerAdditions
  241. * @extends Tech
  242. */
  243. var Flash = function (_Tech) {
  244. inherits(Flash, _Tech);
  245. /**
  246. * Create an instance of this Tech.
  247. *
  248. * @param {Object} [options]
  249. * The key/value store of player options.
  250. *
  251. * @param {Component~ReadyCallback} ready
  252. * Callback function to call when the `Flash` Tech is ready.
  253. */
  254. function Flash(options, ready) {
  255. classCallCheck(this, Flash);
  256. // Set the source when ready
  257. var _this = possibleConstructorReturn(this, _Tech.call(this, options, ready));
  258. if (options.source) {
  259. _this.ready(function () {
  260. this.setSource(options.source);
  261. }, true);
  262. }
  263. // Having issues with Flash reloading on certain page actions
  264. // (hide/resize/fullscreen) in certain browsers
  265. // This allows resetting the playhead when we catch the reload
  266. if (options.startTime) {
  267. _this.ready(function () {
  268. this.load();
  269. this.play();
  270. this.currentTime(options.startTime);
  271. }, true);
  272. }
  273. // Add global window functions that the swf expects
  274. // A 4.x workflow we weren't able to solve for in 5.0
  275. // because of the need to hard code these functions
  276. // into the swf for security reasons
  277. window_1.videojs = window_1.videojs || {};
  278. window_1.videojs.Flash = window_1.videojs.Flash || {};
  279. window_1.videojs.Flash.onReady = Flash.onReady;
  280. window_1.videojs.Flash.onEvent = Flash.onEvent;
  281. window_1.videojs.Flash.onError = Flash.onError;
  282. _this.on('seeked', function () {
  283. this.lastSeekTarget_ = undefined;
  284. });
  285. return _this;
  286. }
  287. /**
  288. * Create the `Flash` Tech's DOM element.
  289. *
  290. * @return {Element}
  291. * The element that gets created.
  292. */
  293. Flash.prototype.createEl = function createEl() {
  294. var options = this.options_;
  295. // If video.js is hosted locally you should also set the location
  296. // for the hosted swf, which should be relative to the page (not video.js)
  297. // Otherwise this adds a CDN url.
  298. // The CDN also auto-adds a swf URL for that specific version.
  299. if (!options.swf) {
  300. options.swf = 'https://vjs.zencdn.net/swf/' + version + '/video-js.swf';
  301. }
  302. // Generate ID for swf object
  303. var objId = options.techId;
  304. // Merge default flashvars with ones passed in to init
  305. var flashVars = mergeOptions({
  306. // SWF Callback Functions
  307. readyFunction: 'videojs.Flash.onReady',
  308. eventProxyFunction: 'videojs.Flash.onEvent',
  309. errorEventProxyFunction: 'videojs.Flash.onError',
  310. // Player Settings
  311. autoplay: options.autoplay,
  312. preload: options.preload,
  313. loop: options.loop,
  314. muted: options.muted
  315. }, options.flashVars);
  316. // Merge default parames with ones passed in
  317. var params = mergeOptions({
  318. // Opaque is needed to overlay controls, but can affect playback performance
  319. wmode: 'opaque',
  320. // Using bgcolor prevents a white flash when the object is loading
  321. bgcolor: '#000000'
  322. }, options.params);
  323. // Merge default attributes with ones passed in
  324. var attributes = mergeOptions({
  325. // Both ID and Name needed or swf to identify itself
  326. id: objId,
  327. name: objId,
  328. 'class': 'vjs-tech'
  329. }, options.attributes);
  330. this.el_ = Flash.embed(options.swf, flashVars, params, attributes);
  331. this.el_.tech = this;
  332. return this.el_;
  333. };
  334. /**
  335. * Called by {@link Player#play} to play using the `Flash` `Tech`.
  336. */
  337. Flash.prototype.play = function play() {
  338. if (this.ended()) {
  339. this.setCurrentTime(0);
  340. }
  341. this.el_.vjs_play();
  342. };
  343. /**
  344. * Called by {@link Player#pause} to pause using the `Flash` `Tech`.
  345. */
  346. Flash.prototype.pause = function pause() {
  347. this.el_.vjs_pause();
  348. };
  349. /**
  350. * A getter/setter for the `Flash` Tech's source object.
  351. * > Note: Please use {@link Flash#setSource}
  352. *
  353. * @param {Tech~SourceObject} [src]
  354. * The source object you want to set on the `Flash` techs.
  355. *
  356. * @return {Tech~SourceObject|undefined}
  357. * - The current source object when a source is not passed in.
  358. * - undefined when setting
  359. *
  360. * @deprecated Since version 5.
  361. */
  362. Flash.prototype.src = function src(_src) {
  363. if (_src === undefined) {
  364. return this.currentSrc();
  365. }
  366. // Setting src through `src` not `setSrc` will be deprecated
  367. return this.setSrc(_src);
  368. };
  369. /**
  370. * A getter/setter for the `Flash` Tech's source object.
  371. *
  372. * @param {Tech~SourceObject} [src]
  373. * The source object you want to set on the `Flash` techs.
  374. */
  375. Flash.prototype.setSrc = function setSrc(src) {
  376. var _this2 = this;
  377. // Make sure source URL is absolute.
  378. src = Url.getAbsoluteURL(src);
  379. this.el_.vjs_src(src);
  380. // Currently the SWF doesn't autoplay if you load a source later.
  381. // e.g. Load player w/ no source, wait 2s, set src.
  382. if (this.autoplay()) {
  383. this.setTimeout(function () {
  384. return _this2.play();
  385. }, 0);
  386. }
  387. };
  388. /**
  389. * Indicates whether the media is currently seeking to a new position or not.
  390. *
  391. * @return {boolean}
  392. * - True if seeking to a new position
  393. * - False otherwise
  394. */
  395. Flash.prototype.seeking = function seeking() {
  396. return this.lastSeekTarget_ !== undefined;
  397. };
  398. /**
  399. * Returns the current time in seconds that the media is at in playback.
  400. *
  401. * @param {number} time
  402. * Current playtime of the media in seconds.
  403. */
  404. Flash.prototype.setCurrentTime = function setCurrentTime(time) {
  405. var seekable = this.seekable();
  406. if (seekable.length) {
  407. // clamp to the current seekable range
  408. time = time > seekable.start(0) ? time : seekable.start(0);
  409. time = time < seekable.end(seekable.length - 1) ? time : seekable.end(seekable.length - 1);
  410. this.lastSeekTarget_ = time;
  411. this.trigger('seeking');
  412. this.el_.vjs_setProperty('currentTime', time);
  413. _Tech.prototype.setCurrentTime.call(this);
  414. }
  415. };
  416. /**
  417. * Get the current playback time in seconds
  418. *
  419. * @return {number}
  420. * The current time of playback in seconds.
  421. */
  422. Flash.prototype.currentTime = function currentTime() {
  423. // when seeking make the reported time keep up with the requested time
  424. // by reading the time we're seeking to
  425. if (this.seeking()) {
  426. return this.lastSeekTarget_ || 0;
  427. }
  428. return this.el_.vjs_getProperty('currentTime');
  429. };
  430. /**
  431. * Get the current source
  432. *
  433. * @method currentSrc
  434. * @return {Tech~SourceObject}
  435. * The current source
  436. */
  437. Flash.prototype.currentSrc = function currentSrc() {
  438. if (this.currentSource_) {
  439. return this.currentSource_.src;
  440. }
  441. return this.el_.vjs_getProperty('currentSrc');
  442. };
  443. /**
  444. * Get the total duration of the current media.
  445. *
  446. * @return {number}
  447. 8 The total duration of the current media.
  448. */
  449. Flash.prototype.duration = function duration() {
  450. if (this.readyState() === 0) {
  451. return NaN;
  452. }
  453. var duration = this.el_.vjs_getProperty('duration');
  454. return duration >= 0 ? duration : Infinity;
  455. };
  456. /**
  457. * Load media into Tech.
  458. */
  459. Flash.prototype.load = function load() {
  460. this.el_.vjs_load();
  461. };
  462. /**
  463. * Get the poster image that was set on the tech.
  464. */
  465. Flash.prototype.poster = function poster() {
  466. this.el_.vjs_getProperty('poster');
  467. };
  468. /**
  469. * Poster images are not handled by the Flash tech so make this is a no-op.
  470. */
  471. Flash.prototype.setPoster = function setPoster() {};
  472. /**
  473. * Determine the time ranges that can be seeked to in the media.
  474. *
  475. * @return {TimeRange}
  476. * Returns the time ranges that can be seeked to.
  477. */
  478. Flash.prototype.seekable = function seekable() {
  479. var duration = this.duration();
  480. if (duration === 0) {
  481. return createTimeRange();
  482. }
  483. return createTimeRange(0, duration);
  484. };
  485. /**
  486. * Get and create a `TimeRange` object for buffering.
  487. *
  488. * @return {TimeRange}
  489. * The time range object that was created.
  490. */
  491. Flash.prototype.buffered = function buffered() {
  492. var ranges = this.el_.vjs_getProperty('buffered');
  493. if (ranges.length === 0) {
  494. return createTimeRange();
  495. }
  496. return createTimeRange(ranges[0][0], ranges[0][1]);
  497. };
  498. /**
  499. * Get fullscreen support -
  500. *
  501. * Flash does not allow fullscreen through javascript
  502. * so this always returns false.
  503. *
  504. * @return {boolean}
  505. * The Flash tech does not support fullscreen, so it will always return false.
  506. */
  507. Flash.prototype.supportsFullScreen = function supportsFullScreen() {
  508. // Flash does not allow fullscreen through javascript
  509. return false;
  510. };
  511. /**
  512. * Flash does not allow fullscreen through javascript
  513. * so this always returns false.
  514. *
  515. * @return {boolean}
  516. * The Flash tech does not support fullscreen, so it will always return false.
  517. */
  518. Flash.prototype.enterFullScreen = function enterFullScreen() {
  519. return false;
  520. };
  521. /**
  522. * Gets available media playback quality metrics as specified by the W3C's Media
  523. * Playback Quality API.
  524. *
  525. * @see [Spec]{@link https://wicg.github.io/media-playback-quality}
  526. *
  527. * @return {Object}
  528. * An object with supported media playback quality metrics
  529. */
  530. Flash.prototype.getVideoPlaybackQuality = function getVideoPlaybackQuality() {
  531. var videoPlaybackQuality = this.el_.vjs_getProperty('getVideoPlaybackQuality');
  532. if (window_1.performance && typeof window_1.performance.now === 'function') {
  533. videoPlaybackQuality.creationTime = window_1.performance.now();
  534. } else if (window_1.performance && window_1.performance.timing && typeof window_1.performance.timing.navigationStart === 'number') {
  535. videoPlaybackQuality.creationTime = window_1.Date.now() - window_1.performance.timing.navigationStart;
  536. }
  537. return videoPlaybackQuality;
  538. };
  539. return Flash;
  540. }(Tech);
  541. // Create setters and getters for attributes
  542. var _readWrite = ['rtmpConnection', 'rtmpStream', 'preload', 'defaultPlaybackRate', 'playbackRate', 'autoplay', 'loop', 'controls', 'volume', 'muted', 'defaultMuted'];
  543. var _readOnly = ['networkState', 'readyState', 'initialTime', 'startOffsetTime', 'paused', 'ended', 'videoWidth', 'videoHeight'];
  544. var _api = Flash.prototype;
  545. /**
  546. * Create setters for the swf on the element
  547. *
  548. * @param {string} attr
  549. * The name of the parameter
  550. *
  551. * @private
  552. */
  553. function _createSetter(attr) {
  554. var attrUpper = attr.charAt(0).toUpperCase() + attr.slice(1);
  555. _api['set' + attrUpper] = function (val) {
  556. return this.el_.vjs_setProperty(attr, val);
  557. };
  558. }
  559. /**
  560. * Create getters for the swf on the element
  561. *
  562. * @param {string} attr
  563. * The name of the parameter
  564. *
  565. * @private
  566. */
  567. function _createGetter(attr) {
  568. _api[attr] = function () {
  569. return this.el_.vjs_getProperty(attr);
  570. };
  571. }
  572. // Create getter and setters for all read/write attributes
  573. for (var i = 0; i < _readWrite.length; i++) {
  574. _createGetter(_readWrite[i]);
  575. _createSetter(_readWrite[i]);
  576. }
  577. // Create getters for read-only attributes
  578. for (var _i = 0; _i < _readOnly.length; _i++) {
  579. _createGetter(_readOnly[_i]);
  580. }
  581. /** ------------------------------ Getters ------------------------------ **/
  582. /**
  583. * Get the value of `rtmpConnection` from the swf.
  584. *
  585. * @method Flash#rtmpConnection
  586. * @return {string}
  587. * The current value of `rtmpConnection` on the swf.
  588. */
  589. /**
  590. * Get the value of `rtmpStream` from the swf.
  591. *
  592. * @method Flash#rtmpStream
  593. * @return {string}
  594. * The current value of `rtmpStream` on the swf.
  595. */
  596. /**
  597. * Get the value of `preload` from the swf. `preload` indicates
  598. * what should download before the media is interacted with. It can have the following
  599. * values:
  600. * - none: nothing should be downloaded
  601. * - metadata: poster and the first few frames of the media may be downloaded to get
  602. * media dimensions and other metadata
  603. * - auto: allow the media and metadata for the media to be downloaded before
  604. * interaction
  605. *
  606. * @method Flash#preload
  607. * @return {string}
  608. * The value of `preload` from the swf. Will be 'none', 'metadata',
  609. * or 'auto'.
  610. */
  611. /**
  612. * Get the value of `defaultPlaybackRate` from the swf.
  613. *
  614. * @method Flash#defaultPlaybackRate
  615. * @return {number}
  616. * The current value of `defaultPlaybackRate` on the swf.
  617. */
  618. /**
  619. * Get the value of `playbackRate` from the swf. `playbackRate` indicates
  620. * the rate at which the media is currently playing back. Examples:
  621. * - if playbackRate is set to 2, media will play twice as fast.
  622. * - if playbackRate is set to 0.5, media will play half as fast.
  623. *
  624. * @method Flash#playbackRate
  625. * @return {number}
  626. * The value of `playbackRate` from the swf. A number indicating
  627. * the current playback speed of the media, where 1 is normal speed.
  628. */
  629. /**
  630. * Get the value of `autoplay` from the swf. `autoplay` indicates
  631. * that the media should start to play as soon as the page is ready.
  632. *
  633. * @method Flash#autoplay
  634. * @return {boolean}
  635. * - The value of `autoplay` from the swf.
  636. * - True indicates that the media ashould start as soon as the page loads.
  637. * - False indicates that the media should not start as soon as the page loads.
  638. */
  639. /**
  640. * Get the value of `loop` from the swf. `loop` indicates
  641. * that the media should return to the start of the media and continue playing once
  642. * it reaches the end.
  643. *
  644. * @method Flash#loop
  645. * @return {boolean}
  646. * - The value of `loop` from the swf.
  647. * - True indicates that playback should seek back to start once
  648. * the end of a media is reached.
  649. * - False indicates that playback should not loop back to the start when the
  650. * end of the media is reached.
  651. */
  652. /**
  653. * Get the value of `mediaGroup` from the swf.
  654. *
  655. * @method Flash#mediaGroup
  656. * @return {string}
  657. * The current value of `mediaGroup` on the swf.
  658. */
  659. /**
  660. * Get the value of `controller` from the swf.
  661. *
  662. * @method Flash#controller
  663. * @return {string}
  664. * The current value of `controller` on the swf.
  665. */
  666. /**
  667. * Get the value of `controls` from the swf. `controls` indicates
  668. * whether the native flash controls should be shown or hidden.
  669. *
  670. * @method Flash#controls
  671. * @return {boolean}
  672. * - The value of `controls` from the swf.
  673. * - True indicates that native controls should be showing.
  674. * - False indicates that native controls should be hidden.
  675. */
  676. /**
  677. * Get the value of the `volume` from the swf. `volume` indicates the current
  678. * audio level as a percentage in decimal form. This means that 1 is 100%, 0.5 is 50%, and
  679. * so on.
  680. *
  681. * @method Flash#volume
  682. * @return {number}
  683. * The volume percent as a decimal. Value will be between 0-1.
  684. */
  685. /**
  686. * Get the value of the `muted` from the swf. `muted` indicates the current
  687. * audio level should be silent.
  688. *
  689. * @method Flash#muted
  690. * @return {boolean}
  691. * - True if the audio should be set to silent
  692. * - False otherwise
  693. */
  694. /**
  695. * Get the value of `defaultMuted` from the swf. `defaultMuted` indicates
  696. * whether the media should start muted or not. Only changes the default state of the
  697. * media. `muted` and `defaultMuted` can have different values. `muted` indicates the
  698. * current state.
  699. *
  700. * @method Flash#defaultMuted
  701. * @return {boolean}
  702. * - The value of `defaultMuted` from the swf.
  703. * - True indicates that the media should start muted.
  704. * - False indicates that the media should not start muted.
  705. */
  706. /**
  707. * Get the value of `networkState` from the swf. `networkState` indicates
  708. * the current network state. It returns an enumeration from the following list:
  709. * - 0: NETWORK_EMPTY
  710. * - 1: NEWORK_IDLE
  711. * - 2: NETWORK_LOADING
  712. * - 3: NETWORK_NO_SOURCE
  713. *
  714. * @method Flash#networkState
  715. * @return {number}
  716. * The value of `networkState` from the swf. This will be a number
  717. * from the list in the description.
  718. */
  719. /**
  720. * Get the value of `readyState` from the swf. `readyState` indicates
  721. * the current state of the media element. It returns an enumeration from the
  722. * following list:
  723. * - 0: HAVE_NOTHING
  724. * - 1: HAVE_METADATA
  725. * - 2: HAVE_CURRENT_DATA
  726. * - 3: HAVE_FUTURE_DATA
  727. * - 4: HAVE_ENOUGH_DATA
  728. *
  729. * @method Flash#readyState
  730. * @return {number}
  731. * The value of `readyState` from the swf. This will be a number
  732. * from the list in the description.
  733. */
  734. /**
  735. * Get the value of `readyState` from the swf. `readyState` indicates
  736. * the current state of the media element. It returns an enumeration from the
  737. * following list:
  738. * - 0: HAVE_NOTHING
  739. * - 1: HAVE_METADATA
  740. * - 2: HAVE_CURRENT_DATA
  741. * - 3: HAVE_FUTURE_DATA
  742. * - 4: HAVE_ENOUGH_DATA
  743. *
  744. * @method Flash#readyState
  745. * @return {number}
  746. * The value of `readyState` from the swf. This will be a number
  747. * from the list in the description.
  748. */
  749. /**
  750. * Get the value of `initialTime` from the swf.
  751. *
  752. * @method Flash#initialTime
  753. * @return {number}
  754. * The `initialTime` proprety on the swf.
  755. */
  756. /**
  757. * Get the value of `startOffsetTime` from the swf.
  758. *
  759. * @method Flash#startOffsetTime
  760. * @return {number}
  761. * The `startOffsetTime` proprety on the swf.
  762. */
  763. /**
  764. * Get the value of `paused` from the swf. `paused` indicates whether the swf
  765. * is current paused or not.
  766. *
  767. * @method Flash#paused
  768. * @return {boolean}
  769. * The value of `paused` from the swf.
  770. */
  771. /**
  772. * Get the value of `ended` from the swf. `ended` indicates whether
  773. * the media has reached the end or not.
  774. *
  775. * @method Flash#ended
  776. * @return {boolean}
  777. * - True indicates that the media has ended.
  778. * - False indicates that the media has not ended.
  779. *
  780. * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-ended}
  781. */
  782. /**
  783. * Get the value of `videoWidth` from the swf. `videoWidth` indicates
  784. * the current width of the media in css pixels.
  785. *
  786. * @method Flash#videoWidth
  787. * @return {number}
  788. * The value of `videoWidth` from the swf. This will be a number
  789. * in css pixels.
  790. */
  791. /**
  792. * Get the value of `videoHeight` from the swf. `videoHeigth` indicates
  793. * the current height of the media in css pixels.
  794. *
  795. * @method Flassh.prototype.videoHeight
  796. * @return {number}
  797. * The value of `videoHeight` from the swf. This will be a number
  798. * in css pixels.
  799. */
  800. /** ------------------------------ Setters ------------------------------ **/
  801. /**
  802. * Set the value of `rtmpConnection` on the swf.
  803. *
  804. * @method Flash#setRtmpConnection
  805. * @param {string} rtmpConnection
  806. * New value to set the `rtmpConnection` property to.
  807. */
  808. /**
  809. * Set the value of `rtmpStream` on the swf.
  810. *
  811. * @method Flash#setRtmpStream
  812. * @param {string} rtmpStream
  813. * New value to set the `rtmpStream` property to.
  814. */
  815. /**
  816. * Set the value of `preload` on the swf. `preload` indicates
  817. * what should download before the media is interacted with. It can have the following
  818. * values:
  819. * - none: nothing should be downloaded
  820. * - metadata: poster and the first few frames of the media may be downloaded to get
  821. * media dimensions and other metadata
  822. * - auto: allow the media and metadata for the media to be downloaded before
  823. * interaction
  824. *
  825. * @method Flash#setPreload
  826. * @param {string} preload
  827. * The value of `preload` to set on the swf. Should be 'none', 'metadata',
  828. * or 'auto'.
  829. */
  830. /**
  831. * Set the value of `defaultPlaybackRate` on the swf.
  832. *
  833. * @method Flash#setDefaultPlaybackRate
  834. * @param {number} defaultPlaybackRate
  835. * New value to set the `defaultPlaybackRate` property to.
  836. */
  837. /**
  838. * Set the value of `playbackRate` on the swf. `playbackRate` indicates
  839. * the rate at which the media is currently playing back. Examples:
  840. * - if playbackRate is set to 2, media will play twice as fast.
  841. * - if playbackRate is set to 0.5, media will play half as fast.
  842. *
  843. * @method Flash#setPlaybackRate
  844. * @param {number} playbackRate
  845. * New value of `playbackRate` on the swf. A number indicating
  846. * the current playback speed of the media, where 1 is normal speed.
  847. */
  848. /**
  849. * Set the value of `autoplay` on the swf. `autoplay` indicates
  850. * that the media should start to play as soon as the page is ready.
  851. *
  852. * @method Flash#setAutoplay
  853. * @param {boolean} autoplay
  854. * - The value of `autoplay` from the swf.
  855. * - True indicates that the media ashould start as soon as the page loads.
  856. * - False indicates that the media should not start as soon as the page loads.
  857. */
  858. /**
  859. * Set the value of `loop` on the swf. `loop` indicates
  860. * that the media should return to the start of the media and continue playing once
  861. * it reaches the end.
  862. *
  863. * @method Flash#setLoop
  864. * @param {boolean} loop
  865. * - True indicates that playback should seek back to start once
  866. * the end of a media is reached.
  867. * - False indicates that playback should not loop back to the start when the
  868. * end of the media is reached.
  869. */
  870. /**
  871. * Set the value of `mediaGroup` on the swf.
  872. *
  873. * @method Flash#setMediaGroup
  874. * @param {string} mediaGroup
  875. * New value of `mediaGroup` to set on the swf.
  876. */
  877. /**
  878. * Set the value of `controller` on the swf.
  879. *
  880. * @method Flash#setController
  881. * @param {string} controller
  882. * New value the current value of `controller` on the swf.
  883. */
  884. /**
  885. * Get the value of `controls` from the swf. `controls` indicates
  886. * whether the native flash controls should be shown or hidden.
  887. *
  888. * @method Flash#controls
  889. * @return {boolean}
  890. * - The value of `controls` from the swf.
  891. * - True indicates that native controls should be showing.
  892. * - False indicates that native controls should be hidden.
  893. */
  894. /**
  895. * Set the value of the `volume` on the swf. `volume` indicates the current
  896. * audio level as a percentage in decimal form. This means that 1 is 100%, 0.5 is 50%, and
  897. * so on.
  898. *
  899. * @method Flash#setVolume
  900. * @param {number} percentAsDecimal
  901. * The volume percent as a decimal. Value will be between 0-1.
  902. */
  903. /**
  904. * Set the value of the `muted` on the swf. `muted` indicates that the current
  905. * audio level should be silent.
  906. *
  907. * @method Flash#setMuted
  908. * @param {boolean} muted
  909. * - True if the audio should be set to silent
  910. * - False otherwise
  911. */
  912. /**
  913. * Set the value of `defaultMuted` on the swf. `defaultMuted` indicates
  914. * whether the media should start muted or not. Only changes the default state of the
  915. * media. `muted` and `defaultMuted` can have different values. `muted` indicates the
  916. * current state.
  917. *
  918. * @method Flash#setDefaultMuted
  919. * @param {boolean} defaultMuted
  920. * - True indicates that the media should start muted.
  921. * - False indicates that the media should not start muted.
  922. */
  923. /* Flash Support Testing -------------------------------------------------------- */
  924. /**
  925. * Check if the Flash tech is currently supported.
  926. *
  927. * @return {boolean}
  928. * - True for Chrome and Safari Desktop and Microsoft Edge and if flash tech is supported
  929. * - False otherwise
  930. */
  931. Flash.isSupported = function () {
  932. // for Chrome Desktop and Safari Desktop
  933. if (videojs__default.browser.IS_CHROME && (!videojs__default.browser.IS_ANDROID || !videojs__default.browser.IS_IOS) || videojs__default.browser.IS_SAFARI && !videojs__default.browser.IS_IOS || videojs__default.browser.IS_EDGE) {
  934. return true;
  935. }
  936. // for other browsers
  937. return Flash.version()[0] >= 10;
  938. };
  939. // Add Source Handler pattern functions to this tech
  940. Tech.withSourceHandlers(Flash);
  941. /*
  942. * Native source handler for flash, simply passes the source to the swf element.
  943. *
  944. * @property {Tech~SourceObject} source
  945. * The source object
  946. *
  947. * @property {Flash} tech
  948. * The instance of the Flash tech
  949. */
  950. Flash.nativeSourceHandler = {};
  951. /**
  952. * Check if the Flash can play the given mime type.
  953. *
  954. * @param {string} type
  955. * The mimetype to check
  956. *
  957. * @return {string}
  958. * 'maybe', or '' (empty string)
  959. */
  960. Flash.nativeSourceHandler.canPlayType = function (type) {
  961. if (type in Flash.formats) {
  962. return 'maybe';
  963. }
  964. return '';
  965. };
  966. /**
  967. * Check if the media element can handle a source natively.
  968. *
  969. * @param {Tech~SourceObject} source
  970. * The source object
  971. *
  972. * @param {Object} [options]
  973. * Options to be passed to the tech.
  974. *
  975. * @return {string}
  976. * 'maybe', or '' (empty string).
  977. */
  978. Flash.nativeSourceHandler.canHandleSource = function (source, options) {
  979. var type = void 0;
  980. /**
  981. * Guess the mime type of a file if it does not have one
  982. *
  983. * @param {Tech~SourceObject} src
  984. * The source object to guess the mime type for
  985. *
  986. * @return {string}
  987. * The mime type that was guessed
  988. */
  989. function guessMimeType(src) {
  990. var ext = Url.getFileExtension(src);
  991. if (ext) {
  992. return 'video/' + ext;
  993. }
  994. return '';
  995. }
  996. if (!source.type) {
  997. type = guessMimeType(source.src);
  998. } else {
  999. // Strip code information from the type because we don't get that specific
  1000. type = source.type.replace(/;.*/, '').toLowerCase();
  1001. }
  1002. return Flash.nativeSourceHandler.canPlayType(type);
  1003. };
  1004. /**
  1005. * Pass the source to the swf.
  1006. *
  1007. * @param {Tech~SourceObject} source
  1008. * The source object
  1009. *
  1010. * @param {Flash} tech
  1011. * The instance of the Flash tech
  1012. *
  1013. * @param {Object} [options]
  1014. * The options to pass to the source
  1015. */
  1016. Flash.nativeSourceHandler.handleSource = function (source, tech, options) {
  1017. tech.setSrc(source.src);
  1018. };
  1019. /**
  1020. * noop for native source handler dispose, as cleanup will happen automatically.
  1021. */
  1022. Flash.nativeSourceHandler.dispose = function () {};
  1023. // Register the native source handler
  1024. Flash.registerSourceHandler(Flash.nativeSourceHandler);
  1025. /**
  1026. * Flash supported mime types.
  1027. *
  1028. * @constant {Object}
  1029. */
  1030. Flash.formats = {
  1031. 'video/flv': 'FLV',
  1032. 'video/x-flv': 'FLV',
  1033. 'video/mp4': 'MP4',
  1034. 'video/m4v': 'MP4'
  1035. };
  1036. /**
  1037. * Called when the the swf is "ready", and makes sure that the swf is really
  1038. * ready using {@link Flash#checkReady}
  1039. *
  1040. * @param {Object} currSwf
  1041. * The current swf object
  1042. */
  1043. Flash.onReady = function (currSwf) {
  1044. var el = Dom.$('#' + currSwf);
  1045. var tech = el && el.tech;
  1046. // if there is no el then the tech has been disposed
  1047. // and the tech element was removed from the player div
  1048. if (tech && tech.el()) {
  1049. // check that the flash object is really ready
  1050. Flash.checkReady(tech);
  1051. }
  1052. };
  1053. /**
  1054. * The SWF isn't always ready when it says it is. Sometimes the API functions still
  1055. * need to be added to the object. If it's not ready, we set a timeout to check again
  1056. * shortly.
  1057. *
  1058. * @param {Flash} tech
  1059. * The instance of the flash tech to check.
  1060. */
  1061. Flash.checkReady = function (tech) {
  1062. // stop worrying if the tech has been disposed
  1063. if (!tech.el()) {
  1064. return;
  1065. }
  1066. // check if API property exists
  1067. if (tech.el().vjs_getProperty) {
  1068. // tell tech it's ready
  1069. tech.triggerReady();
  1070. } else {
  1071. // wait longer
  1072. this.setTimeout(function () {
  1073. Flash.checkReady(tech);
  1074. }, 50);
  1075. }
  1076. };
  1077. /**
  1078. * Trigger events from the swf on the Flash Tech.
  1079. *
  1080. * @param {number} swfID
  1081. * The id of the swf that had the event
  1082. *
  1083. * @param {string} eventName
  1084. * The name of the event to trigger
  1085. */
  1086. Flash.onEvent = function (swfID, eventName) {
  1087. var tech = Dom.$('#' + swfID).tech;
  1088. var args = Array.prototype.slice.call(arguments, 2);
  1089. // dispatch Flash events asynchronously for two reasons:
  1090. // - Flash swallows any exceptions generated by javascript it
  1091. // invokes
  1092. // - Flash is suspended until the javascript returns which may cause
  1093. // playback performance issues
  1094. tech.setTimeout(function () {
  1095. tech.trigger(eventName, args);
  1096. }, 1);
  1097. };
  1098. /**
  1099. * Log errors from the swf on the Flash tech.
  1100. *
  1101. * @param {number} swfID
  1102. * The id of the swf that had an error.
  1103. *
  1104. * @param {string} err
  1105. * The error to set on the Flash Tech.
  1106. *
  1107. * @return {MediaError|undefined}
  1108. * - Returns a MediaError when err is 'srcnotfound'
  1109. * - Returns undefined otherwise.
  1110. */
  1111. Flash.onError = function (swfID, err) {
  1112. var tech = Dom.$('#' + swfID).tech;
  1113. // trigger MEDIA_ERR_SRC_NOT_SUPPORTED
  1114. if (err === 'srcnotfound') {
  1115. return tech.error(4);
  1116. }
  1117. // trigger a custom error
  1118. if (typeof err === 'string') {
  1119. tech.error('FLASH: ' + err);
  1120. } else {
  1121. err.origin = 'flash';
  1122. tech.error(err);
  1123. }
  1124. };
  1125. /**
  1126. * Get the current version of Flash that is in use on the page.
  1127. *
  1128. * @return {Array}
  1129. * an array of versions that are available.
  1130. */
  1131. Flash.version = function () {
  1132. var version$$1 = '0,0,0';
  1133. // IE
  1134. try {
  1135. version$$1 = new window_1.ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
  1136. // other browsers
  1137. } catch (e) {
  1138. try {
  1139. if (navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) {
  1140. version$$1 = (navigator.plugins['Shockwave Flash 2.0'] || navigator.plugins['Shockwave Flash']).description.replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
  1141. }
  1142. } catch (err) {
  1143. // satisfy linter
  1144. }
  1145. }
  1146. return version$$1.split(',');
  1147. };
  1148. /**
  1149. * Only use for non-iframe embeds.
  1150. *
  1151. * @param {Object} swf
  1152. * The videojs-swf object.
  1153. *
  1154. * @param {Object} flashVars
  1155. * Names and values to use as flash option variables.
  1156. *
  1157. * @param {Object} params
  1158. * Style parameters to set on the object.
  1159. *
  1160. * @param {Object} attributes
  1161. * Attributes to set on the element.
  1162. *
  1163. * @return {Element}
  1164. * The embeded Flash DOM element.
  1165. */
  1166. Flash.embed = function (swf, flashVars, params, attributes) {
  1167. var code = Flash.getEmbedCode(swf, flashVars, params, attributes);
  1168. // Get element by embedding code and retrieving created element
  1169. var obj = Dom.createEl('div', { innerHTML: code }).childNodes[0];
  1170. return obj;
  1171. };
  1172. /**
  1173. * Only use for non-iframe embeds.
  1174. *
  1175. * @param {Object} swf
  1176. * The videojs-swf object.
  1177. *
  1178. * @param {Object} flashVars
  1179. * Names and values to use as flash option variables.
  1180. *
  1181. * @param {Object} params
  1182. * Style parameters to set on the object.
  1183. *
  1184. * @param {Object} attributes
  1185. * Attributes to set on the element.
  1186. *
  1187. * @return {Element}
  1188. * The embeded Flash DOM element.
  1189. */
  1190. Flash.getEmbedCode = function (swf, flashVars, params, attributes) {
  1191. var objTag = '<object type="application/x-shockwave-flash" ';
  1192. var flashVarsString = '';
  1193. var paramsString = '';
  1194. var attrsString = '';
  1195. // Convert flash vars to string
  1196. if (flashVars) {
  1197. Object.getOwnPropertyNames(flashVars).forEach(function (key) {
  1198. flashVarsString += key + '=' + flashVars[key] + '&amp;';
  1199. });
  1200. }
  1201. // Add swf, flashVars, and other default params
  1202. params = mergeOptions({
  1203. movie: swf,
  1204. flashvars: flashVarsString,
  1205. // Required to talk to swf
  1206. allowScriptAccess: 'always',
  1207. // All should be default, but having security issues.
  1208. allowNetworking: 'all'
  1209. }, params);
  1210. // Create param tags string
  1211. Object.getOwnPropertyNames(params).forEach(function (key) {
  1212. paramsString += '<param name="' + key + '" value="' + params[key] + '" />';
  1213. });
  1214. attributes = mergeOptions({
  1215. // Add swf to attributes (need both for IE and Others to work)
  1216. data: swf,
  1217. // Default to 100% width/height
  1218. width: '100%',
  1219. height: '100%'
  1220. }, attributes);
  1221. // Create Attributes string
  1222. Object.getOwnPropertyNames(attributes).forEach(function (key) {
  1223. attrsString += key + '="' + attributes[key] + '" ';
  1224. });
  1225. return '' + objTag + attrsString + '>' + paramsString + '</object>';
  1226. };
  1227. // Run Flash through the RTMP decorator
  1228. FlashRtmpDecorator(Flash);
  1229. if (Tech.getTech('Flash')) {
  1230. videojs__default.log.warn('Not using videojs-flash as it appears to already be registered');
  1231. videojs__default.log.warn('videojs-flash should only be used with video.js@6 and above');
  1232. } else {
  1233. videojs__default.registerTech('Flash', Flash);
  1234. }
  1235. Flash.VERSION = version$1;
  1236. var minDoc = {};
  1237. var topLevel = typeof commonjsGlobal !== 'undefined' ? commonjsGlobal :
  1238. typeof window !== 'undefined' ? window : {};
  1239. var doccy;
  1240. if (typeof document !== 'undefined') {
  1241. doccy = document;
  1242. } else {
  1243. doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
  1244. if (!doccy) {
  1245. doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
  1246. }
  1247. }
  1248. var document_1 = doccy;
  1249. // fake out the <object> interaction but leave all the other logic intact
  1250. var MockFlash = function (_Flash) {
  1251. inherits(MockFlash, _Flash);
  1252. function MockFlash() {
  1253. classCallCheck(this, MockFlash);
  1254. return possibleConstructorReturn(this, _Flash.call(this, {}));
  1255. }
  1256. return MockFlash;
  1257. }(Flash);
  1258. QUnit.module('Flash');
  1259. QUnit.test('Flash.canPlaySource', function (assert) {
  1260. var canPlaySource = Flash.canPlaySource;
  1261. // Supported
  1262. assert.ok(canPlaySource({ type: 'video/mp4; codecs=avc1.42E01E,mp4a.40.2' }, {}), 'codecs supported');
  1263. assert.ok(canPlaySource({ type: 'video/mp4' }, {}), 'video/mp4 supported');
  1264. assert.ok(canPlaySource({ type: 'video/x-flv' }, {}), 'video/x-flv supported');
  1265. assert.ok(canPlaySource({ type: 'video/flv' }, {}), 'video/flv supported');
  1266. assert.ok(canPlaySource({ type: 'video/m4v' }, {}), 'video/m4v supported');
  1267. assert.ok(canPlaySource({ type: 'VIDEO/FLV' }, {}), 'capitalized mime type');
  1268. // Not supported
  1269. assert.ok(!canPlaySource({ type: 'video/webm; codecs="vp8, vorbis"' }, {}));
  1270. assert.ok(!canPlaySource({ type: 'video/webm' }, {}));
  1271. });
  1272. QUnit.test('currentTime', function (assert) {
  1273. var getCurrentTime = Flash.prototype.currentTime;
  1274. var setCurrentTime = Flash.prototype.setCurrentTime;
  1275. var seekingCount = 0;
  1276. var _seeking = false;
  1277. var setPropVal = void 0;
  1278. var getPropVal = void 0;
  1279. var result = void 0;
  1280. // Mock out a Flash instance to avoid creating the swf object
  1281. var mockFlash = {
  1282. el_: {
  1283. /* eslint-disable camelcase */
  1284. vjs_setProperty: function vjs_setProperty(prop, val) {
  1285. setPropVal = val;
  1286. },
  1287. vjs_getProperty: function vjs_getProperty() {
  1288. return getPropVal;
  1289. }
  1290. /* eslint-enable camelcase */
  1291. },
  1292. seekable: function seekable() {
  1293. return videojs.createTimeRange(5, 1000);
  1294. },
  1295. trigger: function trigger(event) {
  1296. if (event === 'seeking') {
  1297. seekingCount++;
  1298. }
  1299. },
  1300. seeking: function seeking() {
  1301. return _seeking;
  1302. }
  1303. };
  1304. // Test the currentTime getter
  1305. getPropVal = 3;
  1306. result = getCurrentTime.call(mockFlash);
  1307. assert.equal(result, 3, 'currentTime is retreived from the swf element');
  1308. // Test the currentTime setter
  1309. setCurrentTime.call(mockFlash, 10);
  1310. assert.equal(setPropVal, 10, 'currentTime is set on the swf element');
  1311. assert.equal(seekingCount, 1, 'triggered seeking');
  1312. // Test current time while seeking
  1313. setCurrentTime.call(mockFlash, 20);
  1314. _seeking = true;
  1315. result = getCurrentTime.call(mockFlash);
  1316. assert.equal(result, 20, 'currentTime is retrieved from the lastSeekTarget while seeking');
  1317. assert.notEqual(result, getPropVal, 'currentTime is not retrieved from the element while seeking');
  1318. assert.equal(seekingCount, 2, 'triggered seeking');
  1319. // clamp seeks to seekable
  1320. setCurrentTime.call(mockFlash, 1001);
  1321. result = getCurrentTime.call(mockFlash);
  1322. assert.equal(result, mockFlash.seekable().end(0), 'clamped to the seekable end');
  1323. assert.equal(seekingCount, 3, 'triggered seeking');
  1324. setCurrentTime.call(mockFlash, 1);
  1325. result = getCurrentTime.call(mockFlash);
  1326. assert.equal(result, mockFlash.seekable().start(0), 'clamped to the seekable start');
  1327. assert.equal(seekingCount, 4, 'triggered seeking');
  1328. });
  1329. QUnit.test('dispose removes the object element even before ready fires', function (assert) {
  1330. // This test appears to test bad functionaly that was fixed
  1331. // so it's debateable whether or not it's useful
  1332. var dispose = Flash.prototype.dispose;
  1333. var mockFlash = new MockFlash();
  1334. var noop = function noop() {};
  1335. // Mock required functions for dispose
  1336. mockFlash.off = noop;
  1337. mockFlash.trigger = noop;
  1338. mockFlash.el_ = {};
  1339. dispose.call(mockFlash);
  1340. assert.strictEqual(mockFlash.el_, null, 'swf el is nulled');
  1341. });
  1342. QUnit.test('ready triggering before and after disposing the tech', function (assert) {
  1343. var checkReady = sinon.stub(Flash, 'checkReady');
  1344. var fixtureDiv = document_1.getElementById('qunit-fixture');
  1345. var playerDiv = document_1.createElement('div');
  1346. var techEl = document_1.createElement('div');
  1347. techEl.id = 'foo1234';
  1348. playerDiv.appendChild(techEl);
  1349. fixtureDiv.appendChild(playerDiv);
  1350. // Mock the swf element
  1351. techEl.tech = {
  1352. el: function el() {
  1353. return techEl;
  1354. }
  1355. };
  1356. playerDiv.player = {
  1357. tech: techEl.tech
  1358. };
  1359. Flash.onReady(techEl.id);
  1360. assert.ok(checkReady.called, 'checkReady should be called before the tech is disposed');
  1361. // remove the tech el from the player div to simulate being disposed
  1362. playerDiv.removeChild(techEl);
  1363. Flash.onReady(techEl.id);
  1364. assert.ok(!checkReady.calledTwice, 'checkReady should not be called after the tech is disposed');
  1365. Flash.checkReady.restore();
  1366. });
  1367. QUnit.test('should have the source handler interface', function (assert) {
  1368. assert.ok(Flash.registerSourceHandler, 'has the registerSourceHandler function');
  1369. });
  1370. QUnit.test('canPlayType should select the correct types to play', function (assert) {
  1371. var canPlayType = Flash.nativeSourceHandler.canPlayType;
  1372. assert.equal(canPlayType('video/flv'), 'maybe', 'should be able to play FLV files');
  1373. assert.equal(canPlayType('video/x-flv'), 'maybe', 'should be able to play x-FLV files');
  1374. assert.equal(canPlayType('video/mp4'), 'maybe', 'should be able to play MP4 files');
  1375. assert.equal(canPlayType('video/m4v'), 'maybe', 'should be able to play M4V files');
  1376. assert.equal(canPlayType('video/ogg'), '', 'should return empty string if it can not play the video');
  1377. });
  1378. QUnit.test('canHandleSource should be able to work with src objects without a type', function (assert) {
  1379. var canHandleSource = Flash.nativeSourceHandler.canHandleSource;
  1380. assert.equal('maybe', canHandleSource({ src: 'test.video.mp4' }, {}), 'should guess that it is a mp4 video');
  1381. assert.equal('maybe', canHandleSource({ src: 'test.video.m4v' }, {}), 'should guess that it is a m4v video');
  1382. assert.equal('maybe', canHandleSource({ src: 'test.video.flv' }, {}), 'should guess that it is a flash video');
  1383. assert.equal('', canHandleSource({ src: 'test.video.wgg' }, {}), 'should return empty string if it can not play the video');
  1384. });
  1385. QUnit.test('seekable', function (assert) {
  1386. var seekable = Flash.prototype.seekable;
  1387. var result = void 0;
  1388. var mockFlash = {
  1389. duration: function duration() {
  1390. return this.duration_;
  1391. }
  1392. };
  1393. // Test a normal duration
  1394. mockFlash.duration_ = 23;
  1395. result = seekable.call(mockFlash);
  1396. assert.equal(result.length, 1, 'seekable is non-empty');
  1397. assert.equal(result.start(0), 0, 'starts at zero');
  1398. assert.equal(result.end(0), mockFlash.duration_, 'ends at the duration');
  1399. // Test a zero duration
  1400. mockFlash.duration_ = 0;
  1401. result = seekable.call(mockFlash);
  1402. assert.equal(result.length, mockFlash.duration_, 'seekable is empty with a zero duration');
  1403. });
  1404. QUnit.test('play after ended seeks to the beginning', function (assert) {
  1405. var plays = 0;
  1406. var seeks = [];
  1407. Flash.prototype.play.call({
  1408. el_: {
  1409. /* eslint-disable camelcase */
  1410. vjs_play: function vjs_play() {
  1411. plays++;
  1412. }
  1413. /* eslint-enable camelcase */
  1414. },
  1415. ended: function ended() {
  1416. return true;
  1417. },
  1418. setCurrentTime: function setCurrentTime(time) {
  1419. seeks.push(time);
  1420. }
  1421. });
  1422. assert.equal(plays, 1, 'called play on the SWF');
  1423. assert.equal(seeks.length, 1, 'seeked on play');
  1424. assert.equal(seeks[0], 0, 'seeked to the beginning');
  1425. });
  1426. QUnit.test('duration returns NaN, Infinity or duration according to the HTML standard', function (assert) {
  1427. var duration = Flash.prototype.duration;
  1428. var mockedDuration = -1;
  1429. var mockedReadyState = 0;
  1430. var result = void 0;
  1431. var mockFlash = {
  1432. el_: {
  1433. /* eslint-disable camelcase */
  1434. vjs_getProperty: function vjs_getProperty() {
  1435. return mockedDuration;
  1436. }
  1437. /* eslint-enable camelcase */
  1438. },
  1439. readyState: function readyState() {
  1440. return mockedReadyState;
  1441. }
  1442. };
  1443. result = duration.call(mockFlash);
  1444. assert.ok(Number.isNaN(result), 'duration returns NaN when readyState equals 0');
  1445. mockedReadyState = 1;
  1446. result = duration.call(mockFlash);
  1447. assert.ok(!Number.isFinite(result), 'duration returns Infinity when duration property is less then 0');
  1448. mockedDuration = 1;
  1449. result = duration.call(mockFlash);
  1450. assert.equal(result, 1, 'duration returns duration property when readyState' + ' and duration property are both higher than 0');
  1451. });
  1452. QUnit.test('getVideoPlaybackQuality API exists', function (assert) {
  1453. var propertyCalls = [];
  1454. var videoPlaybackQuality = { test: 'test' };
  1455. var mockFlash = {
  1456. el_: {
  1457. /* eslint-disable camelcase */
  1458. vjs_getProperty: function vjs_getProperty(attr) {
  1459. propertyCalls.push(attr);
  1460. return videoPlaybackQuality;
  1461. }
  1462. /* eslint-enable camelcase */
  1463. }
  1464. };
  1465. assert.deepEqual(Flash.prototype.getVideoPlaybackQuality.call(mockFlash), videoPlaybackQuality, 'called to get property from flash');
  1466. assert.equal(propertyCalls.length, 1, 'only one property call');
  1467. assert.equal(propertyCalls[0], 'getVideoPlaybackQuality', 'called for getVideoPlaybackQuality');
  1468. });
  1469. QUnit.test('getVideoPlaybackQuality uses best available creationTime', function (assert) {
  1470. var origPerformance = window_1.performance;
  1471. var origDate = window_1.Date;
  1472. var videoPlaybackQuality = {};
  1473. var mockFlash = {
  1474. el_: {
  1475. /* eslint-disable camelcase */
  1476. vjs_getProperty: function vjs_getProperty(attr) {
  1477. return videoPlaybackQuality;
  1478. }
  1479. /* eslint-enable camelcase */
  1480. }
  1481. };
  1482. window_1.performance = void 0;
  1483. assert.notOk(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime, 'no creationTime when no performance API available');
  1484. window_1.performance = {
  1485. timing: {}
  1486. };
  1487. assert.notOk(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime, 'no creationTime when performance API insufficient');
  1488. window_1.performance = {
  1489. now: function now() {
  1490. return 4;
  1491. }
  1492. };
  1493. assert.equal(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime, 4, 'creationTime is performance.now when available');
  1494. window_1.Date = {
  1495. now: function now() {
  1496. return 10;
  1497. }
  1498. };
  1499. window_1.performance = {
  1500. timing: {
  1501. navigationStart: 3
  1502. }
  1503. };
  1504. assert.equal(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime, 7, 'creationTime uses Date.now() - navigationStart when available');
  1505. window_1.performance.now = function () {
  1506. return 4;
  1507. };
  1508. assert.equal(Flash.prototype.getVideoPlaybackQuality.call(mockFlash).creationTime, 4, 'creationTime prioritizes performance.now when available');
  1509. window_1.Date = origDate;
  1510. window_1.performance = origPerformance;
  1511. });
  1512. QUnit.module('Flash RTMP');
  1513. var streamToPartsAndBack = function streamToPartsAndBack(url) {
  1514. var parts = Flash.streamToParts(url);
  1515. return Flash.streamFromParts(parts.connection, parts.stream);
  1516. };
  1517. QUnit.test('test using both streamToParts and streamFromParts', function (assert) {
  1518. assert.ok(streamToPartsAndBack('rtmp://myurl.com/isthis') === 'rtmp://myurl.com/&isthis');
  1519. assert.ok(streamToPartsAndBack('rtmp://myurl.com/&isthis') === 'rtmp://myurl.com/&isthis');
  1520. assert.ok(streamToPartsAndBack('rtmp://myurl.com/isthis/andthis') === 'rtmp://myurl.com/isthis/&andthis');
  1521. });
  1522. QUnit.test('test streamToParts', function (assert) {
  1523. var parts = Flash.streamToParts('http://myurl.com/streaming&/is/fun');
  1524. assert.ok(parts.connection === 'http://myurl.com/streaming');
  1525. assert.ok(parts.stream === '/is/fun');
  1526. parts = Flash.streamToParts('http://myurl.com/&streaming&/is/fun');
  1527. assert.ok(parts.connection === 'http://myurl.com/');
  1528. assert.ok(parts.stream === 'streaming&/is/fun');
  1529. parts = Flash.streamToParts('http://myurl.com/really?streaming=fun&really=fun');
  1530. assert.ok(parts.connection === 'http://myurl.com/');
  1531. assert.ok(parts.stream === 'really?streaming=fun&really=fun');
  1532. parts = Flash.streamToParts('http://myurl.com/streaming/is/fun');
  1533. assert.ok(parts.connection === 'http://myurl.com/streaming/is/');
  1534. assert.ok(parts.stream === 'fun');
  1535. parts = Flash.streamToParts('whatisgoingonhere');
  1536. assert.ok(parts.connection === 'whatisgoingonhere');
  1537. assert.ok(parts.stream === '');
  1538. parts = Flash.streamToParts();
  1539. assert.ok(parts.connection === '');
  1540. assert.ok(parts.stream === '');
  1541. });
  1542. QUnit.test('test isStreamingSrc', function (assert) {
  1543. var isStreamingSrc = Flash.isStreamingSrc;
  1544. assert.ok(isStreamingSrc('rtmp://streaming.is/fun'));
  1545. assert.ok(isStreamingSrc('rtmps://streaming.is/fun'));
  1546. assert.ok(isStreamingSrc('rtmpe://streaming.is/fun'));
  1547. assert.ok(isStreamingSrc('rtmpt://streaming.is/fun'));
  1548. // test invalid protocols
  1549. assert.ok(!isStreamingSrc('rtmp:streaming.is/fun'));
  1550. assert.ok(!isStreamingSrc('rtmpz://streaming.is/fun'));
  1551. assert.ok(!isStreamingSrc('http://streaming.is/fun'));
  1552. assert.ok(!isStreamingSrc('https://streaming.is/fun'));
  1553. assert.ok(!isStreamingSrc('file://streaming.is/fun'));
  1554. });
  1555. }(videojs,sinon,QUnit));