2b66df0dd85170eb3bfd9dad2b78bcb4e00aa96e
[lhc/web/wiklou.git] / js2 / mwEmbed / libEmbedVideo / nativeEmbed.js
1 //native embed library:
2 var nativeEmbed = {
3 instanceOf:'nativeEmbed',
4 canPlayThrough:false,
5 grab_try_count:0,
6 onlyLoadFlag:false,
7 urlAppend:'',
8 prevCurrentTime:-1,
9 supports: {
10 'play_head':true,
11 'pause':true,
12 'fullscreen':false,
13 'time_display':true,
14 'volume_control':true,
15
16 'overlays':true,
17 'playlist_swap_loader':true //if the object supports playlist functions
18 },
19 getEmbedHTML : function (){
20 var embed_code = this.getEmbedObj();
21 js_log("embed code: " + embed_code)
22 setTimeout('$j(\'#' + this.id + '\').get(0).postEmbedJS()', 150);
23 return this.wrapEmebedContainer( embed_code);
24 },
25 getEmbedObj:function(){
26 //we want to let mv_embed handle the controls so notice the absence of control attribute
27 // controls=false results in controls being displayed:
28 //http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2008-August/016159.html
29 js_log("native play url:" + this.getSrc() + ' start_offset: '+ this.start_ntp + ' end: ' + this.end_ntp);
30 var eb = '<video ' +
31 'id="' + this.pid + '" ' +
32 'style="width:' + this.width+'px;height:' + this.height + 'px;" ' +
33 'width="' + this.width + '" height="'+this.height+'" '+
34 'src="' + this.getSrc() + '" ';
35
36 /*if(!this.onlyLoadFlag)
37 eb+='autoplay="true" ';*/
38
39 //continue with the other attr:
40 eb+= 'oncanplaythrough="$j(\'#'+this.id+'\').get(0).oncanplaythrough();return false;" ' +
41 'onloadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' +
42 'loadedmetadata="$j(\'#'+this.id+'\').get(0).onloadedmetadata();return false;" ' +
43 'onprogress="$j(\'#'+this.id+'\').get(0).onprogress( event );return false;" '+
44 'onended="$j(\'#'+this.id+'\').get(0).onended();return false;" '+
45 'onseeking="$j(\'#'+this.id+'\').get(0).onseeking();" ' +
46 'onseeked="$j(\'#'+this.id+'\').get(0).onseeked();" >' +
47 '</video>';
48 return eb;
49 },
50 //@@todo : loading progress
51 postEmbedJS:function(){
52 var _this = this;
53 js_log("f:native:postEmbedJS:");
54 this.getVID();
55 if(typeof this.vid != 'undefined'){
56 //always load the media:
57 if( this.onlyLoadFlag ){
58 this.vid.load();
59 }else{
60 //issue play request
61 this.vid.play();
62 }
63 setTimeout('$j(\'#'+this.id+'\').get(0).monitor()',100);
64 }else{
65 js_log('could not grab vid obj trying again:' + typeof this.vid);
66 this.grab_try_count++;
67 if( this.grab_count == 20 ){
68 js_log(' could not get vid object after 10 tries re-run: getEmbedObj()' ) ;
69 }else{
70 setTimeout('$j(\'#'+this.id+'\').get(0).postEmbedJS()', 200);
71 }
72 }
73 },
74 onseeking:function(){
75 js_log("onseeking");
76 this.seeking = true;
77 this.setStatus( gM('mwe-seeking') );
78 },
79 onseeked: function(){
80 this.seeking = false;
81 },
82 doSeek:function(perc){
83 //js_log('native:seek:p: ' + perc+ ' : ' + this.supportsURLTimeEncoding() + ' dur: ' + this.getDuration() + ' sts:' + this.seek_time_sec );
84 //@@todo check if the clip is loaded here (if so we can do a local seek)
85 if( this.supportsURLTimeEncoding() || !this.vid){
86 //make sure we could not do a local seek instead:
87 if( perc < this.bufferedPercent && this.vid.duration && !this.didSeekJump ){
88 js_log("do local seek " + perc + ' is already buffered < ' + this.bufferedPercent);
89 this.doNativeSeek(perc);
90 }else{
91 this.parent_doSeek(perc);
92 }
93 }else if(this.vid && this.vid.duration ){
94 //(could also check bufferedPercent > perc seek (and issue oggz_chop request or not)
95 this.doNativeSeek( perc );
96 }else{
97 this.doPlayThenSeek( perc )
98 }
99 },
100 doNativeSeek:function(perc){
101 this.seek_time_sec=0;
102 this.vid.currentTime = perc * this.vid.duration;
103 this.monitor();
104 },
105 doPlayThenSeek:function(perc){
106 js_log('native::doPlayThenSeek::');
107 var _this = this;
108 this.play();
109 var rfsCount = 0;
110 var readyForSeek = function(){
111 _this.getVID();
112 //if we have duration then we are ready to do the seek
113 if(this.vid && this.vid.duration){
114 _this.doSeek( perc );
115 }else{
116 //try to get player for 10 seconds:
117 if( rfsCount < 200 ){
118 setTimeout(readyForSeek, 50);
119 rfsCount++;
120 }else{
121 js_log('error:doPlayThenSeek failed');
122 }
123 }
124 }
125 readyForSeek();
126 },
127 setCurrentTime: function(pos, callback){
128 var _this = this;
129 this.getVID();
130 if(!this.vid) {
131 this.load();
132 var loaded = function(event) {
133 js_log('native:setCurrentTime (after load): ' + pos + ' : dur: ' + this.getDuration());
134 _this.vid.currentTime = pos;
135 var once = function(event) {
136 callback();
137 _this.vid.removeEventListener('seeked', once, false)
138 };
139 _this.vid.addEventListener('seeked', once, false);
140 _this.removeEventListener('loadedmetadata', loaded, false);
141 };
142 _this.addEventListener('loadedmetadata', loaded, false);
143 } else {
144 //js_log('native:setCurrentTime: ' + pos + ' : ' + this.supportsURLTimeEncoding() + ' dur: ' + this.getDuration() + ' sts:' + this.seek_time_sec );
145 _this.vid.currentTime = pos;
146 var once = function(event) {
147 callback();
148 _this.vid.removeEventListener('seeked', once, false)
149 };
150 _this.vid.addEventListener('seeked', once, false);
151 }
152 },
153 monitor : function(){
154 this.getVID(); //make shure we have .vid obj
155 if(!this.vid){
156 js_log('could not find video embed: '+this.id + ' stop monitor');
157 this.stopMonitor();
158 return false;
159 }
160 //don't update status if we are not the current clip (playlist leekage?) .. should move to playlist overwite of monitor?
161 if(this.pc){
162 if(this.pc.pp.cur_clip.id != this.pc.id)
163 return true;
164 }
165
166 //do a seek check (on seeked does not seem fire consistantly)
167 if( this.prevCurrentTime != -1 && this.prevCurrentTime != 0
168 && this.prevCurrentTime < this.currentTime && this.seeking)
169 this.seeking = false;
170
171 this.prevCurrentTime = this.currentTime;
172
173 //update currentTime
174 this.currentTime = this.vid.currentTime;
175 this.addPresTimeOffset();
176
177 //js_log('currentTime:' + this.currentTime);
178 //js_log('this.currentTime: ' + this.currentTime );
179 //once currentTime is updated call parent_monitor
180 this.parent_monitor();
181 },
182 getSrc:function(){
183 var src = this.parent_getSrc();
184 if( this.urlAppend != '')
185 return src + ( (src.indexOf('?')==-1)?'?':'&') + this.urlAppend;
186 return src;
187 },
188 /*
189 * native callbacks for the video tag:
190 */
191 oncanplaythrough : function(){
192 //js_log('f:oncanplaythrough');
193 this.getVID();
194 if( ! this.paused )
195 this.vid.play();
196 },
197 onloadedmetadata: function(){
198 this.getVID();
199 js_log('f:onloadedmetadata metadata ready (update duration)');
200 //update duration if not set (for now trust the getDuration more than this.vid.duration
201 if( this.getDuration() == 0 && ! isNaN( this.vid.duration ) ){
202 js_log('updaed duration via native video duration: '+ this.vid.duration)
203 this.duration = this.vid.duration;
204 }
205 },
206 onprogress: function(e){
207 this.bufferedPercent = e.loaded / e.total;
208 //js_log("onprogress:" +e.loaded + ' / ' + (e.total) + ' = ' + this.bufferedPercent);
209 },
210 onended:function(){
211 var _this = this
212 this.getVID();
213 js_log('native:onended:' + this.vid.currentTime + ' real dur:' + this.getDuration() );
214 //if we just started (under 1 second played) & duration is much longer.. don't run onClipDone just yet . (bug in firefox native sending onended event early)
215 if(this.vid.currentTime < 1 && this.getDuration() > 1 && this.grab_try_count < 5){
216 js_log('native on ended called with time:' + this.vid.currentTime + ' of total real dur: ' + this.getDuration() + ' attempting to reload src...');
217 var doRetry = function(){
218 _this.urlAppend = 'retry_src=' + _this.grab_try_count;
219 _this.doEmbedHTML();
220 _this.grab_try_count++;
221 }
222 setTimeout(doRetry, 100);
223 }else{
224 js_log('native onClipDone done call');
225 this.onClipDone();
226 }
227 },
228 pause : function(){
229 this.getVID();
230 this.parent_pause(); //update interface
231 if(this.vid){
232 this.vid.pause();
233 }
234 //stop updates:
235 this.stopMonitor();
236 },
237 play:function(){
238 this.getVID();
239 this.parent_play(); //update interface
240 if( this.vid ){
241 this.vid.play();
242 //re-start the monitor:
243 this.monitor();
244 }
245 },
246 toggleMute:function(){
247 this.parent_toggleMute();
248 this.getVID();
249 if(this.vid)
250 this.vid.muted = this.muted;
251 },
252 updateVolumen:function(perc){
253 this.getVID();
254 if(this.vid)
255 this.vid.volume = perc;
256 },
257 getVolumen:function(){
258 this.getVID();
259 if(this.vid)
260 return this.vid.volume;
261 },
262 getNativeDuration:function(){
263 if(this.vid)
264 return this.vid.duration;
265 },
266 load:function(){
267 this.getVID();
268 if( !this.vid ){
269 //no vid loaded
270 js_log('native::load() ... doEmbed');
271 this.onlyLoadFlag = true;
272 this.doEmbedHTML();
273 }else{
274 //won't happen offten
275 this.vid.load();
276 }
277 },
278 // get the embed vlc object
279 getVID : function (){
280 this.vid = $j('#'+this.pid).get(0);
281 },
282 /*
283 * playlist driver
284 * mannages native playlist calls
285 */
286 };