removed output-disable in dbms-output fetching procedure
[mediawiki.git] / js2 / mwEmbed / libEmbedVideo / flowplayerEmbed.js
blobd2cecd056994466ac4671c03f8993decafb10611
1 /**
2  * metavid: mv_flashEmbed builds off of flowplayer api (included first in this file)
3  * THIS WILL BE DEPRECIATED SOON
4  */
6  /**
7  * flowplayer.js 3.0.0-rc5. The Flowplayer API.
8  *
9  * This file is part of Flowplayer, http://flowplayer.org
10  *
11  * Author: Tero Piirainen, <support@flowplayer.org>
12  * Copyright (c) 2008 Flowplayer Ltd
13  *
14  * Released under the MIT License:
15  * http://www.opensource.org/licenses/mit-license.php
16  *
17  * Version: 3.0.0-rc5 - Thu Nov 20 2008 22:09:49 GMT-0000 (GMT+00:00)
18  */
19 ( function() {
22         FEATURES
23         --------
24         - handling multiple instances
25         - Flowplayer programming API
26         - Flowplayer event model
27         - player loading / unloading
28         - $f() function
29         - jQuery support
32 /*jslint glovar: true, browser: true */
33 /*global flowplayer, $f */
35 // {{{ private utility methods
37         function log( args ) {
39                 // write into opera console
40                 if ( typeof opera == 'object' ) {
41                         opera.postError( "$f.fireEvent: " + args.join( " | " ) );
44                 } else if ( typeof console == 'object' ) {
45                         console.log( "$f.fireEvent", [].slice.call( args ) );
46                 }
47         }
49         // thanks: http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
50         function clone ( obj ) {
51                 if ( !obj || typeof obj != 'object' ) { return obj; }
52                 var temp = new obj.constructor();
53                 for ( var key in obj ) {
54                         if ( obj.hasOwnProperty( key ) ) {
55                                 temp[key] = clone ( obj[key] );
56                         }
57                 }
58                 return temp;
59         }
61         // stripped from jQuery, thanks John Resig
62         function each( obj, fn ) {
63                 if ( !obj ) { return; }
65                 var name, i = 0, length = obj.length;
67                 // object
68                 if ( length === undefined ) {
69                         for ( name in obj ) {
70                                 if ( fn.call( obj[name], name, obj[name] ) === false ) { break; }
71                         }
73                 // array
74                 } else {
75                         for ( var value = obj[0];
76                                 i < length && fn.call( value, i, value ) !== false; value = obj[++i] ) {
77                         }
78                 }
80                 return obj;
81         }
83         // convenience
84         function el( id ) {
85                 return document.getElementById( id );
86         }
88         // used extensively. a very simple implementation.
89         function extend( to, from, skipFuncs ) {
90                 if ( to && from ) {
91                         each( from, function( name, value ) {
92                                 if ( !skipFuncs || typeof value != 'function' ) {
93                                         to[name] = value;
94                                 }
95                         } );
96                 }
97         }
99         // var arr = select("elem.className");
100         function select( query ) {
101                 var index = query.indexOf( "." );
102                 if ( index != - 1 ) {
103                         var tag = query.substring( 0, index ) || "*";
104                         var klass = query.substring( index + 1, query.length );
105                         var els = [];
106                         each( document.getElementsByTagName( tag ), function() {
107                                 if ( this.className && this.className.indexOf( klass ) != - 1 ) {
108                                         els.push( this );
109                                 }
110                         } );
111                         return els;
112                 }
113         }
115         // fix event inconsistencies across browsers
116         function stopEvent( e ) {
117                 e = e || window.event;
119                 if ( e.preventDefault ) {
120                         e.stopPropagation();
121                         e.preventDefault();
123                 } else {
124                         e.returnValue = false;
125                         e.cancelBubble = true;
126                 }
127                 return false;
128         }
130         // push an event listener into existing array of listeners
131         function bind( to, evt, fn ) {
132                 to[evt] = to[evt] || [];
133                 to[evt].push( fn );
134         }
137         // generates an unique id
138         function makeId() {
139                 return "_" + ( "" + Math.random() ).substring( 2, 10 );
140         }
142 // }}}
143 // {{{ Clip
144         var Clip = function( json, index, player ) {
145                 // private variables
146                 var self = this;
147                 var cuepoints = { };
148                 var listeners = { };
149                 this.index = index;
151                 // instance variables
152                 if ( typeof json == 'string' ) {
153                         json = { url:json };
154                 }
156                 extend( this, json, true );
158                 // event handling
159                 each( ( "Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop" ).split( "," ),
160                         function() {
162                         var evt = "on" + this;
164                         // before event
165                         if ( evt.indexOf( "*" ) != - 1 ) {
166                                 evt = evt.substring( 0, evt.length - 1 );
167                                 var before = "onBefore" + evt.substring( 2 );
169                                 self[before] = function( fn ) {
170                                         bind( listeners, before, fn );
171                                         return self;
172                                 };
173                         }
175                         self[evt] = function( fn ) {
176                                 bind( listeners, evt, fn );
177                                 return self;
178                         };
180                         // set common clip event listeners to player level
181                         if ( index == - 1 ) {
182                                 if ( self[before] ) {
183                                         player[before] = self[before];
184                                 }
185                                 if ( self[evt] )  {
186                                         player[evt] = self[evt];
187                                 }
188                         }
189                 } );
191                 extend( this, {
192                         onCuepoint: function( points, fn ) {
194                                 // embedded cuepoints
195                                 if ( arguments.length == 1 ) {
196                                         cuepoints.embedded = [null, points];
197                                         return self;
198                                 }
200                                 if ( typeof points == 'number' ) {
201                                         points = [points];
202                                 }
204                                 var fnId = makeId();
205                                 cuepoints[fnId] = [points, fn];
207                                 if ( player.isLoaded() ) {
208                                         player._api().fp_addCuepoints( points, index, fnId );
209                                 }
211                                 return self;
212                         },
213                         update: function( json ) {
214                                 extend( self, json );
216                                 if ( player.isLoaded() ) {
217                                         player._api().fp_updateClip( json, index );
218                                 }
219                                 var conf = player.getConfig();
220                                 var clip = ( index == - 1 ) ? conf.clip : conf.playlist[index];
221                                 extend( clip, json, true );
222                         },
223                         // internal event for performing clip tasks. should be made private someday
224                         _fireEvent: function( evt, arg1, arg2, target ) {
226                                 if ( evt == 'onLoad' ) {
227                                         each( cuepoints, function( key, val ) {
228                                                 player._api().fp_addCuepoints( val[0], index, key );
229                                         } );
230                                         return false;
231                                 }
233                                 // target clip we are working against
234                                 if ( index != - 1 ) {
235                                         target = self;
236                                 }
238                                 if ( evt == 'onCuepoint' ) {
239                                         var fn = cuepoints[arg1];
240                                         if ( fn ) {
241                                                 return fn[1].call( player, target, arg2 );
242                                         }
243                                 }
245                                 if ( evt == 'onStart' || evt == 'onUpdate' ) {
247                                         extend( target, arg1 );
249                                         if ( !target.duration ) {
250                                                 target.duration = arg1.metaData.duration;
251                                         } else {
252                                                 target.fullDuration = arg1.metaData.duration;
253                                         }
254                                 }
256                                 var ret = true;
257                                 each( listeners[evt], function() {
258                                         ret = this.call( player, target, arg1 );
259                                 } );
260                                 return ret;
261                         }
262                 } );
264                 // get cuepoints from config
265                 if ( json.onCuepoint ) {
266                         self.onCuepoint.apply( self, json.onCuepoint );
267                         delete json.onCuepoint;
268                 }
270                 // get other events
271                 each( json, function( key, val ) {
272                         if ( typeof val == 'function' ) {
273                                 bind( listeners, key, val );
274                                 delete json[key];
275                         }
276                 } );
278                 // setup common clip event callbacks for Player object too (shortcuts)
279                 if ( index == - 1 ) {
280                         player.onCuepoint = this.onCuepoint;
281                 }
282         };
284 // }}}
285 // {{{ Plugin
286         var Plugin = function( name, json, player, fn ) {
287                 var listeners = { };
288                 var self = this;
289                 var hasMethods = false;
291                 if ( fn ) {
292                         extend( listeners, fn );
293                 }
295                 // custom callback functions in configuration
296                 each( json, function( key, val ) {
297                         if ( typeof val == 'function' ) {
298                                 listeners[key] = val;
299                                 delete json[key];
300                         }
301                 } );
303                 // core plugin methods
304                 extend( this, {
305                         animate: function( props, speed, fn ) {
306                                 if ( !props ) {
307                                         return self;
308                                 }
310                                 if ( typeof speed == 'function' ) {
311                                         fn = speed;
312                                         speed = 500;
313                                 }
315                                 if ( typeof props == 'string' ) {
316                                         var key = props;
317                                         props = { };
318                                         props[key] = speed;
319                                         speed = 500;
320                                 }
322                                 if ( fn ) {
323                                         var fnId = makeId();
324                                         listeners[fnId] = fn;
325                                 }
327                                 if ( speed === undefined ) { speed = 500; }
328                                 json = player._api().fp_animate( name, props, speed, fnId );
329                                 return self;
330                         },
331                         css: function( props, val ) {
332                                 if ( val !== undefined ) {
333                                         var css = { };
334                                         css[props] = val;
335                                         props = css;
336                                 }
337                                 try {
338                                         json = player._api().fp_css( name, props );
339                                         extend( self, json );
340                                         return self;
341                                 } catch ( e ) {
342                                         js_log( 'flow player could not set css: ' + json );
343                                 }
344                         },
345                         show: function() {
346                                 this.display = 'block';
347                                 player._api().fp_showPlugin( name );
348                                 return self;
349                         },
350                         hide: function() {
351                                 this.display = 'none';
352                                 player._api().fp_hidePlugin( name );
353                                 return self;
354                         },
355                         toggle: function() {
356                                 this.display = player._api().fp_togglePlugin( name );
357                                 return self;
358                         },
359                         fadeTo: function( o, speed, fn ) {
361                                 if ( typeof speed == 'function' ) {
362                                         fn = speed;
363                                         speed = 500;
364                                 }
366                                 if ( fn ) {
367                                         var fnId = makeId();
368                                         listeners[fnId] = fn;
369                                 }
370                                 this.display = player._api().fp_fadeTo( name, o, speed, fnId );
371                                 this.opacity = o;
372                                 return self;
373                         },
374                         fadeIn: function( speed, fn ) {
375                                 return self.fadeTo( 1, speed, fn );
376                         },
377                         fadeOut: function( speed, fn ) {
378                                 return self.fadeTo( 0, speed, fn );
379                         },
380                         getName: function() {
381                                 return name;
382                         },
383                         // internal method not meant to be used by clients
384                         _fireEvent: function( evt, arg ) {
385                                 // update plugins properties & methods
386                                 if ( evt == 'onUpdate' ) {
387                                         var json = arg || player._api().fp_getPlugin( name );
388                                         if ( !json ) { return; }
390                                         Extend( self, json );
391                                         delete self.methods;
392         
393                                         if ( !hasMethods ) {
394                                                 each( json.methods, function() {
395                                                         var method = "" + this;
396         
397                                                         self[method] = function() {
398                                                                 var a = [].slice.call( arguments );
399                                                                 var ret = player._api().fp_invoke( name, method, a );
400                                                                 return ret == 'undefined' ? self : ret;
401                                                         };
402                                                 } );
403                                                 hasMethods = true;
404                                         }
405                                 }
407                                 // plugin callbacks
408                                 var fn = listeners[evt];
410                                 if ( fn ) {
411                                         fn.call( self, arg );
413                                         // "one-shot" callback
414                                         if ( evt.substring( 0, 1 ) == "_" ) {
415                                                 delete listeners[evt];
416                                         }
417                                 }
418                         }
420                 } );
422         };
424 // }}}
425 function Player( wrapper, params, conf ) {
426         // private variables (+ arguments)
427         var
428                 self = this,
429                 api = null,
430                 html,
431                 commonClip,
432                 playlist = [],
433                 plugins = { },
434                 listeners = { },
435                 playerId,
436                 apiId,
437                 activeIndex,
438                 swfHeight,
439                 wrapperHeight;
441 // {{{ public methods
442         extend( self, {
443                 id: function() {
444                         return playerId;
445                 },
446                 isLoaded: function() {
447                         return ( api !== null );
448                 },
449                 getParent: function() {
450                         return wrapper;
451                 },
452                 hide: function( all ) {
453                         if ( all ) { wrapper.style.height = "0px"; }
454                         if ( api ) { api.style.height = "0px"; }
455                         return self;
456                 },
457                 show: function() {
458                         wrapper.style.height = wrapperHeight + "px";
459                         if ( api ) { api.style.height = swfHeight + "px"; }
460                         return self;
461                 },
462                 isHidden: function() {
463                         return api && parseInt( api.style.height, 10 ) === 0;
464                 },
465                 load: function( fn ) {
467                         if ( !api && self._fireEvent( "onBeforeLoad" ) !== false ) {
469                                 // unload all instances
470                                 each( players, function()  {
471                                         this.unload();
472                                 } );
474                                 html = wrapper.innerHTML;
475                                 flashembed( wrapper, params, { config: conf } );
477                                 // function argument
478                                 if ( fn ) {
479                                         fn.cached = true;
480                                         bind( listeners, "onLoad", fn );
481                                 }
482                         }
484                         return self;
485                 },
486                 unload: function() {
487                         if ( api && html.replace( /\s/g, '' ) !== '' && !api.fp_isFullscreen() &&
488                           self._fireEvent( "onBeforeUnload" ) !== false ) {
489                                 api.fp_close();
490                                 wrapper.innerHTML = html;
491                                 self._fireEvent( "onUnload" );
492                                 api = null;
493                         }
495                         return self;
496                 },
497                 getClip: function( index ) {
498                         if ( index === undefined ) {
499                                 index = activeIndex;
500                         }
501                         return playlist[index];
502                 },
503                 getCommonClip: function() {
504                         return commonClip;
505                 },
506                 getPlaylist: function() {
507                         return playlist;
508                 },
509                 getPlugin: function( name ) {
510                   var plugin = plugins[name];
511                         // create plugin if nessessary
512                         if ( !plugin && self.isLoaded() ) {
513                                 var json = self._api().fp_getPlugin( name );
514                                 if ( json ) {
515                                         plugin = new Plugin( name, json, self );
516                                         plugins[name] = plugin;
517                                 }
518                         }
519                         return plugin;
520                 },
521                 getScreen: function() {
522                         return self.getPlugin( "screen" );
523                 },
524                 getControls: function() {
525                         return self.getPlugin( "controls" );
526                 },
527                 getConfig: function() {
528                         return clone ( conf );
529                 },
530                 getFlashParams: function() {
531                         return params;
532                 },
533                 loadPlugin: function( name, url, props, fn ) {
534                         // properties not supplied
535                         if ( typeof props == 'function' ) {
536                                 fn = props;
537                                 props = { };
538                         }
540                         // if fn not given, make a fake id so that plugin's onUpdate get's fired
541                         var fnId = fn ? makeId() : "_";
542                         self._api().fp_loadPlugin( name, url, props, fnId );
544                         // create new plugin
545                         var arg = { };
546                         arg[fnId] = fn;
547                         var p = new Plugin( name, null, self, arg );
548                         plugins[name] = p;
549                         return p;
550                 },
551                 getState: function() {
552                         return api ? api.fp_getState() : - 1;
553                 },
554                 // "lazy" play
555                 play: function( clip ) {
556                         function play() {
557                                 if ( clip !== undefined ) {
558                                         self._api().fp_play( clip );
559                                 } else {
560                                         if ( typeof self._api().fp_play == 'function' )
561                                                 self._api().fp_play();
562                                 }
563                         }
565                         if ( api ) {
566                                 play();
567                         } else {
568                                 self.load( function() {
569                                         play();
570                                 } );
571                         }
573                         return self;
574                 },
575                 getVersion: function() {
576                         var js = "flowplayer.js 3.0.0-rc5";
577                         if ( api ) {
578                                 var ver = api.fp_getVersion();
579                                 ver.push( js );
580                                 return ver;
581                         }
582                         return js;
583                 },
584                 _api: function() {
585                         if ( !api ) {
586                                 throw "Flowplayer " + self.id() + " not loaded. Try moving your call to player's onLoad event";
587                         }
588                         return api;
589                 },
590                 _dump: function() {
591                         console.log( listeners );
592                 }
593         } );
595         // event handlers
596         each( ( "Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,Fullscreen*,FullscreenExit,Error" ).split( "," ),
597                 function() {
598                         var name = "on" + this;
600                         // before event
601                         if ( name.indexOf( "*" ) != - 1 ) {
602                                 name = name.substring( 0, name.length - 1 );
603                                 var name2 = "onBefore" + name.substring( 2 );
604                                 self[name2] = function( fn ) {
605                                         bind( listeners, name2, fn );
606                                         return self;
607                                 };
608                         }
610                         // normal event
611                         self[name] = function( fn ) {
612                                 bind( listeners, name, fn );
613                                 return self;
614                         };
615                 }
616         );
618         // core API methods
619         each( ( "pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,reset" ).split( "," ),
620                 function() {
621                         var name = this;
623                         self[name] = function( arg ) {
624                                 if ( !api ) { return self; }
625                                 try {
626                                         var ret = ( arg === undefined ) ? api["fp_" + name]() : api["fp_" + name]( arg );
627                                         return ret == 'undefined' ? self : ret;
628                                 } catch ( e ) {
629                                         js_log( 'flowplayer could not access fp_ ' + name );
630                                 }
631                         };
632                 }
633         );
635 // }}}
636 // {{{ public method: _fireEvent
637         self._fireEvent = function( evt, arg0, arg1, arg2 ) {
638                 if ( conf.debug ) {
639                         log( arguments );
640                 }
642                 // internal onLoad
643                 if ( evt == 'onLoad' && !api ) {
644                         api = api || el( apiId );
645                         swfHeight = api.clientHeight;
647                         each( playlist, function() {
648                                 this._fireEvent( "onLoad" );
649                         } );
651                         each( plugins, function( name, p ) {
652                                 p._fireEvent( "onUpdate" );
653                         } );
655                         commonClip._fireEvent( "onLoad" );
656                 }
658                 if ( evt == 'onContextMenu' ) {
659                         each( conf.contextMenu[arg0], function( key, fn )  {
660                                 fn.call( self );
661                         } );
662                         return;
663                 }
665                 if ( evt == 'onPluginEvent' ) {
666                         var name = arg0.name || arg0;
667                         var p = plugins[name];
668                         if ( p ) {
669                                 if ( arg0.name ) {
670                                         p._fireEvent( "onUpdate", arg0 );
671                                 }
672                                 p._fireEvent( arg1 );
673                         }
674                         return;
675                 }
677                 // onPlaylistReplace
678                 if ( evt == 'onPlaylistReplace' ) {
679                         playlist = [];
680                         var index = 0;
681                         each( arg0, function() {
682                                 playlist.push( new Clip( this, index++ ) );
683                         } );
684                 }
686                 var ret = true;
688                 // clip event
689                 if ( arg0 === 0 || ( arg0 && arg0 >= 0 ) ) {
690                         activeIndex = arg0;
691                         var clip = playlist[arg0];
693                         if ( clip ) {
694                                 ret = clip._fireEvent( evt, arg1, arg2 );
695                         }
697                         if ( !clip || ret !== false ) {
698                                 // clip argument is given for common clip, because it behaves as the target
699                                 ret = commonClip._fireEvent( evt, arg1, arg2, clip );
700                         }
701                 }
703                 // player event
704                 var i = 0;
705                 each( listeners[evt], function() {
706                         ret = this.call( self, arg0 );
708                         // remove cached entry
709                         if ( this.cached ) {
710                                 listeners[evt].splice( i, 1 );
711                         }
713                         // break loop
714                         if ( ret === false ) { return false;     }
715                         i++;
717                 } );
719                 return ret;
720         };
722 // }}}
723 // {{{ init
724         function init() {
725                 if ( $f( wrapper ) ) {
726                         return null;
727                 }
729                 wrapperHeight = parseInt( wrapper.style.height ) || wrapper.clientHeight;
731                 // register this player into global array of instances
732                 players.push( self );
735                 // flashembed parameters
736                 if ( typeof params == 'string' ) {
737                         params = { src: params };
738                 }
740                 // playerId
741                 playerId = wrapper.id || "fp" + makeId();
742                 apiId = params.id || playerId + "_api";
743                 params.id = apiId;
744                 conf.playerId = playerId;
747                 // plain url is given as config
748                 if ( typeof conf == 'string' ) {
749                         conf = { clip: { url:conf } };
750                 }
752                 // common clip is always there
753                 conf.clip = conf.clip || { };
754                 commonClip = new Clip( conf.clip, - 1, self );
757                 // wrapper href as playlist
758                 if ( wrapper.getAttribute( "href" ) ) {
759                         conf.playlist = [ { url:wrapper.getAttribute( "href", 2 ) }];
760                 }
762                 // playlist
763                 conf.playlist = conf.playlist || [conf.clip];
765                 var index = 0;
766                 each( conf.playlist, function() {
768                         var clip = this;
770                         // clip is an array, we don't allow that
771                         if ( typeof clip == 'object' && clip.length )  {
772                                 clip = "" + clip;
773                         }
775                         if ( !clip.url && typeof clip == 'string' ) {
776                                 clip = { url: clip };
777                         }
779                         // populate common clip properties to each clip
780                         extend( clip, conf.clip, true );
782                         // modify configuration playlist
783                         conf.playlist[index] = clip;
785                         // populate playlist array
786                         clip = new Clip( clip, index, self );
787                         playlist.push( clip );
788                         index++;
789                 } );
792                 // event listeners
793                 each( conf, function( key, val ) {
794                         if ( typeof val == 'function' ) {
795                                 bind( listeners, key, val );
796                                 delete conf[key];
797                         }
798                 } );
801                 // plugins
802                 each( conf.plugins, function( name, val ) {
803                         if ( val ) {
804                                 plugins[name] = new Plugin( name, val, self );
805                         }
806                 } );
809                 // setup controlbar plugin if not explicitly defined
810                 if ( !conf.plugins || conf.plugins.controls === undefined ) {
811                         plugins.controls = new Plugin( "controls", null, self );
812                 }
814                 // Flowplayer uses black background by default
815                 params.bgcolor = params.bgcolor || "#000000";
818                 // setup default settings for express install
819                 params.version = params.version || [9, 0];
820                 params.expressInstall = 'http://www.flowplayer.org/swf/expressinstall.swf';
823                 // click function
824                 function doClick( e ) {
825                         if ( self._fireEvent( "onBeforeClick" ) !== false ) {
826                                 self.load();
827                         }
828                         return stopEvent( e );
829                 }
831                 // defer loading upon click
832                 html = wrapper.innerHTML;
833                 if ( html.replace( /\s/g, '' ) !== '' ) {
835                         if ( wrapper.addEventListener ) {
836                                 wrapper.addEventListener( "click", doClick, false );
838                         } else if ( wrapper.attachEvent ) {
839                                 wrapper.attachEvent( "onclick", doClick );
840                         }
842                 // player is loaded upon page load
843                 } else {
845                         // prevent default action from wrapper (safari problem) loaded
846                         if ( wrapper.addEventListener ) {
847                                 wrapper.addEventListener( "click", stopEvent, false );
848                         }
850                         // load player
851                         self.load();
852                 }
854         }
856         // possibly defer initialization until DOM get's loaded
857         if ( typeof wrapper == 'string' ) {
858                 flashembed.domReady( function() {
859                         var node = el( wrapper );
861                         if ( !node ) {
862                                 throw "Flowplayer cannot access element: " + wrapper;
863                         } else {
864                                 wrapper = node;
865                                 init();
866                         }
867                 } );
869         // we have a DOM element so page is already loaded
870         } else {
871                 init();
872         }
873 // }}}
876 // {{{ flowplayer() & statics
877 // container for player instances
878 var players = [];
880 // this object is returned when multiple player's are requested
881 function Iterator( arr ) {
882         this.length = arr.length;
884         this.each = function( fn )  {
885                 each( arr, fn );
886         };
888         this.size = function() {
889                 return arr.length;
890         };
893 // these two variables are the only global variables
894 window.flowplayer = window.$f = function() {
895         var instance = null;
896         var arg = arguments[0];
898         // $f()
899         if ( !arguments.length ) {
900                 each( players, function() {
901                         if ( this.isLoaded() )  {
902                                 instance = this;
903                                 return false;
904                         }
905                 } );
907                 return instance || players[0];
908         }
910         if ( arguments.length == 1 ) {
911                 // $f(index);
912                 if ( typeof arg == 'number' ) {
913                         return players[arg];
915                 // $f(wrapper || 'containerId' || '*');
916                 } else {
917                         // $f("*");
918                         if ( arg == '*' ) {
919                                 return new Iterator( players );
920                         }
922                         // $f(wrapper || 'containerId');
923                         each( players, function() {
924                                 if ( this.id() == arg.id || this.id() == arg || this.getParent() == arg )  {
925                                         instance = this;
926                                         return false;
927                                 }
928                         } );
930                         return instance;
931                 }
932         }
934         // instance builder
935         if ( arguments.length > 1 ) {
936                 var swf = arguments[1];
937                 var conf = ( arguments.length == 3 ) ? arguments[2] : { };
939                 if ( typeof arg == 'string' ) {
940                         // select arg by classname
941                         if ( arg.indexOf( "." ) != - 1 ) {
942                                 var instances = [];
944                                 each( select( arg ), function() {
945                                         instances.push( new Player( this, clone ( swf ), clone ( conf ) ) );
946                                 } );
948                                 return new Iterator( instances );
950                         // select node by id
951                         } else {
952                                 var node = el( arg );
953                                 return new Player( node !== null ? node : arg, swf, conf );
954                         }
957                 // arg is a DOM element
958                 } else if ( arg ) {
959                         return new Player( arg, swf, conf );
960                 }
961         }
963         return null;
966 extend( window.$f, {
967         // called by Flash External Interface
968         fireEvent: function( id, evt, a0, a1, a2 ) {
969                 var p = $f( id );
970                 return p ? p._fireEvent( evt, a0, a1, a2 ) : null;
971         },
973         // create plugins by modifying Player's prototype
974         addPlugin: function( name, fn ) {
975                 Player.prototype[name] = fn;
976                 return $f;
977         },
979         // utility methods for plugin developers
980         each: each,
982         extend: extend
983 } );
985 // }}}
986 // {{{ jQuery support
988 if ( typeof jQuery == 'function' ) {
989         jQuery.prototype.flowplayer = function( params, conf ) {
991                 // select instances
992                 if ( !arguments.length || typeof arguments[0] == 'number' ) {
993                         var arr = [];
994                         this.each( function()  {
995                                 var p = $f( this );
996                                 if ( p ) {
997                                         arr.push( p );
998                                 }
999                         } );
1000                         return arguments.length ? arr[arguments[0]] : new Iterator( arr );
1001                 }
1003                 // create flowplayer instances
1004                 return this.each( function() {
1005                         $f( this, clone ( params ), conf ? clone ( conf ) : { } );
1006                 } );
1008         };
1012 // }}}
1015 } )();
1017  * flashembed 0.34. Adobe Flash embedding script
1019  * http://flowplayer.org/tools/flash-embed.html
1021  * Copyright (c) 2008 Tero Piirainen (support@flowplayer.org)
1023  * Released under the MIT License:
1024  * http://www.opensource.org/licenses/mit-license.php
1026  * >> Basically you can do anything you want but leave this header as is <<
1028  * first version 0.01 - 03/11/2008
1029  * version 0.34 - Tue Nov 11 2008 09:09:52 GMT-0000 (GMT+00:00)
1030  */
1031 ( function() {
1033 // {{{ utility functions
1035 var jQ = typeof jQuery == 'function';
1038 // from "Pro JavaScript techniques" by John Resig
1039 function isDomReady() {
1041         if ( domReady.done )  { return false; }
1043         var d = document;
1044         if ( d && d.getElementsByTagName && d.getElementById && d.body ) {
1045                 clearInterval( domReady.timer );
1046                 domReady.timer = null;
1048                 for ( var i = 0; i < domReady.ready.length; i++ ) {
1049                         domReady.ready[i].call();
1050                 }
1052                 domReady.ready = null;
1053                 domReady.done = true;
1054         }
1057 // if jQuery is present, use it's more effective domReady method
1058 var domReady = jQ ? jQuery : function( f ) {
1060         if ( domReady.done ) {
1061                 return f();
1062         }
1064         if ( domReady.timer ) {
1065                 domReady.ready.push( f );
1067         } else {
1068                 domReady.ready = [f];
1069                 domReady.timer = setInterval( isDomReady, 13 );
1070         }
1074 // override extend params function
1075 function extend( to, from ) {
1076         if ( from ) {
1077                 for ( key in from ) {
1078                         if ( from.hasOwnProperty( key ) ) {
1079                                 to[key] = from[key];
1080                         }
1081                 }
1082         }
1084         return to;
1088 function concatVars( vars ) {
1089         var out = "";
1091         for ( var key in vars ) {
1092                 if ( vars[key] ) {
1093                         out += [key] + '=' + asString( vars[key] ) + '&';
1094                 }
1095         }
1096         return out.substring( 0, out.length - 1 );
1101 // JSON.asString() function
1102 function asString( obj ) {
1104         switch ( typeOf( obj ) ) {
1105                 case 'string':
1106                         obj = obj.replace( new RegExp( '(["\\\\])', 'g' ), '\\$1' );
1108                         // flash does not handle %- characters well. transforms "50%" to "50pct" (a dirty hack, I admit)
1109                         obj = obj.replace( /^\s?(\d+)%/, "$1pct" );
1110                         return '"' + obj + '"';
1112                 case 'array':
1113                         return '[' + map( obj, function( el ) {
1114                                 return asString( el );
1115                         } ).join( ',' ) + ']';
1117                 case 'function':
1118                         return '"function()"';
1120                 case 'object':
1121                         var str = [];
1122                         for ( var prop in obj ) {
1123                                 if ( obj.hasOwnProperty( prop ) ) {
1124                                         str.push( '"' + prop + '":' + asString( obj[prop] ) );
1125                                 }
1126                         }
1127                         return '{' + str.join( ',' ) + '}';
1128         }
1130         // replace ' --> "  and remove spaces
1131         return String( obj ).replace( /\s/g, " ").replace( /\'/g, "\"" );
1135 // private functions
1136 function typeOf(obj) {
1137         if (obj === null || obj === undefined) { return false; }
1138         var type = typeof obj;
1139         return (type == 'object' && obj.push) ? 'array' : type;
1143 // version 9 bugfix: (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
1144 if (window.attachEvent) {
1145         window.attachEvent("onbeforeunload", function() {
1146                 __flash_unloadHandler = function() {};
1147                 __flash_savedUnloadHandler = function() {};
1148         });
1151 function map(arr, func) {
1152         var newArr = [];
1153         for (var i in arr) {
1154                 if (arr.hasOwnProperty(i)) {
1155                         newArr[i] = func(arr[i]);
1156                 }
1157         }
1158         return newArr;
1161 function getEmbedCode(p, c) {
1162         var html = ' < embed type = "application/x-shockwave-flash" ';
1164         if (p.id) { extend(p, {name:p.id}); }
1166         for (var key in p) {
1167                 if (p[key] !== null) {
1168                         html += key + '="' + p[key] + '"\n\t';
1169                 }
1170         }
1172         if (c) {
1173                  html += 'flashvars=\'' + concatVars( c ) + '\'';
1174         }
1176         // thanks Tom Price (07/17/2008)
1177         html += '/>';
1179         return html;
1182 function getObjectCode( p, c, embeddable ) {
1184         var html = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
1185         html += 'width="' + p.width + '" height="' + p.height + '"';
1187         // force id for IE. otherwise embedded Flash object cannot be returned
1188         if ( !p.id && document.all ) {
1189                 p.id = "_" + ( "" + Math.random() ).substring( 5 );
1190         }
1192         if ( p.id ) {
1193                 html += ' id="' + p.id + '"';
1194         }
1196         html += '>';
1198         // sometimes ie fails to load flash if it's on cache
1199         if ( document.all ) {
1200                 p.src += ( ( p.src.indexOf( "?" ) != - 1 ? "&" : "?" ) + Math.random() );
1201         }
1203         html += '\n\t<param name="movie" value="' + p.src + '" />';
1205         var e = extend( { }, p );
1206         e.id = e.width = e.height = e.src = null;
1208         for ( var k in e ) {
1209                 if ( e[k] !== null ) {
1210                         html += '\n\t<param name="' + k + '" value="' + e[k] + '" />';
1211                 }
1212         }
1214         if ( c ) {
1215                 html += '\n\t<param name="flashvars" value=\'' + concatVars( c ) + '\' />';
1216         }
1218         if ( embeddable ) {
1219                 html += getEmbedCode( p, c );
1220         }
1222         html += "</object>";
1224         return html;
1227 function getFullHTML( p, c ) {
1228         return getObjectCode( p, c, true );
1231 function getHTML( p, c ) {
1232         var isNav = navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length;
1233         return ( isNav ) ? getEmbedCode( p, c ) : getObjectCode( p, c );
1236 // }}}
1239 window.flashembed = function( root, userParams, flashvars ) {
1242 // {{{ construction
1244         // setup params
1245         var params = {
1247                 // very common params
1248                 src: '#',
1249                 width: '100%',
1250                 height: '100%',
1252                 // flashembed specific options
1253                 version:null,
1254                 onFail:null,
1255                 expressInstall:null,
1256                 debug: false,
1258                 // flashembed defaults
1259                 // bgcolor: 'transparent',
1260                 allowfullscreen: true,
1261                 allowscriptaccess: 'always',
1262                 quality: 'high',
1263                 type: 'application/x-shockwave-flash',
1264                 pluginspage: 'http://www.adobe.com/go/getflashplayer'
1265         };
1268         if ( typeof userParams == 'string' ) {
1269                 userParams = { src: userParams };
1270         }
1272         extend( params, userParams );
1274         var version = flashembed.getVersion();
1275         var required = params.version;
1276         var express = params.expressInstall;
1277         var debug = params.debug;
1280         if ( typeof root == 'string' ) {
1281                 var el = document.getElementById( root );
1282                 if ( el ) {
1283                         root = el;
1284                 } else {
1285                         domReady( function() {
1286                                 flashembed( root, userParams, flashvars );
1287                         } );
1288                         return;
1289                 }
1290         }
1292         if ( !root ) { return; }
1295         // is supported
1296         if ( !required || flashembed.isSupported( required ) ) {
1297                 params.onFail = params.version = params.expressInstall = params.debug = null;
1299                 // root.innerHTML may cause broplems: http://domscripting.com/blog/display/99
1300                 // thanks to: Ryan Rud
1301                 // var tmp = document.createElement("extradiv");
1302                 // tmp.innerHTML = getHTML();
1303                 // root.appendChild(tmp);
1305                 root.innerHTML = getHTML( params, flashvars );
1307                 // return our API
1308                 return root.firstChild;
1310         // custom fail event
1311         } else if ( params.onFail ) {
1312                 var ret = params.onFail.call( params, flashembed.getVersion(), flashvars );
1313                 if ( ret === true ) { root.innerHTML = ret; }
1316         // express install
1317         } else if ( required && express && flashembed.isSupported( [6, 65] ) ) {
1319                 extend( params, { src: express } );
1321                 flashvars = {
1322                         MMredirectURL: location.href,
1323                         MMplayerType: 'PlugIn',
1324                         MMdoctitle: document.title
1325                 };
1327                 root.innerHTML = getHTML( params, flashvars );
1329         // not supported
1330         } else {
1332                 // minor bug fixed here 08.04.2008 (thanks JRodman)
1334                 if ( root.innerHTML.replace( /\s/g, '') !== '' ) {
1335                         // custom content was supplied
1337                 } else {
1338                         root.innerHTML =
1339                                 "<h2>Flash version " + required + " or greater is required</h2>" +
1340                                 "<h3>" +
1341                                         ( version[0] > 0 ? "Your version is " + version : "You have no flash plugin installed" ) +
1342                                 "</h3>" +
1343                                 "<p>Download latest version from <a href='" + params.pluginspage + "'>here</a></p>";
1344                 }
1345         }
1347         return root;
1349 // }}}
1355 // {{{ static methods
1357 extend( window.flashembed, {
1359         // returns arr[major, fix]
1360         getVersion: function() {
1362                 var version = [0, 0];
1364                 if ( navigator.plugins && typeof navigator.plugins["Shockwave Flash"] == "object" ) {
1365                         var _d = navigator.plugins["Shockwave Flash"].description;
1366                         if ( typeof _d != "undefined" ) {
1367                                 _d = _d.replace( /^.*\s+(\S+\s+\S+$ )/, "$1" );
1368                                 var _m = parseInt( _d.replace( /^(.*)\..*$/, "$1" ), 10 );
1369                                 var _r = / r / .test( _d ) ? parseInt( _d.replace( /^.*r(.*)$/ , "$1" ), 10 ) : 0;
1370                                 version = [_m, _r];
1371                         }
1373                 } else if ( window.ActiveXObject ) {
1375                         try { // avoid fp 6 crashes
1376                                 var _a = new ActiveXObject( "ShockwaveFlash.ShockwaveFlash.7" );
1378                         } catch ( e ) {
1379                                 try {
1380                                         _a = new ActiveXObject( "ShockwaveFlash.ShockwaveFlash.6" );
1381                                         version = [6, 0];
1382                                         _a.AllowScriptAccess = "always"; // throws if fp < 6.47
1384                                 } catch ( ee ) {
1385                                         if ( version[0] == 6 ) { return; }
1386                                 }
1387                                 try {
1388                                         _a = new ActiveXObject( "ShockwaveFlash.ShockwaveFlash" );
1389                                 } catch ( eee ) {
1391                                 }
1393                         }
1395                         if ( typeof _a == "object" ) {
1396                                 _d = _a.GetVariable( "$version" ); // bugs in fp 6.21 / 6.23
1397                                 if ( typeof _d != "undefined" ) {
1398                                         _d = _d.replace( /^\S+\s+(.*)$/, "$1" ).split( "," );
1399                                         version = [parseInt( _d[0], 10 ), parseInt( _d[2], 10 )];
1400                                 }
1401                         }
1402                 }
1404                 return version;
1405         },
1407         isSupported: function( version ) {
1408                 var now = flashembed.getVersion();
1409                 var ret = ( now[0] > version[0] ) || ( now[0] == version[0] && now[1] >= version[1] );
1410                 return ret;
1411         },
1413         domReady: domReady,
1415         // returns a String representation from JSON object
1416         asString: asString,
1418         getHTML: getHTML,
1420         getFullHTML: getFullHTML
1422 } );
1424 // }}}
1427 // setup jquery support
1428 if ( jQ ) {
1430         jQuery.prototype.flashembed = function( params, flashvars ) {
1431                 return this.each( function() {
1432                         flashembed( this, params, flashvars );
1433                 } );
1434         };
1438 } )();
1440 /************************************************
1441 ********* mv_embed extension to flowplayer.js ***
1442 ************************************************/
1443 var flowplayerEmbed = {
1444         instanceOf:'flowplayerEmbed',
1445         monitorTimerId : 0,
1446         old_pid:0,
1447         didSeekJump:false,
1448         startedTimedPlayback:false,
1449         didDateStartTimeRestore:false,
1450         supports: {
1451                 'play_head' : true,
1452                 'pause' : true,
1453                 'stop' : true,
1454                 'time_display' : true,
1455                 'volume_control' : true
1456         },
1457         getEmbedHTML: function () {
1458                 setTimeout( 'document.getElementById(\'' + this.id + '\').postEmbedJS()', 150 );
1459                 return this.wrapEmebedContainer( this.getEmbedObj() );
1460         },
1461         getEmbedObj:function() {
1462                 // give the embed element a unique pid (work around for flowplayer persistence)
1463                 if ( this.old_pid != 0 ) {
1464                         this.pid = this.pid + '_' + this.old_pid;
1465                 }
1466                 return '<a  ' +
1467                                         'href="' + this.getSrc() + '" ' +
1468                                         'style="display:block;width:' + parseInt( this.width ) + 'px;height:' + parseInt( this.height ) + 'px" ' +
1469                                         'id="' + this.pid + '">' +
1470                                 '</a>';
1471         },
1472         postEmbedJS: function()
1473         {
1474                 var _this = this;
1475                 js_log( 'embedFlow: uri:' + this.getSrc() + "\n" + mv_embed_path + 'libEmbedVideo/binPlayers/flowplayer/flowplayer-3.0.1.swf' ) ;
1476                 var flowConfig = {
1477                         clip: {
1478                                 url: this.getSrc(),
1479                                 // when this is false playback does not start until play button is pressed
1480                                 autoPlay: true
1481                         },
1482                         plugins: {
1483                                 controls: {
1484                                    all: false,
1485                                    fullscreen: true,
1486                                    backgroundColor: 'transparent',
1487                                    backgroundGradient: 'none',
1488                                    autoHide:'always',
1489                                    top:'95%',
1490                                    right:'0px'
1491                                 }
1492                         },
1493                         screen: {
1494                                 opacity : '1.0'
1495                         }
1496                 };
1498                 // if in preview mode set grey and lower volume until "ready"
1499                 if ( this.preview_mode ) {
1500                         flowConfig.screen.opacity = 0.2;
1501                 }
1503                 $f( this.pid,  mv_embed_path + 'binPlayers/flowplayer/flowplayer-3.0.1.swf', flowConfig );
1504                 // get the this.fla value:
1505                 this.getFLA();
1506                 // set up bindings (for when interacting with the swf causes action:
1507                 this.fla.onPause( function() {
1508                         _this.parent_pause();   // update the interface
1509                 } )
1510                 this.fla.onResume( function() {
1511                         _this.parent_play();    // update the interface
1512                 } );
1514                 // start monitor:
1515                 this.monitor();
1516                 this.old_pid++;
1517         },
1518         /* js hooks/controls */
1519         play: function() {
1520                 this.getFLA();
1521                 // update play/pause button etc
1522                 this.parent_play();
1523                 if ( this.fla ) {
1524                         this.fla.play();
1526                         // on a resume make sure volume and opacity are correct
1527                         this.restorePlayer();
1528                         setTimeout( '$j(\'#' + this.id + '\').get(0).monitor()', 250 );
1529                 }
1530         },
1531         // @@todo support mute
1532         toggleMute: function() {
1533                 this.parent_toggleMute();
1534                 this.getFLA();
1535                 if ( this.fla ) {
1536                         if ( this.muted ) {
1538                         } else {
1540                         }
1541                 }
1542         },
1543         // @@ Suport UpDateVolumen
1544         updateVolumen:function( perc ) {
1545                 this.getFLA();
1546                 if ( this.fla )this.fla.setVolume( perc * 100 );
1548     },
1549     // @@ Get Volumen
1550         getVolumen:function() {
1551                 this.getFLA();
1552                 if ( this.fla )
1553                         return this.fla.getVolume() / 100;
1554     },
1555         fullscreen:function() {
1556                 if ( this.fla ) {
1557                         this.fla.fullscreen();
1558                 } else {
1559                         js_log( 'must be playing before you can go fullscreen' );
1560                 }
1561         },
1562         pause : function()
1563         {
1564                 this.getFLA();
1565                 if ( !this.thumbnail_disp ) {
1566                         this.parent_pause();
1567                         if ( this.fla ) {
1568                                 js_log( "Flash:Pause: " + this.fla.isPaused() );
1569                                 if ( this.fla['pause'] ) {
1570                                         if ( ! this.fla.isPaused() ) {
1571                                                 js_log( 'calling plugin pause' );
1572                                                 this.fla.pause();
1574                                                 // restore volume and opacity
1575                                                 this.restorePlayer();
1576                                         }
1577                                 }
1578                         }
1579                 }
1580         },
1581         monitor : function()
1582         {
1583                 var _this = this;
1584                 // date time
1585                 if ( !this.dateStartTime ) {
1586                         var d = new Date();
1587                         this.dateStartTime = d.getTime();
1589                 } else {
1590                         var d = new Date();
1591                         if ( !this.didDateStartTimeRestore  && this.preview_mode )
1592                                 this.fla.setVolume( 0 );
1594                         if ( ( d.getTime() - this.dateStartTime ) > 6000  && !this.didDateStartTimeRestore ) {
1595                                 this.restorePlayer();
1596                         }
1597                 }
1599                 var flash_state = this.fla.getStatus();
1600                 // update the duration from the clip if its zero or not set:
1601                 if ( !this.duration || this.duration == 0 ) {
1602                         if ( this.fla.getClip() ) {
1603                                 this.duration = this.fla.getClip().fullDuration;
1604                                 js_log( 'set duration via clip value: ' + this.getDuration() );
1605                         }
1606                 }
1607                 // update the duration ntp values:
1608                 this.getDuration();
1610                 if ( typeof flash_state == 'undefined' ) {
1611                          var flash_state = {
1612                                  "time" : this.fla.getTime()
1613                          };
1614                         // we are not getting buffered data restore volume and opacity
1615                         this.restorePlayer();
1616                 } else {
1617                         // simplification of buffer state ... should move to support returning time rages like:
1618                         // http://www.whatwg.org/specs/web-apps/current-work/#normalized-timeranges-object
1619                         this.bufferedPercent = flash_state.bufferEnd / this.getDuration();
1620                 }
1621                 // set the current Time (based on timeFormat)
1622                 if ( this.supportsURLTimeEncoding() ) {
1623                         this.currentTime = flash_state.time;
1624                         // js_log('set buffer: ' + flash_state.bufferEnd + ' at time: ' + flash_state.time +' of total dur: ' + this.getDuration());
1625                 } else {
1626                         this.currentTime = flash_state.time + this.start_offset;
1627                         // stop buffering if greater than the duration:
1628                         if ( flash_state.bufferEnd > this.getDuration() + 5 ) {
1629                                 // js_log('should stop buffering (does not seem to work)' + flash_state.bufferEnd + ' > dur: ' + this.getDuration() );
1630                                 this.fla.stopBuffering();
1631                         }
1632                 }
1634                 if ( this.currentTime > npt2seconds( this.start_ntp ) && !this.startedTimedPlayback ) {
1635                         var fail = false;
1636                         try
1637                         {
1638                                 this.restorePlayer();
1639                         }
1640                         catch ( err )
1641                         {
1642                                 js_log( 'failed to set values' );
1643                                 fail = true;
1644                         }
1645                         if ( !fail )
1646                                 this.startedTimedPlayback = true;
1647                 }
1649                 /* to support local seeks */
1650                 if ( this.currentTime > 1 && this.seek_time_sec != 0 && !this.supportsURLTimeEncoding() )
1651                 {
1652                         js_log( 'flashEmbed: _local_ Seeking to ' + this.seek_time_sec );
1653                         this.fla.seek( this.seek_time_sec );
1654                         this.seek_time_sec = 0;
1655                 }
1657                 // checks to see if we reached the end of playback:
1658                 if ( this.duration && this.startedTimedPlayback &&
1659                         (        this.currentTime > ( npt2seconds( this.end_ntp ) + 2 )
1660                                 ||
1661                                 ( this.currentTime > ( npt2seconds( this.end_ntp ) - 1 )
1662                                         && this.prevTime == this.currentTime ) )
1663                         ) {
1664                         js_log( 'prbally reached end of stream: ' + seconds2npt( this.currentTime ) );
1665                         this.onClipDone();
1666                 }
1668                 // update the status and check timmer via universal parent monitor
1669                 this.parent_monitor();
1672                 this.prevTime = this.currentTime;
1673                 // js_log('cur perc loaded: ' + this.fla.getPercentLoaded() +' cur time : ' + (this.currentTime - npt2seconds(this.start_ntp)) +' / ' +(npt2seconds(this.end_ntp)-npt2seconds(this.start_ntp)));
1674         },
1675         restorePlayer:function() {
1676                 if ( !this.fla )
1677                         this.getFLA();
1678                 if ( this.fla ) {
1679                         js_log( 'f:do restorePlayer' );
1680                         this.fla.setVolume( 90 );
1681                         $f().getPlugin( 'screen' ).css( { 'opacity':'1.0' } );
1682                         // set the fallback date restore flag to true:
1683                         this.didDateStartTimeRestore = true;
1684                 }
1685         },
1686         // get the embed fla object
1687         getFLA : function () {
1688                 this.fla = $f( this.pid );
1689         },
1690         stop : function() {
1691                 js_log( 'f:flashEmbed:stop' );
1692                 this.startedTimedPlayback = false;
1693                 if ( this.monitorTimerId != 0 )
1694                 {
1695                         clearInterval( this.monitorTimerId );
1696                         this.monitorTimerId = 0;
1697                 }
1698                 if ( this.fla )
1699                         this.fla.unload();
1700                 this.parent_stop();
1701         },
1702         onStop: function() {
1703                 js_log( 'f:onStop' );
1704                 // stop updates:
1705                 if ( this.monitorTimerId != 0 )
1706                 {
1707                         clearInterval( this.monitorTimerId );
1708                         this.monitorTimerId = 0;
1709                 }
1710         },
1711         onClipDone: function() {
1712                 js_log( 'f:flash:onClipDone' );
1713                 if ( ! this.startedTimedPlayback ) {
1714                         js_log( 'clip done before timed playback started .. not good. (ignoring) ' );
1715                         // keep monitoring:
1716                         this.monitor();
1717                 } else {
1718                         js_log( 'clip done and ' + this.startedTimedPlayback );
1719                         // stop the clip if its not stopped already:
1720                         this.stop();
1721                         this.setStatus( "Clip Done..." );
1722                         // run the onClip done action:
1723                         this.parent_onClipDone();
1724                 }
1725         }