r49630 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r49629‎ | r49630 | r49631 >
Date:17:58, 18 April 2009
Author:dale
Status:deferred
Tags:
Comment:
renamed libEmbedObj to libEmbedVideo
Modified paths:
  • /trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedObj (deleted) (history)
  • /trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo (added) (history)
  • /trunk/extensions/MetavidWiki/skins/mv_embed/mv_embed.js (modified) (history)
  • /trunk/extensions/MetavidWiki/skins/mv_embed/skins/mvpcf/images/clip_thumb_overlay.png (added) (history)
  • /trunk/extensions/MetavidWiki/skins/mv_embed/skins/mvpcf/images/image_thumb_overlay.png (added) (history)

Diff [purge]

Index: trunk/extensions/MetavidWiki/skins/mv_embed/skins/mvpcf/images/image_thumb_overlay.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/skins/mvpcf/images/image_thumb_overlay.png
___________________________________________________________________
Name: svn:mime-type
11 + application/octet-stream
Index: trunk/extensions/MetavidWiki/skins/mv_embed/skins/mvpcf/images/clip_thumb_overlay.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/skins/mvpcf/images/clip_thumb_overlay.png
___________________________________________________________________
Name: svn:mime-type
22 + application/octet-stream
Index: trunk/extensions/MetavidWiki/skins/mv_embed/mv_embed.js
@@ -184,7 +184,7 @@
185185 js_log('jquery loaded');
186186 //load the jQuery dependent plugins:
187187 mvJsLoader.doLoad({
188 - 'embedVideo' : 'libEmbedObj/mv_baseEmbed.js',
 188+ 'embedVideo' : 'libEmbedVideo/mv_baseEmbed.js',
189189 '$j.ui.mouse' : 'jquery/jquery.ui-1.5.2/ui/minified/ui.core.min.js',
190190 '$j.ui.droppable' : 'jquery/jquery.ui-1.5.2/ui/minified/ui.droppable.min.js',
191191 '$j.ui.draggable' : 'jquery/jquery.ui-1.5.2/ui/minified/ui.draggable.min.js'
@@ -375,7 +375,7 @@
376376 else
377377 {
378378 var _this = this;
379 - var plugin_path = mv_embed_path + 'libEmbedObj/mv_'+this.library+'Embed.js';
 379+ var plugin_path = mv_embed_path + 'libEmbedVideo/mv_'+this.library+'Embed.js';
380380 //add the callback:
381381 this.loading_callbacks.push(callback);
382382 //jQuery based get script does not work so well.
@@ -387,7 +387,7 @@
388388 _this.loading_callbacks = null;
389389 });*/
390390
391 - eval('var lib = {"'+this.library+'Embed":\'libEmbedObj/mv_'+this.library+'Embed.js\'}');
 391+ eval('var lib = {"'+this.library+'Embed":\'libEmbedVideo/mv_'+this.library+'Embed.js\'}');
392392 js_log('DO LOAD: '+this.library);
393393 mvJsLoader.doLoad(lib,function(){
394394 //js_log( 'type of lib: ' + eval( 'typeof ' + this.library + 'Embed' ) );
@@ -1161,7 +1161,7 @@
11621162 loadExternalJs( req_url );
11631163 }
11641164 }
1165 -
 1165+//grab wiki form error for wiki html page proccessing (should be depricated)
11661166 function grabWikiFormError ( result_page ){
11671167 var res = {};
11681168 sp = result_page.indexOf('<span class="error">');
@@ -1369,6 +1369,7 @@
13701370 }
13711371 return mv_embed_path;
13721372 }
 1373+
13731374 if (typeof DOMParser == "undefined") {
13741375 DOMParser = function () {}
13751376 DOMParser.prototype.parseFromString = function (str, contentType) {
Index: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_nativeEmbed.js
@@ -0,0 +1,158 @@
 2+//native embed library:
 3+var nativeEmbed = {
 4+ instanceOf:'nativeEmbed',
 5+ canPlayThrough:false,
 6+ grab_try_count:0,
 7+ supports: {
 8+ 'play_head':true,
 9+ 'pause':true,
 10+ 'fullscreen':false,
 11+ 'time_display':true,
 12+ 'volume_control':true,
 13+
 14+ 'overlays':true,
 15+ 'playlist_swap_loader':true //if the object supports playlist functions
 16+ },
 17+ getEmbedHTML : function (){
 18+ var id = (this.pc!=null)?this.pc.pp.id:this.id;
 19+ var embed_code = this.getEmbedObj();
 20+ js_log("embed code: " + embed_code)
 21+ setTimeout('$j(\'#' + id + '\').get(0).postEmbedJS()', 150);
 22+ return this.wrapEmebedContainer( embed_code);
 23+ },
 24+ getEmbedObj:function(){
 25+ //we want to let mv_embed handle the controls so notice the absence of control attribute
 26+ // controls=false results in controls being displayed:
 27+ //http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2008-August/016159.html
 28+ js_log("native play url:" + this.getURI( this.seek_time_sec ));
 29+ return '<video ' +
 30+ 'id="' + this.pid + '" ' +
 31+ 'style="width:' + this.width+'px;height:' + this.height + 'px;" ' +
 32+ 'width="' + this.width + '" height="'+this.height+'" '+
 33+ 'src="' + this.media_element.selected_source.getURI( this.seek_time_sec ) + '" ' +
 34+ 'autoplay="true" '+
 35+ 'oncanplaythrough="$j(\'#'+this.id+'\').get(0).oncanplaythrough();return false;" ' +
 36+ 'onloadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' +
 37+ 'loadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' +
 38+ 'onprogress="$j(\'#'+this.id+'\').get(0).onprogress( event );return false;" '+
 39+ 'onended="$j(\'#'+this.id+'\').get(0).onended();return false;" >' +
 40+ '</video>';
 41+ },
 42+ //@@todo : loading progress
 43+ postEmbedJS:function(){
 44+ js_log("f:native:postEmbedJS:");
 45+ this.getVID();
 46+ if(typeof this.vid != 'undefined'){
 47+ js_log("GOT video object sending PLAY()");
 48+ this.vid.play();
 49+ //this.vid.load(); //does not seem to work so well
 50+ setTimeout('$j(\'#'+this.id+'\').get(0).monitor()',100);
 51+ }else{
 52+ js_log('could not grab vid obj trying again:' + typeof this.vid);
 53+ this.grab_try_count++;
 54+ if( this.grab_count == 10 ){
 55+ js_log(' could not get vid object after 10 tries re-run: getEmbedObj()' ) ;
 56+ }else{
 57+ setTimeout('$j(\'#'+this.id+'\').get(0).postEmbedJS()',100);
 58+ }
 59+ }
 60+ },
 61+ doSeek:function(perc){
 62+ js_log('native:seek:' + this.supportsURLTimeEncoding() + ' dur: ' + this.vid.duration);
 63+ if( this.supportsURLTimeEncoding() ){
 64+ this.parent_doSeek(perc);
 65+ }else if( this.vid.duration ){
 66+ this.vid.currentTime = perc * this.vid.duration;
 67+ }
 68+ },
 69+ monitor : function(){
 70+ this.getVID(); //make shure we have .vid obj
 71+ if(!this.vid){
 72+ js_log('could not find video embed: '+this.id + ' stop monitor');
 73+ this.stopMonitor();
 74+ return false;
 75+ }
 76+ //don't update status if we are not the current clip (playlist leekage?) .. should move to playlist overwite of monitor?
 77+ if(this.pc){
 78+ if(this.pc.pp.cur_clip.id != this.pc.id)
 79+ return true;
 80+ }
 81+
 82+ //update duration if not set (for now trust the getDuration more than this.vid.duration
 83+ this.duration = ( this.getDuration() ) ?this.getDuration() : this.vid.duration;
 84+
 85+ //update currentTime
 86+ this.currentTime = this.vid.currentTime;
 87+
 88+ //once currentTime is updated call parent_monitor
 89+ this.parent_monitor();
 90+ },
 91+ /*
 92+ * native callbacks for the video tag:
 93+ */
 94+ oncanplaythrough : function(){
 95+ js_log('f:oncanplaythrough');
 96+ },
 97+ onloadedmetadata: function(){
 98+ js_log('f:onloadedmetadata get duration: ' +this.vid.duration);
 99+ //this.
 100+ },
 101+ onloadedmetadata: function(){
 102+ js_log('f:onloadedmetadata metadata ready');
 103+ //set the clip duration
 104+ },
 105+ onprogress: function(e){
 106+ this.bufferedPercent = e.loaded / e.total;
 107+ //js_log("onprogress:" +e.loaded + ' / ' + (e.total) + ' = ' + this.bufferedPercent);
 108+ },
 109+ onended:function(){
 110+ //clip "ended"
 111+ js_log('f:onended ');
 112+ //stop monitor
 113+ this.stopMonitor();
 114+ this.stop();
 115+ },
 116+ stopMonitor:function(){
 117+ if( this.monitorTimerId != 0 )
 118+ {
 119+ clearInterval(this.monitorTimerId);
 120+ this.monitorTimerId = 0;
 121+ }
 122+ },
 123+ pause : function(){
 124+ this.getVID();
 125+ this.parent_pause(); //update interface
 126+ if(this.vid){
 127+ this.vid.pause();
 128+ }
 129+ //stop updates:
 130+ this.stopMonitor();
 131+ },
 132+ play:function(){
 133+ this.getVID();
 134+ this.parent_play(); //update interface
 135+ if( this.vid ){
 136+ this.vid.play();
 137+ //re-start the monitor:
 138+ this.monitor();
 139+ }
 140+ },
 141+ playMovieAt:function(order){
 142+ js_log('f:playMovieAt '+order);
 143+ this.play();
 144+ },
 145+ // get the embed vlc object
 146+ getVID : function (){
 147+ this.vid = $j('#'+this.pid).get(0);
 148+ },
 149+ /*
 150+ * playlist driver
 151+ * mannages native playlist calls
 152+ */
 153+ playlistNext:function(){
 154+ if(!this.pc){//make sure we are a clip
 155+ //
 156+
 157+ }
 158+ }
 159+}
\ No newline at end of file
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_nativeEmbed.js
___________________________________________________________________
Name: svn:mergeinfo
1160 +
Name: svn:eol-style
2161 + native
Index: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_baseEmbed.js
@@ -0,0 +1,2044 @@
 2+/* the base video control JSON object with default attributes
 3+* for supported attribute details see README
 4+*/
 5+var default_video_attributes = {
 6+ "id":null,
 7+ "class":null,
 8+ "style":null,
 9+ "name":null,
 10+ "innerHTML":null,
 11+ "width":"320",
 12+ "height":"240",
 13+
 14+ //video attributes:
 15+ "src":null,
 16+ "autoplay":false,
 17+ "start":0,
 18+ "end":null,
 19+ "controls":true,
 20+ "muted":false,
 21+
 22+ //roe url (for xml based metadata)
 23+ "roe":null,
 24+ //if roe includes metadata tracks we can expose a link to metadata
 25+ "show_meta_link":true,
 26+
 27+ //default state attributes per html5 spec:
 28+ //http://www.whatwg.org/specs/web-apps/current-work/#video)
 29+ "paused":true,
 30+ "readyState":0, //http://www.whatwg.org/specs/web-apps/current-work/#readystate
 31+ "currentTime":0, //current playback position (should be updated by plugin)
 32+ "duration":null, //media duration (read from file or the temporal url)
 33+
 34+ //custom attributes for mv_embed:
 35+ "play_button":true,
 36+ "thumbnail":null,
 37+ "linkback":null,
 38+ "embed_link":true,
 39+ "download_link":true,
 40+ "type":null //the content type of the media
 41+};
 42+
 43+/*
 44+ * controlsBuilder:
 45+ *
 46+ */
 47+var ctrlBuilder = {
 48+ height:29,
 49+ supports:{
 50+ 'options':true,
 51+ 'borders':true
 52+ },
 53+ getControls:function(embedObj){
 54+ js_log('f:controlsBuilder');
 55+ this.id = (embedObj.pc)?embedObj.pc.pp.id:embedObj.id;
 56+ this.avaliable_width=embedObj.playerPixelWidth();
 57+ //make pointer to the embedObj
 58+ this.embedObj =embedObj;
 59+ var _this = this;
 60+ $j.each( embedObj.supports, function( i, sup ){
 61+ _this.supports[i] = embedObj.supports[i];
 62+ });
 63+
 64+ //special case vars:
 65+ if( ( embedObj.roe || embedObj.media_element.timedTextSources() )
 66+ && embedObj.show_meta_link )
 67+ this.supports['closed_captions']=true;
 68+
 69+
 70+ //append options to body (if not already there)
 71+ if($j('#mv_embedded_options_'+ctrlBuilder.id).length==0)
 72+ $j('body').append( this.components['mv_embedded_options'].o() );
 73+
 74+ var o='';
 75+ for( var i in this.components ){
 76+ if( this.supports[i] ){
 77+ if( this.avaliable_width > this.components[i].w ){
 78+ //special case with playhead don't add unless we have 60px
 79+ if( i=='play_head' && ctrlBuilder.avaliable_width < 60 )
 80+ continue;
 81+ o+=this.components[i].o();
 82+ this.avaliable_width -= this.components[i].w;
 83+ }else{
 84+ js_log('not enough space for control component:'+i);
 85+ }
 86+ }
 87+ }
 88+ return o;
 89+ },
 90+ /*
 91+ * addControlHooks
 92+ * to be run once controls are attached to the dom
 93+ */
 94+ addControlHooks:function(embedObj){
 95+ //add in drag/seek hooks:
 96+ if(!embedObj.base_seeker_slider_offset && $j('#mv_seeker_slider_'+embedObj.id).get(0))
 97+ embedObj.base_seeker_slider_offset = $j('#mv_seeker_slider_'+embedObj.id).get(0).offsetLeft;
 98+
 99+ //js_log('looking for: #mv_seeker_slider_'+embedObj.id + "\n " +
 100+ // 'start sec: '+embedObj.start_time_sec + ' base offset: '+embedObj.base_seeker_slider_offset);
 101+
 102+ //add play hook:
 103+ $j('#mv_play_pause_button_' + embedObj.id).unbind( "click" ).click(function(){
 104+ $j('#' + embedObj.id).get(0).play();
 105+ });
 106+
 107+ //big_play_link_ play binding:
 108+ $j('#big_play_link_' + embedObj.id).unbind('click').click(function(){
 109+ $j('#' + embedObj.id).get(0).play();
 110+ });
 111+
 112+ //build draggable hook here:
 113+ $j('#mv_seeker_slider_'+embedObj.id).draggable({
 114+ containment:$j('#seeker_bar_'+embedObj.id),
 115+ axis:'x',
 116+ opacity:.6,
 117+ start:function(e, ui){
 118+ var id = (embedObj.pc!=null)?embedObj.pc.pp.id:embedObj.id;
 119+ embedObj.userSlide=true;
 120+ js_log("started dragging set userSlide" + embedObj.userSlide)
 121+ var options = ui.options;
 122+ //remove "play button"
 123+ $j('#big_play_link_'+id).fadeOut('fast');
 124+ //if playlist always start at 0
 125+ embedObj.start_time_sec = (embedObj.instanceOf == 'mvPlayList')?0:
 126+ ntp2seconds(embedObj.getTimeReq().split('/')[0]);
 127+ },
 128+ drag:function(e, ui){
 129+ //@@todo get the -14 number from the skin somehow
 130+ var perc = (($j('#mv_seeker_slider_'+embedObj.id).get(0).offsetLeft-embedObj.base_seeker_slider_offset)
 131+ /
 132+ ($j('#mv_seeker_'+embedObj.id).width()-14));
 133+
 134+ embedObj.jump_time = seconds2ntp( parseInt( embedObj.getDuration() * perc ) + embedObj.start_time_sec);
 135+ //js_log('perc:' + perc + ' * ' + embedObj.getDuration() + ' jt:'+ this.jump_time);
 136+ embedObj.setStatus( gM('seek_to')+' '+embedObj.jump_time );
 137+ //update the thumbnail / frame
 138+ if(embedObj.isPlaying==false){
 139+ embedObj.updateThumbPerc( perc );
 140+ }
 141+ },
 142+ stop:function(e, ui){
 143+ embedObj.userSlide=false;
 144+ //stop the monitor timer:
 145+ if( this.monitorTimerId != 0 )
 146+ {
 147+ clearInterval(this.monitorTimerId);
 148+ this.monitorTimerId = 0;
 149+ }
 150+
 151+ var perc = (($j('#mv_seeker_slider_'+embedObj.id).get(0).offsetLeft-embedObj.base_seeker_slider_offset)
 152+ /
 153+ ($j('#mv_seeker_'+embedObj.id).width()-14));
 154+ js_log('do jump to: '+embedObj.jump_time + ' perc:' +perc);
 155+
 156+ //set seek time (in case we have to do a url seek)
 157+ embedObj.seek_time_sec=ntp2seconds(embedObj.jump_time);
 158+ var test = embedObj;
 159+ embedObj.doSeek(perc);
 160+ }
 161+ });
 162+ },
 163+ components:{
 164+ 'borders':{
 165+ 'w':8,
 166+ 'o':function(){
 167+ return '<span class="border_left">&nbsp;</span>'+
 168+ '<span class="border_right">&nbsp;</span>';
 169+ }
 170+ },
 171+ 'fullscreen':{
 172+ 'w':20,
 173+ 'o':function(){
 174+ return '<div class="fullscreen"><a href="javascript:$j(\'#'+ctrlBuilder.id+'\').get(0).fullscreen();"></a></div>'
 175+ }
 176+ },
 177+ 'options':{
 178+ 'w':26,
 179+ 'o':function(){
 180+ return '<div id="options_button_'+ctrlBuilder.id+'" class="options"><a href="javascript:$j(\'#'+ctrlBuilder.id+'\').get(0).doOptionsHTML();"></a></div>';
 181+ }
 182+ },
 183+ 'mv_embedded_options':{
 184+ 'w':0,
 185+ 'o':function(){
 186+ var o= '<div id="mv_embedded_options_'+ctrlBuilder.id+'" class="videoOptions">'
 187++' <div class="videoOptionsTop"></div>'
 188++' <div class="videoOptionsBox">'
 189++' <div class="block">'
 190++' <h6>Video Options</h6>'
 191++' </div>'
 192++' <div class="block">'
 193++' <p class="short_match"><a href="javascript:$j(\'#'+ctrlBuilder.id+'\').get(0).selectPlaybackMethod();" onClick="$j(\'#mv_embedded_options_'+ctrlBuilder.id+'\').hide();"><span><strong>Stream Selection</strong></span></a></p>'
 194++' <p class="short_match"><a href="javascript:$j(\'#'+ctrlBuilder.id+'\').get(0).showVideoDownload();" onClick="$j(\'#mv_embedded_options_'+ctrlBuilder.id+'\').hide();" ><span><strong>Download</strong></span></a></p>'
 195++' <p class="short_match"><a href="javascript:$j(\'#'+ctrlBuilder.id+'\').get(0).showEmbedCode();" onClick="$j(\'#mv_embedded_options_'+ctrlBuilder.id+'\').hide();" ><span><strong>Share or Embed</strong></span></a></p>';
 196+
 197+ //link to the stream page if we are not already there:
 198+ if( ctrlBuilder.embedObj.roe && typeof mv_stream_interface == 'undefined' )
 199+ o+='<p class="short_match"><a href="javascript:$j(\'#'+ctrlBuilder.id+'\').get(0).doLinkBack()"><span><strong>Source Page</strong></span></a></p>';
 200+
 201+ o+=''
 202++' </div>'
 203++' </div><!--videoOptionsInner-->'
 204++' <div class="videoOptionsBot"></div>'
 205++' </div><!--videoOptions-->';
 206+ return o;
 207+ }
 208+ },
 209+ 'pause':{
 210+ 'w':24,
 211+ 'o':function(){
 212+ return '<div id="mv_play_pause_button_' + ctrlBuilder.id + '" class="play_button"></div>';
 213+ }
 214+ },
 215+ 'closed_captions':{
 216+ 'w':40,
 217+ 'o':function(){
 218+ return '<div class="closed_captions"><a href="javascript:$j(\'#'+ctrlBuilder.id+'\').get(0).showTextInterface();"></a></div>'
 219+ }
 220+ },
 221+ 'volume_control':{
 222+ 'w':22,
 223+ 'o':function(){
 224+ return '<div id="volume_icon_'+ctrlBuilder.id+'" class="volume_icon volume_on"><a href="javascript:$j(\'#'+ctrlBuilder.id+'\').get(0).toggleMute();"></a></div>'
 225+ }
 226+ },
 227+ 'time_display':{
 228+ 'w':80,
 229+ 'o':function(){
 230+ return '<div id="mv_time_'+ctrlBuilder.id+'" class="time">'+ctrlBuilder.embedObj.getTimeReq()+'</div>'
 231+ }
 232+ },
 233+ 'play_head':{
 234+ 'w':0, //special case (takes up remaining space)
 235+ 'o':function(){
 236+ return '<div class="seeker" id="mv_seeker_'+ctrlBuilder.id+'" style="width: ' + (ctrlBuilder.avaliable_width - 18) + 'px;">'+
 237+ ' <div id="seeker_bar_'+ctrlBuilder.id+'" class="seeker_bar">'+
 238+ ' <div class="seeker_bar_outer"></div>'+
 239+ ' <div id="mv_seeker_slider_'+ctrlBuilder.id+'" class="seeker_slider"></div>'+
 240+ ' <div class="mv_progress mv_playback"></div>'+
 241+ ' <div class="mv_progress mv_buffer"></div>'+
 242+ ' <div class="mv_progress mv_highlight"></div>'+
 243+ ' <div class="seeker_bar_close"></div>'+
 244+ ' </div>'+
 245+ ' </div><!--seeker-->'
 246+ }
 247+ }
 248+ }
 249+}
 250+
 251+/**
 252+ * mediaSource class represents a source for a media element.
 253+ * @param {String} type MIME type of the source.
 254+ * @param {String} uri URI of the source.
 255+ * @constructor
 256+ */
 257+function mediaSource(element)
 258+{
 259+ this.init(element);
 260+}
 261+
 262+var mv_default_source_attr= new Array(
 263+ 'id',
 264+ 'src',
 265+ 'title',
 266+ 'timeFormat',
 267+ 'start',
 268+ 'end',
 269+ 'default',
 270+ 'lang'
 271+);
 272+mediaSource.prototype =
 273+{
 274+ /** MIME type of the source. */
 275+ mime_type:null,
 276+ /** URI of the source. */
 277+ uri:null,
 278+ /** Title of the source. */
 279+ title:null,
 280+ /** True if the source has been marked as the default. */
 281+ marked_default:false,
 282+ /** True if the source supports url specification of offset and duration */
 283+ serverSideSeeking:false,
 284+ /** Start offset of the requested segment */
 285+ start_offset:null,
 286+ /** Duration of the requested segment (0 if not known) */
 287+ duration:0,
 288+ is_playable:null,
 289+ upddate_interval:null,
 290+
 291+ id:null,
 292+ start_ntp:null,
 293+ end_ntp:null,
 294+
 295+ init : function(element)
 296+ {
 297+ //js_log('adding mediaSource: ' + element);
 298+ this.src = $j(element).attr('src');
 299+ this.marked_default = false;
 300+ if ( element.tagName.toLowerCase() == 'video')
 301+ this.marked_default = true;
 302+
 303+ //set default timeFormat if we have a time url:
 304+ //not ideal way to discover if content is on an oggz_chop server.
 305+ //should check some other way.
 306+ var pUrl = parseUri ( this.src );
 307+ if(typeof pUrl['queryKey']['t'] != 'undefined'){
 308+ this['timeFormat']='anx';
 309+ }
 310+
 311+ for(var i=0; i < mv_default_source_attr.length; i++){ //for in loop oky on object
 312+ var attr = mv_default_source_attr[ i ];
 313+ if( $j(element).attr( attr ) ) {
 314+ this[ attr ] = $j(element).attr( attr );
 315+ }
 316+ }
 317+
 318+ if ( $j(element).attr('type'))
 319+ this.mime_type = $j(element).attr('type');
 320+ else if ($j(element).attr('content-type'))
 321+ this.mime_type = $j(element).attr('content-type');
 322+ else
 323+ this.mime_type = this.detectType(this.src);
 324+
 325+ //set the title if unset:
 326+ if( !this.title )
 327+ this.title = this.mime_type;
 328+
 329+ this.parseURLDuration();
 330+ },
 331+ updateSource:function(element){
 332+ //for now just update the title:
 333+ if ($j(element).attr("title"))
 334+ this.title = $j(element).attr("title");
 335+ },
 336+ /** updates the src time and start & end
 337+ * @param {String} start_time in NTP format
 338+ * @param {String} end_time in NTP format
 339+ */
 340+ updateSrcTime:function (start_ntp, end_ntp){
 341+ //js_log("f:updateSrcTime: "+ start_ntp+'/'+ end_ntp + ' from org: ' + this.start_ntp+ '/'+this.end_ntp);
 342+ //js_log("pre uri:" + this.src);
 343+ //if we have time we can use:
 344+ if( this.serverSideSeeking ){
 345+ //make sure its a valid start time / end time (else set default)
 346+ if( !ntp2seconds(start_ntp) )
 347+ start_ntp = this.start_ntp;
 348+
 349+ if( !ntp2seconds(end_ntp) )
 350+ end_ntp = this.end_ntp;
 351+
 352+ if( this.timeFormat == 'anx' ){
 353+ this.src = getURLParamReplace(this.src, { 't': start_ntp +'/'+end_ntp } );
 354+ }else if ( this.timeFormat =='mp4'){
 355+ var mp4URL = parseUri( this.src );
 356+ this.src = mp4URL.protocol+'://'+mp4URL.authority + mp4URL.path +
 357+ '?start=' + ( ntp2seconds( start_ntp ) ) +
 358+ '&end=' + ( ntp2seconds( end_ntp ) );
 359+ }
 360+
 361+ //update the duration
 362+ this.parseURLDuration();
 363+ }
 364+ //this.setDuration( )
 365+ //js_log("post uri:" + this.src);
 366+ },
 367+ setDuration:function (duration)
 368+ {
 369+ this.duration = duration;
 370+ this.end_ntp = seconds2ntp(this.start_offset + duration);
 371+ },
 372+ /** MIME type accessor function.
 373+ @return the MIME type of the source.
 374+ @type String
 375+ */
 376+ getMIMEType : function()
 377+ {
 378+ return this.mime_type;
 379+ },
 380+ /** URI accessor function.
 381+ * @param int seek_time_sec (used to adjust the URI for players that can't do local seeks well on given media types)
 382+ @return the URI of the source.
 383+ @type String
 384+ */
 385+ getURI : function(seek_time_sec)
 386+ {
 387+ js_log("f:getURI: tf:" + this.timeFormat +' uri_enc:'+this.serverSideSeeking);
 388+ if( !seek_time_sec || !this.serverSideSeeking ){
 389+ return this.src;
 390+ }
 391+ if( this.timeFormat == 'anx' ){
 392+ var new_url = getURLParamReplace(this.src, { 't': seconds2ntp(seek_time_sec)+'/'+ this.end_ntp } );
 393+ }else if(this.timeFormat=='mp4'){
 394+ var mp4URL = parseUri( this.src );
 395+ var new_url = mp4URL.protocol+'://'+mp4URL.authority + mp4URL.path + '?start='
 396+ + ( seek_time_sec + parseInt(mp4URL.queryKey['start']) );
 397+ }
 398+ //js_log('getURI seek url:'+ new_url);
 399+ return new_url;
 400+ },
 401+ /** Title accessor function.
 402+ @return the title of the source.
 403+ @type String
 404+ */
 405+ getTitle : function()
 406+ {
 407+ return this.title;
 408+ },
 409+ /** Index accessor function.
 410+ @return the source's index within the enclosing mediaElement container.
 411+ @type Integer
 412+ */
 413+ getIndex : function()
 414+ {
 415+ return this.index;
 416+ },
 417+ /*
 418+ * function getDuration in milliseconds
 419+ * special case derive duration from request url
 420+ * supports media_url?t=ntp_start/ntp_end url request format
 421+ */
 422+ parseURLDuration : function(){
 423+ //check if we have a timeFormat:
 424+ if( this.timeFormat ){
 425+ if( this.timeFormat == 'anx' ){
 426+ var annoURL = parseUri( this.src );
 427+ if( annoURL.queryKey['t'] ){
 428+ var times = annoURL.queryKey['t'].split('/');
 429+ this.start_ntp = times[0];
 430+ this.end_ntp = times[1];
 431+ }
 432+ }
 433+ if( this.timeFormat == 'mp4' ){
 434+ var mp4URL = parseUri( this.src );
 435+ if( typeof mp4URL.queryKey['start'] != 'undefined' )
 436+ this.start_ntp = seconds2ntp( mp4URL.queryKey['start'] );
 437+
 438+ if( typeof mp4URL.queryKey['end'] != 'undefined' ){
 439+ this.end_ntp = seconds2ntp( mp4URL.queryKey['end'] );
 440+
 441+ //strip the &end param here (as per the mp4 format request (should fix server side)
 442+ this.src = mp4URL.protocol+'://'+mp4URL.authority + mp4URL.path + '?start=' + mp4URL.queryKey['start'];
 443+ }
 444+ }
 445+ this.serverSideSeeking = true;
 446+ this.start_offset = ntp2seconds(this.start_ntp);
 447+ this.duration = ntp2seconds( this.end_ntp ) - this.start_offset;
 448+ } //time format
 449+
 450+ if( !this.serverSideSeeking ){
 451+ //else normal media request (can't predict the duration without the plugin reading it)
 452+ this.duration = null;
 453+ this.start_offset = 0;
 454+ this.start_ntp = seconds2ntp(this.start_offset);
 455+ }
 456+ //js_log('f:parseURLDuration() for:' + this.src + ' d:' + this.duration);
 457+ },
 458+ /** Attempts to detect the type of a media file based on the URI.
 459+ @param {String} uri URI of the media file.
 460+ @returns The guessed MIME type of the file.
 461+ @type String
 462+ */
 463+ detectType:function(uri)
 464+ {
 465+ //@@todo if media is on the same server as the javascript or we have mv_proxy configured
 466+ //we can issue a HEAD request and read the mime type of the media...
 467+ // (this will detect media mime type independently of the url name)
 468+ //http://www.jibbering.com/2002/4/httprequest.html (this should be done by extending jquery's ajax objects)
 469+ var end_inx = (uri.indexOf('?')!=-1)? uri.indexOf('?') : uri.length;
 470+ var no_param_uri = uri.substr(0, end_inx);
 471+ switch( no_param_uri.substr(no_param_uri.lastIndexOf('.'),4) ){
 472+ case '.flv':return 'video/x-flv';break;
 473+ case '.ogg': case '.ogv': return 'video/ogg';break;
 474+ case '.anx':return 'video/ogg';break;
 475+ }
 476+ }
 477+};
 478+
 479+/** A media element corresponding to a <video> element.
 480+ It is implemented as a collection of mediaSource objects. The media sources
 481+ will be initialized from the <video> element, its child <source> elements,
 482+ and/or the ROE file referenced by the <video> element.
 483+ @param {element} video_element <video> element used for initialization.
 484+ @constructor
 485+*/
 486+function mediaElement(video_element)
 487+{
 488+ this.init(video_element);
 489+};
 490+
 491+mediaElement.prototype =
 492+{
 493+ /** The array of mediaSource elements. */
 494+ sources:null,
 495+ addedROEData:false,
 496+ /** Selected mediaSource element. */
 497+ selected_source:null,
 498+ thumbnail:null,
 499+ linkback:null,
 500+
 501+ /** @private */
 502+ init:function( video_element )
 503+ {
 504+ var _this = this;
 505+ js_log('Initializing mediaElement...' + video_element);
 506+ this.sources = new Array();
 507+ this.thumbnail = mv_default_thumb_url;
 508+ // Process the <video> element
 509+ if($j(video_element).attr("src"))
 510+ this.tryAddSource(video_element);
 511+
 512+ if($j(video_element).attr('thumbnail'))
 513+ this.thumbnail=$j(video_element).attr('thumbnail');
 514+
 515+ if($j(video_element).attr('poster'))
 516+ this.thumbnail=$j(video_element).attr('poster');
 517+
 518+ // Process all inner <source> elements
 519+ //js_log("inner source count: " + video_element.getElementsByTagName('source').length );
 520+
 521+ $j(video_element).children('source,text').each(function(inx, inner_source){
 522+ _this.tryAddSource( inner_source );
 523+ });
 524+ },
 525+ /** Updates the time request for all sources that have a standard time request argument (ie &t=start_time/end_time)
 526+ */
 527+ updateSourceTimes:function(start_ntp, end_ntp){
 528+ var _this = this;
 529+ $j.each(this.sources, function(inx, mediaSource){
 530+ mediaSource.updateSrcTime(start_ntp, end_ntp);
 531+ });
 532+ },
 533+ /*timed Text check*/
 534+ timedTextSources:function(){
 535+ for(var i=0; i < this.sources.length; i++){
 536+ if( this.sources[i].mime_type == 'text/cmml' ||
 537+ this.sources[i].mime_type == 'text/x-srt')
 538+ return true;
 539+ };
 540+ return false;
 541+ },
 542+ /** Returns the array of mediaSources of this element.
 543+ \returns {Array} Array of mediaSource elements.
 544+ */
 545+ getSources:function( mime_filter )
 546+ {
 547+ if(!mime_filter)
 548+ return this.sources;
 549+ //apply mime filter:
 550+ var source_set = new Array();
 551+ for(var i=0; i < this.sources.length ; i++){
 552+ if( this.sources[i].mime_type.indexOf( mime_filter ) != -1 )
 553+ source_set.push( this.sources[i] );
 554+ }
 555+ return source_set;
 556+ },
 557+ getSourceById:function( source_id ){
 558+ for(var i=0; i < this.sources.length ; i++){
 559+ if( this.sources[i].id == source_id)
 560+ return this.sources[i];
 561+ }
 562+ return null;
 563+ },
 564+ /** Selects a particular source for playback.
 565+ */
 566+ selectSource:function(index)
 567+ {
 568+ js_log('f:selectSource:'+index);
 569+ var playable_sources = this.getPlayableSources();
 570+ for(var i=0; i < playable_sources.length; i++){
 571+ if( i==index ){
 572+ this.selected_source = playable_sources[i];
 573+ //update the user selected format:
 574+ embedTypes.players.userSelectFormat( playable_sources[i].mime_type );
 575+ break;
 576+ }
 577+ }
 578+ },
 579+ /** selects the default source via cookie preference, default marked, or by id order
 580+ * */
 581+ autoSelectSource:function(){
 582+ js_log('f:autoSelectSource:');
 583+ //@@todo read user preference for source
 584+ // Select the default source
 585+ var playable_sources = this.getPlayableSources();
 586+ var flash_flag=ogg_flag=false;
 587+ //debugger;
 588+ for(var source=0; source < playable_sources.length; source++){
 589+ var mime_type =playable_sources[source].mime_type;
 590+ if( playable_sources[source].marked_default ){
 591+ js_log('set via marked default: ' + playable_sources[source].marked_default);
 592+ this.selected_source = playable_sources[source];
 593+ return true;
 594+ }
 595+ //set via user-preference
 596+ if(embedTypes.players.preference['format_prefrence']==mime_type){
 597+ js_log('set via preference: '+playable_sources[source].mime_type);
 598+ this.selected_source = playable_sources[source];
 599+ return true;
 600+ }
 601+ }
 602+ //set Ogg via player support
 603+ for(var source=0; source < playable_sources.length; source++){
 604+ js_log('f:autoSelectSource:' + playable_sources[source].mime_type);
 605+ var mime_type =playable_sources[source].mime_type;
 606+ //set source via player
 607+ if(mime_type=='video/ogg' || mime_type=='ogg/video' || mime_type=='video/annodex' || mime_type=='application/ogg'){
 608+ for(var i in embedTypes.players){ //for in loop on object oky
 609+ var player = embedTypes.players[i];
 610+ //debugger;
 611+ if(player.library=='vlc' || player.library=='native'){
 612+ js_log('set via ogg via order')
 613+ this.selected_source = playable_sources[source];
 614+ return true;
 615+ }
 616+ }
 617+ }
 618+ }
 619+ //set h264 flash
 620+ for(var source=0; source < playable_sources.length; source++){
 621+ var mime_type =playable_sources[source].mime_type;
 622+ if( mime_type=='video/h264' ){
 623+ js_log('set via by player preference h264 flash')
 624+ this.selected_source = playable_sources[source];
 625+ return true;
 626+ }
 627+ }
 628+ //set basic flash
 629+ for(var source=0; source < playable_sources.length; source++){
 630+ var mime_type =playable_sources[source].mime_type;
 631+ if( mime_type=='video/x-flv' ){
 632+ js_log('set via by player preference normal flash')
 633+ this.selected_source = playable_sources[source];
 634+ return true;
 635+ }
 636+ }
 637+
 638+ //select first source
 639+ if (!this.selected_source)
 640+ {
 641+ js_log('set via first source:' + playable_sources[0]);
 642+ this.selected_source = playable_sources[0];
 643+ return true;
 644+ }
 645+ },
 646+ /** Returns the thumbnail URL for the media element.
 647+ \returns {String} thumbnail URL
 648+ */
 649+ getThumbnailURL:function()
 650+ {
 651+ return this.thumbnail;
 652+ },
 653+ /** Checks whether there is a stream of a specified MIME type.
 654+ @param {String} mime_type MIME type to check.
 655+ @type {BooleanPrimitive}.
 656+ */
 657+ hasStreamOfMIMEType:function(mime_type)
 658+ {
 659+ for(source in this.sources)
 660+ {
 661+ if(this.sources[source].getMIMEType() == mime_type)
 662+ return true;
 663+ }
 664+ return false;
 665+ },
 666+ isPlayableType:function(mime_type)
 667+ {
 668+ if( embedTypes.players.defaultPlayer( mime_type ) ){
 669+ return true;
 670+ }else{
 671+ return false;
 672+ }
 673+ //if(this.selected_player){
 674+ //return mime_type=='video/ogg' || mime_type=='ogg/video' || mime_type=='video/annodex' || mime_type=='video/x-flv';
 675+ },
 676+ /** Adds a single mediaSource using the provided element if
 677+ the element has a 'src' attribute.
 678+ @param element {element} <video>, <source> or <mediaSource> element.
 679+ */
 680+ tryAddSource:function(element)
 681+ {
 682+ //js_log('f:tryAddSource:'+ $j(element).attr("src"));
 683+ if (! $j(element).attr("src")){
 684+ //js_log("element has no src");
 685+ return false;
 686+ }
 687+ var new_src = $j(element).attr('src');
 688+ //make sure an existing element with the same src does not already exist:
 689+ for( var i=0; i < this.sources.length; i++ ){
 690+ if(this.sources[i].src == new_src){
 691+ //js_log('checking existing: '+this.sources[i].getURI() + ' != '+ new_src);
 692+ //can't add it all but try to update any additional attr:
 693+ this.sources[i].updateSource(element);
 694+ return false;
 695+ }
 696+ }
 697+ var source = new mediaSource( element );
 698+ this.sources.push(source);
 699+ //js_log('pushed source to stack'+ source + 'sl:'+this.sources.length);
 700+ },
 701+ getPlayableSources: function(){
 702+ var playable_sources= new Array();
 703+ for(var i=0; i < this.sources.length; i++){
 704+ if( this.isPlayableType( this.sources[i].mime_type ) ){
 705+ playable_sources.push( this.sources[i] );
 706+ }else{
 707+ js_log("type "+ this.sources[i].mime_type + 'is not playable');
 708+ }
 709+ };
 710+ return playable_sources;
 711+ },
 712+ /* Imports media sources from ROE data.
 713+ * @param roe_data ROE data.
 714+ */
 715+ addROE:function(roe_data){
 716+ js_log('f:addROE');
 717+ this.addedROEData=true;
 718+ var _this = this;
 719+ if( typeof roe_data == 'string' )
 720+ {
 721+ var parser=new DOMParser();
 722+ js_log('ROE data:' + roe_data);
 723+ roe_data=parser.parseFromString(roe_data,"text/xml");
 724+ }
 725+ if( roe_data ){
 726+ $j.each(roe_data.getElementsByTagName('mediaSource'), function(inx, source){
 727+ _this.tryAddSource(source);
 728+ });
 729+ //set the thumbnail:
 730+ $j.each(roe_data.getElementsByTagName('img'), function(inx, n){
 731+ if($j(n).attr("id")=="stream_thumb"){
 732+ js_log('roe:set thumb to '+$j(n).attr("src"));
 733+ _this['thumbnail'] =$j(n).attr("src");
 734+ }
 735+ });
 736+ //set the linkback:
 737+ $j.each(roe_data.getElementsByTagName('link'), function(inx, n){
 738+ if($j(n).attr('id')=='html_linkback'){
 739+ js_log('roe:set linkback to '+$j(n).attr("href"));
 740+ _this['linkback'] = $j(n).attr('href');
 741+ }
 742+ });
 743+ }else{
 744+ js_log('ROE data empty.');
 745+ }
 746+ }
 747+};
 748+
 749+
 750+/** base embedVideo object
 751+ @param element <video> tag used for initialization.
 752+ @constructor
 753+*/
 754+
 755+var embedVideo = function(element) {
 756+ return this.init(element);
 757+};
 758+
 759+embedVideo.prototype = {
 760+ /** The mediaElement object containing all mediaSource objects */
 761+ media_element:null,
 762+ preview_mode:false,
 763+ slider:null,
 764+ ready_to_play:false, //should use html5 ready state
 765+ load_error:false, //used to set error in case of error
 766+ loading_external_data:false,
 767+ thumbnail_updating:false,
 768+ thumbnail_disp:true,
 769+ init_with_sources_loadedDone:false,
 770+ inDOM:false,
 771+ //for onClip done stuff:
 772+ anno_data_cache:null,
 773+ seek_time_sec:0,
 774+ base_seeker_slider_offset:null,
 775+ onClipDone_disp:false,
 776+ supports:{},
 777+ //for seek thumb updates:
 778+ cur_thumb_seek_time:0,
 779+ thumb_seek_interval:null,
 780+ //set the buffered percent:
 781+ bufferedPercent:0,
 782+ //utility functions for property values:
 783+ hx : function ( s ) {
 784+ if ( typeof s != 'String' ) {
 785+ s = s.toString();
 786+ }
 787+ return s.replace( /&/g, '&amp;' )
 788+ . replace( /</g, '&lt;' )
 789+ . replace( />/g, '&gt;' );
 790+ },
 791+ hq : function ( s ) {
 792+ return '"' + this.hx( s ) + '"';
 793+ },
 794+ playerPixelWidth : function()
 795+ {
 796+ var player = $j('#mv_embedded_player_'+this.id).get(0);
 797+ if(typeof player!='undefined' && player['offsetWidth'])
 798+ return player.offsetWidth;
 799+ else
 800+ return parseInt(this.width);
 801+ },
 802+ playerPixelHeight : function()
 803+ {
 804+ var player = $j('#mv_embedded_player_'+this.id).get(0);
 805+ if(typeof player!='undefined' && player['offsetHeight'])
 806+ return player.offsetHeight;
 807+ else
 808+ return parseInt(this.height);
 809+ },
 810+ init: function(element){
 811+ //this.element_pointer = element;
 812+
 813+ //inherit all the default video_attributes
 814+ for(var attr in default_video_attributes){ //for in loop oky on user object
 815+ if(element.getAttribute(attr)){
 816+ this[attr]=element.getAttribute(attr);
 817+ //js_log('attr:' + attr + ' val: ' + video_attributes[attr] +" "+'elm_val:' + element.getAttribute(attr) + "\n (set by elm)");
 818+ }else{
 819+ this[attr]=default_video_attributes[attr];
 820+ //js_log('attr:' + attr + ' val: ' + video_attributes[attr] +" "+ 'elm_val:' + element.getAttribute(attr) + "\n (set by attr)");
 821+ }
 822+ }
 823+ if( this.duration!=null && this.duration.split(':').length >= 2)
 824+ this.duration = ntp2seconds( this.duration );
 825+
 826+ //if style is set override width and height
 827+ var dwh = mv_default_video_size.split('x');
 828+ this.width = element.style.width ? element.style.width : dwh[0];
 829+ this.height = element.style.height ? element.style.height : dwh[1];
 830+ //set the plugin id
 831+ this.pid = 'pid_' + this.id;
 832+
 833+ //grab any innerHTML and set it to missing_plugin_html
 834+ //@@todo we should strip source tags instead of checking and skipping
 835+ if(element.innerHTML!='' && element.getElementsByTagName('source').length==0){
 836+ js_log('innerHTML: ' + element.innerHTML);
 837+ this.user_missing_plugin_html=element.innerHTML;
 838+ }
 839+ // load all of the specified sources
 840+ this.media_element = new mediaElement(element);
 841+ },
 842+ on_dom_swap: function(){
 843+ js_log('f:on_dom_swap');
 844+ // Process the provided ROE file... if we don't yet have sources
 845+ if(this.roe && this.media_element.sources.length==0 ){
 846+ js_log('loading external data');
 847+ this.loading_external_data=true;
 848+ var _this = this;
 849+ do_request(this.roe, function(data)
 850+ {
 851+ //continue
 852+ _this.media_element.addROE( data );
 853+ js_log('added_roe::' + _this.media_element.sources.length);
 854+
 855+ js_log('set loading_external_data=false');
 856+ _this.loading_external_data=false;
 857+
 858+ _this.init_with_sources_loaded();
 859+ });
 860+ }
 861+ },
 862+ init_with_sources_loaded : function()
 863+ {
 864+ js_log('f:init_with_sources_loaded');
 865+ //set flag that we have run this function:
 866+ this.init_with_sources_loadedDone=true;
 867+ //autoseletct the source
 868+ this.media_element.autoSelectSource();
 869+ //auto select player based on prefrence or default order
 870+ if( !this.media_element.selected_source )
 871+ {
 872+ //check for parent clip:
 873+ if( typeof this.pc != 'undefined' ){
 874+ js_log('no sources, type:' +this.type + ' check for html');
 875+ //do load player if just displaying innerHTML:
 876+ if(this.pc.type =='text/html'){
 877+ this.selected_player = embedTypes.players.defaultPlayer( 'text/html' );
 878+ js_log('set selected player:'+ this.selected_player.mime_type);
 879+ }
 880+ }
 881+ }else{
 882+ this.selected_player = embedTypes.players.defaultPlayer( this.media_element.selected_source.mime_type );
 883+ }
 884+ if( this.selected_player ){
 885+ js_log('selected ' + this.selected_player.getName());
 886+ js_log("PLAYBACK TYPE: "+this.selected_player.library);
 887+ this.thumbnail_disp = true;
 888+ this.inheritEmbedObj();
 889+ }else{
 890+ //no source's playable
 891+ var missing_type ='';
 892+ var or ='';
 893+ for( var i=0; i < this.media_element.sources.length; i++){
 894+ missing_type+=or + this.media_element.sources[i].mime_type;
 895+ or=' or ';
 896+ }
 897+ if( this.pc )
 898+ var missing_type = this.pc.type;
 899+
 900+ js_log('no player found for given source type ' + missing_type);
 901+ this.load_error= gM('mv_generic_missing_plugin', missing_type );
 902+ }
 903+ },
 904+ inheritEmbedObj:function(){
 905+ //@@note: tricky cuz direct overwrite is not so ideal.. since the extended object is already tied to the dom
 906+ //clear out any non-base embedObj stuff:
 907+ if(this.instanceOf){
 908+ eval('tmpObj = '+this.instanceOf);
 909+ for(var i in tmpObj){ //for in loop oky for object
 910+ if(this['parent_'+i]){
 911+ this[i]=this['parent_'+i];
 912+ }else{
 913+ this[i]=null;
 914+ }
 915+ }
 916+ }
 917+ //set up the new embedObj
 918+ js_log('f: inheritEmbedObj: embedding with ' + this.selected_player.library);
 919+ var _this = this;
 920+ this.selected_player.load( function()
 921+ {
 922+ //js_log('inheriting '+_this.selected_player.library +'Embed to ' + _this.id + ' ' + $j('#'+_this.id).length);
 923+ //var _this = $j('#'+_this.id).get(0);
 924+ //js_log( 'type of ' + _this.selected_player.library +'Embed + ' +
 925+ // eval('typeof '+_this.selected_player.library +'Embed'));
 926+ eval('embedObj = ' +_this.selected_player.library +'Embed;');
 927+ for(var method in embedObj){ //for in loop oky for object
 928+ //parent method preservation for local overwritten methods
 929+ if(_this[method])
 930+ _this['parent_' + method] = _this[method];
 931+ _this[method]=embedObj[method];
 932+ }
 933+ js_log('TYPEOF_ppause: ' + typeof _this['parent_pause']);
 934+
 935+ if(_this.inheritEmbedOverride){
 936+ _this.inheritEmbedOverride();
 937+ }
 938+ //update controls if possible
 939+ if(!_this.loading_external_data)
 940+ _this.refreshControlsHTML();
 941+
 942+ //js_log("READY TO PLAY:"+_this.id);
 943+ _this.ready_to_play=true;
 944+ _this.getDuration();
 945+ _this.getHTML();
 946+ });
 947+ },
 948+ selectPlayer:function(player)
 949+ {
 950+ var _this = this;
 951+ if(this.selected_player.id != player.id){
 952+ this.selected_player = player;
 953+ this.inheritEmbedObj();
 954+ }
 955+ },
 956+ getTimeReq:function(){
 957+ //js_log('f:getTimeReq:'+ this.getDurationNTP());
 958+ var default_time_req = '0:00:00/' + this.getDurationNTP() ;
 959+ if(!this.media_element)
 960+ return default_time_req;
 961+ if(!this.media_element.selected_source)
 962+ return default_time_req;
 963+ if(!this.media_element.selected_source.end_ntp)
 964+ return default_time_req;
 965+ return this.media_element.selected_source.start_ntp+'/'+this.media_element.selected_source.end_ntp;
 966+ },
 967+ getDuration:function(){
 968+ //update some local pointers for the selected source:
 969+ if( this.media_element.selected_source.duration &&
 970+ this.media_element.selected_source.duration != 0 )
 971+ {
 972+ this.duration = this.media_element.selected_source.duration;
 973+ this.start_offset = this.media_element.selected_source.start_offset;
 974+ this.start_ntp = this.media_element.selected_source.start_ntp;
 975+ this.end_ntp = this.media_element.selected_source.end_ntp;
 976+ }else{
 977+ //update start end_ntp if duration !=0 (set from plugin)
 978+ if(this.duration && this.duration !=0){
 979+ this.start_ntp = '0:0:0';
 980+ this.end_ntp = seconds2ntp( this.duration );
 981+ }
 982+ }
 983+ //return the duration
 984+ return this.duration;
 985+ },
 986+ /* get the duration in ntp format */
 987+ getDurationNTP:function(){
 988+ return seconds2ntp(this.getDuration());
 989+ },
 990+ /*
 991+ * wrapEmebedContainer
 992+ * wraps the embed code into a container to better support playlist function
 993+ * (where embed element is swapped for next clip
 994+ * (where plugin method does not support playlsits)
 995+ */
 996+ wrapEmebedContainer:function(embed_code){
 997+ //check if parent clip is set( ie we are in a playlist so name the embed container by playlistID)
 998+ var id = (this.pc!=null)?this.pc.pp.id:this.id;
 999+ return '<div id="mv_ebct_'+id+'" style="width:'+this.width+'px;height:'+this.height+'px;">' +
 1000+ embed_code +
 1001+ '</div>';
 1002+ },
 1003+ getEmbedHTML : function(){
 1004+ //return this.wrapEmebedContainer( this.getEmbedObj() );
 1005+ return 'function getEmbedHTML should be overitten by embedLib ';
 1006+ },
 1007+ //do seek function (should be overwritten by implementing embedLibs)
 1008+ // first check if seek can be done on locally downloaded content.
 1009+ doSeek : function( perc ){
 1010+ js_log('f:mv_embed:doSeek:'+perc);
 1011+ if( this.supportsURLTimeEncoding() ){
 1012+ js_log('Seeking to ' + this.seek_time_sec + ' (local copy of clip not loaded at' + perc + '%)');
 1013+ this.stop();
 1014+ this.didSeekJump=true;
 1015+ //update the slider
 1016+ this.setSliderValue( perc );
 1017+ }
 1018+
 1019+ //do play in 100ms (give things time to clear)
 1020+ setTimeout('$j(\'#' + this.id + '\').get(0).play()',100);
 1021+ },
 1022+ doEmbedHTML:function()
 1023+ {
 1024+ js_log('f:doEmbedHTML');
 1025+ js_log('thum disp:'+this.thumbnail_disp);
 1026+ var _this = this;
 1027+ this.closeDisplayedHTML();
 1028+
 1029+// if(!this.selected_player){
 1030+// return this.getPluginMissingHTML();
 1031+ //Set "loading" here
 1032+ $j('#mv_embedded_player_'+_this.id).html(''+
 1033+ '<div style="color:black;width:'+this.width+'px;height:'+this.height+'px;">' +
 1034+ gM('loading_plugin') +
 1035+ '</div>'
 1036+ );
 1037+ // schedule embedding
 1038+ this.selected_player.load(function()
 1039+ {
 1040+ js_log('performing embed for ' + _this.id);
 1041+ var embed_code = _this.getEmbedHTML();
 1042+ //js_log('shopuld embed:' + embed_code);
 1043+ $j('#mv_embedded_player_'+_this.id).html(embed_code);
 1044+ });
 1045+ },
 1046+ /* todo abstract out onClipDone chain of functions and merge with mvTextInterface */
 1047+ onClipDone:function(){
 1048+ //stop the clip (load the thumbnail etc)
 1049+ this.stop();
 1050+ var _this = this;
 1051+
 1052+ //if the clip resolution is < 320 don't do fancy onClipDone stuff
 1053+ if(this.width<300){
 1054+ return ;
 1055+ }
 1056+ this.onClipDone_disp=true;
 1057+ this.thumbnail_disp=true;
 1058+ //make sure we are not in preview mode( no end clip actions in preview mode)
 1059+ if( this.preview_mode )
 1060+ return ;
 1061+
 1062+ $j('#img_thumb_'+this.id).css('zindex',1);
 1063+ $j('#big_play_link_'+this.id).hide();
 1064+ //add the liks_info_div black back
 1065+ $j('#dc_'+this.id).append('<div id="liks_info_'+this.id+'" ' +
 1066+ 'style="width:' +parseInt(parseInt(this.width)/2)+'px;'+
 1067+ 'height:'+ parseInt(parseInt(this.height)) +'px;'+
 1068+ 'position:absolute;top:10px;overflow:auto'+
 1069+ 'width: '+parseInt( ((parseInt(this.width)/2)-15) ) + 'px;'+
 1070+ 'left:'+ parseInt( ((parseInt(this.width)/2)+15) ) +'px;">'+
 1071+ '</div>' +
 1072+ '<div id="black_back_'+this.id+'" ' +
 1073+ 'style="z-index:-2;position:absolute;background:#000;' +
 1074+ 'top:0px;left:0px;width:'+parseInt(this.width)+'px;' +
 1075+ 'height:'+parseInt(this.height)+'px;">' +
 1076+ '</div>'
 1077+ );
 1078+
 1079+ //start animation (make thumb small in upper left add in div for "loading"
 1080+ $j('#img_thumb_'+this.id).animate({
 1081+ width:parseInt(parseInt(_this.width)/2),
 1082+ height:parseInt(parseInt(_this.height)/2),
 1083+ top:20,
 1084+ left:10
 1085+ },
 1086+ 1000,
 1087+ function(){
 1088+ //animation done.. add "loading" to div if empty
 1089+ if($j('#liks_info_'+_this.id).html()==''){
 1090+ $j('#liks_info_'+_this.id).html(gM('loading_txt'));
 1091+ }
 1092+ }
 1093+ )
 1094+ //now load roe if run the showNextPrevLinks
 1095+ if(this.roe && this.media_element.addedROEData==false){
 1096+ do_request(this.roe, function(data)
 1097+ {
 1098+ _this.media_element.addROE(data);
 1099+ _this.getNextPrevLinks();
 1100+ });
 1101+ }else{
 1102+ this.getNextPrevLinks();
 1103+ }
 1104+ },
 1105+ //@@todo we should merge getNextPrevLinks with textInterface .. there is repeated code between them.
 1106+ getNextPrevLinks:function(){
 1107+ js_log('f:getNextPrevLinks');
 1108+ var anno_track_url = null;
 1109+ var _this = this;
 1110+ //check for annoative track
 1111+ $j.each(this.media_element.sources, function(inx, n){
 1112+ if(n.mime_type=='text/cmml'){
 1113+ if( n.id == 'Anno_en'){
 1114+ anno_track_url = n.src;
 1115+ }
 1116+ }
 1117+ });
 1118+ if( anno_track_url ){
 1119+ js_log('found annotative track:'+ anno_track_url);
 1120+ //zero out seconds (should improve cache hit rate and generally expands metadata search)
 1121+ //@@todo this could be repalced with a regExp
 1122+ var annoURL = parseUri(anno_track_url);
 1123+ var times = annoURL.queryKey['t'].split('/');
 1124+ var stime_parts = times[0].split(':');
 1125+ var etime_parts = times[1].split(':');
 1126+ //zero out the hour:
 1127+ var new_start = stime_parts[0]+':'+'0:0';
 1128+ //zero out the end sec
 1129+ var new_end = (etime_parts[0]== stime_parts[0])? (etime_parts[0]+1)+':0:0' :etime_parts[0]+':0:0';
 1130+
 1131+ var etime_parts = times[1].split(':');
 1132+
 1133+ var new_anno_track_url = annoURL.protocol +'://'+ annoURL.host + annoURL.path +'?';
 1134+ $j.each(annoURL.queryKey, function(i, val){
 1135+ new_anno_track_url +=(i=='t')?'t='+new_start+'/'+new_end +'&' :
 1136+ i+'='+ val+'&';
 1137+ });
 1138+ var request_key = new_start+'/'+new_end;
 1139+ //check the anno_data cache:
 1140+ //@@todo search cache see if current is in range.
 1141+ if(this.anno_data_cache){
 1142+ js_log('anno data found in cache: '+request_key);
 1143+ this.showNextPrevLinks();
 1144+ }else{
 1145+ do_request(new_anno_track_url, function(cmml_data){
 1146+ js_log('raw response: '+ cmml_data);
 1147+ if(typeof cmml_data == 'string')
 1148+ {
 1149+ var parser=new DOMParser();
 1150+ js_log('Parse CMML data:' + cmml_data);
 1151+ cmml_data=parser.parseFromString(cmml_data,"text/xml");
 1152+ }
 1153+ //init anno_data_cache
 1154+ if(!_this.anno_data_cache)
 1155+ _this.anno_data_cache={};
 1156+ //grab all metadata and put it into the anno_data_cache:
 1157+ $j.each(cmml_data.getElementsByTagName('clip'), function(inx, clip){
 1158+ _this.anno_data_cache[ $j(clip).attr("id") ]={
 1159+ 'start_time_sec':ntp2seconds($j(clip).attr("start").replace('npt:','')),
 1160+ 'end_time_sec':ntp2seconds($j(clip).attr("end").replace('npt:','')),
 1161+ 'time_req':$j(clip).attr("start").replace('npt:','')+'/'+$j(clip).attr("end").replace('npt:','')
 1162+ };
 1163+ //grab all its meta
 1164+ _this.anno_data_cache[ $j(clip).attr("id") ]['meta']={};
 1165+ $j.each(clip.getElementsByTagName('meta'),function(imx, meta){
 1166+ //js_log('adding meta: '+ $j(meta).attr("name")+ ' = '+ $j(meta).attr("content"));
 1167+ _this.anno_data_cache[$j(clip).attr("id")]['meta'][$j(meta).attr("name")]=$j(meta).attr("content");
 1168+ });
 1169+ });
 1170+ _this.showNextPrevLinks();
 1171+ });
 1172+ }
 1173+ }else{
 1174+ js_log('no annotative track found');
 1175+ $j('#liks_info_'+this.id).html('no metadata found for next, previous links');
 1176+ }
 1177+ //query current request time +|- 60s to get prev next speech links.
 1178+ },
 1179+ showNextPrevLinks:function(){
 1180+ js_log('f:showNextPrevLinks');
 1181+ //int requested links:
 1182+ var link = {
 1183+ 'prev':'',
 1184+ 'current':'',
 1185+ 'next':''
 1186+ }
 1187+ var curTime = this.getTimeReq().split('/');
 1188+
 1189+ var s_sec = ntp2seconds(curTime[0]);
 1190+ var e_sec = ntp2seconds(curTime[1]);
 1191+ js_log('showNextPrevLinks: req time: '+ s_sec + ' to ' + e_sec);
 1192+ //now we have all the data in anno_data_cache
 1193+ var current_done=false;
 1194+ for(var clip_id in this.anno_data_cache){ //for in loop oky for object
 1195+ var clip = this.anno_data_cache[clip_id];
 1196+ //js_log('on clip:'+ clip_id);
 1197+ //set prev_link (if cur_link is still empty)
 1198+ if( s_sec > clip.end_time_sec){
 1199+ link.prev = clip_id;
 1200+ js_log('showNextPrevLinks: ' + s_sec + ' < ' + clip.end_time_sec + ' set prev');
 1201+ }
 1202+
 1203+ if(e_sec==clip.end_time_sec && s_sec== clip.start_time_sec)
 1204+ current_done = true;
 1205+ //current clip is not done:
 1206+ if( e_sec < clip.end_time_sec && link.current=='' && !current_done){
 1207+ link.current = clip_id;
 1208+ js_log('showNextPrevLinks: ' + e_sec + ' < ' + clip.end_time_sec + ' set current');
 1209+ }
 1210+
 1211+ //set end clip (first clip where start time is > end_time of req
 1212+ if( e_sec < clip.start_time_sec && link.next==''){
 1213+ link.next = clip_id;
 1214+ js_log('showNextPrevLinks: '+ e_sec + ' < '+ clip.start_time_sec + ' && ' + link.next );
 1215+ }
 1216+ }
 1217+ var html='';
 1218+ if(link.prev=='' && link.current=='' && link.next==''){
 1219+ html='<p><a href="'+this.media_element.linkbackgetMsg+'">clip page</a>';
 1220+ }else{
 1221+ for(var link_type in link){
 1222+ var link_id = link[link_type];
 1223+ if(link_id!=''){
 1224+ var clip = this.anno_data_cache[link_id];
 1225+ var title_msg='';
 1226+ for(var j in clip['meta']){
 1227+ title_msg+=j.replace(/_/g,' ') +': ' +clip['meta'][j].replace(/_/g,' ') +" <br>";
 1228+ }
 1229+ var time_req = clip.time_req;
 1230+ if(link_type=='current') //if current start from end of current clip play to end of current meta:
 1231+ time_req = curTime[1]+ '/' + seconds2ntp( clip.end_time_sec );
 1232+
 1233+ //do special linkbacks for metavid content:
 1234+ var regTimeCheck = new RegExp(/[0-9]+:[0-9]+:[0-9]+\/[0-9]+:[0-9]+:[0-9]+/);
 1235+ html+='<p><a ';
 1236+ if( regTimeCheck.test( this.media_element.linkback ) ){
 1237+ html+=' href="'+ this.media_element.linkback.replace(regTimeCheck,time_req) +'" ';
 1238+ }else{
 1239+ html+=' href="#" onClick="$j(\'#'+this.id+'\').get(0).playByTimeReq(\''+
 1240+ time_req + '\'); return false; "';
 1241+ }
 1242+ html+=' title="' + title_msg + '">' +
 1243+ gM(link_type+'_clip_msg') +
 1244+ '</a><br><span style="font-size:small">'+ title_msg +'<span></p>';
 1245+ }
 1246+ }
 1247+ }
 1248+ //js_og("should set html:"+ html);
 1249+ $j('#liks_info_'+this.id).html(html);
 1250+ },
 1251+ playByTimeReq: function(time_req){
 1252+ js_log('f:playByTimeReq: '+time_req );
 1253+ this.stop();
 1254+ this.updateVideoTimeReq(time_req);
 1255+ this.play();
 1256+ },
 1257+ doThumbnailHTML:function()
 1258+ {
 1259+ var _this = this;
 1260+ js_log('f:doThumbnailHTML'+ this.thumbnail_disp);
 1261+ this.closeDisplayedHTML();
 1262+ this.thumbnail_disp = true;
 1263+
 1264+ $j('#mv_embedded_player_'+this.id).html( this.getThumbnailHTML() );
 1265+ this.paused = true;
 1266+ },
 1267+ refreshControlsHTML:function(){
 1268+ js_log('refreshing controls HTML');
 1269+ if($j('#mv_embedded_controls_'+this.id).length==0)
 1270+ {
 1271+ js_log('#mv_embedded_controls_'+this.id + ' not present, returning');
 1272+ return;
 1273+ }else{
 1274+ $j('#mv_embedded_controls_'+this.id).html( this.getControlsHTML() );
 1275+ ctrlBuilder.addControlHooks(this);
 1276+ }
 1277+ },
 1278+ getControlsHTML:function()
 1279+ {
 1280+ return ctrlBuilder.getControls( this );
 1281+ },
 1282+ getHTML : function (){
 1283+ //@@todo check if we have sources avaliable
 1284+ js_log('f:getHTML : ' + this.id );
 1285+ var _this = this;
 1286+ var html_code = '';
 1287+ html_code = '<div id="videoPlayer_'+this.id+'" style="width:'+this.width+'px;" class="videoPlayer">';
 1288+ html_code += '<div style="width:'+parseInt(this.width)+'px;height:'+parseInt(this.height)+'px;" id="mv_embedded_player_'+this.id+'">' +
 1289+ this.getThumbnailHTML() +
 1290+ '</div>';
 1291+ //js_log("mvEmbed:controls "+ typeof this.controls);
 1292+ if(this.controls)
 1293+ {
 1294+ js_log("f:getHTML:AddControls");
 1295+ html_code +='<div id="mv_embedded_controls_' + this.id + '" class="controls" style="width:' + this.width + 'px">';
 1296+ html_code += this.getControlsHTML();
 1297+ html_code +='</div>';
 1298+ //block out some space by encapulating the top level div
 1299+ $j(this).wrap('<div style="width:'+parseInt(this.width)+'px;height:'
 1300+ +(parseInt(this.height)+ctrlBuilder.height)+'px"></div>');
 1301+ }
 1302+ html_code += '</div>'; //videoPlayer div close
 1303+ //js_log('should set: '+this.id);
 1304+ $j(this).html( html_code );
 1305+ //add hooks once Controls are in DOM
 1306+ ctrlBuilder.addControlHooks(this);
 1307+
 1308+ //js_log('set this to: ' + $j(this).html() );
 1309+ //alert('stop');
 1310+ //if auto play==true directly embed the plugin
 1311+ if(this.autoplay)
 1312+ {
 1313+ js_log('activating autoplay');
 1314+ this.play();
 1315+ }
 1316+ },
 1317+ /*
 1318+ * get missing plugin html (check for user included code)
 1319+ */
 1320+ getPluginMissingHTML : function(){
 1321+ //keep the box width hight:
 1322+ var out = '<div style="width:'+this.width+'px;height:'+this.height+'px">';
 1323+ if(this.user_missing_plugin_html){
 1324+ out+= this.user_missing_plugin_html;
 1325+ }else{
 1326+ out+= gM('generic_missing_plugin') + ' or <a title="'+gM('download_clip')+'" href="'+this.src +'">'+gM('download_clip')+'</a>';
 1327+ }
 1328+ return out + '</div>';
 1329+ },
 1330+ updateVideoTimeReq:function(time_req){
 1331+ js_log('f:updateVideoTimeReq');
 1332+ var time_parts =time_req.split('/');
 1333+ this.updateVideoTime(time_parts[0], time_parts[1]);
 1334+ },
 1335+ //update video time
 1336+ updateVideoTime:function(start_ntp, end_ntp){
 1337+ //update media
 1338+ this.media_element.updateSourceTimes( start_ntp, end_ntp );
 1339+ //update mv_time
 1340+ this.setStatus(start_ntp+'/'+end_ntp);
 1341+ //reset slider
 1342+ this.setSliderValue(0);
 1343+ //reset seek_offset:
 1344+ if(this.media_element.selected_source.serverSideSeeking)
 1345+ this.seek_time_sec=0;
 1346+ else
 1347+ this.seek_time_sec=ntp2seconds(start_ntp);
 1348+ },
 1349+ //@@todo overwite by embed library if we can render frames natavily
 1350+ renderTimelineThumbnail:function( options ){
 1351+ var my_thumb_src = this.media_element.getThumbnailURL();
 1352+
 1353+ if( my_thumb_src.indexOf('t=') !== -1){
 1354+ var time_ntp = seconds2ntp ( options.time + parseInt(this.start_offset) );
 1355+ my_thumb_src = getURLParamReplace( my_thumb_src, { 't':time_ntp, 'size': options.size } );
 1356+ }
 1357+ var thumb_class = (typeof options['thumb_class'] !='undefined')? options['thumb_class'] : '';
 1358+ return '<div class="' + thumb_class + '" src="' + my_thumb_src +'" '+
 1359+ 'style="height:' + options.height + 'px;' +
 1360+ 'width:' + options.width + 'px" >' +
 1361+ '<img src="' + my_thumb_src +'" '+
 1362+ 'style="height:' + options.height + 'px;' +
 1363+ 'width:' + options.width + 'px">' +
 1364+ '</div>';
 1365+ },
 1366+ updateThumbTimeNTP:function( time){
 1367+ this.updateThumbTime( ntp2seconds(time) - parseInt(this.start_offset) );
 1368+ },
 1369+ updateThumbTime:function( float_sec ){
 1370+ //js_log('updateThumbTime:'+float_sec);
 1371+ var _this = this;
 1372+ if( typeof this.org_thum_src=='undefined' ){
 1373+ this.org_thum_src = this.media_element.getThumbnailURL();
 1374+ }
 1375+ if( this.org_thum_src.indexOf('t=') !== -1){
 1376+ this.last_thumb_url = getURLParamReplace(this.org_thum_src,
 1377+ { 't' : seconds2ntp( float_sec + parseInt(this.start_offset)) } );
 1378+ if(!this.thumbnail_updating){
 1379+ this.updateThumbnail(this.last_thumb_url ,false);
 1380+ this.last_thumb_url =null;
 1381+ }
 1382+ }
 1383+ },
 1384+ //for now provide a src url .. but need to figure out how to copy frames from video for plug-in based thumbs
 1385+ updateThumbPerc:function( perc ){
 1386+ return this.updateThumbTime( (this.getDuration() * perc) );
 1387+ },
 1388+ //updates the thumbnail if the thumbnail is being displayed
 1389+ updateThumbnail : function(src, quick_switch){
 1390+ //make sure we don't go to the same url if we are not already updating:
 1391+ if( !this.thumbnail_updating && $j('#img_thumb_'+this.id).attr('src')== src )
 1392+ return false;
 1393+ //if we are already updating don't issue a new update:
 1394+ if( this.thumbnail_updating && $j('#new_img_thumb_'+this.id).attr('src')== src )
 1395+ return false;
 1396+
 1397+ js_log('update thumb: ' + src);
 1398+
 1399+ if(quick_switch){
 1400+ $j('#img_thumb_'+this.id).attr('src', src);
 1401+ }else{
 1402+ var _this = this;
 1403+ //if still animating remove new_img_thumb_
 1404+ if(this.thumbnail_updating==true)
 1405+ $j('#new_img_thumb_'+this.id).stop().remove();
 1406+
 1407+ if(this.thumbnail_disp){
 1408+ js_log('set to thumb:'+ src);
 1409+ this.thumbnail_updating=true;
 1410+ $j('#dc_'+this.id).append('<img src="'+src+'" ' +
 1411+ 'style="display:none;position:absolute;zindex:2;top:0px;left:0px;" ' +
 1412+ 'width="'+this.width+'" height="'+this.height+'" '+
 1413+ 'id = "new_img_thumb_'+this.id+'" />');
 1414+ //js_log('appended: new_img_thumb_');
 1415+ $j('#new_img_thumb_'+this.id).fadeIn("slow", function(){
 1416+ //once faded in remove org and rename new:
 1417+ $j('#img_thumb_'+_this.id).remove();
 1418+ $j('#new_img_thumb_'+_this.id).attr('id', 'img_thumb_'+_this.id);
 1419+ $j('#img_thumb_'+_this.id).css('zindex','1');
 1420+ _this.thumbnail_updating=false;
 1421+ //js_log("done fadding in "+ $j('#img_thumb_'+_this.id).attr("src"));
 1422+
 1423+ //if we have a thumb queued update to that
 1424+ if(_this.last_thumb_url){
 1425+ var src_url =_this.last_thumb_url;
 1426+ _this.last_thumb_url=null;
 1427+ _this.updateThumbnail(src_url);
 1428+ }
 1429+ });
 1430+ }
 1431+ }
 1432+ },
 1433+ /** Returns the HTML code for the video when it is in thumbnail mode.
 1434+ This includes the specified thumbnail as well as buttons for
 1435+ playing, configuring the player, inline cmml display, HTML linkback,
 1436+ download, and embed code.
 1437+ */
 1438+ getThumbnailHTML : function ()
 1439+ {
 1440+ var thumb_html = '';
 1441+ var class_atr='';
 1442+ var style_atr='';
 1443+ //if(this.class)class_atr = ' class="'+this.class+'"';
 1444+ //if(this.style)style_atr = ' style="'+this.style+'"';
 1445+ // else style_atr = 'overflow:hidden;height:'+this.height+'px;width:'+this.width+'px;';
 1446+ this.thumbnail = this.media_element.getThumbnailURL();
 1447+
 1448+ //put it all in the div container dc_id
 1449+ thumb_html+= '<div id="dc_'+this.id+'" style="position:relative;'+
 1450+ ' overflow:hidden; top:0px; left:0px; width:'+this.playerPixelWidth()+'px; height:'+this.playerPixelHeight()+'px; z-index:0;">'+
 1451+ '<img width="'+this.playerPixelWidth()+'" height="'+this.playerPixelHeight()+'" style="position:relative;width:'+this.playerPixelWidth()+';height:'+this.playerPixelHeight()+'"' +
 1452+ ' id="img_thumb_'+this.id+'" src="' + this.thumbnail + '">';
 1453+
 1454+ if(this.play_button==true)
 1455+ thumb_html+=this.getPlayButton();
 1456+
 1457+ thumb_html+='</div>';
 1458+ return thumb_html;
 1459+ },
 1460+ getEmbeddingHTML:function()
 1461+ {
 1462+ var thumbnail = this.media_element.getThumbnailURL();
 1463+
 1464+ var embed_thumb_html;
 1465+ if(thumbnail.substring(0,1)=='/'){
 1466+ eURL = parseUri(mv_embed_path);
 1467+ embed_thumb_html = eURL.protocol + '://' + eURL.host + thumbnail;
 1468+ //js_log('set from mv_embed_path:'+embed_thumb_html);
 1469+ }else{
 1470+ embed_thumb_html = (thumbnail.indexOf('http://')!=-1)?thumbnail:mv_embed_path + thumbnail;
 1471+ }
 1472+ var embed_code_html = '&lt;script type=&quot;text/javascript&quot; ' +
 1473+ 'src=&quot;'+mv_embed_path+'mv_embed.js&quot;&gt;&lt;/script&gt' +
 1474+ '&lt;video ';
 1475+ if(this.roe){
 1476+ embed_code_html+='roe=&quot;'+this.roe+'&quot; &gt;';
 1477+ }else{
 1478+ embed_code_html+='src=&quot;'+this.src+'&quot; ' +
 1479+ 'thumbnail=&quot;'+embed_thumb_html+'&quot;&gt;';
 1480+ }
 1481+ //close the video tag
 1482+ embed_code_html+='&lt;/video&gt;';
 1483+
 1484+ return embed_code_html;
 1485+ },
 1486+ doOptionsHTML:function()
 1487+ {
 1488+ var sel_id = (this.pc!=null)?this.pc.pp.id:this.id;
 1489+ var pos = $j('#options_button_'+sel_id).offset();
 1490+ pos['top']=pos['top']+24;
 1491+ pos['left']=pos['left']-124;
 1492+ //js_log('pos of options button: t:'+pos['top']+' l:'+ pos['left']);
 1493+ $j('#mv_embedded_options_'+sel_id).css(pos).toggle();
 1494+ return;
 1495+ },
 1496+ getPlayButton:function(id){
 1497+ if(!id)id=this.id;
 1498+ return '<div id="big_play_link_'+id+'" class="large_play_button" '+
 1499+ 'style="left:'+((this.playerPixelWidth()-130)/2)+'px;'+
 1500+ 'top:'+((this.playerPixelHeight()-96)/2)+'px;"></div>';
 1501+ },
 1502+ doLinkBack:function(){
 1503+ if(this.roe && this.media_element.addedROEData==false){
 1504+ var _this = this;
 1505+ this.displayHTML(gM('loading_txt'));
 1506+ do_request(this.roe, function(data)
 1507+ {
 1508+ _this.media_element.addROE(data);
 1509+ _this.doLinkBack();
 1510+ });
 1511+ }else{
 1512+ if(this.media_element.linkback){
 1513+ window.location = this.media_element.linkback;
 1514+ }else{
 1515+ this.displayHTML(gM('could_not_find_linkback'));
 1516+ }
 1517+ }
 1518+ },
 1519+ //display the code to remotely embed this video:
 1520+ showEmbedCode : function(embed_code){
 1521+ if(!embed_code)
 1522+ embed_code = this.getEmbeddingHTML();
 1523+ var o='';
 1524+ if(this.linkback){
 1525+ o+='<a class="email" href="'+this.linkback+'">Share Clip via Link</a> '+
 1526+ '<p>or</p> ';
 1527+ }
 1528+ o+='<span style="color:#FFF;font-size:14px;">Embed Clip in Blog or Site</span><br>'+
 1529+ '<span style="color:#FFF;font-size:12px;"><a style="color:red" href="http://metavid.org/wiki/Security_Notes_on_Remote_Embedding">'+
 1530+ 'Read This</a> before embeding.</span>'+
 1531+ '<div class="embed_code"> '+
 1532+ '<textarea onClick="this.select();" id="embedding_user_html_'+this.id+'" name="embed">' +
 1533+ embed_code+
 1534+ '</textarea> '+
 1535+ '<button onClick="$j(\'#'+this.id+'\').get(0).copyText(); return false;" class="copy_to_clipboard">Copy to Clipboard</button> '+
 1536+ '</div> '+
 1537+ '</div>';
 1538+ this.displayHTML(o);
 1539+ },
 1540+ copyText:function(){
 1541+ $j('#embedding_user_html_'+this.id).focus().select();
 1542+ if(document.selection){
 1543+ CopiedTxt = document.selection.createRange();
 1544+ CopiedTxt.execCommand("Copy");
 1545+ }
 1546+ },
 1547+ showTextInterface:function(){
 1548+ var _this = this;
 1549+ //display the text container with loading text:
 1550+ //@@todo support position config
 1551+ var loc = $j(this).position();
 1552+ if($j('#metaBox_'+this.id).length==0){
 1553+ $j(this).after('<div style="position:absolute;z-index:10;'+
 1554+ 'top:' + (loc.top) + 'px;' +
 1555+ 'left:' + (parseInt( loc.left ) + parseInt(this.width) + 10 )+'px;' +
 1556+ 'height:'+ parseInt( this.height )+'px;width:400px;' +
 1557+ 'background:white;border:solid black;' +
 1558+ 'display:none;" ' +
 1559+ 'id="metaBox_' + this.id + '">'+
 1560+ gM('loading_txt') +
 1561+ '</div>');
 1562+ }
 1563+ //fade in the text display
 1564+ $j('#metaBox_'+this.id).fadeIn("fast");
 1565+ //check if textObj present:
 1566+ if(typeof this.textInterface == 'undefined' ){
 1567+ //load the default text interface:
 1568+ mvJsLoader.doLoad({
 1569+ 'mvTextInterface':'libTimedText/mvTextInterface.js',
 1570+ '$j.fn.hoverIntent':'jquery/plugins/jquery.hoverIntent.js'
 1571+ }, function(){
 1572+
 1573+ _this.textInterface = new mvTextInterface( _this );
 1574+ //show interface
 1575+ _this.textInterface.show();
 1576+ js_log("NEW TEXT INTERFACE");
 1577+ for(var i in _this.textInterface.availableTracks){
 1578+ js_log("tracks in new interface: "+_this.id+ ' tid:' + i);
 1579+ }
 1580+ }
 1581+ );
 1582+ }else{
 1583+ //show interface
 1584+ this.textInterface.show();
 1585+ }
 1586+ },
 1587+ closeTextInterface:function(){
 1588+ js_log('closeTextInterface '+ typeof this.textInterface);
 1589+ if(typeof this.textInterface !== 'undefined' ){
 1590+ this.textInterface.close();
 1591+ }
 1592+ },
 1593+ /** Generic function to display custom HTML inside the mv_embed element.
 1594+ The code should call the closeDisplayedHTML function to close the
 1595+ display of the custom HTML and restore the regular mv_embed display.
 1596+ @param {String} HTML code for the selection list.
 1597+ */
 1598+ displayHTML:function(html_code)
 1599+ {
 1600+ var sel_id = (this.pc!=null)?this.pc.pp.id:this.id;
 1601+
 1602+ if(!this.supports['overlays'])
 1603+ this.stop();
 1604+
 1605+ //put select list on-top
 1606+ //make sure the parent is relatively positioned:
 1607+ $j('#'+sel_id).css('position', 'relative');
 1608+ //set height width (check for playlist container)
 1609+ var width = (this.pc)?this.pc.pp.width:this.playerPixelWidth();
 1610+ var height = (this.pc)?this.pc.pp.height:this.playerPixelHeight();
 1611+
 1612+ if(this.pc)
 1613+ height+=(this.pc.pp.pl_layout.title_bar_height + this.pc.pp.pl_layout.control_height);
 1614+
 1615+ var fade_in = true;
 1616+ if($j('#blackbg_'+sel_id).length!=0)
 1617+ {
 1618+ fade_in = false;
 1619+ $j('#blackbg_'+sel_id).remove();
 1620+ }
 1621+ //fade in a black bg div ontop of everything
 1622+ var div_code = '<div id="blackbg_'+sel_id+'" class="videoComplete" ' +
 1623+ 'style="height:'+parseInt(height)+'px;width:'+parseInt(width)+'px;">'+
 1624+// '<span class="displayHTML" id="con_vl_'+this.id+'" style="position:absolute;top:20px;left:20px;color:white;">' +
 1625+ '<div class="videoOptionsComplete">'+
 1626+ //@@TODO: this style should go to .css
 1627+ '<span style="float:right;margin-right:10px">' +
 1628+ '<a href="#" style="color:white;" onClick="$j(\'#'+sel_id+'\').get(0).closeDisplayedHTML();return false;">close</a>' +
 1629+ '</span>'+
 1630+ '<div id="mv_disp_inner_'+sel_id+'" style="padding-top:10px;">'+
 1631+ html_code
 1632+ +'</div>'+
 1633+// close_link+'</span>'+
 1634+ '</div></div>';
 1635+ $j('#'+sel_id).prepend(div_code);
 1636+ if (fade_in)
 1637+ $j('#blackbg_'+sel_id).fadeIn("slow");
 1638+ else
 1639+ $j('#blackbg_'+sel_id).show();
 1640+ return false; //onclick action return false
 1641+ },
 1642+ /** Close the custom HTML displayed using displayHTML and restores the
 1643+ regular mv_embed display.
 1644+ */
 1645+ closeDisplayedHTML:function(){
 1646+ var sel_id = (this.pc!=null)?this.pc.pp.id:this.id;
 1647+ $j('#blackbg_'+sel_id).fadeOut("slow", function(){
 1648+ $j('#blackbg_'+sel_id).remove();
 1649+ });
 1650+ return false;//onclick action return false
 1651+ },
 1652+ selectPlaybackMethod:function(){
 1653+ //get id (in case where we have a parent container)
 1654+ var this_id = (this.pc!=null)?this.pc.pp.id:this.id;
 1655+
 1656+ var _this=this;
 1657+ var out='<span style="color:#FFF;background-color:black;"><blockquote style="background-color:black;">';
 1658+ var _this=this;
 1659+ //js_log('selected src'+ _this.media_element.selected_source.url);
 1660+ $j.each( this.media_element.getPlayableSources(), function(source_id, source){
 1661+ var default_player = embedTypes.players.defaultPlayer( source.getMIMEType() );
 1662+
 1663+ var is_selected = (source == _this.media_element.selected_source);
 1664+ var image_src = mv_embed_path+'images/stream/';
 1665+
 1666+ //set the Playable source type:
 1667+ if( source.mime_type == 'video/x-flv' ){
 1668+ image_src += 'flash_icon_';
 1669+ }else if( source.mime_type == 'video/h264'){
 1670+ //for now all mp4 content is pulled from archive.org (so use archive.org icon)
 1671+ image_src += 'archive_org_';
 1672+ }else{
 1673+ image_src += 'fish_xiph_org_';
 1674+ }
 1675+ image_src += is_selected ? 'color':'bw';
 1676+ image_src += '.png';
 1677+
 1678+ if (default_player)
 1679+ {
 1680+ out += '<img src="'+image_src+'"/>';
 1681+ if( ! is_selected )
 1682+ out+='<a href="#" class="sel_source" id="sc_' + source_id + '_' + default_player.id +'">';
 1683+ out += source.getTitle()+ (is_selected?'</a>':'') + ' ';
 1684+
 1685+ //output the player select code:
 1686+ var supporting_players = embedTypes.players.getMIMETypePlayers( source.getMIMEType() );
 1687+ out+='<div id="player_select_list_' + source_id + '" class="player_select_list"><ul>';
 1688+ for(var i=0; i < supporting_players.length ; i++){
 1689+ if( _this.selected_player.id == supporting_players[i].id && is_selected ){
 1690+ out+='<li style="border-style:dashed;margin-left:20px;">'+
 1691+ '<img border="0" width="16" height="16" src="' + mv_embed_path + 'images/plugin.png">' +
 1692+ supporting_players[i].getName() +
 1693+ '</li>';
 1694+ }else{
 1695+ //else gray plugin and the plugin with link to select
 1696+ out+='<li style="margin-left:20px;">'+
 1697+ '<a href="#" class="sel_source" id="sc_' + source_id + '_' + supporting_players[i].id +'">'+
 1698+ '<img border="0" width="16" height="16" src="'+mv_embed_path+'images/plugin_disabled.png">'+
 1699+ supporting_players[i].getName() +
 1700+ '</a>'+
 1701+ '</li>';
 1702+ }
 1703+ }
 1704+ out+='</ul></div>';
 1705+ }else
 1706+ out+= source.getTitle() + ' - no player available';
 1707+ });
 1708+ out+='</blockquote></span>';
 1709+ this.displayHTML(out);
 1710+
 1711+ //set up the click bindings:
 1712+ $j('.sel_source').each(function(){
 1713+ $j(this).click(function(){
 1714+ var iparts = $j(this).attr( 'id' ).replace(/sc_/,'').split('_');
 1715+ var source_id = iparts[0];
 1716+ var default_player_id = iparts[1];
 1717+ js_log('source id: ' + source_id + ' player id: ' + default_player_id);
 1718+
 1719+ $j('#' + this_id ).get(0).closeDisplayedHTML();
 1720+ $j('#' + _this.id ).get(0).media_element.selectSource( source_id );
 1721+
 1722+ embedTypes.players.userSelectPlayer( default_player_id,
 1723+ _this.media_element.sources[ source_id ].getMIMEType() );
 1724+
 1725+ //be sure to issue a stop
 1726+ $j('#' + this_id ).get(0).stop();
 1727+
 1728+ //don't follow the empty # link:
 1729+ return false;
 1730+ });
 1731+ });
 1732+ },
 1733+ /*download list is too complicated ... rewrite for clarity: */
 1734+ showVideoDownload:function(){
 1735+ //load the roe if available (to populate out download options:
 1736+ //js_log('f:showVideoDownload '+ this.roe + ' ' + this.media_element.addedROEData);
 1737+ if(this.roe && this.media_element.addedROEData==false){
 1738+ var _this = this;
 1739+ this.displayHTML(gM('loading_txt'));
 1740+ do_request(this.roe, function(data)
 1741+ {
 1742+ _this.media_element.addROE(data);
 1743+ $j('#mv_disp_inner_'+_this.id).html( _this.getShowVideoDownload() );
 1744+ });
 1745+ }else{
 1746+ this.displayHTML( this.getShowVideoDownload() );
 1747+ }
 1748+ },
 1749+ getShowVideoDownload:function(){
 1750+ var out='<b style="color:white;">'+gM('download_segment')+'</b><br>';
 1751+ out+='<span style="color:white"><blockquote style="background:#000">';
 1752+ var dl_list='';
 1753+ var dl_txt_list='';
 1754+
 1755+ $j.each(this.media_element.getSources(), function(index, source){
 1756+ var dl_line = '<li>' + '<a style="color:white" href="' + source.getURI() +'"> '
 1757+ + source.getTitle()+'</a> '+ '</li>'+"\n";
 1758+ if( source.getURI().indexOf('?t=')!==-1){
 1759+ out+=dl_line;
 1760+ }else if(this.getMIMEType()=="text/cmml"){
 1761+ dl_txt_list+=dl_line;
 1762+ }else{
 1763+ dl_list+=dl_line;
 1764+ }
 1765+ });
 1766+ if(dl_list!='')
 1767+ out+='</blockquote>'+gM('download_full')+'<blockquote style="background:#000">' + dl_list + '</blockquote>';
 1768+ if(dl_txt_list!='')
 1769+ out+='</blockquote>'+gM('download_text')+'<blockquote style="background:#000">' + dl_txt_list +'</blockquote></span>';
 1770+ return out;
 1771+ },
 1772+ /*
 1773+ * base embed controls
 1774+ * the play button calls
 1775+ */
 1776+ play:function(){
 1777+ var this_id = (this.pc!=null)?this.pc.pp.id:this.id;
 1778+ js_log( "mv_embed play:" + this.id);
 1779+ js_log('thum disp:'+this.thumbnail_disp);
 1780+ //check if thumbnail is being displayed and embed html
 1781+ if( this.thumbnail_disp ){
 1782+ if( !this.selected_player ){
 1783+ js_log('no selected_player');
 1784+ //this.innerHTML = this.getPluginMissingHTML();
 1785+ //$j(this).html(this.getPluginMissingHTML());
 1786+ $j('#'+this.id).html( this.getPluginMissingHTML() );
 1787+ }else{
 1788+ this.doEmbedHTML();
 1789+ this.onClipDone_disp=false;
 1790+ this.paused=false;
 1791+ this.thumbnail_disp=false;
 1792+ }
 1793+ }else{
 1794+ //the plugin is already being displayed
 1795+ this.paused=false; //make sure we are not "paused"
 1796+ }
 1797+ $j("#mv_play_pause_button_" + this_id).attr({
 1798+ 'class':'pause_button'
 1799+ }).unbind( "click" ).click(function(){
 1800+ $j('#' + this_id ).get(0).pause();
 1801+ });
 1802+ },
 1803+ /*
 1804+ * base embed pause
 1805+ * there is no general way to pause the video
 1806+ * must be overwritten by embed object to support this functionality.
 1807+ */
 1808+ pause: function(){
 1809+ var this_id = (this.pc!=null)?this.pc.pp.id:this.id;
 1810+ js_log('mv_embed:do pause');
 1811+ //(playing) do pause
 1812+ this.paused=true;
 1813+ //update the ctrl "paused state"
 1814+ $j("#mv_play_pause_button_" + this_id).attr({
 1815+ 'class':'play_button'
 1816+ }).unbind( "click" ).click(function(){
 1817+ $j('#'+this_id).get(0).play();
 1818+ });
 1819+ },
 1820+ /*
 1821+ * base embed stop (can be overwritten by the plugin)
 1822+ */
 1823+ stop: function(){
 1824+ var _this = this;
 1825+ js_log('mvEmbed:stop:'+this.id);
 1826+
 1827+ //no longer seeking:
 1828+ this.didSeekJump=false;
 1829+
 1830+ //first issue pause to update interface (only call the parent)
 1831+ if(this['parent_pause']){
 1832+ this.parent_pause();
 1833+ }else{
 1834+ this.pause();
 1835+ }
 1836+ //reset the currentTime:
 1837+ this.currentTime=0;
 1838+ //check if thumbnail is being displayed in which case do nothing
 1839+ if(this.thumbnail_disp){
 1840+ //already in stooped state
 1841+ js_log('already in stopped state');
 1842+ }else{
 1843+ //rewrite the html to thumbnail disp
 1844+ this.doThumbnailHTML();
 1845+ this.bufferedPercent=0; //reset buffer state
 1846+ this.setSliderValue(0);
 1847+ this.setStatus( this.getTimeReq() );
 1848+ }
 1849+ //make sure the big playbutton is has click action:
 1850+ $j('#big_play_link_' + _this.id).unbind('click').click(function(){
 1851+ $j('#' +_this.id).get(0).play();
 1852+ });
 1853+
 1854+ if(this.update_interval)
 1855+ {
 1856+ clearInterval(this.update_interval);
 1857+ this.update_interval = null;
 1858+ }
 1859+ },
 1860+ toggleMute:function(){
 1861+ var this_id = (this.pc!=null)?this.pc.pp.id:this.id;
 1862+ js_log('f:toggleMute');
 1863+ if(this.muted){
 1864+ this.muted=false;
 1865+ $j('#volume_icon_'+this_id).removeClass('volume_off').addClass('volume_on');
 1866+ }else{
 1867+ this.muted=true;
 1868+ $j('#volume_icon_'+this_id).removeClass('volume_on').addClass('volume_off');
 1869+ }
 1870+ },
 1871+ fullscreen:function(){
 1872+ js_log('fullscreen not supported for this plugin type');
 1873+ },
 1874+ /* returns bool true if playing or paused, false if stooped
 1875+ */
 1876+ isPlaying : function(){
 1877+ if(this.thumbnail_disp){
 1878+ //in stoped state
 1879+ return false;
 1880+ }else if( this.paused ){
 1881+ //paused state
 1882+ return false;
 1883+ }else{
 1884+ return true;
 1885+ }
 1886+ },
 1887+ isPaused : function(){
 1888+ return this.isPlaying() && this.paused;
 1889+ },
 1890+ isStoped : function(){
 1891+ return this.thumbnail_disp;
 1892+ },
 1893+ playlistSupport:function(){
 1894+ //by default not supported (implemented in js)
 1895+ return false;
 1896+ },
 1897+ postEmbedJS:function(){
 1898+ return '';
 1899+ },
 1900+ //do common monitor code like update the playhead and play status
 1901+ //plugin objects are responsible for updating currentTime
 1902+ monitor:function(){
 1903+ if( this.currentTime && this.currentTime > 0 && this.duration){
 1904+ if( !this.userSlide ){
 1905+ if( this.start_offset ){ //if start offset included add that in:
 1906+ this.setSliderValue( ( this.currentTime - this.start_offset ) / this.duration );
 1907+ this.setStatus( seconds2ntp(this.currentTime) + '/'+ seconds2ntp(this.start_offset+this.duration ));
 1908+ }else{
 1909+ this.setSliderValue( this.currentTime / this.duration );
 1910+ this.setStatus( seconds2ntp(this.currentTime) + '/' + seconds2ntp(this.duration ));
 1911+ }
 1912+ }
 1913+ }else{
 1914+ //js_log(' ct:' + this.currentTime + ' dur: ' + this.duration);
 1915+ if( this.isStoped() ){
 1916+ this.setStatus( this.getTimeReq() );
 1917+ }else if( this.isPaused() ){
 1918+ this.setStatus( "paused" );
 1919+ }else if( this.isPlaying() ){
 1920+ if( this.currentTime && ! this.duration )
 1921+ this.setStatus( seconds2ntp( this.currentTime ) + ' /' );
 1922+ else
 1923+ this.setStatus(" - - - ");
 1924+ }else{
 1925+ this.setStatus( this.getTimeReq() );
 1926+ }
 1927+ }
 1928+
 1929+ //update monitorTimerId to call child monitor
 1930+ if( ! this.monitorTimerId ){
 1931+ if(document.getElementById(this.id)){
 1932+ this.monitorTimerId = setInterval('$j(\'#'+this.id+'\').get(0).monitor()', 250);
 1933+ }
 1934+ }
 1935+ },
 1936+ getPluginEmbed : function(){
 1937+ if (window.document[this.pid]){
 1938+ return window.document[this.pid];
 1939+ }
 1940+ if (embedTypes.msie){
 1941+ return document.getElementById(this.pid );
 1942+ }else{
 1943+ if (document.embeds && document.embeds[this.pid])
 1944+ return document.embeds[this.pid];
 1945+ }
 1946+ return null;
 1947+ },
 1948+ //HELPER Functions for selected source
 1949+ /*
 1950+ * returns the selected source url for players to play
 1951+ */
 1952+ getURI : function( seek_time_sec ){
 1953+ return this.media_element.selected_source.getURI( this.seek_time_sec );
 1954+ },
 1955+ supportsURLTimeEncoding: function(){
 1956+ //do head request if on the same domain
 1957+ return this.media_element.selected_source.serverSideSeeking;
 1958+ },
 1959+ setSliderValue: function(perc, hide_progress){
 1960+
 1961+ //js_log('setSliderValue:'+perc+' ct:'+ this.currentTime);
 1962+ var this_id = (this.pc)?this.pc.pp.id:this.id;
 1963+ //alinment offset:
 1964+ if(!this.mv_seeker_width)
 1965+ this.mv_seeker_width = $j('#mv_seeker_slider_'+this_id).width();
 1966+
 1967+ var val = Math.round( perc * $j('#mv_seeker_'+this_id).width() - (this.mv_seeker_width*perc));
 1968+ if(val > ($j('#mv_seeker_'+this_id).width() -this.mv_seeker_width) )
 1969+ val = $j('#mv_seeker_'+this_id).width() -this.mv_seeker_width ;
 1970+ if(val < 0)
 1971+ val = 0;
 1972+ $j('#mv_seeker_slider_'+this_id).css('left', (val)+'px' );
 1973+
 1974+ //update the playback progress bar
 1975+ if( ! hide_progress ){
 1976+ $j('#mv_seeker_' + this_id + ' .mv_playback').css("width", Math.round( val + (this.mv_seeker_width*.5) ) + 'px' );
 1977+ }else{
 1978+ //hide the progress bar
 1979+ $j('#mv_seeker_' + this_id + ' .mv_playback').css("width", "0px");
 1980+ }
 1981+
 1982+ //update the buffer progress bar (if available )
 1983+ if( this.bufferedPercent != 0 ){
 1984+ //js_log('bufferedPercent: ' + this.bufferedPercent);
 1985+ if(this.bufferedPercent > 1)
 1986+ this.bufferedPercent=1;
 1987+ $j('#mv_seeker_' + this_id + ' .mv_buffer').css("width", (this.bufferedPercent*100) +'%' );
 1988+ }else{
 1989+ $j('#mv_seeker_' + this_id + ' .mv_buffer').css("width", '0px' );
 1990+ }
 1991+
 1992+ //js_log('set#mv_seeker_slider_'+this_id + ' perc in: ' + perc + ' * ' + $j('#mv_seeker_'+this_id).width() + ' = set to: '+ val + ' - '+ Math.round(this.mv_seeker_width*perc) );
 1993+ //js_log('op:' + offset_perc + ' *('+perc+' * ' + $j('#slider_'+id).width() + ')');
 1994+ },
 1995+ highlightPlaySection:function(options){
 1996+ js_log('highlightPlaySection');
 1997+ var this_id = (this.pc)?this.pc.pp.id:this.id;
 1998+ var dur = this.getDuration();
 1999+ var hide_progress = true;
 2000+ //set the left percet and update the slider:
 2001+ rel_start_sec = ( ntp2seconds( options['start']) - this.start_offset );
 2002+
 2003+ var slider_perc=0;
 2004+ if( rel_start_sec <= 0 ){
 2005+ left_perc =0;
 2006+ options['start'] = seconds2ntp( this.start_offset );
 2007+ rel_start_sec=0;
 2008+ this.setSliderValue( 0 , hide_progress);
 2009+ }else{
 2010+ left_perc = parseInt( (rel_start_sec / dur)*100 ) ;
 2011+ slider_perc = (left_perc / 100);
 2012+ }
 2013+ if( ! this.isPlaying() ){
 2014+ this.setSliderValue( slider_perc , hide_progress);
 2015+ }
 2016+
 2017+ width_perc = parseInt( (( ntp2seconds( options['end'] ) - ntp2seconds( options['start'] ) ) / dur)*100 ) ;
 2018+ if( (width_perc + left_perc) > 100 ){
 2019+ width_perc = 100 - left_perc;
 2020+ }
 2021+ //js_log('should hl: '+rel_start_sec+ '/' + dur + ' re:' + rel_end_sec+' lp:' + left_perc + ' width: ' + width_perc);
 2022+ $j('#mv_seeker_' + this_id + ' .mv_highlight').css({
 2023+ 'left':left_perc+'%',
 2024+ 'width':width_perc+'%'
 2025+ }).show();
 2026+
 2027+ this.jump_time = options['start'];
 2028+ this.seek_time_sec = ntp2seconds( options['start']);
 2029+ //trim output to
 2030+ this.setStatus( gM('seek_to')+' '+ seconds2ntp( this.seek_time_sec ) );
 2031+ js_log('DO update: ' + this.jump_time);
 2032+ this.updateThumbTime( rel_start_sec );
 2033+ },
 2034+ hideHighlight:function(){
 2035+ var this_id = (this.pc)?this.pc.pp.id:this.id;
 2036+ $j('#mv_seeker_' + this_id + ' .mv_highlight').hide();
 2037+ this.setStatus( this.getTimeReq() );
 2038+ this.setSliderValue( 0 );
 2039+ },
 2040+ setStatus:function(value){
 2041+ var id = (this.pc)?this.pc.pp.id:this.id;
 2042+ //update status:
 2043+ $j('#mv_time_'+id).html(value);
 2044+ }
 2045+}
\ No newline at end of file
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_baseEmbed.js
___________________________________________________________________
Name: svn:mergeinfo
12046 +
Name: svn:eol-style
22047 + native
Index: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_quicktimeEmbed.js
@@ -0,0 +1,82 @@
 2+//any plugin specific msg:
 3+gMsg['ogg-no-xiphqt']='You do not appear to have the XiphQT component for QuickTime. QuickTime cannot play ' +
 4+ 'Ogg files without this component. Please ' +
 5+ '<a href="http://www.mediawiki.org/wiki/Extension:OggHandler/Client_download">download XiphQT</a> or choose another player.';
 6+
 7+var quicktimeEmbed = {
 8+ instanceOf:'quicktimeEmbed',
 9+ qtTimers:{},
 10+ getEmbedHTML : function (){
 11+ var controls_html ='';
 12+ js_log('embedObj control is: '+this.controls);
 13+ if(this.controls){
 14+ controls_html+= this.getControlsHtml('stop');
 15+ //if in playlist mode get prev/next and run postEmbedJS():
 16+ if(this.pc){
 17+ controls_html+= this.pc.pp.getPLControls();
 18+ setTimeout('document.getElementById(\''+this.id+'\').postEmbedJS()', 150);
 19+ }
 20+ }
 21+ return this.wrapEmebedContainer( this.getEmbedObj() )+ controls_html;
 22+ },
 23+ getEmbedObj:function(){
 24+ var controllerHeight = 16; // by observation
 25+ var extraAttribs = '';
 26+ if ( embedTypes.playerType == 'quicktime-activex' ) {
 27+ extraAttribs = 'classid="clsid:02BF25D5..."';
 28+ }
 29+ // Poll for completion
 30+ var this_ = this;
 31+ this.qtTimers[this.pid] = window.setInterval( this.makeQuickTimePollFunction(), 500 );
 32+
 33+ return "<div><object id=" + this.pid +
 34+ " type='video/quicktime'" +
 35+ " width=" + this.width +
 36+ " height=" + this.height + controllerHeight +
 37+
 38+ // See http://svn.wikimedia.org/viewvc/mediawiki?view=rev&revision=25605
 39+ " data=" + this.hq( this.extPathUrl + '/null_file.mov' ) +
 40+ ' ' + extraAttribs +
 41+ ">" +
 42+ // Scale, don't clip
 43+ "<param name='SCALE' value='Aspect'/>" +
 44+ "<param name='AUTOPLAY' value='True'/>" +
 45+ "<param name='src' value=" + mv_embed_path + 'null_file.mov' + "/>" +
 46+ "<param name='QTSRC' value=" + this.media_element.selected_source.getURI(this.seek_time_sec) + "/>" +
 47+ "</object></div>";
 48+ },
 49+ makeQuickTimePollFunction : function ( ) {
 50+ var this_ = this;
 51+ return function () {
 52+ var videoElt = document.getElementById( this_.pid );
 53+ if ( videoElt ) {
 54+ // Detect XiphQT (may throw)
 55+ var xiphQtVersion = false, done = false;
 56+ js_log('try quicktime: getComponent:');
 57+ try {
 58+ xiphQtVersion = videoElt.GetComponentVersion('imdc','XiTh', 'Xiph');
 59+ done = true;
 60+ } catch ( e ) {}
 61+ js_log('done with try');
 62+ if ( done ) {
 63+ window.clearInterval( this_.qtTimers[this_.pid] );
 64+ if ( !xiphQtVersion || xiphQtVersion == '0.0' ) {
 65+ $j(this_).html(gM('ogg-no-xiphqt'));
 66+ /*var div = document.createElement( 'div' );
 67+ div.className = 'ogg-player-options';
 68+ div.style.cssText = 'width:' + ( params.width - 10 ) + 'px;'
 69+ div.innerHTML = this_.gM( 'ogg-no-xiphqt' );
 70+ var optionsDiv = document.getElementById( params.id + '_options_box' );
 71+ if ( optionsDiv ) {
 72+ elt.insertBefore( div, optionsDiv.parentNode );
 73+ } else {
 74+ elt.appendChild( div );
 75+ }*/
 76+ }
 77+ // Disable autoplay on back button
 78+ //this_.setParam( videoElt, 'AUTOPLAY', 'False' );
 79+ }
 80+ }
 81+ };
 82+ },
 83+}
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_quicktimeEmbed.js
___________________________________________________________________
Name: svn:mergeinfo
184 +
Name: svn:eol-style
285 + native
Index: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_genericEmbed.js
@@ -0,0 +1,9 @@
 2+/* the most simple implementation used for unknown application/ogg plugin */
 3+var genericEmbed={
 4+ instanceOf:'genericEmbed',
 5+ getEmbedHTML:function(){
 6+ return '<object type="application/ogg" '+
 7+ 'width="'+this.width+'" height="'+this.height+'" ' +
 8+ 'data="' + this.getURI( this.seek_time_sec ) + '"></object>';
 9+ }
 10+}
\ No newline at end of file
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_genericEmbed.js
___________________________________________________________________
Name: svn:mergeinfo
111 +
Name: svn:eol-style
212 + native
Index: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_flashEmbed.js
@@ -0,0 +1,1833 @@
 2+/**
 3+ * metavid: mv_flashEmbed builds off of flowplayer api (included first in this file)
 4+ */
 5+
 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() {
 20+
 21+/*
 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
 30+*/
 31+
 32+
 33+/*jslint glovar: true, browser: true */
 34+/*global flowplayer, $f */
 35+
 36+// {{{ private utility methods
 37+
 38+ function log(args) {
 39+
 40+ // write into opera console
 41+ if (typeof opera == 'object') {
 42+ opera.postError("$f.fireEvent: " + args.join(" | "));
 43+
 44+
 45+ } else if (typeof console == 'object') {
 46+ console.log("$f.fireEvent", [].slice.call(args));
 47+ }
 48+ }
 49+
 50+
 51+ // thanks: http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
 52+ function clone(obj) {
 53+ if (!obj || typeof obj != 'object') { return obj; }
 54+ var temp = new obj.constructor();
 55+ for (var key in obj) {
 56+ if (obj.hasOwnProperty(key)) {
 57+ temp[key] = clone(obj[key]);
 58+ }
 59+ }
 60+ return temp;
 61+ }
 62+
 63+ // stripped from jQuery, thanks John Resig
 64+ function each(obj, fn) {
 65+ if (!obj) { return; }
 66+
 67+ var name, i = 0, length = obj.length;
 68+
 69+ // object
 70+ if (length === undefined) {
 71+ for (name in obj) {
 72+ if (fn.call(obj[name], name, obj[name]) === false) { break; }
 73+ }
 74+
 75+ // array
 76+ } else {
 77+ for (var value = obj[0];
 78+ i < length && fn.call( value, i, value ) !== false; value = obj[++i]) {
 79+ }
 80+ }
 81+
 82+ return obj;
 83+ }
 84+
 85+
 86+ // convenience
 87+ function el(id) {
 88+ return document.getElementById(id);
 89+ }
 90+
 91+
 92+ // used extensively. a very simple implementation.
 93+ function extend(to, from, skipFuncs) {
 94+ if (to && from) {
 95+ each(from, function(name, value) {
 96+ if (!skipFuncs || typeof value != 'function') {
 97+ to[name] = value;
 98+ }
 99+ });
 100+ }
 101+ }
 102+
 103+ // var arr = select("elem.className");
 104+ function select(query) {
 105+ var index = query.indexOf(".");
 106+ if (index != -1) {
 107+ var tag = query.substring(0, index) || "*";
 108+ var klass = query.substring(index + 1, query.length);
 109+ var els = [];
 110+ each(document.getElementsByTagName(tag), function() {
 111+ if (this.className && this.className.indexOf(klass) != -1) {
 112+ els.push(this);
 113+ }
 114+ });
 115+ return els;
 116+ }
 117+ }
 118+
 119+ // fix event inconsistencies across browsers
 120+ function stopEvent(e) {
 121+ e = e || window.event;
 122+
 123+ if (e.preventDefault) {
 124+ e.stopPropagation();
 125+ e.preventDefault();
 126+
 127+ } else {
 128+ e.returnValue = false;
 129+ e.cancelBubble = true;
 130+ }
 131+ return false;
 132+ }
 133+
 134+ // push an event listener into existing array of listeners
 135+ function bind(to, evt, fn) {
 136+ to[evt] = to[evt] || [];
 137+ to[evt].push(fn);
 138+ }
 139+
 140+
 141+ // generates an unique id
 142+ function makeId() {
 143+ return "_" + ("" + Math.random()).substring(2, 10);
 144+ }
 145+
 146+//}}}
 147+
 148+
 149+// {{{ Clip
 150+
 151+ var Clip = function(json, index, player) {
 152+
 153+ // private variables
 154+ var self = this;
 155+ var cuepoints = {};
 156+ var listeners = {};
 157+ this.index = index;
 158+
 159+ // instance variables
 160+ if (typeof json == 'string') {
 161+ json = {url:json};
 162+ }
 163+
 164+ extend(this, json, true);
 165+
 166+ // event handling
 167+ each(("Begin*,Start,Pause*,Resume*,Seek*,Stop*,Finish*,LastSecond,Update,BufferFull,BufferEmpty,BufferStop").split(","),
 168+ function() {
 169+
 170+ var evt = "on" + this;
 171+
 172+ // before event
 173+ if (evt.indexOf("*") != -1) {
 174+ evt = evt.substring(0, evt.length -1);
 175+ var before = "onBefore" + evt.substring(2);
 176+
 177+ self[before] = function(fn) {
 178+ bind(listeners, before, fn);
 179+ return self;
 180+ };
 181+ }
 182+
 183+ self[evt] = function(fn) {
 184+ bind(listeners, evt, fn);
 185+ return self;
 186+ };
 187+
 188+
 189+ // set common clip event listeners to player level
 190+ if (index == -1) {
 191+ if (self[before]) {
 192+ player[before] = self[before];
 193+ }
 194+ if (self[evt]) {
 195+ player[evt] = self[evt];
 196+ }
 197+ }
 198+
 199+ });
 200+
 201+ extend(this, {
 202+
 203+
 204+ onCuepoint: function(points, fn) {
 205+
 206+ // embedded cuepoints
 207+ if (arguments.length == 1) {
 208+ cuepoints.embedded = [null, points];
 209+ return self;
 210+ }
 211+
 212+ if (typeof points == 'number') {
 213+ points = [points];
 214+ }
 215+
 216+ var fnId = makeId();
 217+ cuepoints[fnId] = [points, fn];
 218+
 219+ if (player.isLoaded()) {
 220+ player._api().fp_addCuepoints(points, index, fnId);
 221+ }
 222+
 223+ return self;
 224+ },
 225+
 226+ update: function(json) {
 227+ extend(self, json);
 228+
 229+ if (player.isLoaded()) {
 230+ player._api().fp_updateClip(json, index);
 231+ }
 232+ var conf = player.getConfig();
 233+ var clip = (index == -1) ? conf.clip : conf.playlist[index];
 234+ extend(clip, json, true);
 235+ },
 236+
 237+
 238+ // internal event for performing clip tasks. should be made private someday
 239+ _fireEvent: function(evt, arg1, arg2, target) {
 240+
 241+ if (evt == 'onLoad') {
 242+ each(cuepoints, function(key, val) {
 243+ player._api().fp_addCuepoints(val[0], index, key);
 244+ });
 245+ return false;
 246+ }
 247+
 248+ // target clip we are working against
 249+ if (index != -1) {
 250+ target = self;
 251+ }
 252+
 253+ if (evt == 'onCuepoint') {
 254+ var fn = cuepoints[arg1];
 255+ if (fn) {
 256+ return fn[1].call(player, target, arg2);
 257+ }
 258+ }
 259+
 260+ if (evt == 'onStart' || evt == 'onUpdate') {
 261+
 262+ extend(target, arg1);
 263+
 264+ if (!target.duration) {
 265+ target.duration = arg1.metaData.duration;
 266+ } else {
 267+ target.fullDuration = arg1.metaData.duration;
 268+ }
 269+ }
 270+
 271+ var ret = true;
 272+ each(listeners[evt], function() {
 273+ ret = this.call(player, target, arg1);
 274+ });
 275+ return ret;
 276+ }
 277+
 278+ });
 279+
 280+
 281+ // get cuepoints from config
 282+ if (json.onCuepoint) {
 283+ self.onCuepoint.apply(self, json.onCuepoint);
 284+ delete json.onCuepoint;
 285+ }
 286+
 287+ // get other events
 288+ each(json, function(key, val) {
 289+ if (typeof val == 'function') {
 290+ bind(listeners, key, val);
 291+ delete json[key];
 292+ }
 293+ });
 294+
 295+
 296+ // setup common clip event callbacks for Player object too (shortcuts)
 297+ if (index == -1) {
 298+ player.onCuepoint = this.onCuepoint;
 299+ }
 300+
 301+ };
 302+
 303+//}}}
 304+
 305+
 306+// {{{ Plugin
 307+
 308+ var Plugin = function(name, json, player, fn) {
 309+
 310+ var listeners = {};
 311+ var self = this;
 312+ var hasMethods = false;
 313+
 314+ if (fn) {
 315+ extend(listeners, fn);
 316+ }
 317+
 318+ // custom callback functions in configuration
 319+ each(json, function(key, val) {
 320+ if (typeof val == 'function') {
 321+ listeners[key] = val;
 322+ delete json[key];
 323+ }
 324+ });
 325+
 326+ // core plugin methods
 327+ extend(this, {
 328+
 329+ animate: function(props, speed, fn) {
 330+ if (!props) {
 331+ return self;
 332+ }
 333+
 334+ if (typeof speed == 'function') {
 335+ fn = speed;
 336+ speed = 500;
 337+ }
 338+
 339+ if (typeof props == 'string') {
 340+ var key = props;
 341+ props = {};
 342+ props[key] = speed;
 343+ speed = 500;
 344+ }
 345+
 346+ if (fn) {
 347+ var fnId = makeId();
 348+ listeners[fnId] = fn;
 349+ }
 350+
 351+ if (speed === undefined) { speed = 500; }
 352+ json = player._api().fp_animate(name, props, speed, fnId);
 353+ return self;
 354+ },
 355+
 356+ css: function(props, val) {
 357+ if (val !== undefined) {
 358+ var css = {};
 359+ css[props] = val;
 360+ props = css;
 361+ }
 362+ try{
 363+ json = player._api().fp_css(name, props);
 364+ extend(self, json);
 365+ return self;
 366+ }catch(e){
 367+ js_log('flow player could not set css: ' + json);
 368+ }
 369+ },
 370+
 371+ show: function() {
 372+ this.display = 'block';
 373+ player._api().fp_showPlugin(name);
 374+ return self;
 375+ },
 376+
 377+ hide: function() {
 378+ this.display = 'none';
 379+ player._api().fp_hidePlugin(name);
 380+ return self;
 381+ },
 382+
 383+ toggle: function() {
 384+ this.display = player._api().fp_togglePlugin(name);
 385+ return self;
 386+ },
 387+
 388+ fadeTo: function(o, speed, fn) {
 389+
 390+ if (typeof speed == 'function') {
 391+ fn = speed;
 392+ speed = 500;
 393+ }
 394+
 395+ if (fn) {
 396+ var fnId = makeId();
 397+ listeners[fnId] = fn;
 398+ }
 399+ this.display = player._api().fp_fadeTo(name, o, speed, fnId);
 400+ this.opacity = o;
 401+ return self;
 402+ },
 403+
 404+ fadeIn: function(speed, fn) {
 405+ return self.fadeTo(1, speed, fn);
 406+ },
 407+
 408+ fadeOut: function(speed, fn) {
 409+ return self.fadeTo(0, speed, fn);
 410+ },
 411+
 412+ getName: function() {
 413+ return name;
 414+ },
 415+
 416+
 417+ // internal method not meant to be used by clients
 418+ _fireEvent: function(evt, arg) {
 419+
 420+
 421+ // update plugins properties & methods
 422+ if (evt == 'onUpdate') {
 423+ var json = arg || player._api().fp_getPlugin(name);
 424+ if (!json) { return; }
 425+
 426+ extend(self, json);
 427+ delete self.methods;
 428+
 429+ if (!hasMethods) {
 430+ each(json.methods, function() {
 431+ var method = "" + this;
 432+
 433+ self[method] = function() {
 434+ var a = [].slice.call(arguments);
 435+ var ret = player._api().fp_invoke(name, method, a);
 436+ return ret == 'undefined' ? self : ret;
 437+ };
 438+ });
 439+ hasMethods = true;
 440+ }
 441+ }
 442+
 443+ // plugin callbacks
 444+ var fn = listeners[evt];
 445+
 446+ if (fn) {
 447+
 448+ fn.call(self, arg);
 449+
 450+ // "one-shot" callback
 451+ if (evt.substring(0, 1) == "_") {
 452+ delete listeners[evt];
 453+ }
 454+ }
 455+ }
 456+
 457+ });
 458+
 459+ };
 460+
 461+
 462+//}}}
 463+
 464+
 465+function Player(wrapper, params, conf) {
 466+
 467+ // private variables (+ arguments)
 468+ var
 469+ self = this,
 470+ api = null,
 471+ html,
 472+ commonClip,
 473+ playlist = [],
 474+ plugins = {},
 475+ listeners = {},
 476+ playerId,
 477+ apiId,
 478+ activeIndex,
 479+ swfHeight,
 480+ wrapperHeight;
 481+
 482+
 483+// {{{ public methods
 484+
 485+ extend(self, {
 486+
 487+ id: function() {
 488+ return playerId;
 489+ },
 490+
 491+ isLoaded: function() {
 492+ return (api !== null);
 493+ },
 494+
 495+ getParent: function() {
 496+ return wrapper;
 497+ },
 498+
 499+ hide: function(all) {
 500+ if (all) { wrapper.style.height = "0px"; }
 501+ if (api) { api.style.height = "0px"; }
 502+ return self;
 503+ },
 504+
 505+ show: function() {
 506+ wrapper.style.height = wrapperHeight + "px";
 507+ if (api) { api.style.height = swfHeight + "px"; }
 508+ return self;
 509+ },
 510+
 511+ isHidden: function() {
 512+ return api && parseInt(api.style.height, 10) === 0;
 513+ },
 514+
 515+
 516+ load: function(fn) {
 517+
 518+ if (!api && self._fireEvent("onBeforeLoad") !== false) {
 519+
 520+ // unload all instances
 521+ each(players, function() {
 522+ this.unload();
 523+ });
 524+
 525+ html = wrapper.innerHTML;
 526+ flashembed(wrapper, params, {config: conf});
 527+
 528+ // function argument
 529+ if (fn) {
 530+ fn.cached = true;
 531+ bind(listeners, "onLoad", fn);
 532+ }
 533+ }
 534+
 535+ return self;
 536+ },
 537+
 538+ unload: function() {
 539+
 540+ if (api && html.replace(/\s/g, '') !== '' && !api.fp_isFullscreen() &&
 541+ self._fireEvent("onBeforeUnload") !== false) {
 542+ api.fp_close();
 543+ wrapper.innerHTML = html;
 544+ self._fireEvent("onUnload");
 545+ api = null;
 546+ }
 547+
 548+ return self;
 549+ },
 550+
 551+ getClip: function(index) {
 552+ if (index === undefined) {
 553+ index = activeIndex;
 554+ }
 555+ return playlist[index];
 556+ },
 557+
 558+
 559+ getCommonClip: function() {
 560+ return commonClip;
 561+ },
 562+
 563+ getPlaylist: function() {
 564+ return playlist;
 565+ },
 566+
 567+ getPlugin: function(name) {
 568+ var plugin = plugins[name];
 569+
 570+ // create plugin if nessessary
 571+ if (!plugin && self.isLoaded()) {
 572+ var json = self._api().fp_getPlugin(name);
 573+ if (json) {
 574+ plugin = new Plugin(name, json, self);
 575+ plugins[name] = plugin;
 576+ }
 577+ }
 578+ return plugin;
 579+ },
 580+
 581+ getScreen: function() {
 582+ return self.getPlugin("screen");
 583+ },
 584+
 585+ getControls: function() {
 586+ return self.getPlugin("controls");
 587+ },
 588+
 589+ getConfig: function() {
 590+ return clone(conf);
 591+ },
 592+
 593+ getFlashParams: function() {
 594+ return params;
 595+ },
 596+
 597+ loadPlugin: function(name, url, props, fn) {
 598+
 599+ // properties not supplied
 600+ if (typeof props == 'function') {
 601+ fn = props;
 602+ props = {};
 603+ }
 604+
 605+ // if fn not given, make a fake id so that plugin's onUpdate get's fired
 606+ var fnId = fn ? makeId() : "_";
 607+ self._api().fp_loadPlugin(name, url, props, fnId);
 608+
 609+ // create new plugin
 610+ var arg = {};
 611+ arg[fnId] = fn;
 612+ var p = new Plugin(name, null, self, arg);
 613+ plugins[name] = p;
 614+ return p;
 615+ },
 616+
 617+
 618+ getState: function() {
 619+ return api ? api.fp_getState() : -1;
 620+ },
 621+
 622+ // "lazy" play
 623+ play: function(clip) {
 624+
 625+ function play() {
 626+ if (clip !== undefined) {
 627+ self._api().fp_play(clip);
 628+ } else {
 629+ if(typeof self._api().fp_play == 'function')
 630+ self._api().fp_play();
 631+ }
 632+ }
 633+
 634+ if (api) {
 635+ play();
 636+
 637+ } else {
 638+ self.load(function() {
 639+ play();
 640+ });
 641+ }
 642+
 643+ return self;
 644+ },
 645+
 646+ getVersion: function() {
 647+ var js = "flowplayer.js 3.0.0-rc5";
 648+ if (api) {
 649+ var ver = api.fp_getVersion();
 650+ ver.push(js);
 651+ return ver;
 652+ }
 653+ return js;
 654+ },
 655+
 656+ _api: function() {
 657+ if (!api) {
 658+ throw "Flowplayer " +self.id()+ " not loaded. Try moving your call to player's onLoad event";
 659+ }
 660+ return api;
 661+ },
 662+
 663+ _dump: function() {
 664+ console.log(listeners);
 665+ }
 666+
 667+ });
 668+
 669+
 670+ // event handlers
 671+ each(("Click*,Load*,Unload*,Keypress*,Volume*,Mute*,Unmute*,PlaylistReplace,Fullscreen*,FullscreenExit,Error").split(","),
 672+ function() {
 673+ var name = "on" + this;
 674+
 675+ // before event
 676+ if (name.indexOf("*") != -1) {
 677+ name = name.substring(0, name.length -1);
 678+ var name2 = "onBefore" + name.substring(2);
 679+ self[name2] = function(fn) {
 680+ bind(listeners, name2, fn);
 681+ return self;
 682+ };
 683+ }
 684+
 685+ // normal event
 686+ self[name] = function(fn) {
 687+ bind(listeners, name, fn);
 688+ return self;
 689+ };
 690+ }
 691+ );
 692+
 693+
 694+ // core API methods
 695+ each(("pause,resume,mute,unmute,stop,toggle,seek,getStatus,getVolume,setVolume,getTime,isPaused,isPlaying,startBuffering,stopBuffering,isFullscreen,reset").split(","),
 696+ function() {
 697+ var name = this;
 698+
 699+ self[name] = function(arg) {
 700+ if (!api) { return self; }
 701+ try{
 702+ var ret = (arg === undefined) ? api["fp_" + name]() : api["fp_" + name](arg);
 703+ return ret == 'undefined' ? self : ret;
 704+ }catch (e){
 705+ js_log('flowplayer could not access fp_ '+ name);
 706+ }
 707+ };
 708+ }
 709+ );
 710+
 711+//}}}
 712+
 713+
 714+// {{{ public method: _fireEvent
 715+
 716+ self._fireEvent = function(evt, arg0, arg1, arg2) {
 717+
 718+ if (conf.debug) {
 719+ log(arguments);
 720+ }
 721+
 722+ // internal onLoad
 723+ if (evt == 'onLoad' && !api) {
 724+
 725+ api = api || el(apiId);
 726+ swfHeight = api.clientHeight;
 727+
 728+ each(playlist, function() {
 729+ this._fireEvent("onLoad");
 730+ });
 731+
 732+ each(plugins, function(name, p) {
 733+ p._fireEvent("onUpdate");
 734+ });
 735+
 736+
 737+ commonClip._fireEvent("onLoad");
 738+ }
 739+
 740+ if (evt == 'onContextMenu') {
 741+ each(conf.contextMenu[arg0], function(key, fn) {
 742+ fn.call(self);
 743+ });
 744+ return;
 745+ }
 746+
 747+ if (evt == 'onPluginEvent') {
 748+ var name = arg0.name || arg0;
 749+ var p = plugins[name];
 750+ if (p) {
 751+ if (arg0.name) {
 752+ p._fireEvent("onUpdate", arg0);
 753+ }
 754+ p._fireEvent(arg1);
 755+ }
 756+ return;
 757+ }
 758+
 759+ // onPlaylistReplace
 760+ if (evt == 'onPlaylistReplace') {
 761+ playlist = [];
 762+ var index = 0;
 763+ each(arg0, function() {
 764+ playlist.push(new Clip(this, index++));
 765+ });
 766+ }
 767+
 768+ var ret = true;
 769+
 770+ // clip event
 771+ if (arg0 === 0 || (arg0 && arg0 >= 0)) {
 772+
 773+ activeIndex = arg0;
 774+ var clip = playlist[arg0];
 775+
 776+ if (clip) {
 777+ ret = clip._fireEvent(evt, arg1, arg2);
 778+ }
 779+
 780+ if (!clip || ret !== false) {
 781+
 782+ // clip argument is given for common clip, because it behaves as the target
 783+ ret = commonClip._fireEvent(evt, arg1, arg2, clip);
 784+ }
 785+ }
 786+
 787+ // player event
 788+ var i = 0;
 789+ each(listeners[evt], function() {
 790+ ret = this.call(self, arg0);
 791+
 792+ // remove cached entry
 793+ if (this.cached) {
 794+ listeners[evt].splice(i, 1);
 795+ }
 796+
 797+ // break loop
 798+ if (ret === false) { return false; }
 799+ i++;
 800+
 801+ });
 802+
 803+ return ret;
 804+ };
 805+
 806+//}}}
 807+
 808+
 809+// {{{ init
 810+
 811+ function init() {
 812+
 813+ if ($f(wrapper)) {
 814+ return null;
 815+ }
 816+
 817+ wrapperHeight = parseInt(wrapper.style.height) || wrapper.clientHeight;
 818+
 819+ // register this player into global array of instances
 820+ players.push(self);
 821+
 822+
 823+ // flashembed parameters
 824+ if (typeof params == 'string') {
 825+ params = {src: params};
 826+ }
 827+
 828+ // playerId
 829+ playerId = wrapper.id || "fp" + makeId();
 830+ apiId = params.id || playerId + "_api";
 831+ params.id = apiId;
 832+ conf.playerId = playerId;
 833+
 834+
 835+ // plain url is given as config
 836+ if (typeof conf == 'string') {
 837+ conf = {clip:{url:conf}};
 838+ }
 839+
 840+ // common clip is always there
 841+ conf.clip = conf.clip || {};
 842+ commonClip = new Clip(conf.clip, -1, self);
 843+
 844+
 845+ // wrapper href as playlist
 846+ if (wrapper.getAttribute("href")) {
 847+ conf.playlist = [{url:wrapper.getAttribute("href", 2)}];
 848+ }
 849+
 850+ // playlist
 851+ conf.playlist = conf.playlist || [conf.clip];
 852+
 853+ var index = 0;
 854+ each(conf.playlist, function() {
 855+
 856+ var clip = this;
 857+
 858+ // clip is an array, we don't allow that
 859+ if (typeof clip == 'object' && clip.length) {
 860+ clip = "" + clip;
 861+ }
 862+
 863+ if (!clip.url && typeof clip == 'string') {
 864+ clip = {url: clip};
 865+ }
 866+
 867+ // populate common clip properties to each clip
 868+ extend(clip, conf.clip, true);
 869+
 870+ // modify configuration playlist
 871+ conf.playlist[index] = clip;
 872+
 873+ // populate playlist array
 874+ clip = new Clip(clip, index, self);
 875+ playlist.push(clip);
 876+ index++;
 877+ });
 878+
 879+
 880+ // event listeners
 881+ each(conf, function(key, val) {
 882+ if (typeof val == 'function') {
 883+ bind(listeners, key, val);
 884+ delete conf[key];
 885+ }
 886+ });
 887+
 888+
 889+ // plugins
 890+ each(conf.plugins, function(name, val) {
 891+ if (val) {
 892+ plugins[name] = new Plugin(name, val, self);
 893+ }
 894+ });
 895+
 896+
 897+ // setup controlbar plugin if not explicitly defined
 898+ if (!conf.plugins || conf.plugins.controls === undefined) {
 899+ plugins.controls = new Plugin("controls", null, self);
 900+ }
 901+
 902+ // Flowplayer uses black background by default
 903+ params.bgcolor = params.bgcolor || "#000000";
 904+
 905+
 906+ // setup default settings for express install
 907+ params.version = params.version || [9,0];
 908+ params.expressInstall = 'http://www.flowplayer.org/swf/expressinstall.swf';
 909+
 910+
 911+ // click function
 912+ function doClick(e) {
 913+ if (self._fireEvent("onBeforeClick") !== false) {
 914+ self.load();
 915+ }
 916+ return stopEvent(e);
 917+ }
 918+
 919+ // defer loading upon click
 920+ html = wrapper.innerHTML;
 921+ if (html.replace(/\s/g, '') !== '') {
 922+
 923+ if (wrapper.addEventListener) {
 924+ wrapper.addEventListener("click", doClick, false);
 925+
 926+ } else if (wrapper.attachEvent) {
 927+ wrapper.attachEvent("onclick", doClick);
 928+ }
 929+
 930+ // player is loaded upon page load
 931+ } else {
 932+
 933+ // prevent default action from wrapper (safari problem) loaded
 934+ if (wrapper.addEventListener) {
 935+ wrapper.addEventListener("click", stopEvent, false);
 936+ }
 937+
 938+ // load player
 939+ self.load();
 940+ }
 941+
 942+ }
 943+
 944+ // possibly defer initialization until DOM get's loaded
 945+ if (typeof wrapper == 'string') {
 946+ flashembed.domReady(function() {
 947+ var node = el(wrapper);
 948+
 949+ if (!node) {
 950+ throw "Flowplayer cannot access element: " + wrapper;
 951+ } else {
 952+ wrapper = node;
 953+ init();
 954+ }
 955+ });
 956+
 957+ // we have a DOM element so page is already loaded
 958+ } else {
 959+ init();
 960+ }
 961+
 962+
 963+//}}}
 964+
 965+
 966+}
 967+
 968+
 969+// {{{ flowplayer() & statics
 970+
 971+// container for player instances
 972+var players = [];
 973+
 974+
 975+// this object is returned when multiple player's are requested
 976+function Iterator(arr) {
 977+
 978+ this.length = arr.length;
 979+
 980+ this.each = function(fn) {
 981+ each(arr, fn);
 982+ };
 983+
 984+ this.size = function() {
 985+ return arr.length;
 986+ };
 987+}
 988+
 989+// these two variables are the only global variables
 990+window.flowplayer = window.$f = function() {
 991+
 992+ var instance = null;
 993+ var arg = arguments[0];
 994+
 995+
 996+ // $f()
 997+ if (!arguments.length) {
 998+ each(players, function() {
 999+ if (this.isLoaded()) {
 1000+ instance = this;
 1001+ return false;
 1002+ }
 1003+ });
 1004+
 1005+ return instance || players[0];
 1006+ }
 1007+
 1008+ if (arguments.length == 1) {
 1009+
 1010+ // $f(index);
 1011+ if (typeof arg == 'number') {
 1012+ return players[arg];
 1013+
 1014+
 1015+ // $f(wrapper || 'containerId' || '*');
 1016+ } else {
 1017+
 1018+ // $f("*");
 1019+ if (arg == '*') {
 1020+ return new Iterator(players);
 1021+ }
 1022+
 1023+ // $f(wrapper || 'containerId');
 1024+ each(players, function() {
 1025+ if (this.id() == arg.id || this.id() == arg || this.getParent() == arg) {
 1026+ instance = this;
 1027+ return false;
 1028+ }
 1029+ });
 1030+
 1031+ return instance;
 1032+ }
 1033+ }
 1034+
 1035+ // instance builder
 1036+ if (arguments.length > 1) {
 1037+
 1038+ var swf = arguments[1];
 1039+ var conf = (arguments.length == 3) ? arguments[2] : {};
 1040+
 1041+ if (typeof arg == 'string') {
 1042+
 1043+ // select arg by classname
 1044+ if (arg.indexOf(".") != -1) {
 1045+ var instances = [];
 1046+
 1047+ each(select(arg), function() {
 1048+ instances.push(new Player(this, clone(swf), clone(conf)));
 1049+ });
 1050+
 1051+ return new Iterator(instances);
 1052+
 1053+ // select node by id
 1054+ } else {
 1055+ var node = el(arg);
 1056+ return new Player(node !== null ? node : arg, swf, conf);
 1057+ }
 1058+
 1059+
 1060+ // arg is a DOM element
 1061+ } else if (arg) {
 1062+ return new Player(arg, swf, conf);
 1063+ }
 1064+
 1065+ }
 1066+
 1067+ return null;
 1068+};
 1069+
 1070+extend(window.$f, {
 1071+
 1072+ // called by Flash External Interface
 1073+ fireEvent: function(id, evt, a0, a1, a2) {
 1074+ var p = $f(id);
 1075+ return p ? p._fireEvent(evt, a0, a1, a2) : null;
 1076+ },
 1077+
 1078+
 1079+ // create plugins by modifying Player's prototype
 1080+ addPlugin: function(name, fn) {
 1081+ Player.prototype[name] = fn;
 1082+ return $f;
 1083+ },
 1084+
 1085+ // utility methods for plugin developers
 1086+ each: each,
 1087+
 1088+ extend: extend
 1089+
 1090+});
 1091+
 1092+//}}}
 1093+
 1094+
 1095+//{{{ jQuery support
 1096+
 1097+if (typeof jQuery == 'function') {
 1098+
 1099+ jQuery.prototype.flowplayer = function(params, conf) {
 1100+
 1101+ // select instances
 1102+ if (!arguments.length || typeof arguments[0] == 'number') {
 1103+ var arr = [];
 1104+ this.each(function() {
 1105+ var p = $f(this);
 1106+ if (p) {
 1107+ arr.push(p);
 1108+ }
 1109+ });
 1110+ return arguments.length ? arr[arguments[0]] : new Iterator(arr);
 1111+ }
 1112+
 1113+ // create flowplayer instances
 1114+ return this.each(function() {
 1115+ $f(this, clone(params), conf ? clone(conf) : {});
 1116+ });
 1117+
 1118+ };
 1119+
 1120+}
 1121+
 1122+//}}}
 1123+
 1124+
 1125+})();
 1126+/**
 1127+ * flashembed 0.34. Adobe Flash embedding script
 1128+ *
 1129+ * http://flowplayer.org/tools/flash-embed.html
 1130+ *
 1131+ * Copyright (c) 2008 Tero Piirainen (support@flowplayer.org)
 1132+ *
 1133+ * Released under the MIT License:
 1134+ * http://www.opensource.org/licenses/mit-license.php
 1135+ *
 1136+ * >> Basically you can do anything you want but leave this header as is <<
 1137+ *
 1138+ * first version 0.01 - 03/11/2008
 1139+ * version 0.34 - Tue Nov 11 2008 09:09:52 GMT-0000 (GMT+00:00)
 1140+ */
 1141+(function() {
 1142+
 1143+//{{{ utility functions
 1144+
 1145+var jQ = typeof jQuery == 'function';
 1146+
 1147+
 1148+// from "Pro JavaScript techniques" by John Resig
 1149+function isDomReady() {
 1150+
 1151+ if (domReady.done) { return false; }
 1152+
 1153+ var d = document;
 1154+ if (d && d.getElementsByTagName && d.getElementById && d.body) {
 1155+ clearInterval(domReady.timer);
 1156+ domReady.timer = null;
 1157+
 1158+ for (var i = 0; i < domReady.ready.length; i++) {
 1159+ domReady.ready[i].call();
 1160+ }
 1161+
 1162+ domReady.ready = null;
 1163+ domReady.done = true;
 1164+ }
 1165+}
 1166+
 1167+// if jQuery is present, use it's more effective domReady method
 1168+var domReady = jQ ? jQuery : function(f) {
 1169+
 1170+ if (domReady.done) {
 1171+ return f();
 1172+ }
 1173+
 1174+ if (domReady.timer) {
 1175+ domReady.ready.push(f);
 1176+
 1177+ } else {
 1178+ domReady.ready = [f];
 1179+ domReady.timer = setInterval(isDomReady, 13);
 1180+ }
 1181+};
 1182+
 1183+
 1184+// override extend params function
 1185+function extend(to, from) {
 1186+ if (from) {
 1187+ for (key in from) {
 1188+ if (from.hasOwnProperty(key)) {
 1189+ to[key] = from[key];
 1190+ }
 1191+ }
 1192+ }
 1193+
 1194+ return to;
 1195+}
 1196+
 1197+
 1198+function concatVars(vars) {
 1199+ var out = "";
 1200+
 1201+ for (var key in vars) {
 1202+ if (vars[key]) {
 1203+ out += [key] + '=' + asString(vars[key]) + '&';
 1204+ }
 1205+ }
 1206+ return out.substring(0, out.length -1);
 1207+}
 1208+
 1209+
 1210+
 1211+// JSON.asString() function
 1212+function asString(obj) {
 1213+
 1214+ switch (typeOf(obj)){
 1215+ case 'string':
 1216+ obj = obj.replace(new RegExp('(["\\\\])', 'g'), '\\$1');
 1217+
 1218+ // flash does not handle %- characters well. transforms "50%" to "50pct" (a dirty hack, I admit)
 1219+ obj = obj.replace(/^\s?(\d+)%/, "$1pct");
 1220+ return '"' +obj+ '"';
 1221+
 1222+ case 'array':
 1223+ return '['+ map(obj, function(el) {
 1224+ return asString(el);
 1225+ }).join(',') +']';
 1226+
 1227+ case 'function':
 1228+ return '"function()"';
 1229+
 1230+ case 'object':
 1231+ var str = [];
 1232+ for (var prop in obj) {
 1233+ if (obj.hasOwnProperty(prop)) {
 1234+ str.push('"'+prop+'":'+ asString(obj[prop]));
 1235+ }
 1236+ }
 1237+ return '{'+str.join(',')+'}';
 1238+ }
 1239+
 1240+ // replace ' --> " and remove spaces
 1241+ return String(obj).replace(/\s/g, " ").replace(/\'/g, "\"");
 1242+}
 1243+
 1244+
 1245+// private functions
 1246+function typeOf(obj) {
 1247+ if (obj === null || obj === undefined) { return false; }
 1248+ var type = typeof obj;
 1249+ return (type == 'object' && obj.push) ? 'array' : type;
 1250+}
 1251+
 1252+
 1253+// version 9 bugfix: (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
 1254+if (window.attachEvent) {
 1255+ window.attachEvent("onbeforeunload", function() {
 1256+ __flash_unloadHandler = function() {};
 1257+ __flash_savedUnloadHandler = function() {};
 1258+ });
 1259+}
 1260+
 1261+function map(arr, func) {
 1262+ var newArr = [];
 1263+ for (var i in arr) {
 1264+ if (arr.hasOwnProperty(i)) {
 1265+ newArr[i] = func(arr[i]);
 1266+ }
 1267+ }
 1268+ return newArr;
 1269+}
 1270+
 1271+function getEmbedCode(p, c) {
 1272+ var html = '<embed type="application/x-shockwave-flash" ';
 1273+
 1274+ if (p.id) { extend(p, {name:p.id}); }
 1275+
 1276+ for (var key in p) {
 1277+ if (p[key] !== null) {
 1278+ html += key + '="' +p[key]+ '"\n\t';
 1279+ }
 1280+ }
 1281+
 1282+ if (c) {
 1283+ html += 'flashvars=\'' + concatVars(c) + '\'';
 1284+ }
 1285+
 1286+ // thanks Tom Price (07/17/2008)
 1287+ html += '/>';
 1288+
 1289+ return html;
 1290+}
 1291+
 1292+function getObjectCode(p, c, embeddable) {
 1293+
 1294+ var html = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
 1295+ html += 'width="' + p.width + '" height="' + p.height + '"';
 1296+
 1297+ // force id for IE. otherwise embedded Flash object cannot be returned
 1298+ if (!p.id && document.all) {
 1299+ p.id = "_" + ("" + Math.random()).substring(5);
 1300+ }
 1301+
 1302+ if (p.id) {
 1303+ html += ' id="' + p.id + '"';
 1304+ }
 1305+
 1306+ html += '>';
 1307+
 1308+ // sometimes ie fails to load flash if it's on cache
 1309+ if (document.all) {
 1310+ p.src += ((p.src.indexOf("?") != -1 ? "&" : "?") + Math.random());
 1311+ }
 1312+
 1313+ html += '\n\t<param name="movie" value="'+ p.src +'" />';
 1314+
 1315+ var e = extend({}, p);
 1316+ e.id = e.width = e.height = e.src = null;
 1317+
 1318+ for (var k in e) {
 1319+ if (e[k] !== null) {
 1320+ html += '\n\t<param name="'+ k +'" value="'+ e[k] +'" />';
 1321+ }
 1322+ }
 1323+
 1324+ if (c) {
 1325+ html += '\n\t<param name="flashvars" value=\'' + concatVars(c) + '\' />';
 1326+ }
 1327+
 1328+ if (embeddable) {
 1329+ html += getEmbedCode(p, c);
 1330+ }
 1331+
 1332+ html += "</object>";
 1333+
 1334+ return html;
 1335+}
 1336+
 1337+function getFullHTML(p, c) {
 1338+ return getObjectCode(p, c, true);
 1339+}
 1340+
 1341+function getHTML(p, c) {
 1342+ var isNav = navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length;
 1343+ return (isNav) ? getEmbedCode(p, c) : getObjectCode(p, c);
 1344+}
 1345+
 1346+//}}}
 1347+
 1348+
 1349+window.flashembed = function(root, userParams, flashvars) {
 1350+
 1351+
 1352+//{{{ construction
 1353+
 1354+ // setup params
 1355+ var params = {
 1356+
 1357+ // very common params
 1358+ src: '#',
 1359+ width: '100%',
 1360+ height: '100%',
 1361+
 1362+ // flashembed specific options
 1363+ version:null,
 1364+ onFail:null,
 1365+ expressInstall:null,
 1366+ debug: false,
 1367+
 1368+ // flashembed defaults
 1369+ // bgcolor: 'transparent',
 1370+ allowfullscreen: true,
 1371+ allowscriptaccess: 'always',
 1372+ quality: 'high',
 1373+ type: 'application/x-shockwave-flash',
 1374+ pluginspage: 'http://www.adobe.com/go/getflashplayer'
 1375+ };
 1376+
 1377+
 1378+ if (typeof userParams == 'string') {
 1379+ userParams = {src: userParams};
 1380+ }
 1381+
 1382+ extend(params, userParams);
 1383+
 1384+ var version = flashembed.getVersion();
 1385+ var required = params.version;
 1386+ var express = params.expressInstall;
 1387+ var debug = params.debug;
 1388+
 1389+
 1390+ if (typeof root == 'string') {
 1391+ var el = document.getElementById(root);
 1392+ if (el) {
 1393+ root = el;
 1394+ } else {
 1395+ domReady(function() {
 1396+ flashembed(root, userParams, flashvars);
 1397+ });
 1398+ return;
 1399+ }
 1400+ }
 1401+
 1402+ if (!root) { return; }
 1403+
 1404+
 1405+ // is supported
 1406+ if (!required || flashembed.isSupported(required)) {
 1407+ params.onFail = params.version = params.expressInstall = params.debug = null;
 1408+
 1409+ // root.innerHTML may cause broplems: http://domscripting.com/blog/display/99
 1410+ // thanks to: Ryan Rud
 1411+ // var tmp = document.createElement("extradiv");
 1412+ // tmp.innerHTML = getHTML();
 1413+ // root.appendChild(tmp);
 1414+
 1415+ root.innerHTML = getHTML(params, flashvars);
 1416+
 1417+ // return our API
 1418+ return root.firstChild;
 1419+
 1420+ // custom fail event
 1421+ } else if (params.onFail) {
 1422+ var ret = params.onFail.call(params, flashembed.getVersion(), flashvars);
 1423+ if (ret === true) { root.innerHTML = ret; }
 1424+
 1425+
 1426+ // express install
 1427+ } else if (required && express && flashembed.isSupported([6,65])) {
 1428+
 1429+ extend(params, {src: express});
 1430+
 1431+ flashvars = {
 1432+ MMredirectURL: location.href,
 1433+ MMplayerType: 'PlugIn',
 1434+ MMdoctitle: document.title
 1435+ };
 1436+
 1437+ root.innerHTML = getHTML(params, flashvars);
 1438+
 1439+ // not supported
 1440+ } else {
 1441+
 1442+ // minor bug fixed here 08.04.2008 (thanks JRodman)
 1443+
 1444+ if (root.innerHTML.replace(/\s/g, '') !== '') {
 1445+ // custom content was supplied
 1446+
 1447+ } else {
 1448+ root.innerHTML =
 1449+ "<h2>Flash version " + required + " or greater is required</h2>" +
 1450+ "<h3>" +
 1451+ (version[0] > 0 ? "Your version is " + version : "You have no flash plugin installed") +
 1452+ "</h3>" +
 1453+ "<p>Download latest version from <a href='" + params.pluginspage + "'>here</a></p>";
 1454+ }
 1455+ }
 1456+
 1457+ return root;
 1458+
 1459+//}}}
 1460+
 1461+
 1462+};
 1463+
 1464+
 1465+//{{{ static methods
 1466+
 1467+extend(window.flashembed, {
 1468+
 1469+ // returns arr[major, fix]
 1470+ getVersion: function() {
 1471+
 1472+ var version = [0, 0];
 1473+
 1474+ if (navigator.plugins && typeof navigator.plugins["Shockwave Flash"] == "object") {
 1475+ var _d = navigator.plugins["Shockwave Flash"].description;
 1476+ if (typeof _d != "undefined") {
 1477+ _d = _d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
 1478+ var _m = parseInt(_d.replace(/^(.*)\..*$/, "$1"), 10);
 1479+ var _r = /r/.test(_d) ? parseInt(_d.replace(/^.*r(.*)$/, "$1"), 10) : 0;
 1480+ version = [_m, _r];
 1481+ }
 1482+
 1483+ } else if (window.ActiveXObject) {
 1484+
 1485+ try { // avoid fp 6 crashes
 1486+ var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
 1487+
 1488+ } catch(e) {
 1489+ try {
 1490+ _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
 1491+ version = [6, 0];
 1492+ _a.AllowScriptAccess = "always"; // throws if fp < 6.47
 1493+
 1494+ } catch(ee) {
 1495+ if (version[0] == 6) { return; }
 1496+ }
 1497+ try {
 1498+ _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
 1499+ } catch(eee) {
 1500+
 1501+ }
 1502+
 1503+ }
 1504+
 1505+ if (typeof _a == "object") {
 1506+ _d = _a.GetVariable("$version"); // bugs in fp 6.21 / 6.23
 1507+ if (typeof _d != "undefined") {
 1508+ _d = _d.replace(/^\S+\s+(.*)$/, "$1").split(",");
 1509+ version = [parseInt(_d[0], 10), parseInt(_d[2], 10)];
 1510+ }
 1511+ }
 1512+ }
 1513+
 1514+ return version;
 1515+ },
 1516+
 1517+ isSupported: function(version) {
 1518+ var now = flashembed.getVersion();
 1519+ var ret = (now[0] > version[0]) || (now[0] == version[0] && now[1] >= version[1]);
 1520+ return ret;
 1521+ },
 1522+
 1523+ domReady: domReady,
 1524+
 1525+ // returns a String representation from JSON object
 1526+ asString: asString,
 1527+
 1528+ getHTML: getHTML,
 1529+
 1530+ getFullHTML: getFullHTML
 1531+
 1532+});
 1533+
 1534+//}}}
 1535+
 1536+
 1537+// setup jquery support
 1538+if (jQ) {
 1539+
 1540+ jQuery.prototype.flashembed = function(params, flashvars) {
 1541+ return this.each(function() {
 1542+ flashembed(this, params, flashvars);
 1543+ });
 1544+ };
 1545+
 1546+}
 1547+
 1548+})();
 1549+
 1550+/************************************************
 1551+********* mv_embed extension to flowplayer.js ***
 1552+************************************************/
 1553+var flashEmbed = {
 1554+ instanceOf:'flashEmbed',
 1555+ monitorTimerId : 0,
 1556+ old_pid:0,
 1557+ didSeekJump:false,
 1558+ startedTimedPlayback:false,
 1559+ didDateStartTimeRestore:false,
 1560+ supports: {
 1561+ 'play_head':true,
 1562+ 'pause':true,
 1563+ 'stop':true,
 1564+ //'fullscreen':true,
 1565+ 'time_display':true,
 1566+ //'volume_control':true,
 1567+ 'overlay':false,
 1568+ 'fullscreen':false
 1569+ },
 1570+ getEmbedHTML: function (){
 1571+ setTimeout('document.getElementById(\''+this.id+'\').postEmbedJS()', 150);
 1572+ return this.wrapEmebedContainer( this.getEmbedObj() );
 1573+ },
 1574+ getEmbedObj:function(){
 1575+ /*return '<a href="' + this.media_element.selected_source.getURI(this.seek_time_sec) +'" '+
 1576+ 'style="display:block;width:' + this.width + 'px;height:' + this.height + 'px" '+
 1577+ 'id="' + this.pid + '"> rewrite me'+
 1578+ '</a>';*/
 1579+ //give the embed element a unique pid (work around for flowplayer persistence)
 1580+ if( this.old_pid!=0 ){
 1581+ this.pid = this.pid +'_'+ this.old_pid;
 1582+ }
 1583+ return '<a '+
 1584+ 'href="'+ this.media_element.selected_source.getURI( this.seek_time_sec ) + '" '+
 1585+ 'style="display:block;width:' + parseInt(this.width) + 'px;height:' + parseInt(this.height) + 'px" '+
 1586+ 'id="'+this.pid+'">'+
 1587+ '</a>';
 1588+ },
 1589+ postEmbedJS: function()
 1590+ {
 1591+ var _this = this;
 1592+ js_log('embedFlow: uri:'+ _this.media_element.selected_source.getURI(this.seek_time_sec) + "\n"+ mv_embed_path + 'flowplayer/flowplayer-3.0.1.swf' ) ;
 1593+ var flowConfig = {
 1594+ clip: {
 1595+ url: _this.media_element.selected_source.getURI(this.seek_time_sec),
 1596+ // when this is false playback does not start until play button is pressed
 1597+ autoPlay: true
 1598+ },
 1599+ plugins: {
 1600+ controls: {
 1601+ all: false,
 1602+ fullscreen: true,
 1603+ backgroundColor: 'transparent',
 1604+ backgroundGradient: 'none',
 1605+ autoHide:'always',
 1606+ top:'95%',
 1607+ right:'0px'
 1608+ }
 1609+ },
 1610+ screen: {
 1611+ opacity : '1.0'
 1612+ }
 1613+ };
 1614+
 1615+ //if in preview mode set grey and lower volume until "ready"
 1616+ if( this.preview_mode ){
 1617+ flowConfig.screen.opacity = 0.2;
 1618+ }
 1619+
 1620+ $f(this.pid, mv_embed_path + 'flowplayer/flowplayer-3.0.1.swf', flowConfig);
 1621+ //get the this.fla value:
 1622+ this.getFLA();
 1623+ //set up bindings (for when interacting with the swf causes action:
 1624+ this.fla.onPause(function(){
 1625+ _this.parent_pause(); //update the interface
 1626+ })
 1627+ this.fla.onResume( function(){
 1628+ _this.parent_play(); //update the interface
 1629+ });
 1630+
 1631+ //start monitor:
 1632+ this.monitor();
 1633+ this.old_pid++;
 1634+ },
 1635+ /* js hooks/controls */
 1636+ play: function(){
 1637+ this.getFLA();
 1638+ //update play/pause button etc
 1639+ this.parent_play();
 1640+ if( this.fla ){
 1641+ this.fla.play();
 1642+
 1643+ //on a resume make sure volume and opacity are correct
 1644+ this.restorePlayer();
 1645+
 1646+ setTimeout('$j(\'#'+this.id+'\').get(0).monitor()', 250);
 1647+ }
 1648+ },
 1649+ //@@todo support mute
 1650+ toggleMute: function(){
 1651+ parent_toggleMute();
 1652+ this.getFLA();
 1653+ if(this.fla){
 1654+ if(this.muted){
 1655+
 1656+ }else{
 1657+
 1658+ }
 1659+ }
 1660+ },
 1661+ fullscreen:function(){
 1662+ if(this.fla){
 1663+ this.fla.fullscreen();
 1664+ }else{
 1665+ js_log('must be playing before you can go fullscreen');
 1666+ }
 1667+ },
 1668+ pause : function()
 1669+ {
 1670+ this.getFLA();
 1671+ if(!this.thumbnail_disp){
 1672+ this.parent_pause();
 1673+ if(this.fla){
 1674+ js_log("Flash:Pause: " + this.fla.isPaused() );
 1675+ if( this.fla['pause'] ){
 1676+ if( ! this.fla.isPaused() ){
 1677+ js_log('calling plugin pause');
 1678+ this.fla.pause();
 1679+
 1680+ //restore volume and opacity
 1681+ this.restorePlayer();
 1682+ }
 1683+ }
 1684+ }
 1685+ }
 1686+ },
 1687+ monitor : function()
 1688+ {
 1689+ var _this = this;
 1690+ //date time
 1691+ if( !this.dateStartTime ){
 1692+ var d = new Date();
 1693+ this.dateStartTime = d.getTime();
 1694+
 1695+ }else{
 1696+ var d = new Date();
 1697+ if( !this.didDateStartTimeRestore && this.preview_mode)
 1698+ this.fla.setVolume(0);
 1699+
 1700+ if( (d.getTime() - this.dateStartTime) > 6000 && !this.didDateStartTimeRestore){
 1701+ js_log('more than 6 seconds have passed since first monitor call issue restore');
 1702+ this.restorePlayer();
 1703+ }
 1704+ }
 1705+
 1706+ var flash_state = this.fla.getStatus();
 1707+ //update the duration from the clip if its zero or not set:
 1708+ if( !this.duration || this.duration==0 ){
 1709+ if( this.fla.getClip() ){
 1710+ this.duration = this.fla.getClip().fullDuration;
 1711+ js_log('set duration via clip value: ' + this.getDuration() );
 1712+ }
 1713+ }
 1714+ //update the duration ntp values:
 1715+ this.getDuration();
 1716+
 1717+ if( typeof flash_state == 'undefined' ){
 1718+ var flash_state = {
 1719+ "time" : this.fla.getTime()
 1720+ };
 1721+ //we are not getting buffered data restore volume and opacity
 1722+ this.restorePlayer();
 1723+ }else{
 1724+ //simplification of buffer state ... should move to support returning time rages like:
 1725+ //http://www.whatwg.org/specs/web-apps/current-work/#normalized-timeranges-object
 1726+ this.bufferedPercent = flash_state.bufferEnd / this.getDuration();
 1727+ }
 1728+ //set the current Time (based on timeFormat)
 1729+ if( this.media_element.selected_source.timeFormat =='anx' ){
 1730+ this.currentTime = flash_state.time;
 1731+ //js_log('set buffer: ' + flash_state.bufferEnd + ' at time: ' + flash_state.time +' of total dur: ' + this.getDuration());
 1732+ }else{
 1733+ this.currentTime = flash_state.time + this.media_element.selected_source.start_offset;
 1734+ //stop buffering if greater than the duration:
 1735+ if( flash_state.bufferEnd > this.getDuration() + 5 ){
 1736+ //js_log('should stop buffering (does not seem to work)' + flash_state.bufferEnd + ' > dur: ' + this.getDuration() );
 1737+ this.fla.stopBuffering();
 1738+ }
 1739+ }
 1740+
 1741+ if(this.currentTime > ntp2seconds(this.start_ntp) && !this.startedTimedPlayback){
 1742+ var fail = false;
 1743+ try
 1744+ {
 1745+ this.restorePlayer();
 1746+ }
 1747+ catch(err)
 1748+ {
 1749+ js_log('failed to set values');
 1750+ fail = true;
 1751+ }
 1752+ if(!fail)
 1753+ this.startedTimedPlayback=true;
 1754+ }
 1755+
 1756+ /* to support local seeks */
 1757+ if(this.currentTime > 1 && this.seek_time_sec != 0 && !this.supportsURLTimeEncoding() )
 1758+ {
 1759+ js_log('flashEmbed: _local_ Seeking to ' + this.seek_time_sec);
 1760+ this.fla.seek( this.seek_time_sec );
 1761+ this.seek_time_sec = 0;
 1762+ }
 1763+
 1764+ //checks to see if we reached the end of playback:
 1765+ if(this.duration && this.startedTimedPlayback &&
 1766+ ( this.currentTime > (ntp2seconds(this.end_ntp)+1)
 1767+ ||
 1768+ ( this.currentTime > (ntp2seconds(this.end_ntp)-1)
 1769+ && this.prevTime == this.currentTime) )
 1770+ ){
 1771+ js_log('prbally reached end of stream: '+this.currentTime);
 1772+ this.onClipDone();
 1773+ }
 1774+
 1775+ //update the status and check timmer via universal parent monitor
 1776+ this.parent_monitor();
 1777+
 1778+
 1779+ this.prevTime = this.currentTime;
 1780+ //js_log('cur perc loaded: ' + this.fla.getPercentLoaded() +' cur time : ' + (this.currentTime - ntp2seconds(this.start_ntp)) +' / ' +(ntp2seconds(this.end_ntp)-ntp2seconds(this.start_ntp)));
 1781+ },
 1782+ restorePlayer:function(){
 1783+ if(!this.fla)
 1784+ this.getFLA();
 1785+ if(this.fla){
 1786+ js_log('f:do restorePlayer');
 1787+ this.fla.setVolume(90);
 1788+ $f().getPlugin('screen').css({'opacity':'1.0'} );
 1789+
 1790+ //set the fallback date restore flag to true:
 1791+ this.didDateStartTimeRestore=true;
 1792+ }
 1793+ },
 1794+ // get the embed fla object
 1795+ getFLA : function (){
 1796+ this.fla = $f(this.pid);
 1797+ },
 1798+ stop : function(){
 1799+ js_log('f:flashEmbed:stop');
 1800+ this.startedTimedPlayback=false;
 1801+ if (this.monitorTimerId != 0 )
 1802+ {
 1803+ clearInterval(this.monitorTimerId);
 1804+ this.monitorTimerId = 0;
 1805+ }
 1806+ if(this.fla)
 1807+ this.fla.unload();
 1808+ this.parent_stop();
 1809+ },
 1810+ onStop: function(){
 1811+ js_log('f:onStop');
 1812+ //stop updates:
 1813+ if( this.monitorTimerId != 0 )
 1814+ {
 1815+ clearInterval(this.monitorTimerId);
 1816+ this.monitorTimerId = 0;
 1817+ }
 1818+ },
 1819+ onClipDone: function(){
 1820+ js_log('f:flash:onClipDone');
 1821+ if( ! this.startedTimedPlayback){
 1822+ js_log('clip done before timed playback started .. not good. (ignoring) ');
 1823+ //keep monitoring:
 1824+ this.monitor();
 1825+ }else{
 1826+ js_log('clip done and '+ this.startedTimedPlayback);
 1827+ //stop the clip if its not stopped already:
 1828+ this.stop();
 1829+ this.setStatus("Clip Done...");
 1830+ //run the onClip done action:
 1831+ this.parent_onClipDone();
 1832+ }
 1833+ }
 1834+}
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_flashEmbed.js
___________________________________________________________________
Name: svn:mergeinfo
11835 +
Name: svn:eol-style
21836 + native
Index: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_javaEmbed.js
@@ -0,0 +1,137 @@
 2+var javaEmbed = {
 3+ instanceOf:'javaEmbed',
 4+ iframe_src:'',
 5+ logged_domain_error:false,
 6+ supports: {
 7+ 'play_head':true,
 8+ 'pause':true,
 9+ 'stop':true,
 10+ 'fullscreen':false,
 11+ 'time_display':true,
 12+ 'volume_control':false
 13+ },
 14+ getEmbedHTML : function (){
 15+ if(this.controls)
 16+ setTimeout('document.getElementById(\''+this.id+'\').postEmbedJS()', 150);
 17+ //set a default duration of 30 seconds: cortao should detect duration.
 18+ return this.wrapEmebedContainer( this.getEmbedObj() );
 19+ },
 20+ getEmbedObj:function(){
 21+ js_log("java play url:" + this.getURI( this.seek_time_sec ));
 22+ //get the duration
 23+ this.getDuration();
 24+ //if still unset set to an arbitrary time 60 seconds:
 25+ if(!this.duration)this.duration=60;
 26+ if( mv_java_iframe ){
 27+ //make sure iframe and embed path match (java security model)
 28+ var iframe_src='';
 29+ var src = this.getURI( this.seek_time_sec );
 30+ //make url absolute:
 31+ if(src[0]=='/'){
 32+ //js_log('java: media relative path from:'+ document.URL);
 33+ var pURL=parseUri(document.URL);
 34+ src= pURL.protocol + '://' + pURL.authority + src;
 35+ }else if(src.indexOf('://')===-1){
 36+ //js_log('java: media relative file');
 37+ var pURL=parseUri(document.URL);
 38+ src= pURL.protocol + '://' + pURL.authority + pURL.directory + src;
 39+ }
 40+ js_log('java media url: '+ src);
 41+ var parent_domain='';
 42+ //set the domain locally and for the script:
 43+ var doc_host = parseUri(document.location).host;
 44+ if( doc_host ){
 45+ js_log('set parent domain:' + doc_host);
 46+ //set the parent domain:
 47+ document.domain = doc_host;
 48+
 49+ iframe_src = parseUri(src).protocol + '://'+
 50+ parseUri(src).authority +
 51+ mv_media_iframe_path + 'cortado_iframe.php';
 52+ js_log('iframe source: ' + iframe_src);
 53+ //set the domain of the script:
 54+ parent_domain = '&parent_domain=' + doc_host;
 55+
 56+ js_log('parent_domain: ' + parent_domain);
 57+ }else{
 58+ iframe_src = mv_embed_path + 'cortado_iframe.php';
 59+ }
 60+ //js_log('base iframe src:'+ iframe_src);
 61+ iframe_src+= "?media_url=" + src.replace('?','%3F').replace('&','%26') + '&id=' + this.pid;
 62+ iframe_src+= "&width=" + this.width + "&height=" + this.height;
 63+ iframe_src+= "&duration=" + this.duration;
 64+ iframe_src+=parent_domain;
 65+
 66+ //check for the mvMsgFrame
 67+ /*if($j('#mvMsgFrame').length == 0){
 68+ js_log('appened mvMsgFrame');
 69+ //add it to the dom: (sh
 70+ $j('body').prepend( '<iframe id="mvMsgFrame" width="0" height="0" scrolling=no marginwidth=0 marginheight=0 src="#none"></iframe>' );
 71+ }*/
 72+ js_log("about to set iframe source and embed code");
 73+ this.iframe_src = iframe_src;
 74+ var embed_code = '<iframe id="iframe_' + this.pid + '" width="'+this.width+'" height="'+this.height+'" '+
 75+ 'frameborder="0" scrolling="no" marginwidth="0" marginheight="0" ' +
 76+ 'src = "'+ this.iframe_src + '"></iframe>';
 77+ js_log('going to embed: ' + embed_code);
 78+ return embed_code;
 79+ }else{
 80+ //load directly in the page..
 81+ // (media must be on the same server or applet must be signed)
 82+ return ''+
 83+ '<applet id="'+this.pid+'" code="com.fluendo.player.Cortado.class" archive="cortado-ovt-stripped_r34336.jar" width="'+this.width+'" height="'+this.height+'"> '+ "\n"+
 84+ '<param name="url" value="'+this.media_element.selected_source.src+'" /> ' + "\n"+
 85+ '<param name="local" value="false"/>'+ "\n"+
 86+ '<param name="keepaspect" value="true" />'+ "\n"+
 87+ '<param name="video" value="true" />'+"\n"+
 88+ '<param name="audio" value="true" />'+"\n"+
 89+ '<param name="seekable" value="true" />'+"\n"+
 90+ '<param name="duration" value="'+this.duration+'" />'+"\n"+
 91+ '<param name="bufferSize" value="200" />'+"\n"+
 92+ '</applet>';
 93+ }
 94+ },
 95+ postEmbedJS:function(){
 96+ //reset logged domain error flag:
 97+ this.logged_domain_error = false;
 98+ //start monitor:
 99+ this.monitor();
 100+ },
 101+ monitor:function(){
 102+ if( this.getJCE() ) {
 103+ try{
 104+ //java reads "playtime" not ogg media time.. so add the start_offset or seek_offset
 105+ //js_log(' ct: ' + this.jce.getPlayPosition() + ' so:' + this.start_offset + ' st:' + this.seek_time_sec);
 106+ this.currentTime = (this.seek_time_sec==0)?
 107+ this.jce.getPlayPosition() + this.start_offset :
 108+ this.jce.getPlayPosition() + this.seek_time_sec ;
 109+ }catch (e){
 110+ ///js_log('could not get time from jPlayer: ' + e);
 111+ }
 112+ }
 113+ //once currentTime is updated call parent_monitor
 114+ this.parent_monitor();
 115+ },
 116+ //get java cortado embed object
 117+ getJCE:function(){
 118+ if( ! mv_java_iframe ){
 119+ this.jce = $j('#'+this.pid).get(0);
 120+ }else{
 121+ if( $j('#iframe_' + this.pid ).length > 0 )
 122+ try{
 123+ this.jce = $j('#iframe_' + this.pid ).get(0).contentWindow.jPlayer;
 124+ }catch (e){
 125+ if(!this.logged_domain_error)
 126+ js_log("failed to grab jce we wont have time updates for java");
 127+ this.logged_domain_error = true;
 128+ }
 129+ else
 130+ return false;
 131+ }
 132+ return this.jce;
 133+ },
 134+ pause:function(){
 135+ this.parent_pause();
 136+ this.stop();
 137+ }
 138+}
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_javaEmbed.js
___________________________________________________________________
Name: svn:mergeinfo
1139 +
Name: svn:eol-style
2140 + native
Index: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_oggplayEmbed.js
@@ -0,0 +1,253 @@
 2+/*
 3+ * oggPlay embed
 4+ * plugin: http://www.annodex.net/software/plugin/index.html
 5+ * javascript refrence: http://wiki.xiph.org/index.php/OggPlayJavascriptAPI
 6+ @@TODO should be depreciated... no one is maintaining oggPlay
 7+ */
 8+var oggplayEmbed = {
 9+ instanceOf:'oggplayEmbed',
 10+ pl_aqueue:Array(),
 11+ pl_pqueue:Array(),
 12+ start_pos:0,
 13+ getEmbedHTML:function(){
 14+ var controls_html='';
 15+ //setup the interface controls if requested
 16+ if(this.controls){
 17+ /*for the ogg playhead we need scriptaculus/prototype */
 18+ //try and get the interface
 19+ if( this.get_interface_lib(true) ){
 20+ js_log('interface loaded');
 21+ controls_html =this.getControlsHtml('all');
 22+ controls_html+='<div style="clear:both;">';
 23+ }else{
 24+ //if not present, it's loading
 25+ return 'loading interface <blink>...</blink>';
 26+ }
 27+ }
 28+ setTimeout('document.getElementById(\''+this.id+'\').postEmbedJS()', 150);
 29+ return this.wrapEmebedContainer(this.getEmbedObj() ) + controls_html;
 30+ },
 31+ getEmbedObj:function(){
 32+ return '<embed type="application/liboggplay" ' +
 33+ 'id="'+this.pid + '" ' +
 34+ 'src="'+this.media_element.selected_source.getURI(this.seek_time_sec)+'" '+
 35+ 'width="'+this.width+'" height="'+this.height+'">' +
 36+ '</embed>';
 37+ },
 38+ postEmbedJS:function(){
 39+ this.getOggElement();
 40+ if(this.controls){
 41+ setTimeout('document.getElementById(\''+this.id+'\').monitor()',250);
 42+ }
 43+ //check if in playlist mode:
 44+ if(this.pc){
 45+ var plObj = this.pc.pp;
 46+ var _this = this;
 47+
 48+ //register a callback for next clip:
 49+ this.ogg.registerPlaylistCallback(
 50+ {
 51+ call:function(){document.getElementById(plObj.id).playlistNext();}
 52+ }
 53+ );
 54+
 55+ //js_log('current pl pos:'+this.ogg.getCurrentPlaylistPosition() );
 56+ //load up the playlist inserting on either side of the current clip
 57+ $j.each(plObj.tracks[0].clips, function(i, clip){
 58+ if(i < plObj.cur_clip.order){
 59+ //js_log('insert before:'+ clip.src);
 60+ _this.insertMovieBefore(clip.src);
 61+ }else if(i > plObj.cur_clip.order){
 62+ //js_log('insert after:'+ clip.src);
 63+ _this.appendMovie(clip.src);
 64+ }
 65+ });
 66+ //js_log('current pl pos:'+this.ogg.getCurrentPlaylistPosition() );
 67+ //js_log('current pl length:'+this.ogg.getPlaylistLength() );
 68+ //append/insert any clips that the user added (before the ogg object was ready)
 69+ while(this.pl_aqueue.length!=0){
 70+ this.appendMovie(this.pl_aqueue.pop() );
 71+ }
 72+ while(this.pl_pqueue.length!=0){
 73+ this.insertMovieBefore(this.pl_pqueue.pop() );
 74+ }
 75+ }
 76+ //update the duration
 77+ this.getDuration();
 78+ },
 79+ monitor:function(){
 80+ if(this.ogg){
 81+ //js_log('state:' + this.ogg.getCurrentState());
 82+ if(this.ogg){
 83+ switch(this.ogg.getCurrentState()){
 84+ //paused
 85+ case 0:
 86+ this.onPaused();
 87+ break;
 88+ //plaing
 89+ case 1:
 90+ this.onPlaying();
 91+ break;
 92+ //finished
 93+ case 2:
 94+ this.onStop();
 95+ //assume reached the end:
 96+ break;
 97+ }
 98+ }
 99+ }
 100+ if(!this.monitorTimerId ){
 101+ this.monitorTimerId = setInterval('document.getElementById(\''+this.id+'\').monitor()', 250);
 102+ }
 103+ },
 104+ onPlaying:function(){
 105+ var mediaLen = this.ogg.getMovieLength();
 106+ if( mediaLen > 0 )
 107+ {
 108+ // seekable media
 109+ //as long as the user is not interacting with the playhead update:
 110+ if(! this.userSlide){
 111+ var start_offset=this.start_offset;
 112+ //if in playlist mode make sure we have the right start_offset:
 113+ if(this.pc)
 114+ start_offset = this.pc.pp.cur_clip.embed.start_offset;
 115+
 116+ var oog_position = (this.ogg.getPlayPosition()-start_offset) / this.duration;
 117+ //js_log('current pos: ' + this.ogg.getPlayPosition() + '-' +start_offset+' /'+ this.ogg.getMovieLength() + ' =' + oog_position);
 118+ this.setSliderValue(oog_position);
 119+ this.setStatus(this.getTimeInfo());
 120+ }else{
 121+ //update info to seek to:
 122+ this.setStatus('seek to: ' + seconds2ntp( (this.start_offset /1000)+
 123+ Math.round((this.sliderVal*mediaLen)/1000) ));
 124+ }
 125+ }else{
 126+ //@@todo find out if movie is buffering or live stream
 127+ this.setStatus(innerHTML = 'buffering<blink>...</blink>');
 128+ }
 129+ },
 130+ getTimeInfo:function(){
 131+ return seconds2ntp(Math.round(this.ogg.getPlayPosition() / 1000) )+
 132+ "/" + seconds2ntp(Math.round(this.duration+this.start_offset) / 1000);
 133+ },
 134+ doSeek:function(v){
 135+ var mediaLen = this.ogg.getMovieLength();
 136+ js_log('seek to: '+v+' in ntp:' + seconds2ntp(Math.round( (v*mediaLen)/1000) ) );
 137+ var mediaLen = this.ogg.getMovieLength();
 138+ //usto need: this.start_offset
 139+ this.ogg.setPlayPosition( v*mediaLen );
 140+ //js_log('seeking to: '+( v*mediaLen)+ ' of ' +mediaLen );
 141+ this.setStatus('seeking<blink>...</blink>');
 142+ },
 143+ onPaused:function(){
 144+ //document.getElementById("PlayOrPause").value = " Play ";
 145+ },
 146+ onStop:function(){
 147+ if(this.controls){
 148+ this.setSliderValue(0);
 149+ this.setStatus("-:--:--/-:--:--");
 150+ }
 151+ //call the stop to (reload the thumbnail)
 152+ //document.getElementById("PlayOrPause").value = " Play ";
 153+ //document.getElementById("PlayOrPause").disabled = false;
 154+ },
 155+ getDuration:function(){
 156+ //trust the url more than (getMovieLength) for anx content
 157+ if(this.parent_getDuration()==null){
 158+ //make sure the ogg is ready:
 159+ if(!this.thumbnail_disp){
 160+ this.getOggElement();
 161+ if(this.ogg){
 162+ this.duration = this.ogg.getMovieLength();
 163+ }else{
 164+ this.duration=null;
 165+ }
 166+ }
 167+ }
 168+ return this.duration;
 169+ },
 170+ getOggElement:function(){
 171+ if(document.getElementById(this.pid)){
 172+ this.ogg = this.getPluginEmbed();
 173+ }else{
 174+ this.ogg=null;
 175+ }
 176+ js_log('this.ogg: '+ this.ogg);
 177+ },
 178+ playlistPrev:function(){
 179+ if(this.ogg){
 180+ this.ogg.playlistPrev();
 181+ }
 182+ },
 183+ playlistNext:function(){
 184+ if(this.ogg){
 185+ this.ogg.playlistNext();
 186+ //update the start_offset value:
 187+ this.getDuration();
 188+ }
 189+ },
 190+ insertMovieBefore:function(url, pos){
 191+ if(url){
 192+ if(this.ogg){
 193+ if(!pos)var pos = this.ogg.getCurrentPlaylistPosition();
 194+ this.ogg.insertMovieBefore(pos, url);
 195+ }else{
 196+ this.pl_pqueue.push(url);
 197+ }
 198+ }
 199+ },
 200+ //append the url if this.ogg is present else put it in the plqueue
 201+ appendMovie:function(url){
 202+ if(url){
 203+ if(this.ogg){
 204+ this.ogg.appendMovie(url);
 205+ }else{
 206+ this.pl_aqueue.push(url);
 207+ }
 208+ }
 209+ },
 210+ playMovieAt:function(pos){
 211+ this.getOggElement();
 212+ if(this.ogg){
 213+ js_log('ogg.playMovieAT');
 214+ this.ogg.playMovieAt(pos);
 215+ }else{
 216+ js_log('this.play');
 217+ this.start_pos = pos;
 218+ this.play();
 219+ }
 220+ },
 221+ play:function (){
 222+ this.getOggElement();
 223+ if(!this.ogg || this.thumbnail_disp){
 224+ this.parent_play();
 225+ }else{
 226+ //if finished restart
 227+ if(this.ogg.getCurrentState()==2){
 228+ this.ogg.restart();
 229+ //if paused:play
 230+ }else if(this.ogg.getCurrentState()==0){
 231+ this.ogg.play();
 232+ }
 233+ this.paused=false;
 234+ }
 235+ //update the duration
 236+ this.getDuration();
 237+ },
 238+ pause:function(){
 239+ this.ogg.pause();
 240+ },
 241+ stop: function(){
 242+ js_log('oggplay stop:' + this.thumbnail_disp);
 243+ if(!this.thumbnail_disp){
 244+ if( this.monitorTimerId != 0 )
 245+ {
 246+ clearInterval(this.monitorTimerId);
 247+ this.monitorTimerId = 0;
 248+ }
 249+ //do a full stop ( swap out the embed code)
 250+ this.onStop();
 251+ this.parent_stop();
 252+ }
 253+ }
 254+}
\ No newline at end of file
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_oggplayEmbed.js
___________________________________________________________________
Name: svn:mergeinfo
1255 +
Name: svn:eol-style
2256 + native
Index: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_htmlEmbed.js
@@ -0,0 +1,174 @@
 2+/*
 3+ * used to embed HTML as a movie clip
 4+ * for use with mv_playlist SMIL additions
 5+ * (we make assumptions about this.pc (parent clip) being available)
 6+ */
 7+var pcHtmlEmbedDefaults={
 8+ 'dur':4 //default duration of 4seconds
 9+}
 10+var htmlEmbed ={
 11+ supports: {
 12+ 'play_head':true,
 13+ 'pause':true,
 14+ 'fullscreen':false,
 15+ 'time_display':true,
 16+ 'volume_control':true,
 17+
 18+ 'overlays':true,
 19+ 'playlist_swap_loader':true //if the object supports playlist functions
 20+ },
 21+ ready_to_play:true,
 22+ pauseTime:0,
 23+ currentTime:0,
 24+ start_offset:0,
 25+ monitorTimerId:false,
 26+ play:function(){
 27+ //call the parent
 28+ this.parent_play();
 29+
 30+ js_log('f:play: htmlEmbedWrapper');
 31+ var ct = new Date();
 32+ this.clockStartTime = ct.getTime();
 33+
 34+ //start up monitor:
 35+ this.monitor();
 36+ },
 37+ stop:function(){
 38+ this.pause();
 39+ //window.clearInterval( this.monitorTimerId );
 40+ },
 41+ pause:function(){
 42+ js_log('f:pause: htmlEmbedWrapper');
 43+ var ct = new Date();
 44+ this.pauseTime = this.currentTime;
 45+ js_log('pause time: '+ this.pauseTime);
 46+
 47+ window.clearInterval( this.monitorTimerId );
 48+ },
 49+ //monitor just needs to keep track of time (do it at frame rate time) .
 50+ monitor:function(){
 51+ //js_log('html:monitor: '+ this.currentTime);
 52+ var ct = new Date();
 53+ this.currentTime =( ( ct.getTime() - this.clockStartTime )/1000 ) +this.pauseTime;
 54+ var ct = new Date();
 55+ //js_log('mvPlayList:monitor trueTime: '+ this.currentTime);
 56+
 57+ if( ! this.monitorTimerId ){
 58+ if(document.getElementById(this.id)){
 59+ if( !MV_ANIMATION_CB_RATE )
 60+ var MV_ANIMATION_CB_RATE= 33;
 61+ this.monitorTimerId = window.setInterval('$j(\'#'+this.id+'\').get(0).monitor()', 250);
 62+ }
 63+ }
 64+ },
 65+ //set up minimal media_element emulation:
 66+ media_element:{
 67+ autoSelectSource:function(){
 68+ return true;
 69+ },
 70+ selectedPlayer:{
 71+ library:"html"
 72+ },
 73+ selected_source:{
 74+ serverSideSeeking:false
 75+ },
 76+ timedTextSources:function(){
 77+ return false;
 78+ }
 79+ },
 80+ inheritEmbedObj:function(){
 81+ return true;
 82+ },
 83+ renderTimelineThumbnail:function( options ){
 84+ //generate a scaled down version _that_ we can clone if nessisary
 85+ //add a not vissiable container to the body:
 86+ var do_refresh = (typeof options['refresh'] != 'undefined')?true:false;
 87+
 88+ var thumb_render_id = this.id +'_thumb_render_'+ options.height;
 89+ if( $j('#' + thumb_render_id ).length == 0 || do_refresh ){
 90+ //set the font scale down percentage: (kind of arbitrary)
 91+ var scale_perc = options.width / this.pc.pp.width;
 92+ //js_log('scale_perc:'+options.width + ' / '+ $j(this).width()+ ' = '+scale_perc );
 93+ //min scale font percent of 70 (overflow is hidden)
 94+ var font_perc = ( Math.round( scale_perc*100 ) < 80 )?80:Math.round( scale_perc*100 );
 95+ var thumb_class = (typeof options['thumb_class'] !='undefined')? options['thumb_class'] : '';
 96+
 97+ $j('body').append( '<div id="' + thumb_render_id + '" style="display:none">'+
 98+ '<div class="' + thumb_class + '" '+
 99+ 'style="width:'+options.width+'px;height:'+options.height+'px;" >'+
 100+ this.getThumbnailHTML() +
 101+ '</div>'+
 102+ '</div>'
 103+ );
 104+ //scale down the fonts:
 105+ $j('#' + thumb_render_id + ' *').filter('span,div,p,h,h1,h2,h3,h4,h5,h6').css('font-size',font_perc+'%')
 106+
 107+ //replace out links:
 108+ $j('#' + thumb_render_id +' a').each(function(){
 109+ $j(this).replaceWith("<span>" + $j(this).html() + "</span>");
 110+ });
 111+
 112+ //scale images that have width or height:
 113+ $j('#' + thumb_render_id + ' img').filter('[width]').each(function(){
 114+ $j(this).attr({
 115+ 'width': Math.round( $j(this).attr('width') * scale_perc ),
 116+ 'height': Math.round( $j(this).attr('height') * scale_perc )
 117+ }
 118+ );
 119+ });
 120+ }
 121+ return $j('#' + thumb_render_id ).html();
 122+ },
 123+ //nothing to update in static html display: (return a static representation)
 124+ //@@todo render out a mini text "preview"
 125+ updateThumbTime:function( float_time ){
 126+ return ;
 127+ },
 128+ getEmbedHTML:function(){
 129+ js_log('f:html:getEmbedHTML: ' + this.id);
 130+ //set up the css for our parent div:
 131+ $j(this).css({'width':this.pc.pp.width, 'height':this.pc.pp.height, 'overflow':"hidden"});
 132+ //@@todo support more smil animation layout stuff:
 133+
 134+ //wrap output in videoPlayer_ div:
 135+ $j(this).html('<div id="videoPlayer_'+ this.id+'">'+this.getThumbnailHTML()+'</div>');
 136+ },
 137+ getThumbnailHTML:function(){
 138+ var out='';
 139+ if( this.pc.type =='image/jpeg'){
 140+ js_log('should put src: '+this.pc.src);
 141+ out = '<img width="'+this.pc.pp.width+'" height="'+this.pc.pp.height+'" src="'+this.pc.src+'">';
 142+ }else{
 143+ out = this.pc.wholeText;
 144+ }
 145+ //js_log('f:getThumbnailHTML: got thumb: '+out);
 146+ return out;
 147+ },
 148+ doThumbnailHTML:function(){
 149+ js_log('f:htmlEmbed:doThumbnailHTML');
 150+ this.getEmbedHTML();
 151+ },
 152+ /* since its just html display get the "embed" right away */
 153+ getHTML:function(){
 154+ js_log('getHTML: htmlEmbed');
 155+ this.getEmbedHTML();
 156+ },
 157+ getDuration:function(){
 158+ if(this.pc.dur)
 159+ return this.pc.dur;
 160+ //return default value:
 161+ return pcHtmlEmbedDefaults.dur;
 162+ },
 163+ updateVideoTime:function(start_ntp, end_ntp){
 164+ //since we don't really have timeline for html elements just take the delta and set it as the duration
 165+ this.pc.dur = ntp2seconds(end_ntp) - ntp2seconds(start_ntp);
 166+ },
 167+ //gives a chance to make any nesseary external requests
 168+ //@@todo we can "start loading images" if we want
 169+ on_dom_swap:function(){
 170+ this.loading_external_data=false
 171+ this.ready_to_play=true;
 172+ debugger;
 173+ return ;
 174+ }
 175+}
\ No newline at end of file
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_htmlEmbed.js
___________________________________________________________________
Name: svn:eol-style
1176 + native
Index: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_vlcEmbed.js
@@ -0,0 +1,301 @@
 2+/*
 3+* vlc embed based on: http://people.videolan.org/~damienf/plugin-0.8.6.html
 4+* javascript api: http://www.videolan.org/doc/play-howto/en/ch04.html
 5+* assume version > 0.8.5.1
 6+*/
 7+var vlcEmbed = {
 8+ instanceOf:'vlcEmbed',
 9+ supports: {'play_head':true,
 10+ 'pause':true,
 11+ 'stop':true,
 12+ 'fullscreen':true,
 13+ 'time_display':true,
 14+ 'volume_control':false,
 15+
 16+ 'playlist_driver':true, //if the object supports playlist functions
 17+ 'overlay':false
 18+ },
 19+ //init vars:
 20+ monitorTimerId : 0,
 21+ prevState : 0,
 22+ currentTime:0,
 23+ duration:0,
 24+ userSlide:false,
 25+ pejs_count:0, //post embed js count
 26+
 27+ getEmbedHTML: function(){
 28+ //give VLC 150ms to initialize before we start playback
 29+ //@@todo should be able to do this as an ready event
 30+ this.pejs_count=0;
 31+ setTimeout('document.getElementById(\''+this.id+'\').postEmbedJS()', 150);
 32+ return this.getEmbedObj();
 33+ },
 34+ getEmbedObj:function(){
 35+ var embed_code = '<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" '+
 36+ 'codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab#Version=0,8,6,0" '+
 37+ 'id="' + this.pid + '" events="True" height="'+this.height+'" width="'+this.width+'">'+
 38+ '<param name="MRL" value="">'+
 39+ '<param name="ShowDisplay" value="True">'+
 40+ '<param name="AutoLoop" value="False">'+
 41+ '<param name="AutoPlay" value="False">'+
 42+ '<param name="Volume" value="50">'+
 43+ '<param name="StartTime" value="0">'+
 44+ '<embed pluginspage="http://www.videolan.org" type="application/x-vlc-plugin" '+
 45+ 'progid="VideoLAN.VLCPlugin.2" name="' + this.pid + '" height="'+this.height+'" width="'+this.width+'">'+
 46+ '</object>';
 47+ js_log('embed with: ' + embed_code);
 48+ return embed_code;
 49+ },
 50+
 51+ /*
 52+ * some java script to start vlc playback after the embed:
 53+ */
 54+ postEmbedJS: function(){
 55+ //load a pointer to the vlc into the object (this.vlc)
 56+ this.getVLC();
 57+ if( this.vlc.log ){
 58+ //manipulate the dom object to make sure vlc has the correct size:
 59+ this.vlc.style.width=this.width;
 60+ this.vlc.style.height=this.height;
 61+ this.vlc.playlist.items.clear();
 62+ //@@todo if client supports seeking no need to send seek_offset to URI
 63+ js_log('vlc play::' + this.media_element.selected_source.getURI( this.seek_time_sec ));
 64+ var itemId = this.vlc.playlist.add( this.media_element.selected_source.getURI( this.seek_time_sec ) );
 65+ if( itemId != -1 ){
 66+ //play
 67+ this.vlc.playlist.playItem(itemId);
 68+ }else{
 69+ js_log("error:cannot play at the moment !");
 70+ }
 71+ //if controls enabled start up javascript interface and monitor:
 72+ if(this.controls){
 73+ //activate the slider: scriptaculus based)
 74+ //this.activateSlider();
 75+ //start doing status updates every 1/10th of a second
 76+ }
 77+ setTimeout('$j(\'#'+this.id+'\').get(0).monitor()',100);
 78+ }else{
 79+ js_log('postEmbedJS:vlc not ready');
 80+ this.pejs_count++;
 81+ if( this.pejs_count < 10 ){
 82+ setTimeout('document.getElementById(\''+this.id+'\').postEmbedJS()',100);
 83+ }else{
 84+ js_log('vlc never ready');
 85+ }
 86+ }
 87+ },
 88+ /* //disable local seeking (while we don't know what we have avaliable)
 89+ doSeek : function(value){
 90+ if( this.vlc ) {
 91+ if( (this.vlc.input.state == 3) && (this.vlc.input.position != value) )
 92+ {
 93+ this.vlc.input.position = value;
 94+ this.setStatus( 'seeking...' );
 95+ }
 96+ }
 97+ },*/
 98+ playMovieAt: function (order){
 99+ //@@todo add clips to playlist after (order) and then play
 100+ this.play();
 101+ },
 102+ /*
 103+ * updates the status time
 104+ */
 105+ monitor: function(){
 106+ this.getVLC();
 107+ if(this.vlc.log){
 108+ //js_log( 'state:' + this.vlc.input.state);
 109+ //js_log('time: ' + this.vlc.input.time);
 110+ //js_log('pos: ' + this.vlc.input.position);
 111+ if( this.vlc.log.messages.count > 0 ){
 112+ // there is one or more messages in the log
 113+ var iter = this.vlc.log.messages.iterator();
 114+ while( iter.hasNext ){
 115+ var msg = iter.next();
 116+ var msgtype = msg.type.toString();
 117+ if( (msg.severity == 1) && (msgtype == "input") )
 118+ {
 119+ js_log( msg.message );
 120+ }
 121+ }
 122+ // clear the log once finished to avoid clogging
 123+ this.vlc.log.messages.clear();
 124+ }
 125+ var newState = this.vlc.input.state;
 126+ if( this.prevState != newState ){
 127+ if( newState == 0 )
 128+ {
 129+ // current media has stopped
 130+ this.onStop();
 131+ //assume we reached the end: (since it was not a js call to stop)
 132+ this.onClipDone();
 133+ }
 134+ else if( newState == 1 )
 135+ {
 136+ // current media is opening/connecting
 137+ this.onOpen();
 138+ }
 139+ else if( newState == 2 )
 140+ {
 141+ // current media is buffering data
 142+ this.onBuffer();
 143+ }
 144+ else if( newState == 3 )
 145+ {
 146+ // current media is now playing
 147+ this.onPlay();
 148+ }
 149+ else if( this.vlc.input.state == 4 )
 150+ {
 151+ // current media is now paused
 152+ this.onPause();
 153+ }
 154+ this.prevState = newState;
 155+ }else if( newState == 3 ){
 156+ // current media is playing
 157+ this.onPlaying();
 158+ }
 159+ }
 160+ //update the status and check timmer via universal parent monitor
 161+ this.parent_monitor();
 162+ },
 163+/* events */
 164+ onOpen: function(){
 165+ this.setStatus("Opening...");
 166+ //document.getElementById("info_"+this.id).innerHTML = "Opening...";
 167+ //document.getElementById("PlayOrPause").disabled = true;
 168+ //document.getElementById("Stop").disabled = false;
 169+ },
 170+ onBuffer: function(){
 171+ this.setStatus("Buffering...");
 172+ //document.getElementById("info_"+this.id).innerHTML = "Buffering...";
 173+ //document.getElementById("PlayOrPause").disabled = true;
 174+ //document.getElementById("Stop").disabled = false;
 175+ },
 176+ onPlay: function(){
 177+ //document.getElementById("PlayOrPause").value = "Pause";
 178+ //document.getElementById("PlayOrPause").disabled = false;
 179+ //document.getElementById("Stop").disabled = false;
 180+ this.onPlaying();
 181+ },
 182+ liveFeedRoll: 0,
 183+ onPlaying: function(){
 184+ if(this.seek_time_sec != 0 && !this.supportsURLTimeEncoding() )
 185+ {
 186+ js_log('Seeking to ' + this.seek_time_sec);
 187+ this.vlc.input.time = this.seek_time_sec * 1000;
 188+ this.vlc.input.rate=1.0;
 189+ this.seek_time_sec = 0;
 190+ }
 191+ //for now trust the duration from url over vlc input.length
 192+ if( ! this.media_element.selected_source.end_ntp && this.vlc.input.length>0)
 193+ {
 194+ js_log('setting duration to ' + this.vlc.input.length /1000);
 195+ this.media_element.selected_source.setDuration( this.vlc.input.length /1000);
 196+ }
 197+
 198+ this.duration = (this.getDuration())?this.getDuration():this.vlc.input.length /1000;
 199+ /*if(this.duration!=this.vlc.input.length /1000){
 200+ this.duration = this.vlc.input.length /1000;
 201+ }*/
 202+ //update the currentTime attribute
 203+ if( this.media_element.selected_source.timeFormat =='anx' ){
 204+ this.currentTime = this.vlc.input.time/1000;
 205+ //js_log('set buffer: ' + flash_state.bufferEnd + ' at time: ' + flash_state.time +' of total dur: ' + this.getDuration());
 206+
 207+ //if we are way out of range... add offset (hack)
 208+ if( ( this.currentTime + 10 ) < ntp2seconds( this.start_ntp) ){
 209+ this.currentTime = (this.vlc.input.time/1000) + this.media_element.selected_source.start_offset;
 210+ }
 211+ }else{
 212+ this.currentTime = (this.vlc.input.time/1000) + this.media_element.selected_source.start_offset;
 213+ }
 214+ //updates hanlded by parent monitor and currentTime
 215+ },
 216+ onPause: function(){
 217+ this.parent_pause(); //update the inteface if paused via native control
 218+ },
 219+ onStop: function(){
 220+ //
 221+ // disable logging
 222+ this.vlc.log.verbosity = -1;
 223+ //document.getElementById("Stop").disabled = true;
 224+ if(this.controls){
 225+ this.setSliderValue(0);
 226+ this.setStatus("-:--:--/-:--:--");
 227+ }
 228+ //stop updates:
 229+ if( this.monitorTimerId != 0 )
 230+ {
 231+ clearInterval(this.monitorTimerId);
 232+ this.monitorTimerId = 0;
 233+ }
 234+ //document.getElementById("PlayOrPause").value = " Play ";
 235+ //document.getElementById("PlayOrPause").disabled = false;
 236+ },
 237+ /* js hooks/controls */
 238+ play : function(){
 239+ js_log('f:vlcPlay');
 240+ this.getVLC();
 241+ //call the parent
 242+ this.parent_play();
 243+ if( this.vlc ){
 244+ //plugin is already being present send play call:
 245+ // clear the message log and enable error logging
 246+ if( this.vlc.log ){
 247+ this.vlc.log.verbosity = 1;
 248+ this.vlc.log.messages.clear();
 249+ }
 250+ if(this.vlc.playlist)
 251+ this.vlc.playlist.play();
 252+
 253+ this.monitor();
 254+ this.paused=false;
 255+ }
 256+ },
 257+ stop : function(){
 258+ js_log(this.vlc);
 259+ if(typeof this.vlc != 'undefined' ){
 260+ if(typeof this.vlc.playlist != 'undefined'){
 261+ this.vlc.playlist.stop();
 262+ if( this.monitorTimerId != 0 )
 263+ {
 264+ clearInterval(this.monitorTimerId);
 265+ this.monitorTimerId = 0;
 266+ }
 267+ }
 268+ }
 269+ //this.onStop();
 270+ //do parent stop
 271+ this.parent_stop();
 272+ },
 273+ pause : function(){
 274+ this.parent_pause(); //update the inteface if paused via native control
 275+ if(this.vlc){
 276+ this.vlc.playlist.togglePause();
 277+ }
 278+ },
 279+ fullscreen : function(){
 280+ if(this.vlc){
 281+ if(this.vlc.video)
 282+ this.vlc.video.toggleFullscreen();
 283+ }
 284+ },
 285+ /* returns current time in float seconds
 286+ * as per html5 we should just have an attribute by name of CurrentTime
 287+ * http://www.whatwg.org/specs/web-apps/current-work/#currenttime
 288+ currentTime : function(){
 289+ if(typeof this.vlc != 'undefined' ){
 290+ if(typeof this.vlc.input != 'undefined' ){
 291+ return this.vlc.input.time/1000;
 292+ }
 293+ }
 294+ return '0';
 295+ },
 296+ */
 297+ // get the embed vlc object
 298+ getVLC : function(){
 299+ this.vlc = this.getPluginEmbed();
 300+ }
 301+}
 302+
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo/mv_vlcEmbed.js
___________________________________________________________________
Name: svn:mergeinfo
1303 +
Name: svn:eol-style
2304 + native
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo
___________________________________________________________________
Name: svn:mergeinfo
3305 +

Status & tagging log