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