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 |
1 | 1 | + 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 |
2 | 2 | + application/octet-stream |
Index: trunk/extensions/MetavidWiki/skins/mv_embed/mv_embed.js |
— | — | @@ -184,7 +184,7 @@ |
185 | 185 | js_log('jquery loaded'); |
186 | 186 | //load the jQuery dependent plugins: |
187 | 187 | mvJsLoader.doLoad({ |
188 | | - 'embedVideo' : 'libEmbedObj/mv_baseEmbed.js', |
| 188 | + 'embedVideo' : 'libEmbedVideo/mv_baseEmbed.js', |
189 | 189 | '$j.ui.mouse' : 'jquery/jquery.ui-1.5.2/ui/minified/ui.core.min.js', |
190 | 190 | '$j.ui.droppable' : 'jquery/jquery.ui-1.5.2/ui/minified/ui.droppable.min.js', |
191 | 191 | '$j.ui.draggable' : 'jquery/jquery.ui-1.5.2/ui/minified/ui.draggable.min.js' |
— | — | @@ -375,7 +375,7 @@ |
376 | 376 | else |
377 | 377 | { |
378 | 378 | 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'; |
380 | 380 | //add the callback: |
381 | 381 | this.loading_callbacks.push(callback); |
382 | 382 | //jQuery based get script does not work so well. |
— | — | @@ -387,7 +387,7 @@ |
388 | 388 | _this.loading_callbacks = null; |
389 | 389 | });*/ |
390 | 390 | |
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\'}'); |
392 | 392 | js_log('DO LOAD: '+this.library); |
393 | 393 | mvJsLoader.doLoad(lib,function(){ |
394 | 394 | //js_log( 'type of lib: ' + eval( 'typeof ' + this.library + 'Embed' ) ); |
— | — | @@ -1161,7 +1161,7 @@ |
1162 | 1162 | loadExternalJs( req_url ); |
1163 | 1163 | } |
1164 | 1164 | } |
1165 | | - |
| 1165 | +//grab wiki form error for wiki html page proccessing (should be depricated) |
1166 | 1166 | function grabWikiFormError ( result_page ){ |
1167 | 1167 | var res = {}; |
1168 | 1168 | sp = result_page.indexOf('<span class="error">'); |
— | — | @@ -1369,6 +1369,7 @@ |
1370 | 1370 | } |
1371 | 1371 | return mv_embed_path; |
1372 | 1372 | } |
| 1373 | + |
1373 | 1374 | if (typeof DOMParser == "undefined") { |
1374 | 1375 | DOMParser = function () {} |
1375 | 1376 | 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 |
1 | 160 | + |
Name: svn:eol-style |
2 | 161 | + 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"> </span>'+ |
| 168 | + '<span class="border_right"> </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, '&' ) |
| 788 | + . replace( /</g, '<' ) |
| 789 | + . replace( />/g, '>' ); |
| 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 = '<script type="text/javascript" ' + |
| 1473 | + 'src="'+mv_embed_path+'mv_embed.js"></script>' + |
| 1474 | + '<video '; |
| 1475 | + if(this.roe){ |
| 1476 | + embed_code_html+='roe="'+this.roe+'" >'; |
| 1477 | + }else{ |
| 1478 | + embed_code_html+='src="'+this.src+'" ' + |
| 1479 | + 'thumbnail="'+embed_thumb_html+'">'; |
| 1480 | + } |
| 1481 | + //close the video tag |
| 1482 | + embed_code_html+='</video>'; |
| 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 |
1 | 2046 | + |
Name: svn:eol-style |
2 | 2047 | + 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 |
1 | 84 | + |
Name: svn:eol-style |
2 | 85 | + 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 |
1 | 11 | + |
Name: svn:eol-style |
2 | 12 | + 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 |
1 | 1835 | + |
Name: svn:eol-style |
2 | 1836 | + 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 |
1 | 139 | + |
Name: svn:eol-style |
2 | 140 | + 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 |
1 | 255 | + |
Name: svn:eol-style |
2 | 256 | + 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 |
1 | 176 | + 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 |
1 | 303 | + |
Name: svn:eol-style |
2 | 304 | + native |
Property changes on: trunk/extensions/MetavidWiki/skins/mv_embed/libEmbedVideo |
___________________________________________________________________ |
Name: svn:mergeinfo |
3 | 305 | + |