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