UNPKG

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