Bug 20489 Configure illegal file characters https://bugzilla.wikimedia.org/show_bug...
[mediawiki.git] / js2 / mwEmbed / libAddMedia / mvAdvFirefogg.js
blobc56681578b9de1b9ad741db6ed53bc324a740d01
1 /*
2  * Adds advanced firefogg support (let you control and structure advanced controls over many aspects of video encoding)
3  */
5 //@@todo put all msg text into loadGM json
7 loadGM({
8         "fogg-help-sticky" : "Help (click to stick)",
9         "fogg-cg-preset" : "Preset: <strong>$1<\/strong>",
10         "fogg-cg-quality" : "Basic quality and resolution control",
11         "fogg-cg-meta" : "Metadata for the clip",
12         "fogg-cg-range" : "Encoding range",
13         "fogg-cg-advVideo" : "Advanced video encoding controls",
14         "fogg-cg-advAudio" : "Advanced audio encoding controls",
15         "fogg-preset-custom" : "Custom settings"
16 });
18 var mvAdvFirefogg = function( iObj ){
19         return this.init( iObj );
21 var default_mvAdvFirefogg_config = {
22         //which config groups to include
23         'config_groups'  : ['preset', 'range', 'quality', 'meta', 'advVideo', 'advAudio'],
25         //if you want to load any custom presets must follow the mvAdvFirefogg.presetConf json outline below
26         'custom_presets'        : {},
28         //any firefog config properties that may need to be excluded from options
29         'exclude_settings' : [],
31         //the control container (where we put all the controls)
32         'target_control_container':false
35 mvAdvFirefogg.prototype = {
36         //the global groupings and titles for for configuration options :
37         config_groups : [ 'preset', 'range', 'quality', 'meta', 'advVideo', 'advAudio'],
38         //list of pre-sets:
39         //local instance encoder config:
40 default_local_settings:{
41         'd'     : 'webvideo',
42         'type'  : 'select',
43         'selectVal': ['webvideo'],
44         'group' : "preset",
45         'pSet' : {
46                 'custom':{
47                         'descKey': 'fogg-preset-custom',
48                         'conf': {}
49                 },
50                 'webvideo': {
51                         'desc': "Web Video Theora, Vorbis 400kbs & 400px max width",
52                         'conf': {
53                                 'maxSize'      : 400,
54                                 'videoBitrate' : 544,
55                                 'audioBitrate' : 96,
56                                 'noUpscaling'  : true,
57                         }
58                 },
59                 'savebandwith': {
60                         'desc': "Low Bandwith Theora, Vorbis 164kbs & 200px max size",
61                         'conf': {
62                                 'maxSize'       : 200,
63                                 'videoBitrate'  : 164,
64                                 'audioBitrate'  : 32,
65                                 'samplerate'    : 22050,
66                                 'framerate'     : 15,
67                                 'channels'      : 1,
68                                 'noUpscaling'   : true
69                         }
70                 },
71                 'hqstream':{
72                         'desc': "High Quality Theora, Vorbis 1080px max width",
73                         'conf': {
74                                 'maxSize'      : 1080,
75                                 'videoQuality' : 6,
76                                 'audioQuality' : 3,
77                                 'noUpscaling'  : true,
78                         }
79                 },
80         }
82         local_settings: {},
84         //core firefogg default encoder configuration
85         //see encoder options here: http://www.firefogg.org/dev/index.html
86         default_encoder_config : {
87                 //base quality settings:
88                 'videoQuality': {
89                         'd'     : 5,
90                         't'     : 'Video Quality',
91                         'range' : {'min':0,'max':10},
92                         'type'  : 'slider',
93                         'group' : 'quality',
94                         'help'  : "Used to set the <i>Visual Quality</i> of the encoded video. (not used if you set bitrate in advanced controls below)"
95                 },
96                 'twopass':{
97                         't'     : "Two Pass Encoding",
98                         'type'  : "boolean",
99                         'group' : "quality",
100                         'help'  : "Two Pass Encoding enables more consitant quality by making two passes over the video file"
101                 },
102                 'starttime':{
103                         't'             : "Start Second",
104                         'type'  : "float",
105                         'group' : "range",
106                         'help'  : "Only encode from time in seconds"
107                 },
108                 'endtime':{
109                         't'             : "End Second",
110                         'type'  : "float",
111                         'group' : "range",
112                         'help'  : "only encode to time in seconds"
113                 },
114                 'audioQuality': {
115                         'd'                     : 1,
116                         't'                     : 'Audio Quality',
117                         'range'  : {'min':-1,'max':10},
118                         'type'    : 'slider',
119                         'group'  : 'quality',
120                         'help'    : "Used to set the <i>Acoustic Quality</i> of the encoded audio. (not used if you set bitrate in advanced controls below)"
121                 },
122                 'videoCodec':{
123                         'd'                     : "theora",
124                         't'                     : 'Video Codec',
125                         'selectVal'     : ['theora'],
126                         'type'          : "select",
127                         'group'         : "quality",
128                         'help'    : "Used to select the clip video codec. Presently only Theora is supported. More about the <a href=\"http://www.theora.org/\">theora codec</a> "
129                 },
130                 'audioCodec':{
131                         'd'                     : "vorbis",
132                         't'                     : 'Audio Codec',
133                         'selectVal'     : ['vorbis'],
134                         'type'          : "select",
135                         'group'         : "quality",
136                         'help'    : "Used to set the clip audio codec. Presently only Vorbis is supported. More about the <a href=\"http://www.vorbis.com//\">vorbis codec</a> "
137                 },
138                 'width': {
139                         't'                     : 'Video Width',
140                         'range'  : {'min':0,'max':1080},
141                         'step'          : 4,
142                         'type'    : 'slider',
143                         'group'  : "quality",
144                         'help'          : "Resize to given width."
145                 },
146                 'height': {
147                         't'                     : 'Video Height',
148                         'range'  : {'min':0,'max':1080},
149                         'step'          : 4,
150                         'type'          : "slider",
151                         'group'         : "quality",
152                         'help'          : "Resize to given height"
153                 },
154                 //advanced Video control configs:
155                 'videoBitrate':{
156                         't'                     : 'Video Bitrate',
157                         'range'         : {'min':1, 'max':16778},
158                         'type'          : "slider",
159                         'group'         : "advVideo",
160                         'help'          : "Video Bitrate sets the encoding bitrate for video in (kb/s)"
161                 } ,
162                 'framerate':{
163                         't'                     : 'Framerate',
164                         'd'                     : '24',
165                         'selectVal'     : ['12', '16', {'24000:1001':'23.97'}, '24', '25', {'30000:1001':'29.97'}, '30'],
166                         'type'             : "select",
167                         'group'         : "advVideo",
168                         'help'             : "The video Framerate. More about <a target=\"_new\" href=\"http://en.wikipedia.org/wiki/Frame_rate\">Framerate</a>"
169                 },
170                 'aspect':{
171                         't'                     : 'Aspect Ratio',
172                         'd'                     : '4:3',
173                         'type'          : "select",
174                         'selectVal'     : ['4:3', '16:9'],
175                         'group'         : "advVideo",
176                         'help'          : "The video aspect ratio can be fraction 4:3 or 16:9. More about <a target=\"_new\" href=\"http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29\">aspect ratios</a>"
177                 },
178                 'keyframeInterval':{
179                         'd'                     : '64',
180                         't'                     : 'Key Frame Interval',
181                         'range'  : {'min':0,'max':65536},
182                         'numberType': 'force keyframe every $1 frames',
183                         'type'           : 'int',
184                         'group'         : 'advVideo',
185                         'help'          : "The keyframe interval in frames. Note: Most codecs force keyframes if the difference between frames is greater than keyframe encode size. More about <a href=\"http://en.wikipedia.org/wiki/I-frame\">keyframes</a>"
186                 },
187                 'denoise':{
188                         'type'          : "boolean",
189                         't'                     : "Denoise Filter",
190                         'group'         : 'advVideo',
191                         'help'          : "Denoise input video. More about <a target=\"_new\" href=\"http://en.wikipedia.org/wiki/Video_denoising\">denoise</a>"
192                 },
193                 'novideo':{
194                         't'                     : "No Video",
195                         'type'          : "boolean",
196                         'group'         : 'advVideo',
197                         'help'          : "disable video in the output"
198                 },
200                 //advanced Audio control Config:
201                 'audioBitrate':{
202                         't'                     : "Audio Bitrate",
203                         'range'         : {'min':32,'max':500},
204                         'numberType': '$1 kbs',
205                         'type'          : 'slider',
206                         'group'         : 'advAudio'
207                 },
208                 'samplerate':{
209                         't'             : "Audio Sample Rate",
210                         'type'          : 'select',
211                         'selectVal'     : [{'22050':'22 kHz'}, {'44100':'44 khz'}, {'48000':'48 khz'}],
212                         'formatSelect'  : function(val){
213                                 return (Math.round(val/100)*10) + ' Hz';
214                         },
215                         'help'          : "set output samplerate (in Hz)."
216                 },
217                 'noaudio':{
218                         't'             : "No Audio",
219                         'type'          : 'boolean',
220                         'group'         : 'advAudio',
221                         'help'          : "disable audio in the output"
222                 },
224                 //meta tags:
225                 'title':{
226                         't'     : "Title",
227                         'type'  : 'string',
228                         'group' : 'meta',
229                         'help'  : "A title for your clip"
230                 },
231                 'artist':{
232                         't'     : "Artist Name",
233                         'type'  : 'string',
234                         'group' : 'meta',
235                         'help'  : "The artist that created this clip"
236                 },
237                 'date':{
238                         't'     : "Date",
239                         'group' : 'meta',
240                         'type'  : 'date',
241                         'help'  : "The date the footage was created or released"
242                 },
243                 'location':{
244                         't'     : "Location",
245                         'type'  : 'string',
246                         'group' : 'meta',
247                         'help'  : "The location of the footage"
248                 },
249                 'organization':{
250                         't'     : "Organization",
251                         'type'  : 'string',
252                         'group' : 'meta',
253                         'help'  : "Name of organization (studio)"
254                 },
255                 'copyright':{
256                         't'     : "Copyright",
257                         'type'  : 'string',
258                         'group' : 'meta',
259                         'help'  : "The Copyright of the clip"
260                 },
261                 'license':{
262                         't'        : "License",
263                         'type'  : 'string',
264                         'group'   : 'meta',
265                         'help'  : "The license of the clip (preferably a creative commons url)"
266                 },
267                 'contact':{
268                         't'     : "Contact",
269                         'type'  : 'string',
270                         'group' : 'meta',
271                         'help'  : "Contact link"
272                 }
273         },
274         init:function( iObj ){
275                 //setup a "supported" iObj:
276                 for(var i in iObj){
277                         if( typeof default_mvAdvFirefogg_config [i] != 'undefined' ){
278                                 this[i] = iObj[i];
279                         }
280                 }
281                 //inherit the base mvFirefogg class:
282                 var myFogg = new mvFirefogg( iObj );
283                 for(var i in myFogg){
284                         if( typeof this[i] != 'undefined'){
285                                 this[ 'basefogg_' + i ] = myFogg[i];
286                         }else{
287                                 this[ i ] = myFogg[i];
288                         }
289                 }
290         },
291         setupForm:function(){
292                 //call base firefogg form setup
293                 basefogg_setupForm();
295                 //gennerate the control html
296                 this.doControlHTML();
298                 //setup control bindings:
299                 this.doControlBindings();
301         },
302         doControlHTML: function(){
303                 js_log("adv doControlHTML");
304                 var _this = this;
305                 //load presets from cookie:
306                 this.loadEncSettings();
308                 //add base control buttons:
309                 this.basefogg_doControlHTML();
311                 //build the config group outpouts
312                 var gdout ='';
313                 $j.each(this.config_groups, function(inx, group_key){
314                         gdout+= '<div> '+
315                                 '<h3><a href="#" class="gd_'+group_key+'" >' + gM('fogg-cg-'+group_key) + '</a></h3>'+
316                                         '<div>';
317                         //output that group control options:
318                         gdout+='<table width="' + ($j(_this.selector).width()-60) + '" ><tr><td width="35%"></td><td width="65%"></td></tr>';
319                         //output the special prset output
320                         if(group_key=='preset'){
321                                 gdout += _this.proccessPresetControl();
322                         }
323                         for(var cK in _this.default_encoder_config){
324                                 var cConf = _this.default_encoder_config[cK];
325                                 if(cConf.group == group_key){
326                                         gdout+= _this.proccessCkControlHTML( cK );
327                                 }
328                         }
329                         gdout+='</table>';
330                         gdout+=         '</div>' +
331                                  '</div>';
333                 });
334                 //add the control container:
335                 if(!this.target_control_container){
336                         this.target_control_container = this.selector + ' .control_container';
337                         //set the target contorl container to height
338                         $j(this.selector).append( '<p><div class="control_container"></div>' );
339                 }
340                 //hide the container and add the output
341                 $j(this.target_control_container).hide();
342                 $j(this.target_control_container).html( gdout );
344         },
345         //custom advanced target rewrites:
346         getTargetHtml:function(target){
347                 if(     target=='target_btn_select_file' ||
348                         target=='target_btn_select_new_file'||
349                         target=='target_btn_save_local_file'){
350                         var icon = (target=='target_btn_save_local_file')?'ui-icon-video':'ui-icon-folder-open';
351                         return   '<a class="ui-state-default ui-corner-all ui-icon_link '+
352                                                 target +'" href="#"><span class="ui-icon ' + icon + '"/>' +
353                                                 gM( 'fogg-' + target.substring(11) ) +
354                                         '</a>';
355                 }else if(  target=='target_btn_select_url'){
356                         //return the btnHtml:
357                         return $j.btnHtml( gM( 'fogg-' + target.substring(11) ), target,  'link');
359                 }else if(       target=='target_use_latest_fox' ||
360                                         target=='target_please_install' ||
361                                         target == 'target_passthrough_mode'){
362                         return '<div style="margin-top:1em;padding: 0pt 0.7em;" class="ui-state-error ui-corner-all ' +
363                                         target + '">' +
364                                         '<p><span style="float: left; margin-right: 0.3em;" class="ui-icon ui-icon-alert"/>'+
365                                         gM( 'fogg-' + target.substring(7)) +'</p>'+
366                                 '</div>';
367                 }else if( target == 'target_input_file_name'){
368                         return '<br><br><input style="" class="text ui-widget-content ui-corner-all ' + target + '" '+
369                                         'type="text" value="' + gM( 'fogg-' + target.substring(11)) + '" size="60" /> ';
370                 }else{
371                         js_log('call : basefogg_getTargetHtml');
372                         return this.basefogg_getTargetHtml(target);
373                 }
374         },
375         proccessPresetControl:function(){
376                 var out='';
377                 var _this = this;
378                 js_log('proccessPresetControl::');
379                 if(typeof this.local_settings.pSet!= 'undefined' ){
380                         out+= '<select class="_preset_select">';
381                         $j.each(this.local_settings.pSet, function(pKey, pSet){
382                                 var pDesc = (pSet.descKey) ? gM(pSet.descKey) : pSet.desc;
383                                 var sel = (_this.local_settings.d == pKey)?' selected':'';
384                                 out+='<option value="'+pKey+'" '+sel+'>'+ pDesc+'</option>';
385                         });
386                         out+='</select>';
387                         }
388                 return out;
389         },
390         proccessCkControlHTML:function( cK ){
391                 var cConf =  this.default_encoder_config[cK];
392                 var out ='';
393                 out+='<tr><td valign="top">'+
394                         '<label for="_' + cK + '">' +
395                          cConf.t + ':' +
396                          '<span title="' + gM('fogg-help-sticky') + '" class="help_'+ cK + ' ui-icon ui-icon-info" style="float:left"></span>'+
397                          '</label></td><td valign="top">';
398                 //if we don't value for this:
399                 var dv = ( this.default_encoder_config[cK].d ) ? this.default_encoder_config[cK].d : '';
400                 //switch on the config type
401                 switch( cConf.type ){
402                         case 'string':
403                         case 'date':
404                         case 'int':
405                         case 'float':
406                                 var size = ( cConf.type =='string' ||cConf.type == 'date' )?'14':'4';
407                                 out+= '<input size="' + size + '" type="text" class="_' + cK + ' text ui-widget-content ui-corner-all" value="' + dv + '" >' ;
408                         break;
409                         case 'boolean':
410                                 var checked_attr = (dv===true)?' checked="true"':'';
411                                 out+='<input type="checkbox" class="_'+cK+ ' ui-widget-content ui-corner-all" ' + checked_attr + '>';
412                         break;
413                         case 'slider':
414                                 var strMax = this.default_encoder_config[ cK ].range.max + '';
415                                 maxdigits = strMax.length +1;
416                                 out+= '<input type="text" maxlength="'+maxdigits+'" size="' +maxdigits + '" '+
417                                         'class="_'+cK+ ' text ui-widget-content ui-corner-all" style="display:inline;border:0; color:#f6931f; font-weight:bold;" ' +
418                                         'value="' + dv + '" >' +
419                                         '<div class="slider_' + cK + '"></div>';
420                         break;
421                         case 'select':
422                                 out+= '<select class="_' + cK + '">'+
423                                                 '<option value=""> </option>';
424                                 for(var i in cConf.selectVal){
425                                         var val = cConf.selectVal[i];
426                                         if(typeof val == 'string'){
427                                                 var sel = (     cConf.selectVal[i] == val)?' selected':'';
428                                                 out+= '<option value="'+val+'"'+sel+'>'+val+'</option>';
429                                         }else if(typeof val == 'object'){
430                                                 for(var key in val){
431                                                         hr_val = val[key];
432                                                 }
433                                                 var sel = ( cConf.selectVal[i] == key )?' selected':'';
435                                                 out+= '<option value="'+key+'"'+sel+'>'+hr_val+'</option>';
436                                         }
437                                 }
438                                 out+='</select>';
439                         break;
440                 }
441                 //output the help row:
442                 if(cConf.help){
443                         out+='<div class="helpRow_' + cK + '">'+
444                                         '<span class="helpClose_' + cK + ' ui-icon ui-icon-circle-close" '+
445                                         'title="Close Help"'+
446                                         'style="float:left"/>'+
447                                  cConf.help +
448                                  '</div>';
449                 }
450                 out+='</td></tr><tr><td colspan="2" height="10"></td></tr>';
451                 return out;
452         },
453         selectByUrl:function(){
454                 var urlValue = prompt("Please enter the source media url you would like to transcode from.","http://");
455                 if( urlValue ){
456                         //update the mode:
457                         this.sourceMode = 'url';
458                         this.sourceUrl = urlValue;
459                         this.selectFoggActions();
460                         this.autoEncoderSettings();
461                         //update the input target
462                         $j(this.target_input_file_name).unbind().val( urlValue ).removeAttr('readonly');
463                 }
464         },
465         doControlBindings:function(){
466                 var _this = this;
467                 _this.basefogg_doControlBindings();
468                 //show the select by url if present:
469                 /*$j( this.target_btn_select_url ).unbind(
470                         ).attr('disabled', false
471                         ).css({'display':'inline'}
472                         ).click(function(){
473                                 _this.selectByUrl();
474                 });
475                 */
478                 //hide the base advanced controls untill a file is selected:
479                 $j(this.target_control_container).hide();
481                 var helpState = {};
482                 //do some display tweeks:
483                 js_log('tw:' + $j(this.selector).width() +
484                                 'ssf:' + $j(this.target_btn_select_new_file).width() +
485                                 'sf:' +  $j(this.target_btn_save_local_file).width() );
487                 //set width to 250
488                 $j(this.target_input_file_name).width( 250 );
490                 //special preset action:
491                 $j(this.selector + ' ._preset_select').change(function(){
492                         _this.updatePresetSelection( $j(this).val() );
493                 });
495                 //bind control actions
496                 for(var cK in this.default_encoder_config){
497                         var cConf =  this.default_encoder_config[cK];
498                         //set up the help for all types:
499                         if(cConf.help){
500                                 //initial state is hidden:
501                                 $j( this.selector + ' .helpRow_' + cK).hide();
502                                 $j(this.selector + ' .help_' + cK).click(function(){
503                                         //get the ckId (assume its the last class)
504                                         var cK = _this.getClassId(this, 'help_');
506                                         if(helpState[cK]){
507                                                 $j(_this.selector + ' .helpRow_' + cK).hide('slow');
508                                                 helpState[cK] = false;
509                                         }else{
510                                                 $j(_this.selector + ' .helpRow_' + cK).show('slow');
511                                                 helpState[cK] = true;
512                                         }
513                                         return false;
514                                 }).hover(
515                                         function(){
516                                                 //get the ckId (assume its the last class)
517                                                 var cK = _this.getClassId(this, 'help_');
518                                                 $j( _this.selector + ' .helpRow_' + cK).show('slow');
519                                         },function(){
520                                                 var cK = _this.getClassId(this, 'help_');
521                                                 if(!helpState[cK])
522                                                         $j( _this.selector + ' .helpRow_' + cK).hide('slow')
523                                         }
524                                 );
525                                 $j( _this.selector + ' .helpClose_' + cK).click(function(){
526                                         js_log("close help: " +cK);
527                                         //get the ckId (assume its the last class)
528                                         var cK = _this.getClassId(this, 'helpClose_');
529                                         $j(_this.selector + ' .helpRow_' + cK).hide('slow');
530                                         helpState[cK] = false;
531                                         return false;
532                                 }).css('cursor', 'pointer');
533                         }else{
534                                 $j(this.selector + ' .help_' + cK).hide();
535                         }
537                         //setup bindings for change values: (validate input)
539                         switch( cConf.type ){
540                                 case 'boolean':
541                                         $j(_this.selector + ' ._'+cK).click(function(){
542                                                 _this.updateLocalValue(  _this.getClassId(this), $j(this).is(":checked") );
543                                                 _this.updatePresetSelection('custom');
544                                         })
545                                 break;
546                                 case 'select':
547                                 case 'string':
548                                 case 'int':
549                                 case 'float':
550                                         //@@check if we have a validate function on the string
551                                         $j(_this.selector + ' ._'+cK).change(function(){
552                                                 $j(this).val( _this.updateLocalValue(
553                                                         _this.getClassId(this),
554                                                         $j(this).val() ));
555                                                 _this.updatePresetSelection('custom');
556                                         })
557                                 break;
558                                 case 'date':
559                                         $j(_this.selector + ' ._'+cK).datepicker({
560                                                         changeMonth: true,
561                                                         changeYear: true,
562                                                         dateFormat: 'd MM, yy',
563                                                         onSelect: function(dateText) {
564                                                                 _this.updateInterfaceValue(_this.getClassId(this), dateText);
565                                                         }
566                                         });
567                                 break;
568                                 case 'slider':
569                                         $j(this.selector + ' .slider_' + cK ).slider({
570                                                 range: "min",
571                                                 animate: true,
572                                                 step: (cConf.step)?cConf.step:1,
573                                                 value: $j( this.selector +' ._' + cK ).val(),
574                                                 min: this.default_encoder_config[ cK ].range.min,
575                                                 max: this.default_encoder_config[ cK ].range.max,
576                                                 slide: function(event, ui) {
577                                                         $j( _this.selector + ' ._' + _this.getClassId(this, 'slider_') ).val( ui.value );
579                                                         //maintain source video aspect ratio:
580                                                         if(_this.getClassId(this, 'slider_') == 'width'){
581                                                                 var hv = parseInt((_this.sourceFileInfo.video[0]['height']/_this.sourceFileInfo.video[0]['width'])* ui.value );
582                                                                 //update the height value:        the new hight value is > that orginal the slider:
583                                                                 if(hv > _this.updateInterfaceValue('height', hv))
584                                                                         return false;
585                                                         }
586                                                         if(_this.getClassId(this, 'slider_') == 'height'){
587                                                                 var wv = parseInt((_this.sourceFileInfo.video[0]['width']/_this.sourceFileInfo.video[0]['height'])* ui.value );
588                                                                 //update the height value:        the new hight value is > that orginal the slider:
589                                                                 if(wv > _this.updateInterfaceValue('width', wv))
590                                                                         return false;
591                                                         }
592                                                 },
593                                                 change: function(event, ui){
594                                                         //update the local settings
595                                                         _this.updateLocalValue( _this.getClassId(this, 'slider_'), ui.value);
596                                                         _this.updatePresetSelection('custom');
597                                                 }
598                                         })
599                                         $j( this.selector +' ._' + cK).change(function(){
600                                                 var scid = _this.getClassId(this);
601                                                 var valdVal = _this.updateLocalValue(scid.substr(1),$j(this).val() );
602                                                 _this.updatePresetSelection('custom');
603                                                 //(validate user form input)
604                                                 $j(this).val(valdVal);
605                                                 //update the slider
606                                                 js_log("update: " + _this.selector + ' .slider' + scid);
607                                                 $j(_this.selector + ' .slider'+ scid).slider('option', 'value', valdVal );
608                                         });
609                                 break
610                         }
611                 }
612                 $j(this.target_control_container).accordion({
613                         header: "h3",
614                         collapsible: true,
615                         active: false,
616                         fillSpace: true
617                 });
619                 //do config value updates if any
620                 this.updateValuesInHtml();
621         },
622         updatePresetSelection:function( pKey ){
623                 //update the local key:
624                 this.local_settings.d = pKey;
625                  //js_log('update preset desc: '+ pKey);
626                 var pset_desc = '';
627                 if(this.local_settings.pSet[ pKey  ].desc){
628                         pset_desc = this.local_settings.pSet[ pKey  ].desc;
629                 }else{
630                         pset_desc = gM('fogg-preset-'+ pKey);
631                 }
632                 //update the preset title:
633                 $j( this.selector + ' .gd_preset' ).html(
634                         gM('fogg-cg-preset', pset_desc)
635                 );
636                 //update the selector
637                 $j(this.selector + ' ._preset_select').val(pKey);
638         },
639         /*
640          * updates the interface
641          */
642         updateInterfaceValue:function(confKey, val){
643                 var _this = this;
644                 if(!val){
645                         return ;
646                 }
647                 //js_log('updateInterfaceValue:: ' + confKey + ' v:' + val + ' cv:'+ _this.selector + '._'+ confKey+' len:' + $j(_this.selector + ' ._'+confKey).length );
648                 //lookup the type
649                 if(typeof this.default_encoder_config[confKey] == 'undefined'){
650                         js_error('error: missing default key: '+ confKey);
651                         return false;
652                 }
654                 //update the local value (if not already up-to-date
655                 if( this.local_settings.pSet['custom']['conf'][confKey] != val ){
656                         val = this.updateLocalValue(confKey, val);
657                 }
658                 //update the text filed:
659                 $j(_this.selector + ' ._'+confKey).val( val );
660                 //update the interaface widget:
661                 switch(this.default_encoder_config[confKey].type){
662                         case 'slider':
663                                 $j(_this.selector + ' .slider_' + confKey).slider('option',
664                                                 'value', $j(_this.selector + ' ._'+ confKey).val() );
665                         break;
666                 }
667                 return val;
668         },
669         updateLocalValue:function(confKey, value){
670                 //update the local value (return the value we acutally set)
671                 if(typeof this.default_encoder_config[confKey] == 'undefined'){
672                   js_log("Error:could not update conf key:" + confKey)
673                   return value;
674                 }
675                 dec = this.default_encoder_config[confKey];
676                 if(dec.range){
677                         value = parseInt(value);
678                         var min = ( dec.range.local_min) ? dec.range.local_min  :dec.range.min;
679                         if(value < min)
680                                 value = min;
681                         var max = ( dec.range.local_max) ? dec.range.local_max : dec.range.max
682                         if(value > max)
683                                 value = max;
684                 }
685                 if(dec.type=='int')
686                         value = parseInt(value);
688                 //step value:
689                 /*if(dec.step){
690                         if((value % dec.step)!=0){
691                                 value = value - (value % dec.step);
692                         }
693                 }*/
695                 js_log('update:local_settings:custom:conf:'+ confKey + ' = ' + value);
696                 this.local_settings.pSet['custom']['conf'][confKey] = value;
698                 return value;
699         },
700         getLocalValue:function(confKey){
701                 return this.local_settings.pSet['custom']['conf'][confKey];
702         },
703         getClassId:function(elm, rmstr){
704                 var elmclass = $j(elm).attr("class").split(' ').slice(0,1).toString();
705                 if(rmstr){
706                         return elmclass.replace( rmstr, '' );
707                 }else{
708                         //strip leading underscore:
709                         return (elmclass[0]=='_')?elmclass.substr(1):elmclass;
710                 }
711         },
712         /*
713          * sets up the autoEncoder settings
714          */
715         autoEncoderSettings:function(){
716                 var _this = this;
717                 //do the base encoder settings setup:
718                 this.basefogg_autoEncoderSettings();
719                 //make sure we are "encoding" if not display not a video file eror:
720                 if( this.encoder_settings['passthrough'] ){
721                         js_log("in passthrough mode (hide control)");
722                         //hide all controls
723                         //dispaly not encodable video
724                         $j(this.target_control_container).hide('slow');
725                         $j(this.target_passthrough_mode).show('slow');
726                         return ;
727                 }
728                 //restore display:
729                 $j(this.target_control_container).show('slow');
730                 $j(this.target_passthrough_mode).hide('slow');
732                 //do setup settings based on local_settings /default_encoder_config with sourceFileInfo
733                 //see: http://firefogg.org/dev/sourceInfo_example.html
734                 var setValues = function(k, val, maxVal) {
735                         if( k !== false){
736                                 //update the value if unset:
737                                 _this.updateLocalValue(k, val);
738                         }
739                         if( maxVal ){
740                                  //update the local range:
741                                 if(_this.default_encoder_config[k].range){
742                                         _this.default_encoder_config[k].range.local_max = maxVal;
743                                 }
744                         }
745                 }
746                 //container level settings
747                 for(var i in this.sourceFileInfo){
748                         var val = this.sourceFileInfo[i];
749                         var k = false;
750                         var maxVal= false;
751                         switch(i){
752                                 //do nothing with these:
753                                 case 'bitrate':
754                                         k = 'videoBitrate';
755                                         maxVal = (val*2 > this.default_encoder_config[k])?this.default_encoder_config[k]:val*2;
756                                 break;
757                         }
758                         setValues(k, val, maxVal);
759                 }
760                 //video stream settings
761                 for(var i in this.sourceFileInfo.video[0]){
762                         var val = this.sourceFileInfo.video[0][i];
763                         var k = false;
764                         var maxVal= false;
765                         switch(i){
766                                 case 'width':
767                                 case 'height':
768                                         k = i;
769                                         maxVal = val;
770                                 break;
771                         }
772                         setValues(k, val, maxVal);
773                 }
774                 //audio stream settings, assumes for now thare is only one stream
775                 for(var i in this.sourceFileInfo.audio[0]){
776                         var val = this.sourceFileInfo.audio[0][i];
777                         var k = false;
778                         var maxVal= false;
779                         switch(i){
780                                 case 'bitrate':
781                                         k = 'audioBitrate';
782                                         maxVal = (val*2 > this.default_encoder_config[k])?this.default_encoder_config[k]:val*2;
783                                 break;
784                         }
785                         setValues(k, val, maxVal);
786                 }
788                 //set all values to new default ranges & update slider:
789                 $j.each(this.default_encoder_config, function(inx, val){
790                         if($j(_this.selector + ' ._'+inx).length!=0){
791                                 if(typeof val.range != 'undefined'){
792                                         //udate slider range
793                                         var new_max = (val.range.local_max)?val.range.local_max: val.range.max
794                                         $j( _this.selector + ' .slider_'+inx).slider('option', 'max', new_max);
796                                         //update slider/input value:
797                                         _this.updateInterfaceValue(inx, _this.local_settings.pSet['custom']['conf'][inx]);
798                                 }
799                         }
800                 });
801                 //update values
802                 this.updateValuesInHtml();
803         },
804         doEncode:function(){
805                 //update the encoder settings (from local settings)
806                 pKey = this.local_settings.d;
807                 this.encoder_settings = this.local_settings.pSet[ pKey ].conf;
808                 this.basefogg_doEncode();
809         },
810         updateValuesInHtml:function(){
811                 js_log('updateValuesInHtml::');
812                 var _this = this;
813                 var pKey = this.local_settings.d;
814                 this.updatePresetSelection( pKey );
816                 //set the actual HTML & widgets based on any local settings values:
817                 $j.each(_this.local_settings.pSet['custom']['conf'], function(inx, val){
818                         if($j(_this.selector + ' ._'+inx).length !=0){
819                                 $j(_this.selector + ' ._'+inx).val( val );
820                         }
821                 });
822         },
823         //restors settings from a cookie if you have them)
824         loadEncSettings:function( force ){
825                 if($j.cookie('fogg_encoder_config')){
826                         js_log("load:fogg_encoder_config from cookie ");
827                         this.local_settings = JSON.parse( $j.cookie('fogg_settings') );
828                 }
829                 //set to default if not loaded yet:
830                 if( this.local_settings &&  this.local_settings.pSet && this.local_settings.pSet['custom']['conf']){
831                         js_log('local settings already populated');
832                 }else{
833                         this.local_settings  = this.default_local_settings;
834                 }
836         },
837         //clear preset settings:
838         clearSettings:function(force){
840         },
841         //save settings to the cookie
842         saveEncSettings:function(){
843                 $j.cookie('fogg_settings', JSON.stringify( this.local_settings ) );
844         }