UNPKG

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