working on widget video resizing integration
[living-lab-site.git] / js / jquery.ui.nsvideo.js
1 /*
2  * jQuery UI NS-Video 1.0.0 beta
3  *
4  * Copyright 2011, Călin-Andrei Burloiu
5  * Dual licensed under the MIT or GPL Version 2 licenses.
6  * http://jquery.org/license
7  *
8  *
9  * Depends:
10  *   jquery.ui.core.js
11  *   jquery.ui.widget.js
12  */
13 (function( $, undefined ) {
14
15 $.widget( "ui.nsvideo", {
16         version: "1.0.0 beta",
17         options: {
18                 type: 'ns-html5',
19                 srcIndex: 0,
20                 width: 0,
21                 height: 0,
22                 minWidth: 0,
23                 maxWidth: 0,
24                 showStatus: true,
25                 refreshInterval: 0.1,   // seconds
26                 autoplay: false
27         },
28
29         min: 0,
30
31         _create: function() {
32                 var widget = this;
33                 
34                 widget.element
35                         .addClass( "ui-widget ui-widget-content ui-corner-all" );
36                 
37                 widget.$videoContainer = $('<div class="ui-nsvideo-nsplugin"></div>')
38                         .appendTo(widget.element);
39                 widget.$progressContainer = $('<div class="ui-nsvideo-progress-container ui-widget-content ui-corner-top"></div>')
40                         .appendTo(widget.element);
41                 widget.$progress = $('<div class="ui-nsvideo-progress"></div>')
42                         .appendTo(widget.$progressContainer);
43                 widget.$loadedProgress = $('<div class="ui-nsvideo-loaded-progress"></div>')
44                         .appendTo(widget.$progress);
45                 widget.$controls = $('<div class="ui-nsvideo-controls ui-widget-content ui-corner-bottom"></div>')
46                         .appendTo(widget.element);
47                 
48                 widget.video();
49                 
50                 // Time progress slider with load progress also
51                 widget.$loadedProgress
52                         // TODO an object that inherits progressbar should be used in order to customize min value.
53                         .progressbar({
54                                 value: 0
55                         });
56                 widget.$progress
57                         .slider({
58                                         value: 0,
59                                         min: 0,
60                                         max: 1000,
61                                         slide: function(event, ui) {
62                                                 widget.videoPlugin('crtTime', [ui.value]);
63                                         }
64                         });
65                 
66                 // Play / Pause
67                 $('<button class="ui-nsvideo-play ui-nsvideo-button ui-nsvideo-control-left">Play / Pause</button>')
68                         .appendTo(widget.$controls)
69                         .button({
70                                 text: false,
71                                 icons: { primary: "ui-icon-play" }
72                         })
73                         .click(function() {
74                                 widget.videoPlugin('togglePlay');
75                         });
76                 
77                 // Time information (current and total)
78                 widget.$time = $('<div class="ui-nsvideo-time ui-nsvideo-text ui-nsvideo-control-left">--:-- / --:--</div>')
79                         .appendTo(widget.$controls);
80                         
81                 // Full screen
82                 $('<button class="ui-nsvideo-fullscreen ui-nsvideo-button ui-nsvideo-control-right">Full Screen</button>')
83                         .appendTo(widget.$controls)
84                         .button({
85                                 text: false,
86                                 icons: { primary: "ui-icon-arrow-4-diag" }
87                         })
88                         .click(function() {
89                                 widget.videoPlugin('fullscreen');
90                         });
91
92                 // Video format buttonset
93                 if (typeof widget.options.src == 'object')
94                 {
95                         var $formats = $('<form><div class="ui-nsvideo-formats ui-nsvideo-control-right"></div></form>')
96                                 .appendTo(widget.$controls);
97                         $formats = $('.ui-nsvideo-formats', $formats[0]);
98                         $.each(widget.options.src, function(index, value) {
99                                 id = widget.element.attr('id') + '-format-' + index;
100                                 definition = value.res.substring(value.res.indexOf('x')+1)+'p';
101                                 $('<input type="radio" id="' + id + '" name="format" />')
102                                         .appendTo($formats)
103                                         .attr('checked', (index == widget.options.srcIndex))
104                                         .click(function() {
105                                                 widget.videoPlugin('pause');
106                                                 widget.srcIndex(index);
107                                         });
108                                 $('<label for="' + id + '">' + definition + '</label>')
109                                         .appendTo($formats);
110                         });
111                         
112                         $formats.buttonset();
113                 }
114                 
115                 // Volume
116                 $('<div class="ui-nsvideo-volume ui-nsvideo-control-right"></div>')
117                         .appendTo(widget.$controls)
118                         .slider({
119                                 range: "min",
120                                 min: 0,
121                                 max: 100,
122                                 slide: function(event, ui) {
123                                         widget.videoPlugin('volume', [ui.value]);
124                                 }
125                         });
126                 
127                 // Toggle Mute
128                 $('<button class="ui-nsvideo-mute ui-nsvideo-button ui-nsvideo-control-right">Mute</button>')
129                         .appendTo(widget.$controls)
130                         .button({
131                                 text: false,
132                                 icons: { primary: "ui-icon-volume-on" }
133                         })
134                         .click(function() {
135                                 widget.videoPlugin('toggleMute');
136                         });
137                         
138                 // Status information
139                 if (widget.options.showStatus)
140                 {
141                         widget.$stateText = $('<div class="ui-nsvideo-text ui-nsvideo-control-right">...</div>')
142                                 .appendTo(widget.$controls)
143                                 .css('cursor', 'pointer')
144                                 .click(function() {
145                                         widget.videoPlugin('refreshAll');
146                                 });
147                 }
148                 
149                 // Clear fix helper
150                 $('<div class="ui-helper-clearfix"></div>')
151                         .appendTo(widget.$controls);
152                         
153                 // Initialize video plugin
154                 widget.$video.ready(function() {
155                         //widget.videoPlugin('init');
156                 });
157         },
158
159         _destroy: function() {
160                 
161         },
162
163         _setOption: function( key, value ) {
164                 // TODO
165                 if ( key === "TODO" ) {
166                         
167                 }
168
169                 this._super( "_setOption", key, value );
170         },
171         
172         _leadingZeros: function(number, length) {
173                 if (!length)
174                         length = 2;
175                 
176                 var str = '';
177                 
178                 if (isNaN(number))
179                 {
180                         for (var i=0; i<length; i++)
181                                 str += '-';
182                         return str;
183                 }
184                 
185                 str += number;
186                 while (str.length < length) 
187                 {
188                         str = '0' + str;
189                 }
190
191                 return str;
192         },
193         
194         video: function() {
195                 widget = this;
196                 
197                 // Select video source.
198                 // If src option is string, that's the source.
199                 // If src is an object, there is a list of associative arrays, each
200                 // one having the mandatory keys "src" and "res" (resolution).
201                 var src = widget.crtSrc();
202                 if (src == null)
203                         return widget;
204                 
205                 widget.$videoContainer.html('');
206                 
207                 var width = widget.options.width;
208                 var height = widget.options.height;
209                 
210                 // HTML5
211                 if (widget.options.type == 'ns-html5'
212                         || widget.options.type == 'html5')
213                 {
214                         widget.$video = $('<video id="' + widget.element.attr('id') + '-video" src="' + src + '"' + (width == 0 ? '' : ' width="' + width + '"') + (height == 0 ? '' : ' height="' + height + '"') + ' preload="auto"' + (widget.options.autoplay ? ' autoplay="autoplay"' : '') + '>'
215                                 +'Error: Your browser does not support HTML5 or the video format!'
216                         +'</video>')
217                                 .appendTo(widget.$videoContainer)
218                                 .bind({
219                                         ended: function() {
220                                                 widget.html5.pause();
221                                         },
222                                         play: function() {
223                                                 widget.html5.play();
224                                         },
225                                         pause: function() {
226                                                 widget.html5.pause();
227                                         },
228                                         timeupdate: function() {
229                                                 widget.html5.refreshTime();
230                                         },
231                                         progress: function() {
232                                                 widget.html5.refreshLoadedProgress();
233                                         },
234                                         loadedmetadata: function() {
235                                                 widget.html5.refreshTime();
236                                                 widget.html5.refreshVolume();
237                                                 widget._setWidgetWidth();
238                                         },
239                                         seeked: function() {
240                                                 widget.html5.play();
241                                         },
242                                         volumechange: function() {
243                                                 widget.html5.refreshVolume();
244                                         }
245                                 });
246                 }
247                 // VLC
248                 else if (widget.options.type == 'ns-vlc'
249                         || widget.options.type == 'vlc')
250                 {
251                         var embedType;
252                         if (widget.options.type == 'ns-vlc')
253                                 embedType = 'application/x-ns-stream';
254                         else
255                                 embedType = 'application/x-vlc-plugin';
256                         
257                         if (navigator.appName == "Netscape")
258                         {
259                                 widget.$video = $('<embed type="' + embedType + '" name="vlcVideo" id="' + widget.element.attr('id') + '-video" autoplay="' + (widget.options.autoplay ? 'yes' : 'no') + '" loop="no" width="' + (width == 0 ? '640' : width) + '" height="' + (height == 0 ? '480' : height) + '" target="' + src + '" />')
260                                         .appendTo(widget.$videoContainer);
261                         }
262                         else
263                         {
264                                 widget.$video = $('<object classid="clsid:1800B8AF-4E33-43C0-AFC7-894433C13538" width="' + (width == 0 ? '640' : width) + '" height="' + (height == 0 ? '480' : height) + '" id="' + widget.element.attr('id') + '-video" name="vlcVideo" events="True" target="">'
265                                                 + '<param name="Src" value="' + src + '" />'
266                                                 + '<param name="ShowDisplay" value="True" />'
267                                                 + '<param name="Loop" value="False" />'
268                                                 + '<param name="AutoPlay" value="' + (widget.options.autoplay ? 'True' : 'False') + '" />'
269                                                 + '<param name="Toolbar" value="False" />'
270                                         + '</object>')
271                                         .appendTo(widget.$videoContainer);
272                         }
273                 }
274                 
275                 widget.$video.css('position', 'relative');
276                 
277                 // Adjust video size for auto-resizing within ranges minWidth and
278                 // maxWidth.
279                 if (widget.options.minWidth != 0 && widget.options.maxWidth != 0
280                         && typeof widget.options.src == 'object'
281                         && (typeof widget.options.src[ widget.options.srcIndex ].res)
282                                 != 'undefined'
283                         && (typeof widget.options.src[ widget.options.srcIndex ].dar)
284                                 != 'undefined')
285                 {
286                         var resolution = widget.options.src[ widget.options.srcIndex ].res;
287                         var dar = widget.options.src[ widget.options.srcIndex ].dar;
288                         var darL = parseInt(
289                                 dar.substring(0, dar.indexOf(':')));
290                         var darR = parseInt(
291                                 dar.substring(dar.indexOf(':') + 1));
292                         var videoHeight = parseInt(
293                                 resolution.substring(resolution.indexOf('x') + 1));
294                         var videoWidth = Math.round(videoHeight * darL / darR);
295                         // Video width must be between minWidth and maxWidth pixels.
296                         if (videoWidth > widget.options.maxWidth)
297                         {
298                                 videoHeight = Math.round(widget.options.maxWidth / videoWidth
299                                         * videoHeight);
300                                 videoWidth = widget.options.maxWidth;
301                         }
302                         else if (videoWidth < widget.options.minWidth)
303                         {
304                                 videoHeight = Math.round(widget.options.minWidth / videoWidth
305                                         * videoHeight);
306                                 videoWidth = widget.options.minWidth;
307                         }
308                         console.log(videoWidth + ' ' + videoHeight);
309                         widget.$video.css('width', videoWidth);
310                         widget.$video.css('height', videoHeight);
311                 }
312                 
313                 widget._setWidgetWidth();
314         },
315         
316         _setWidgetWidth: function() {
317                 if (widget.$video.width() < 640)
318                 {
319                         widget.element.css('width',
320                                                         640 + 8 + 'px');
321                         widget.$video.css('left', 
322                                 Math.round(widget.$videoContainer.width()/2 
323                                 - widget.$video.width()/2)
324                                 + 'px');
325                 }
326                 else
327                 {
328                         widget.element.css('width',
329                                                         widget.$video.width() + 8 + 'px');
330                         widget.$video.css('left', '0');
331                 }
332         },
333         
334         setPlayButton: function() {
335                 $('button.ui-nsvideo-play', widget.element[0])
336                         .button('option', 'icons', { primary: "ui-icon-play" })
337                         .button('refresh');
338         },
339         setPauseButton: function() {
340                 $('button.ui-nsvideo-play', widget.element[0])
341                         .button('option', 'icons', { primary: "ui-icon-pause" })
342                         .button('refresh');
343         },
344         setMuteButton: function() {
345                 $('button.ui-nsvideo-mute', widget.element[0])
346                         .button('option', 'icons', { primary: "ui-icon-volume-off" })
347                         .button('refresh');
348         },
349         setUnmuteButton: function() {
350                 $('button.ui-nsvideo-mute', widget.element[0])
351                         .button('option', 'icons', { primary: "ui-icon-volume-on" })
352                         .button('refresh');
353         },
354         setTimeText: function(text) {
355                 //$('.ui-nsvideo-time', widget.element[0])
356                 this.$time
357                         .html(text);
358         },
359         setVolumeSlider: function(vol) {
360                 $('.ui-nsvideo-volume', widget.element[0])
361                         .slider('value', vol);
362         },
363         setProgressSlider: function(prog) {
364                 $('.ui-nsvideo-progress', widget.element[0])
365                         .slider('value', prog);
366         },
367         setLoadedProgressSlider: function(prog) {
368                 $('.ui-nsvideo-loaded-progress', widget.element[0])
369                         .progressbar('value', prog);
370         },
371         
372         videoPlugin: function(method, args) {
373                 if (typeof args == 'undefined')
374                         args = [];
375                 var videoPlugin = null;
376                 
377                 if (this.options.type.indexOf('html5') != -1)
378                 {
379                         videoPlugin = this.html5;
380                 }
381                 else if (this.options.type.indexOf('vlc') != -1)
382                 {
383                         videoPlugin = this.vlc;
384                 }
385                 
386                 if (videoPlugin)
387                         return videoPlugin[method].apply(this, args);
388                 
389                 return null;
390         },
391         
392         srcIndex: function(srcIndex) {
393                 var widget = this;
394                 
395                 if (typeof srcIndex == 'undefined')
396                         return widget.options.srcIndex;
397                 
398                 widget.options.srcIndex = srcIndex;
399                 
400                 // Refresh.
401                 widget.video();
402                 
403                 return widget;
404         },
405         
406         type: function(type) {
407                 var widget = this;
408                 
409                 if (typeof type == 'undefined')
410                         return widget.options.type;
411                 
412                 widget.options.type = type;
413                 widget.video();
414                 
415                 // Initialize video plugin
416                 widget.$video.ready(function() {
417                         widget.videoPlugin('init');
418                 });
419                 
420                 return widget;
421         },
422         
423         crtSrc: function() {
424                 var src;
425                 var widget = this;
426                 
427                 if (typeof widget.options.src == 'string')
428                         src = widget.options.src;
429                 else if (typeof widget.options.src == 'object')
430                 {
431                         if (typeof widget.options.srcIndex == 'undefined')
432                                 return null;
433                         
434                         if (typeof widget.options.src[ widget.options.srcIndex ].src
435                                 == 'undefined')
436                                 return null;
437                         
438                         src = widget.options.src[ widget.options.srcIndex ].src;
439                 }
440                 
441                 if (widget.options.type == 'ns-html5')
442                         src = 'tribe://' + src;
443                 
444                 return src;
445         },
446         
447         html5: {
448                 widget: this,
449                 //lastTime: null,
450                 
451                 init: function() {
452                         //widget.html5.refreshAll();
453                         
454                         //if (widget.options.autoplay)
455                         //      widget.html5.play();
456                 },
457                 
458                 togglePlay: function() {
459                         if (widget.$video[0].paused)
460                         {
461                                 widget.html5.play();
462                         }
463                         else
464                         {
465                                 widget.html5.pause();
466                         }
467                 },
468
469                 play: function() {
470                         if (widget.$video[0].paused)
471                                 widget.$video[0].play();
472                         
473                         widget.setPauseButton();
474                         
475                         return widget;
476                 },
477                 
478                 pause: function() {
479                         if (!widget.$video[0].paused)
480                                 widget.$video[0].pause();
481                         
482                         widget.setPlayButton();
483
484                         return widget;
485                 },
486                 
487                 toggleMute: function() {
488                         if (!widget.$video[0].muted)
489                         {
490                                 widget.html5.mute();
491                         }
492                         else
493                         {
494                                 widget.html5.unmute();
495                         }
496                 },
497                   
498                 mute: function() {
499                         if (!widget.$video[0].muted)
500                                 widget.$video[0].muted = true;
501                         
502                         widget.setMuteButton();
503                         
504                         return widget;
505                 },
506                 
507                 unmute: function() {
508                         if (widget.$video[0].muted)
509                                 widget.$video[0].muted = false;
510                         
511                         widget.setUnmuteButton();
512                         
513                         return widget;
514                 },
515                 
516                 /**
517                 * Volume value is expressed in percents.
518                 */
519                 volume: function(vol) {
520                         if (typeof vol == 'undefined')
521                                 return Math.round(widget.$video[0].volume * 100);
522                         
523                         widget.html5.unmute();
524                         widget.$video[0].volume = vol / 100;
525                         
526                         return widget;
527                 },
528                 
529                 /**
530                  * Seek position is a value between 0 and 1000.
531                  */
532                 crtTime: function(pos) {
533                         // getter
534                         if (typeof pos == 'undefined')
535                         {
536                                 var crtTime = widget.$video[0].currentTime;
537                                 var totTime = widget.$video[0].duration;
538                                 if (isNaN(totTime) || totTime == 0)
539                                         return 0;
540                                 else
541                                         return Math.round(crtTime / totTime * 1000.0);
542                         }
543                         
544                         // setter
545                         widget.$video[0].currentTime = 
546                                 pos / 1000 * widget.$video[0].duration;
547                 },
548                   
549                 refreshAll: function() {
550                         widget.html5.refreshState();
551                         widget.html5.refreshVolume();
552                         widget.html5.refreshLoadedProgress();
553                         widget.$time.html('--:-- / --:--');
554                         widget.$stateText.html('...');
555                         widget.html5.refreshTime();
556                 },
557                 
558                 refreshTime: function() {
559                         if (widget.$video[0].seeking)
560                                 return widget;
561                         
562                         var crtTime = widget.$video[0].currentTime;
563                         var totTime = widget.$video[0].duration;
564                         
565                         // Refresh only at refreshInterval seconds to save CPU time.
566                         var delta = crtTime - widget.html5.lastTime;
567                         if (typeof widget.html5.lastTime !== "undefined"
568                                 && delta >= 0 && delta < widget.options.refreshInterval)
569                                 return widget;
570                         widget.html5.lastTime = crtTime;
571                         
572                         // Current time string
573                         var crtH = Math.floor(crtTime / 3600);
574                         var crtM = Math.floor((crtTime / 60) % 60);
575                         var crtS = Math.floor(crtTime % 60);
576                         var strCrtTime = 
577                                 (crtH == 0 ? '' : (widget._leadingZeros(crtH) + ':'))
578                                 + widget._leadingZeros(crtM) + ':' + widget._leadingZeros(crtS);
579                                 
580                         // Total time string
581                         var totH = Math.floor(totTime / 3600);
582                         var totM = Math.floor((totTime / 60) % 60);
583                         var totS = Math.floor(totTime % 60);
584                         var strTotTime = 
585                                 (totH == 0 || isNaN(totH) ? '' : (widget._leadingZeros(totH) + ':'))
586                                 + widget._leadingZeros(totM) + ':' + widget._leadingZeros(totS);
587                         
588                         widget.setTimeText('' + strCrtTime + ' / ' + strTotTime);
589                         
590                         // Update time progress slider.
591                         widget.html5.refreshProgress();
592                         
593                         return widget;
594                 },
595                 
596                 refreshState: function() {
597                         // TODO refresh HTML5 plugin state
598                         
599                         return widget;
600                 },
601
602                 refreshVolume: function() {
603                         var vol;
604                         
605                         if (widget.$video[0].muted)
606                                 vol = 0;
607                         else
608                                 vol = Math.floor(widget.$video[0].volume * 100);
609                         
610                         widget.setVolumeSlider(vol);
611                         
612                         return widget;
613                 },
614                 
615                 refreshProgress: function() {
616                         widget.setProgressSlider(widget.html5.crtTime());
617                         
618                         return widget;
619                 },
620                 
621                 /**
622                 * Supported for Firefox 4.0 or later.
623                 */
624                 refreshLoadedProgress: function() {
625                         // Return if buffering status not available in browser.
626                         if (typeof widget.$video[0].buffered == 'undefined'
627                                 || widget.$video[0].buffered.length === 0)
628                                 return widget;
629                         
630                         var loadedTime = widget.$video[0].buffered.end(0);
631                         var totTime = widget.$video[0].duration;
632                         var percent;
633                         if (isNaN(totTime) || totTime == 0)
634                                 percent = 0
635                         else
636                                 percent = Math.floor(loadedTime / totTime * 100);
637                         
638                         widget.setLoadedProgressSlider(percent);
639                         
640                         return widget;
641                 },
642
643                 fullscreen: function() {
644                         alert('Your web browser does not support switching to full screen in HTML5 mode with this button. You can switch to full screen manually by right clicking on the video and choosing "Full Screen" from the popup menu.');
645                 }
646         },
647         
648         vlc: {
649                 widget: this,
650                 timerHandle: null,
651                 
652                 STATES: {
653                         IDLE_CLOSE: [0, "Idle / Close"],
654                         OPENING: [1, "Opening..."],
655                         BUFFERING: [2, "Buffering..."],
656                         PLAYING: [3, "Playing..."],
657                         PAUSED: [4, "Paused"],
658                         STOPPING: [5, "Stopping..."],
659                         ERROR: [6, "Error!"]
660                 },
661                 
662                 init: function() {
663                         if (widget.options.autoplay)
664                                 widget.vlc.play();
665                         widget.vlc.refreshAll();
666                 },
667                 
668                 togglePlay: function() {
669                         if (! widget.$video[0].playlist.isPlaying)
670                         {
671                                 widget.vlc.play();
672                         }
673                         else
674                         {
675                                 widget.vlc.pause();
676                         }
677                 },
678                 
679                 play: function() {
680                         if (! widget.$video[0].playlist.isPlaying)
681                                 widget.$video[0].playlist.play();
682                         
683                         widget.setPauseButton();
684                         
685                         // Schedule information refreshment at refreshInterval seconds.
686                         if (! widget.vlc.timerHandle)
687                                 widget.vlc.timerHandle = setTimeout(widget.vlc.refreshHandler, 
688                                                                                 widget.options.refreshInterval * 1000);
689                                 
690                         widget.vlc.refreshState();
691                         
692                         return widget;
693                 },
694                 
695                 pause: function() {
696                         if (widget.$video[0].playlist.isPlaying)
697                                 widget.$video[0].playlist.togglePause();
698                         
699                         widget.setPlayButton();
700                         
701                         // Cancel information refreshment scheduling.
702                         clearTimeout(widget.vlc.timerHandle);
703                         widget.vlc.timerHandle = null;
704                         
705                         widget.vlc.refreshState();
706
707                         return widget;
708                 },
709                 
710                 toggleMute: function() {
711                         if (! widget.$video[0].audio.mute)
712                         {
713                                 widget.vlc.mute();
714                         }
715                         else
716                         {
717                                 widget.vlc.unmute();
718                         }
719                 },
720                   
721                 mute: function() {
722                         if (! widget.$video[0].audio.mute)
723                                 widget.$video[0].audio.toggleMute();
724                         
725                         widget.setMuteButton();
726                         
727                         widget.vlc.refreshVolume();
728                         
729                         return widget;
730                 },
731                 
732                 unmute: function() {
733                         if (widget.$video[0].audio.mute)
734                                 widget.$video[0].audio.toggleMute();
735                         
736                         widget.setUnmuteButton();
737                         
738                         widget.vlc.refreshVolume();
739                         
740                         return widget;
741                 },
742                 
743                 /**
744                 * Volume value is expressed in percents.
745                 */
746                 volume: function(vol) {
747                         if (typeof vol == 'undefined')
748                                 return Math.round(widget.$video[0].audio.volume);
749                         
750                         widget.vlc.unmute();
751                         widget.$video[0].audio.volume = vol;
752                         
753                         return widget;
754                 },
755                 
756                 /**
757                  * Seek position is a value between 0 and 1000.
758                  */
759                 crtTime: function(pos) {
760                         // getter
761                         if (typeof pos == 'undefined')
762                         {
763                                 var crtTime = widget.$video[0].input.time;
764                                 var totTime = widget.$video[0].input.length;
765                                 if (isNaN(totTime) || totTime == 0)
766                                         return 0;
767                                 else
768                                         return Math.round(crtTime / totTime * 1000.0);
769                         }
770                         
771                         // setter
772                         widget.$video[0].input.time = 
773                                 pos / 1000 * widget.$video[0].input.length;
774                                 
775                         widget.vlc.refreshState();
776                 },
777                 
778                 /**
779                  * Timeout callback called at refreshInterval during playing in order
780                  * to refresh information.
781                  */
782                 refreshHandler: function() {
783                         if (widget.$video[0].input.state
784                                 == widget.vlc.STATES.PLAYING[0])
785                         {
786                                 widget.vlc.refreshTime();
787                                 widget.vlc.timerHandle = setTimeout(widget.vlc.refreshHandler, 
788                                                                                 widget.options.refreshInterval * 1000);
789                         }
790                         else
791                                 widget.vlc.pause();
792                         
793                         widget.vlc.refreshState();
794                 },
795                 
796                 refreshAll: function() {
797                         widget.vlc.refreshState();
798                         widget.vlc.refreshVolume();
799                         widget.vlc.refreshLoadedProgress();
800                         
801                         try {
802                                 widget.vlc.refreshTime();
803                         } catch(e) {
804                                 console.log(e);
805                                 widget.$time.html('--:-- / --:--');
806                         }
807                 },
808                 
809                 refreshTime: function() {
810                         // TODO while seeking (maybe not necessary for VLC)
811 //                      if (widget.$video[0].seeking)
812 //                              return widget;
813                         
814                         // Time values in seconds.
815                         var crtTime = widget.$video[0].input.time / 1000.0;
816                         var totTime = widget.$video[0].input.length / 1000.0;
817                         //var crtTime = widget.$video[0].input.position * totTime;
818                         
819                         // Current time string
820                         var crtH = Math.floor(crtTime / 3600);
821                         var crtM = Math.floor((crtTime / 60) % 60);
822                         var crtS = Math.floor(crtTime % 60);
823                         var strCrtTime = 
824                                 (crtH == 0 ? '' : (widget._leadingZeros(crtH) + ':'))
825                                 + widget._leadingZeros(crtM) + ':' + widget._leadingZeros(crtS);
826                                 
827                         // Total time string
828                         var totH = Math.floor(totTime / 3600);
829                         var totM = Math.floor((totTime / 60) % 60);
830                         var totS = Math.floor(totTime % 60);
831                         var strTotTime = 
832                                 (totH == 0 || isNaN(totH) ? '' : (widget._leadingZeros(totH) + ':'))
833                                 + widget._leadingZeros(totM) + ':' + widget._leadingZeros(totS);
834                         
835                         widget.setTimeText('' + strCrtTime + ' / ' + strTotTime);
836                         
837                         // Update time progress slider.
838                         widget.vlc.refreshProgress();
839                         
840                         return widget;
841                 },
842                 
843                 _state: function(code) {
844                         var r;
845                         $.each(widget.vlc.STATES, function(index, value) {
846                                 if ('' + code == '' + value[0])
847                                 {
848                                         r = value;
849                                         return false;
850                                 }
851                         });
852                         
853                         return r;
854                 },
855                 
856                 refreshState: function() {
857                         widget.$stateText
858                                 .html(widget.vlc._state(widget.$video[0].input.state)[1]);
859                 },
860
861                 refreshVolume: function() {
862                         var vol;
863                         
864                         if (widget.$video[0].audio.mute)
865                                 vol = 0;
866                         else
867                                 vol = Math.floor(widget.$video[0].audio.volume);
868                         
869                         widget.setVolumeSlider(vol);
870                         
871                         return widget;
872                 },
873                 
874                 refreshProgress: function() {
875                         widget.setProgressSlider(widget.vlc.crtTime());
876                         
877                         return widget;
878                 },
879                 
880                 /**
881                 * Not supported for VLC.
882                 */
883                 refreshLoadedProgress: function() {
884                         // TODO Currently not possible through VLC API.
885                         
886                         return widget;
887                 },
888
889                 fullscreen: function() {
890                         widget.$video[0].video.toggleFullscreen();
891                 }
892         }
893 });
894
895 })( jQuery );