OSDN Git Service

MacGui: adds x264 option widgets for b-rdo, weight, and b-pyramid. And a little layou...
[handbrake-jp/handbrake-jp-git.git] / macosx / Controller.mm
1 /* $Id: Controller.mm,v 1.79 2005/11/04 19:41:32 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.m0k.org/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "Controller.h"
8 #include "a52dec/a52.h"
9
10 #define _(a) NSLocalizedString(a,NULL)
11
12
13
14
15
16 static int FormatSettings[3][4] =
17   { { HB_MUX_MP4 | HB_VCODEC_FFMPEG | HB_ACODEC_FAAC,
18       HB_MUX_MP4 | HB_VCODEC_X264   | HB_ACODEC_FAAC,
19       0,
20       0 },
21     { HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
22       HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_AC3,
23       HB_MUX_AVI | HB_VCODEC_X264   | HB_ACODEC_LAME,
24       HB_MUX_AVI | HB_VCODEC_X264   | HB_ACODEC_AC3 },
25     { HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_VORBIS,
26       HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
27       0,
28       0 } };
29
30 /*******************************
31  * HBController implementation *
32  *******************************/
33 @implementation HBController
34
35 - init
36 {
37     self    = [super init];
38     fHandle = NULL;
39     return self;
40 }
41
42 - (void) applicationDidFinishLaunching: (NSNotification *) notification
43 {
44
45
46     int    build;
47     char * version;
48
49
50     /* Init libhb */
51     fHandle = hb_init( HB_DEBUG_NONE, [[NSUserDefaults
52         standardUserDefaults] boolForKey:@"CheckForUpdates"] );
53         /* Set the Growl Delegate */
54         HBController *hbGrowlDelegate = [[HBController alloc] init];
55         [GrowlApplicationBridge setGrowlDelegate: hbGrowlDelegate];    
56     /* Init others controllers */
57     [fScanController    SetHandle: fHandle];
58     [fPictureController SetHandle: fHandle];
59     [fQueueController   SetHandle: fHandle];
60         
61     fChapterTitlesDelegate = [[ChapterTitles alloc] init];
62     [fChapterTable setDataSource:fChapterTitlesDelegate];
63
64      /* Call UpdateUI every 2/10 sec */
65     [[NSRunLoop currentRunLoop] addTimer: [NSTimer
66         scheduledTimerWithTimeInterval: 0.2 target: self
67         selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
68         forMode: NSModalPanelRunLoopMode];
69
70     if( ( build = hb_check_update( fHandle, &version ) ) > -1 )
71     {
72         /* Update available - tell the user */
73         
74         NSBeginInformationalAlertSheet( _( @"Update is available" ),
75             _( @"Go get it!" ), _( @"Discard" ), NULL, fWindow, self,
76             @selector( UpdateAlertDone:returnCode:contextInfo: ),
77             NULL, NULL, [NSString stringWithFormat:
78             _( @"HandBrake %s (build %d) is now available for download." ),
79             version, build] );
80         return;
81
82     }
83
84     /* Show scan panel ASAP */
85     [self performSelectorOnMainThread: @selector(ShowScanPanel:)
86         withObject: NULL waitUntilDone: NO];
87 }
88
89 - (NSApplicationTerminateReply) applicationShouldTerminate:
90     (NSApplication *) app
91 {
92     if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
93     {
94         [self Cancel: NULL];
95         return NSTerminateCancel;
96     }
97     
98     /* Clean up */
99     hb_close( &fHandle );
100     return NSTerminateNow;
101 }
102
103 - (void) awakeFromNib
104 {
105     [fWindow center];
106
107     [self TranslateStrings];
108
109
110 //[self registrationDictionaryForGrowl];
111 /* Init User Presets .plist */
112         /* We declare the default NSFileManager into fileManager */
113         NSFileManager * fileManager = [NSFileManager defaultManager];
114         //presetPrefs = [[NSUserDefaults standardUserDefaults] retain];
115         /* we set the files and support paths here */
116         AppSupportDirectory = @"~/Library/Application Support/HandBrake";
117     AppSupportDirectory = [AppSupportDirectory stringByExpandingTildeInPath];
118     
119         UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
120     UserPresetsFile = [UserPresetsFile stringByExpandingTildeInPath];
121         
122         x264ProfilesFile = @"~/Library/Application Support/HandBrake/x264Profiles.plist";
123     x264ProfilesFile = [x264ProfilesFile stringByExpandingTildeInPath];
124         /* We check for the app support directory for media fork */
125         if ([fileManager fileExistsAtPath:AppSupportDirectory] == 0) 
126         {
127                 // If it doesnt exist yet, we create it here 
128                 [fileManager createDirectoryAtPath:AppSupportDirectory attributes:nil];
129         }
130         // We check for the presets.plist here
131         
132         if ([fileManager fileExistsAtPath:UserPresetsFile] == 0) 
133         {
134
135                 [fileManager createFileAtPath:UserPresetsFile contents:nil attributes:nil];
136                 
137         }
138         // We check for the x264profiles.plist here
139          
140         if ([fileManager fileExistsAtPath:x264ProfilesFile] == 0) 
141         {
142         
143                 [fileManager createFileAtPath:x264ProfilesFile contents:nil attributes:nil];
144         }
145     
146         
147   UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
148   UserPresetsFile = [[UserPresetsFile stringByExpandingTildeInPath]retain];
149
150   UserPresets = [[NSMutableArray alloc] initWithContentsOfFile:UserPresetsFile];
151   if (nil == UserPresets) 
152   {
153     UserPresets = [[NSMutableArray alloc] init];
154         [self AddFactoryPresets:NULL];
155   }
156   /* Show/Dont Show Presets drawer upon launch based
157   on user preference DefaultPresetsDrawerShow*/
158   if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0)
159                 {
160           [fPresetDrawer open];
161                 }
162
163
164
165     /* Destination box*/
166     [fDstFormatPopUp removeAllItems];
167     [fDstFormatPopUp addItemWithTitle: _( @"MP4 file" )];
168     [fDstFormatPopUp addItemWithTitle: _( @"AVI file" )];
169     [fDstFormatPopUp addItemWithTitle: _( @"OGM file" )];
170     [fDstFormatPopUp selectItemAtIndex: 0];
171
172     [self FormatPopUpChanged: NULL];
173     /* We enable the create chapters checkbox here since we are .mp4 */ 
174         [fCreateChapterMarkers setEnabled: YES];
175         if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultChapterMarkers"] > 0)
176         {
177                 [fCreateChapterMarkers setState: NSOnState];
178         }
179     [fDstFile2Field setStringValue: [NSString stringWithFormat:
180         @"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
181
182     /* Video encoder */
183     [fVidEncoderPopUp removeAllItems];
184     [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
185     [fVidEncoderPopUp addItemWithTitle: @"XviD"];
186
187     /* Video quality */
188     [fVidTargetSizeField setIntValue: 700];
189         [fVidBitrateField    setIntValue: 1000];
190
191     [fVidQualityMatrix   selectCell: fVidBitrateCell];
192     [self VideoMatrixChanged: NULL];
193
194     /* Video framerate */
195     [fVidRatePopUp removeAllItems];
196         [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
197     for( int i = 0; i < hb_video_rates_count; i++ )
198     {
199         [fVidRatePopUp addItemWithTitle:
200             [NSString stringWithCString: hb_video_rates[i].string]];
201     }
202     [fVidRatePopUp selectItemAtIndex: 0];
203         
204         /* Picture Settings */
205         [fPicLabelPAROutp setStringValue: @""];
206         [fPicLabelPAROutputX setStringValue: @""];
207         [fPicSettingPARWidth setStringValue: @""];
208         [fPicSettingPARHeight setStringValue:  @""];
209         
210     /* Audio bitrate */
211     [fAudBitratePopUp removeAllItems];
212     for( int i = 0; i < hb_audio_bitrates_count; i++ )
213     {
214         [fAudBitratePopUp addItemWithTitle:
215             [NSString stringWithCString: hb_audio_bitrates[i].string]];
216     }
217     [fAudBitratePopUp selectItemAtIndex: hb_audio_bitrates_default];
218
219     /* Audio samplerate */
220     [fAudRatePopUp removeAllItems];
221     for( int i = 0; i < hb_audio_rates_count; i++ )
222     {
223         [fAudRatePopUp addItemWithTitle:
224             [NSString stringWithCString: hb_audio_rates[i].string]];
225     }
226     [fAudRatePopUp selectItemAtIndex: hb_audio_rates_default];
227
228     /* Bottom */
229     [fStatusField setStringValue: @""];
230
231     [self EnableUI: NO];
232     [fPauseButton setEnabled: NO];
233     [fRipButton setEnabled: NO];
234
235
236
237 }
238
239 // register a test notification and make
240 // it enabled by default
241 #define SERVICE_NAME @"Encode Done"
242 - (NSDictionary *)registrationDictionaryForGrowl 
243
244 NSDictionary *registrationDictionary = [NSDictionary dictionaryWithObjectsAndKeys: 
245 [NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_ALL, 
246 [NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_DEFAULT, 
247 nil]; 
248
249 return registrationDictionary; 
250
251 - (void) TranslateStrings
252 {
253     [fSrcDVD1Field      setStringValue: _( @"DVD:" )];
254     [fSrcTitleField     setStringValue: _( @"Title:" )];
255     [fSrcChapterField   setStringValue: _( @"Chapters:" )];
256     [fSrcChapterToField setStringValue: _( @"to" )];
257     [fSrcDuration1Field setStringValue: _( @"Duration:" )];
258
259     [fDstFormatField    setStringValue: _( @"File format:" )];
260     [fDstCodecsField    setStringValue: _( @"Codecs:" )];
261     [fDstFile1Field     setStringValue: _( @"File:" )];
262     [fDstBrowseButton   setTitle:       _( @"Browse" )];
263
264     [fVidRateField      setStringValue: _( @"Framerate (fps):" )];
265     [fVidEncoderField   setStringValue: _( @"Encoder:" )];
266     [fVidQualityField   setStringValue: _( @"Quality:" )];
267 }
268
269 /***********************************************************************
270  * UpdateDockIcon
271  ***********************************************************************
272  * Shows a progression bar on the dock icon, filled according to
273  * 'progress' (0.0 <= progress <= 1.0).
274  * Called with progress < 0.0 or progress > 1.0, restores the original
275  * icon.
276  **********************************************************************/
277 - (void) UpdateDockIcon: (float) progress
278 {
279     NSImage * icon;
280     NSData * tiff;
281     NSBitmapImageRep * bmp;
282     uint32_t * pen;
283     uint32_t black = htonl( 0x000000FF );
284     uint32_t red   = htonl( 0xFF0000FF );
285     uint32_t white = htonl( 0xFFFFFFFF );
286     int row_start, row_end;
287     int i, j;
288
289     /* Get application original icon */
290     icon = [NSImage imageNamed: @"NSApplicationIcon"];
291
292     if( progress < 0.0 || progress > 1.0 )
293     {
294         [NSApp setApplicationIconImage: icon];
295         return;
296     }
297
298     /* Get it in a raw bitmap form */
299     tiff = [icon TIFFRepresentationUsingCompression:
300             NSTIFFCompressionNone factor: 1.0];
301     bmp = [NSBitmapImageRep imageRepWithData: tiff];
302     
303     /* Draw the progression bar */
304     /* It's pretty simple (ugly?) now, but I'm no designer */
305
306     row_start = 3 * (int) [bmp size].height / 4;
307     row_end   = 7 * (int) [bmp size].height / 8;
308
309     for( i = row_start; i < row_start + 2; i++ )
310     {
311         pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
312         for( j = 0; j < (int) [bmp size].width; j++ )
313         {
314             pen[j] = black;
315         }
316     }
317     for( i = row_start + 2; i < row_end - 2; i++ )
318     {
319         pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
320         pen[0] = black;
321         pen[1] = black;
322         for( j = 2; j < (int) [bmp size].width - 2; j++ )
323         {
324             if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) )
325             {
326                 pen[j] = red;
327             }
328             else
329             {
330                 pen[j] = white;
331             }
332         }
333         pen[j]   = black;
334         pen[j+1] = black;
335     }
336     for( i = row_end - 2; i < row_end; i++ )
337     {
338         pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
339         for( j = 0; j < (int) [bmp size].width; j++ )
340         {
341             pen[j] = black;
342         }
343     }
344
345     /* Now update the dock icon */
346     tiff = [bmp TIFFRepresentationUsingCompression:
347             NSTIFFCompressionNone factor: 1.0];
348     icon = [[NSImage alloc] initWithData: tiff];
349     [NSApp setApplicationIconImage: icon];
350     [icon release];
351 }
352
353 - (void) UpdateUI: (NSTimer *) timer
354 {
355
356     hb_state_t s;
357     hb_get_state( fHandle, &s );
358
359     switch( s.state )
360     {
361         case HB_STATE_IDLE:
362             break;
363
364         case HB_STATE_SCANNING:
365             [fScanController UpdateUI: &s];
366             break;
367
368 #define p s.param.scandone
369         case HB_STATE_SCANDONE:
370         {
371             hb_list_t  * list;
372             hb_title_t * title;
373                         int indxpri=0;    // Used to search the longuest title (default in combobox)
374                         int longuestpri=0; // Used to search the longuest title (default in combobox)
375
376             [fScanController UpdateUI: &s];
377
378             list = hb_get_titles( fHandle );
379
380             if( !hb_list_count( list ) )
381             {
382                 break;
383             }
384
385
386             [fSrcTitlePopUp removeAllItems];
387             for( int i = 0; i < hb_list_count( list ); i++ )
388             {
389                 title = (hb_title_t *) hb_list_item( list, i );
390                 /*Set DVD Name at top of window*/
391                                 [fSrcDVD2Field setStringValue: [NSString
392                   stringWithUTF8String: title->name]];  
393                                 
394                                 /* Use the dvd name in the default output field here 
395                                 May want to add code to remove blank spaces for some dvd names*/
396                                 /* Check to see if the last destination has been set,use if so, if not, use Desktop */
397                                 if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"])
398                                 {
399                                 [fDstFile2Field setStringValue: [NSString stringWithFormat:
400                 @"%@/%@.mp4", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[NSString
401                   stringWithUTF8String: title->name]]];
402                                 }
403                                 else
404                                 {
405                                 [fDstFile2Field setStringValue: [NSString stringWithFormat:
406                 @"%@/Desktop/%@.mp4", NSHomeDirectory(),[NSString
407                   stringWithUTF8String: title->name]]];
408                                 }
409
410                   
411                 if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds)
412                 {
413                         longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds;
414                         indxpri=i;
415                 }
416                 
417                                 
418                 int format = [fDstFormatPopUp indexOfSelectedItem];
419                                 char * ext = NULL;
420                                 switch( format )
421                 {
422                  case 0:
423                                          
424                                          /*Get Default MP4 File Extension for mpeg4 (.mp4 or .m4v) from prefs*/
425                                          if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
426                                          {
427                                          ext = "m4v";
428                                          }
429                                      else
430                                      {
431                                          ext = "mp4";
432                                          }
433                                         break;
434                                 case 1: 
435                      ext = "avi";
436                      break;
437                                 case 2:
438                      ext = "ogm";
439                                  break;
440                                    }
441                                 
442                                 
443                                 NSString * string = [fDstFile2Field stringValue];
444                                 /* Add/replace File Output name to the correct extension*/
445                                 if( [string characterAtIndex: [string length] - 4] == '.' )
446                                 {
447                                         [fDstFile2Field setStringValue: [NSString stringWithFormat:
448                                                 @"%@.%s", [string substringToIndex: [string length] - 4],
449                                                 ext]];
450                                 }
451                                 else
452                                 {
453                                         [fDstFile2Field setStringValue: [NSString stringWithFormat:
454                                                 @"%@.%s", string, ext]];
455                                 }
456
457                                 
458                             [fSrcTitlePopUp addItemWithTitle: [NSString
459                     stringWithFormat: @"%d - %02dh%02dm%02ds",
460                     title->index, title->hours, title->minutes,
461                     title->seconds]];
462                         
463             }
464             // Select the longuest title
465                         [fSrcTitlePopUp selectItemAtIndex: indxpri];
466             /* We set the Settings Display to "Default" here
467                         until we get default presets implemented */
468                         [fPresetSelectedDisplay setStringValue: @"Default"];
469                         
470             [self TitlePopUpChanged: NULL];
471             [self EnableUI: YES];
472             [fPauseButton setEnabled: NO];
473             [fRipButton   setEnabled: YES];
474             break;
475         }
476 #undef p
477
478 #define p s.param.working
479         case HB_STATE_WORKING:
480         {
481             float progress_total;
482             NSMutableString * string;
483
484             /* Update text field */
485             string = [NSMutableString stringWithFormat:
486                 _( @"Encoding: task %d of %d, %.2f %%" ),
487                 p.job_cur, p.job_count, 100.0 * p.progress];
488             if( p.seconds > -1 )
489             {
490                 [string appendFormat:
491                     _( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)" ),
492                     p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds];
493             }
494             [fStatusField setStringValue: string];
495
496             /* Update slider */
497             progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
498             [fRipIndicator setIndeterminate: NO];
499             [fRipIndicator setDoubleValue: 100.0 * progress_total];
500
501             /* Update dock icon */
502             [self UpdateDockIcon: progress_total];
503
504             [fPauseButton setEnabled: YES];
505             [fPauseButton setTitle: _( @"Pause" )];
506             [fRipButton setEnabled: YES];
507             [fRipButton setTitle: _( @"Cancel" )];
508             break;
509         }
510 #undef p
511
512 #define p s.param.muxing
513         case HB_STATE_MUXING:
514         {
515             NSMutableString * string;
516                         
517             /* Update text field */
518             string = [NSMutableString stringWithFormat:
519                 _( @"Muxing..." )];
520             [fStatusField setStringValue: string];
521                         
522             /* Update slider */
523             [fRipIndicator setIndeterminate: YES];
524             [fRipIndicator startAnimation: nil];
525                         
526             /* Update dock icon */
527             [self UpdateDockIcon: 1.0];
528                         
529             [fPauseButton setEnabled: YES];
530             [fPauseButton setTitle: _( @"Pause" )];
531             [fRipButton setEnabled: YES];
532             [fRipButton setTitle: _( @"Cancel" )];
533             break;
534         }
535 #undef p
536                         
537         case HB_STATE_PAUSED:
538                     [fStatusField setStringValue: _( @"Paused" )];
539             [fPauseButton setEnabled: YES];
540             [fPauseButton setTitle: _( @"Resume" )];
541             [fRipButton setEnabled: YES];
542             [fRipButton setTitle: _( @"Cancel" )];
543             break;
544
545         case HB_STATE_WORKDONE:
546         {
547             //[self EnableUI: YES];
548             [fStatusField setStringValue: _( @"Done." )];
549             [fRipIndicator setIndeterminate: NO];
550             [fRipIndicator setDoubleValue: 0.0];
551             [fRipButton setTitle: _( @"Start" )];
552                         
553             /* Restore dock icon */
554             [self UpdateDockIcon: -1.0];
555                         
556             [fPauseButton setEnabled: NO];
557             [fPauseButton setTitle: _( @"Pause" )];
558             [fRipButton setEnabled: YES];
559             [fRipButton setTitle: _( @"Start" )];
560                         
561             /* FIXME */
562             hb_job_t * job;
563             while( ( job = hb_job( fHandle, 0 ) ) )
564             {
565                 hb_rem( fHandle, job );
566             }
567             
568                         if (fEncodeState != 2) // if the encode has not been cancelled
569                         {
570                                 /* Lets alert the user that the encode has finished */
571                                 /*Growl Notification*/
572                                 [self showGrowlDoneNotification: NULL];
573                                 /*On Screen Notification*/
574                                 int status;
575                                 NSBeep();
576                                 status = NSRunAlertPanel(@"Put down that cocktail...",@"your HandBrake encode is done!", @"OK", nil, nil);
577                                 //[NSApp requestUserAttention:NSInformationalRequest];
578                                 [NSApp requestUserAttention:NSCriticalRequest];
579                                 if ( status == NSAlertDefaultReturn ) 
580                                 {
581                                         [self EnableUI: YES];
582                                 }
583                         }
584                         else
585                         {
586                         [self EnableUI: YES];
587                         }
588             break;
589         }
590     }
591
592     /* Lets show the queue status
593         here in the main window*/
594
595         int count = hb_count( fHandle );
596         if( count )
597         {
598             [fQueueStatus setStringValue: [NSString stringWithFormat:
599                 @"%d task%s in the queue",
600                 count, ( count > 1 ) ? "s" : ""]];
601         }
602         else
603         {
604             [fQueueStatus setStringValue: @""];
605         }
606
607     [[NSRunLoop currentRunLoop] addTimer: [NSTimer
608         scheduledTimerWithTimeInterval: 0.2 target: self
609         selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
610         forMode: NSModalPanelRunLoopMode];
611 }
612
613 -(IBAction)showGrowlDoneNotification:(id)sender
614 {
615
616   
617   [GrowlApplicationBridge 
618           notifyWithTitle:@"Put down that cocktail..." 
619               description:@"your HandBrake encode is done!" 
620          notificationName:SERVICE_NAME
621                  iconData:nil 
622                  priority:0 
623                  isSticky:1 
624              clickContext:nil];
625 }
626
627 - (void) EnableUI: (bool) b
628 {
629     NSControl * controls[] =
630       { fSrcDVD1Field, fSrcDVD2Field, fSrcTitleField, fSrcTitlePopUp,
631         fSrcChapterField, fSrcChapterStartPopUp, fSrcChapterToField,
632         fSrcChapterEndPopUp, fSrcDuration1Field, fSrcDuration2Field,
633         fDstFormatField, fDstFormatPopUp, fDstCodecsField,
634         fDstCodecsPopUp, fDstFile1Field, fDstFile2Field,
635         fDstBrowseButton, fVidRateField, fVidRatePopUp,
636         fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
637         fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp,
638         fAudLang1Field, fAudLang1PopUp, fAudLang2Field, fAudLang2PopUp,
639         fAudTrack1MixLabel, fAudTrack1MixPopUp, fAudTrack2MixLabel, fAudTrack2MixPopUp,
640         fAudRateField, fAudRatePopUp, fAudBitrateField,
641         fAudBitratePopUp, fPictureButton,fQueueStatus, 
642                 fPicSrcWidth,fPicSrcHeight,fPicSettingWidth,fPicSettingHeight,
643                 fPicSettingARkeep,fPicSettingDeinterlace,fPicSettingARkeepDsply,
644                 fPicSettingDeinterlaceDsply,fPicLabelSettings,fPicLabelSrc,fPicLabelOutp,
645                 fPicLabelAr,fPicLabelDeinter,fPicLabelSrcX,fPicLabelOutputX,
646                 fPicLabelPAROutp,fPicLabelPAROutputX,fPicSettingPARWidth,fPicSettingPARHeight,
647                 fPicSettingPARDsply,fPicLabelAnamorphic,tableView,fPresetsAdd,fPresetsDelete,
648                 fCreateChapterMarkers,fX264optViewTitleLabel,fDisplayX264Options,fDisplayX264OptionsLabel,fX264optBframesLabel,
649                 fX264optBframesPopUp,fX264optRefLabel,fX264optRefPopUp,fX264optNfpskipLabel,fX264optNfpskipPopUp,
650                 fX264optNodctdcmtLabel,fX264optNodctdcmtPopUp,fX264optSubmeLabel,fX264optSubmePopUp,
651                 fX264optTrellisLabel,fX264optTrellisPopUp,fX264optMixedRefsLabel,fX264optMixedRefsPopUp,
652                 fX264optMotionEstLabel,fX264optMotionEstPopUp,fX264optMERangeLabel,fX264optMERangePopUp,
653                 fX264optWeightBLabel,fX264optWeightBPopUp,fX264optBRDOLabel,fX264optBRDOPopUp,
654                 fX264optBPyramidLabel,fX264optBPyramidPopUp};
655
656     for( unsigned i = 0;
657          i < sizeof( controls ) / sizeof( NSControl * ); i++ )
658     {
659         if( [[controls[i] className] isEqualToString: @"NSTextField"] )
660         {
661             NSTextField * tf = (NSTextField *) controls[i];
662             if( ![tf isBezeled] )
663             {
664                 [tf setTextColor: b ? [NSColor controlTextColor] :
665                     [NSColor disabledControlTextColor]];
666                 continue;
667             }
668         }
669         [controls[i] setEnabled: b];
670
671     }
672         
673         if (b) {
674
675         /* if we're enabling the interface, check if the audio mixdown controls need to be enabled or not */
676         /* these will have been enabled by the mass control enablement above anyway, so we're sense-checking it here */
677         [self SetEnabledStateOfAudioMixdownControls: NULL];
678         
679         } else {
680
681                 [tableView setEnabled: NO];
682         
683         }
684
685     [self VideoMatrixChanged: NULL];
686 }
687
688 - (IBAction) ShowScanPanel: (id) sender
689 {
690     [fScanController Show];
691 }
692
693 - (BOOL) windowShouldClose: (id) sender
694 {
695     /* Stop the application when the user closes the window */
696     [NSApp terminate: self];
697     return YES;
698 }
699
700 - (IBAction) VideoMatrixChanged: (id) sender;
701 {
702     bool target, bitrate, quality;
703
704     target = bitrate = quality = false;
705     if( [fVidQualityMatrix isEnabled] )
706     {
707         switch( [fVidQualityMatrix selectedRow] )
708         {
709             case 0:
710                 target = true;
711                 break;
712             case 1:
713                 bitrate = true;
714                 break;
715             case 2:
716                 quality = true;
717                 break;
718         }
719     }
720     [fVidTargetSizeField  setEnabled: target];
721     [fVidBitrateField     setEnabled: bitrate];
722     [fVidQualitySlider    setEnabled: quality];
723     [fVidTwoPassCheck     setEnabled: !quality &&
724         [fVidQualityMatrix isEnabled]];
725     if( quality )
726     {
727         [fVidTwoPassCheck setState: NSOffState];
728     }
729
730     [self QualitySliderChanged: sender];
731     [self CalculateBitrate:     sender];
732         [self CustomSettingUsed: sender];
733 }
734
735 - (IBAction) QualitySliderChanged: (id) sender
736 {
737     [fVidConstantCell setTitle: [NSString stringWithFormat:
738         _( @"Constant quality: %.0f %%" ), 100.0 *
739         [fVidQualitySlider floatValue]]];
740                 [self CustomSettingUsed: sender];
741 }
742
743 - (IBAction) BrowseFile: (id) sender
744 {
745     /* Open a panel to let the user choose and update the text field */
746     NSSavePanel * panel = [NSSavePanel savePanel];
747         /* We get the current file name and path from the destination field here */
748         [panel beginSheetForDirectory: [[fDstFile2Field stringValue] stringByDeletingLastPathComponent] file: [[fDstFile2Field stringValue] lastPathComponent]
749                                    modalForWindow: fWindow modalDelegate: self
750                                    didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
751                                           contextInfo: NULL];
752 }
753
754 - (void) BrowseFileDone: (NSSavePanel *) sheet
755     returnCode: (int) returnCode contextInfo: (void *) contextInfo
756 {
757     if( returnCode == NSOKButton )
758     {
759         [fDstFile2Field setStringValue: [sheet filename]];
760                 
761     }
762 }
763
764 - (IBAction) ShowPicturePanel: (id) sender
765 {
766     hb_list_t  * list  = hb_get_titles( fHandle );
767     hb_title_t * title = (hb_title_t *) hb_list_item( list,
768             [fSrcTitlePopUp indexOfSelectedItem] );
769
770     /* Resize the panel */
771     NSSize newSize;
772     newSize.width  = 246 + title->width;
773     newSize.height = 80 + title->height;
774     [fPicturePanel setContentSize: newSize];
775
776     [fPictureController SetTitle: title];
777
778     [NSApp beginSheet: fPicturePanel modalForWindow: fWindow
779         modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
780     [NSApp runModalForWindow: fPicturePanel];
781     [NSApp endSheet: fPicturePanel];
782     [fPicturePanel orderOut: self];
783         [self CalculatePictureSizing: sender];
784 }
785
786 - (IBAction) ShowQueuePanel: (id) sender
787 {
788     /* Update the OutlineView */
789     [fQueueController Update: sender];
790
791     /* Show the panel */
792     [NSApp beginSheet: fQueuePanel modalForWindow: fWindow
793         modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
794     [NSApp runModalForWindow: fQueuePanel];
795     [NSApp endSheet: fQueuePanel];
796     [fQueuePanel orderOut: self];
797 }
798
799 - (void) PrepareJob
800 {
801     hb_list_t  * list  = hb_get_titles( fHandle );
802     hb_title_t * title = (hb_title_t *) hb_list_item( list,
803             [fSrcTitlePopUp indexOfSelectedItem] );
804     hb_job_t * job = title->job;
805     //int i;
806
807     /* Chapter selection */
808     job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;
809     job->chapter_end   = [fSrcChapterEndPopUp   indexOfSelectedItem] + 1;
810         
811     /* Format and codecs */
812     int format = [fDstFormatPopUp indexOfSelectedItem];
813     int codecs = [fDstCodecsPopUp indexOfSelectedItem];
814     job->mux    = FormatSettings[format][codecs] & HB_MUX_MASK;
815     job->vcodec = FormatSettings[format][codecs] & HB_VCODEC_MASK;
816     job->acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
817     /* We set the chapter marker extraction here based on the format being
818         mpeg4 and the checkbox being checked */
819         if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fCreateChapterMarkers state] == NSOnState)
820         {
821         job->chapter_markers = 1;
822         }
823         else
824         {
825         job->chapter_markers = 0;
826         }
827     if( ( job->vcodec & HB_VCODEC_FFMPEG ) &&
828         [fVidEncoderPopUp indexOfSelectedItem] > 0 )
829     {
830         job->vcodec = HB_VCODEC_XVID;
831     }
832     if( job->vcodec & HB_VCODEC_X264 )
833     {
834          if ([fVidEncoderPopUp indexOfSelectedItem] > 0 )
835             {
836                 /* Just use new Baseline Level 3.0 
837                 Lets Deprecate Baseline Level 1.3*/
838                 job->h264_level = 30;
839                 job->mux = HB_MUX_IPOD;
840         /* move sanity check for iPod Encoding here */
841                 job->pixel_ratio = 0 ;
842
843                 }
844                 
845                 /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake
846                 Currently only used with Constant Quality setting*/
847                 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2)
848                 {
849                 /* Can only be used with svn rev >= 89 */
850                         job->crf = 1;
851                 }
852                 
853                 /* Below Sends x264 options to the core library if x264 is selected*/
854                 /* First we look to see if a user preset has been selected that contains a x264 optional string CurUserPresetChosenNum = nil */
855                 //if (curUserPresetChosenNum != nil)
856                 //{
857                         
858                         /* Lets use this as per Nyx, Thanks Nyx! fDisplayX264Options*/
859                         job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */  
860                         strcpy(job->x264opts, [[fDisplayX264Options stringValue] UTF8String]);
861                         //strcpy(job->x264opts, [[chosenPreset valueForKey:@"x264Option"] UTF8String]);
862                         //job->x264opts = [[chosenPreset valueForKey:@"x264Option"] cString];
863                 //}
864                 //else
865                 //{
866                     /* if not, then we check to see if there is a x264 opt in the preferences and use that if we want */
867                         //job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
868                         /* Lets use this as per Nyx, Thanks Nyx! */
869                         //job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */  
870                         //strcpy(job->x264opts, [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String]);
871                 //} 
872                 
873                 
874                 
875         job->h264_13 = [fVidEncoderPopUp indexOfSelectedItem];
876     }
877
878     /* Video settings */
879     if( [fVidRatePopUp indexOfSelectedItem] > 0 )
880     {
881         job->vrate      = 27000000;
882         job->vrate_base = hb_video_rates[[fVidRatePopUp
883             indexOfSelectedItem]-1].rate;
884     }
885     else
886     {
887         job->vrate      = title->rate;
888         job->vrate_base = title->rate_base;
889     }
890
891     switch( [fVidQualityMatrix selectedRow] )
892     {
893         case 0:
894             /* Target size.
895                Bitrate should already have been calculated and displayed
896                in fVidBitrateField, so let's just use it */
897         case 1:
898             job->vquality = -1.0;
899             job->vbitrate = [fVidBitrateField intValue];
900             break;
901         case 2:
902             job->vquality = [fVidQualitySlider floatValue];
903             job->vbitrate = 0;
904             break;
905     }
906
907     job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState );
908     
909
910
911     /* Subtitle settings */
912     job->subtitle = [fSubPopUp indexOfSelectedItem] - 1;
913
914     /* Audio tracks and mixdowns */
915     /* check for the condition where track 2 has an audio selected, but track 1 does not */
916     /* we will use track 2 as track 1 in this scenario */
917     if ([fAudLang1PopUp indexOfSelectedItem] > 0)
918     {
919         job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
920         job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1; /* will be -1 if "none" is selected */
921         job->audios[2] = -1;
922         job->audio_mixdowns[0] = [[fAudTrack1MixPopUp selectedItem] tag];
923         job->audio_mixdowns[1] = [[fAudTrack2MixPopUp selectedItem] tag];
924     }
925     else if ([fAudLang2PopUp indexOfSelectedItem] > 0)
926     {
927         job->audios[0] = [fAudLang2PopUp indexOfSelectedItem] - 1;
928         job->audio_mixdowns[0] = [[fAudTrack2MixPopUp selectedItem] tag];
929         job->audios[1] = -1;
930     }
931     else
932     {
933         job->audios[0] = -1;
934     }
935
936     /* Audio settings */
937     job->arate = hb_audio_rates[[fAudRatePopUp
938                      indexOfSelectedItem]].rate;
939     job->abitrate = [[fAudBitratePopUp selectedItem] tag];
940
941 }
942
943
944
945 - (IBAction) AddToQueue: (id) sender
946 {
947 /* We get the destination directory from the destingation field here */
948         NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
949         /* We check for a valid destination here */
950         if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0) 
951         {
952                 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
953         }
954         else
955         {
956                 
957                 hb_list_t  * list  = hb_get_titles( fHandle );
958                 hb_title_t * title = (hb_title_t *) hb_list_item( list,
959                                                                                                                   [fSrcTitlePopUp indexOfSelectedItem] );
960                 hb_job_t * job = title->job;
961                 
962                 [self PrepareJob];
963                 
964                 /* Destination file */
965                 job->file = [[fDstFile2Field stringValue] UTF8String];
966                 
967                 if( [fVidTwoPassCheck state] == NSOnState )
968                 {
969                         job->pass = 1;
970                         hb_add( fHandle, job );
971                         job->pass = 2;
972                         
973                         job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */  
974                         strcpy(job->x264opts, [[fDisplayX264Options stringValue] UTF8String]);
975                         
976                         hb_add( fHandle, job );
977                 }
978                 else
979                 {
980                         job->pass = 0;
981                         hb_add( fHandle, job );
982                 }
983         
984         [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
985         }
986 }
987
988 - (IBAction) Rip: (id) sender
989 {
990     /* Rip or Cancel ? */
991     if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
992     {
993         [self Cancel: sender];
994         return;
995     }
996         /* if there is no job in the queue, then add it to the queue and rip 
997         otherwise, there are already jobs in queue, so just rip the queue */
998         int count = hb_count( fHandle );
999         if( count < 1 )
1000         {
1001                 [self AddToQueue: sender];
1002                 }
1003     
1004             /* We check for duplicate name here */
1005         if( [[NSFileManager defaultManager] fileExistsAtPath:
1006             [fDstFile2Field stringValue]] )
1007     {
1008         NSBeginCriticalAlertSheet( _( @"File already exists" ),
1009             _( @"Cancel" ), _( @"Overwrite" ), NULL, fWindow, self,
1010             @selector( OverwriteAlertDone:returnCode:contextInfo: ),
1011             NULL, NULL, [NSString stringWithFormat:
1012             _( @"Do you want to overwrite %@?" ),
1013             [fDstFile2Field stringValue]] );
1014         return;
1015     }
1016         /* We get the destination directory from the destination field here */
1017         NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
1018         /* We check for a valid destination here */
1019         if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0) 
1020         {
1021                 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
1022         }
1023         else
1024         {
1025         [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
1026                 [self _Rip];
1027         }
1028         
1029
1030
1031 }
1032
1033 - (void) OverwriteAlertDone: (NSWindow *) sheet
1034     returnCode: (int) returnCode contextInfo: (void *) contextInfo
1035 {
1036     if( returnCode == NSAlertAlternateReturn )
1037     {
1038         [self _Rip];
1039     }
1040 }
1041
1042 - (void) UpdateAlertDone: (NSWindow *) sheet
1043     returnCode: (int) returnCode contextInfo: (void *) contextInfo
1044 {
1045     if( returnCode == NSAlertAlternateReturn )
1046     {
1047         /* Show scan panel */
1048         [self performSelectorOnMainThread: @selector(ShowScanPanel:)
1049             withObject: NULL waitUntilDone: NO];
1050         return;
1051     }
1052
1053     /* Go to HandBrake homepage and exit */
1054     [self OpenHomepage: NULL];
1055     [NSApp terminate: self];
1056 }
1057
1058 - (void) _Rip
1059 {
1060     /* Let libhb do the job */
1061     hb_start( fHandle );
1062         /*set the fEncodeState State */
1063         fEncodeState = 1;
1064
1065     /* Disable interface */
1066    [self EnableUI: NO];
1067     [fPauseButton setEnabled: NO];
1068     [fRipButton   setEnabled: NO];
1069 }
1070
1071 - (IBAction) Cancel: (id) sender
1072 {
1073     NSBeginCriticalAlertSheet( _( @"Cancel - Are you sure?" ),
1074         _( @"Keep working" ), _( @"Cancel encoding" ), NULL, fWindow, self,
1075         @selector( _Cancel:returnCode:contextInfo: ), NULL, NULL,
1076         _( @"Encoding won't be recoverable." ) );
1077 }
1078
1079 - (void) _Cancel: (NSWindow *) sheet
1080     returnCode: (int) returnCode contextInfo: (void *) contextInfo
1081 {
1082     if( returnCode == NSAlertAlternateReturn )
1083     {
1084         hb_stop( fHandle );
1085         [fPauseButton setEnabled: NO];
1086         [fRipButton   setEnabled: NO];
1087                 /*set the fEncodeState State */
1088              fEncodeState = 2;
1089     }
1090 }
1091
1092 - (IBAction) Pause: (id) sender
1093 {
1094     [fPauseButton setEnabled: NO];
1095     [fRipButton   setEnabled: NO];
1096
1097     if( [[fPauseButton title] isEqualToString: _( @"Resume" )] )
1098     {
1099         hb_resume( fHandle );
1100     }
1101     else
1102     {
1103         hb_pause( fHandle );
1104     }
1105 }
1106
1107 - (IBAction) TitlePopUpChanged: (id) sender
1108 {
1109     hb_list_t  * list  = hb_get_titles( fHandle );
1110     hb_title_t * title = (hb_title_t*)
1111         hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1112                 
1113                 
1114     /* If Auto Naming is on. We create an output filename of dvd name - title number */
1115     if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"] > 0)
1116         {
1117                 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1118                         @"%@/%@-%d.%@", [[fDstFile2Field stringValue] stringByDeletingLastPathComponent],
1119                         [NSString stringWithUTF8String: title->name],
1120                         [fSrcTitlePopUp indexOfSelectedItem] + 1,
1121                         [[fDstFile2Field stringValue] pathExtension]]]; 
1122         }
1123
1124     /* Update chapter popups */
1125     [fSrcChapterStartPopUp removeAllItems];
1126     [fSrcChapterEndPopUp   removeAllItems];
1127     for( int i = 0; i < hb_list_count( title->list_chapter ); i++ )
1128     {
1129         [fSrcChapterStartPopUp addItemWithTitle: [NSString
1130             stringWithFormat: @"%d", i + 1]];
1131         [fSrcChapterEndPopUp addItemWithTitle: [NSString
1132             stringWithFormat: @"%d", i + 1]];
1133     }
1134     [fSrcChapterStartPopUp selectItemAtIndex: 0];
1135     [fSrcChapterEndPopUp   selectItemAtIndex:
1136         hb_list_count( title->list_chapter ) - 1];
1137     [self ChapterPopUpChanged: NULL];
1138
1139 /* Start Get and set the initial pic size for display */
1140         hb_job_t * job = title->job;
1141         fTitle = title; 
1142         /* Turn Deinterlace on/off depending on the preference */
1143         if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultDeinterlaceOn"] > 0)
1144         {
1145                 job->deinterlace = 1;
1146         }
1147         else
1148         {
1149                 job->deinterlace = 0;
1150         }
1151         
1152         /* Pixel Ratio Setting */
1153         if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
1154     {
1155
1156                 job->pixel_ratio = 1 ;
1157         }
1158         else
1159         {
1160                 job->pixel_ratio = 0 ;
1161         }
1162         /*Set Source Size Fields Here */
1163         [fPicSrcWidth setStringValue: [NSString stringWithFormat:
1164                                                          @"%d", fTitle->width]];
1165         [fPicSrcHeight setStringValue: [NSString stringWithFormat:
1166                                                          @"%d", fTitle->height]];
1167         /* We get the originial output picture width and height and put them
1168         in variables for use with some presets later on */
1169         PicOrigOutputWidth = job->width;
1170         PicOrigOutputHeight = job->height;
1171         /* we test getting the max output value for pic sizing here to be used later*/
1172         [fPicSettingWidth setStringValue: [NSString stringWithFormat:
1173                 @"%d", PicOrigOutputWidth]];
1174         [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1175                 @"%d", PicOrigOutputHeight]];
1176         /* we run the picture size values through
1177         CalculatePictureSizing to get all picture size
1178         information*/
1179         [self CalculatePictureSizing: NULL];
1180         /* Run Through EncoderPopUpChanged to see if there
1181                 needs to be any pic value modifications based on encoder settings */
1182         //[self EncoderPopUpChanged: NULL];
1183         /* END Get and set the initial pic size for display */ 
1184
1185     /* Update subtitle popups */
1186     hb_subtitle_t * subtitle;
1187     [fSubPopUp removeAllItems];
1188     [fSubPopUp addItemWithTitle: @"None"];
1189     for( int i = 0; i < hb_list_count( title->list_subtitle ); i++ )
1190     {
1191         subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, i );
1192
1193         /* We cannot use NSPopUpButton's addItemWithTitle because
1194            it checks for duplicate entries */
1195         [[fSubPopUp menu] addItemWithTitle: [NSString stringWithCString:
1196             subtitle->lang] action: NULL keyEquivalent: @""];
1197     }
1198     [fSubPopUp selectItemAtIndex: 0];
1199     
1200     /* Update chapter table */
1201     [fChapterTitlesDelegate resetWithTitle:title];
1202     [fChapterTable reloadData];
1203
1204     /* Update audio popups */
1205     [self AddAllAudioTracksToPopUp: fAudLang1PopUp];
1206     [self AddAllAudioTracksToPopUp: fAudLang2PopUp];
1207     /* search for the first instance of our prefs default language for track 1, and set track 2 to "none" */
1208         NSString * audioSearchPrefix = [[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
1209     [self SelectAudioTrackInPopUp: fAudLang1PopUp searchPrefixString: audioSearchPrefix selectIndexIfNotFound: 1];
1210     [self SelectAudioTrackInPopUp: fAudLang2PopUp searchPrefixString: NULL selectIndexIfNotFound: 0];
1211         
1212         /* changing the title may have changed the audio channels on offer, */
1213         /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1214         [self AudioTrackPopUpChanged: fAudLang1PopUp];
1215         [self AudioTrackPopUpChanged: fAudLang2PopUp];
1216
1217 }
1218
1219 - (IBAction) ChapterPopUpChanged: (id) sender
1220 {
1221     hb_list_t  * list  = hb_get_titles( fHandle );
1222     hb_title_t * title = (hb_title_t *)
1223         hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1224
1225     hb_chapter_t * chapter;
1226     int64_t        duration = 0;
1227     for( int i = [fSrcChapterStartPopUp indexOfSelectedItem];
1228          i <= [fSrcChapterEndPopUp indexOfSelectedItem]; i++ )
1229     {
1230         chapter = (hb_chapter_t *) hb_list_item( title->list_chapter, i );
1231         duration += chapter->duration;
1232     }
1233     
1234     duration /= 90000; /* pts -> seconds */
1235     [fSrcDuration2Field setStringValue: [NSString stringWithFormat:
1236         @"%02lld:%02lld:%02lld", duration / 3600, ( duration / 60 ) % 60,
1237         duration % 60]];
1238
1239     [self CalculateBitrate: sender];
1240 }
1241
1242 - (IBAction) FormatPopUpChanged: (id) sender
1243 {
1244     NSString * string = [fDstFile2Field stringValue];
1245     int format = [fDstFormatPopUp indexOfSelectedItem];
1246     char * ext = NULL;
1247
1248     /* Update the codecs popup */
1249     [fDstCodecsPopUp removeAllItems];
1250     switch( format )
1251     {
1252         case 0:
1253                                 /*Get Default MP4 File Extension*/
1254                                 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
1255                                 {
1256                                 ext = "m4v";
1257                                 }
1258                                 else
1259                                 {
1260                                 ext = "mp4";
1261                                 }
1262             [fDstCodecsPopUp addItemWithTitle:
1263                 _( @"MPEG-4 Video / AAC Audio" )];
1264             [fDstCodecsPopUp addItemWithTitle:
1265                 _( @"AVC/H.264 Video / AAC Audio" )];
1266                         /* We enable the create chapters checkbox here since we are .mp4*/
1267                         [fCreateChapterMarkers setEnabled: YES];
1268                         break;
1269         case 1: 
1270             ext = "avi";
1271             [fDstCodecsPopUp addItemWithTitle:
1272                 _( @"MPEG-4 Video / MP3 Audio" )];
1273             [fDstCodecsPopUp addItemWithTitle:
1274                 _( @"MPEG-4 Video / AC-3 Audio" )];
1275             [fDstCodecsPopUp addItemWithTitle:
1276                 _( @"AVC/H.264 Video / MP3 Audio" )];
1277             [fDstCodecsPopUp addItemWithTitle:
1278                 _( @"AVC/H.264 Video / AC-3 Audio" )];
1279                         /* We disable the create chapters checkbox here since we are NOT .mp4 
1280                         and make sure it is unchecked*/
1281                         [fCreateChapterMarkers setEnabled: NO];
1282                         [fCreateChapterMarkers setState: NSOffState];
1283             break;
1284         case 2:
1285             ext = "ogm";
1286             [fDstCodecsPopUp addItemWithTitle:
1287                 _( @"MPEG-4 Video / Vorbis Audio" )];
1288             [fDstCodecsPopUp addItemWithTitle:
1289                 _( @"MPEG-4 Video / MP3 Audio" )];
1290             /* We disable the create chapters checkbox here since we are NOT .mp4 
1291                         and make sure it is unchecked*/
1292                         [fCreateChapterMarkers setEnabled: NO];
1293                         [fCreateChapterMarkers setState: NSOffState];
1294                         break;
1295     }
1296     [self CodecsPopUpChanged: NULL];
1297
1298     /* Add/replace to the correct extension */
1299     if( [string characterAtIndex: [string length] - 4] == '.' )
1300     {
1301         [fDstFile2Field setStringValue: [NSString stringWithFormat:
1302             @"%@.%s", [string substringToIndex: [string length] - 4],
1303             ext]];
1304     }
1305     else
1306     {
1307         [fDstFile2Field setStringValue: [NSString stringWithFormat:
1308             @"%@.%s", string, ext]];
1309     }
1310
1311         /* changing the format may mean that we can / can't offer mono or 6ch, */
1312         /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1313         [self AudioTrackPopUpChanged: fAudLang1PopUp];
1314         [self AudioTrackPopUpChanged: fAudLang2PopUp];
1315
1316         /* We call method method to change UI to reflect whether a preset is used or not*/
1317         [self CustomSettingUsed: sender];       
1318         
1319 }
1320
1321 - (IBAction) CodecsPopUpChanged: (id) sender
1322 {
1323     int format = [fDstFormatPopUp indexOfSelectedItem];
1324     int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1325         [fX264optView setHidden: YES];
1326         [fX264optViewTitleLabel setStringValue: @"Only Used With The x264 (H.264) Codec"];
1327         
1328
1329     /* Update the encoder popup*/
1330     if( ( FormatSettings[format][codecs] & HB_VCODEC_X264 ) )
1331     {
1332         /* MPEG-4 -> H.264 */
1333         [fVidEncoderPopUp removeAllItems];
1334                 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 Main)"];
1335                 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 iPod)"];
1336         [fX264optView setHidden: NO];
1337                 [fX264optViewTitleLabel setStringValue: @""];
1338                 
1339     }
1340     else if( ( FormatSettings[format][codecs] & HB_VCODEC_FFMPEG ) )
1341     {
1342         /* H.264 -> MPEG-4 */
1343         [fVidEncoderPopUp removeAllItems];
1344         [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
1345         [fVidEncoderPopUp addItemWithTitle: @"XviD"];
1346         [fVidEncoderPopUp selectItemAtIndex: 0];
1347                                 
1348     }
1349
1350     if( FormatSettings[format][codecs] & HB_ACODEC_AC3 )
1351     {
1352         /* AC-3 pass-through: disable samplerate and bitrate */
1353         [fAudRatePopUp    setEnabled: NO];
1354         [fAudBitratePopUp setEnabled: NO];
1355     }
1356     else
1357     {
1358         [fAudRatePopUp    setEnabled: YES];
1359         [fAudBitratePopUp setEnabled: YES];
1360     }
1361
1362         /* changing the codecs on offer may mean that we can / can't offer mono or 6ch, */
1363         /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1364         [self AudioTrackPopUpChanged: fAudLang1PopUp];
1365         [self AudioTrackPopUpChanged: fAudLang2PopUp];
1366
1367     [self CalculateBitrate: sender];
1368     /* We call method method to change UI to reflect whether a preset is used or not*/
1369         [self CustomSettingUsed: sender];
1370 }
1371
1372 - (IBAction) EncoderPopUpChanged: (id) sender
1373 {
1374     
1375         /* Check to see if we need to modify the job pic values based on x264 (iPod) encoder selection */
1376     if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1 && [fVidEncoderPopUp indexOfSelectedItem] == 1)
1377     {
1378         hb_job_t * job = fTitle->job;
1379         job->pixel_ratio = 0 ;
1380         
1381                  if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPicSizeAutoiPod"] > 0)
1382                  {
1383                  
1384                  if (job->width > 640)
1385                                 {
1386                                 job->width = 640;
1387                                 }
1388                  job->keep_ratio = 1;
1389                  hb_fix_aspect( job, HB_KEEP_WIDTH );
1390                  
1391                  }
1392
1393         }
1394     
1395         [self CalculatePictureSizing: sender];
1396         /* We call method method to change UI to reflect whether a preset is used or not*/    
1397     [self CustomSettingUsed: sender];
1398 }
1399
1400 - (IBAction) SetEnabledStateOfAudioMixdownControls: (id) sender
1401 {
1402
1403     /* enable/disable the mixdown text and popupbutton for audio track 1 */
1404     [fAudTrack1MixPopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
1405     [fAudTrack1MixLabel setTextColor: ([fAudLang1PopUp indexOfSelectedItem] == 0) ?
1406         [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
1407
1408     /* enable/disable the mixdown text and popupbutton for audio track 2 */
1409     [fAudTrack2MixPopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
1410     [fAudTrack2MixLabel setTextColor: ([fAudLang2PopUp indexOfSelectedItem] == 0) ?
1411         [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
1412
1413 }
1414
1415 - (IBAction) AddAllAudioTracksToPopUp: (id) sender
1416 {
1417
1418     hb_list_t  * list  = hb_get_titles( fHandle );
1419     hb_title_t * title = (hb_title_t*)
1420         hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1421
1422         hb_audio_t * audio;
1423
1424     [sender removeAllItems];
1425     [sender addItemWithTitle: _( @"None" )];
1426     for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
1427     {
1428         audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
1429         [[sender menu] addItemWithTitle:
1430             [NSString stringWithCString: audio->lang]
1431             action: NULL keyEquivalent: @""];
1432     }
1433     [sender selectItemAtIndex: 0];
1434
1435 }
1436
1437 - (IBAction) SelectAudioTrackInPopUp: (id) sender searchPrefixString: (NSString *) searchPrefixString selectIndexIfNotFound: (int) selectIndexIfNotFound
1438 {
1439
1440     /* this method can be used to find a language, or a language-and-source-format combination, by passing in the appropriate string */
1441     /* e.g. to find the first French track, pass in an NSString * of "Francais" */
1442     /* e.g. to find the first English 5.1 AC3 track, pass in an NSString * of "English (AC3) (5.1 ch)" */
1443     /* if no matching track is found, then selectIndexIfNotFound is used to choose which track to select instead */
1444     
1445         if (searchPrefixString != NULL) 
1446         {
1447
1448         for( int i = 0; i < [sender numberOfItems]; i++ )
1449         {
1450             /* Try to find the desired search string */
1451             if ([[[sender itemAtIndex: i] title] hasPrefix:searchPrefixString])
1452             {
1453                 [sender selectItemAtIndex: i];
1454                 return;
1455             }
1456         }
1457         /* couldn't find the string, so select the requested "search string not found" item */
1458         /* index of 0 means select the "none" item */
1459         /* index of 1 means select the first audio track */
1460         [sender selectItemAtIndex: selectIndexIfNotFound];
1461         }
1462     else
1463     {
1464         /* if no search string is provided, then select the selectIndexIfNotFound item */
1465         [sender selectItemAtIndex: selectIndexIfNotFound];
1466     }
1467
1468 }
1469
1470 - (IBAction) AudioTrackPopUpChanged: (id) sender
1471 {
1472     /* utility function to call AudioTrackPopUpChanged without passing in a mixdown-to-use */
1473     [self AudioTrackPopUpChanged: sender mixdownToUse: 0];
1474 }
1475
1476 - (IBAction) AudioTrackPopUpChanged: (id) sender mixdownToUse: (int) mixdownToUse
1477 {
1478
1479     /* make sure we have a selected title before continuing */
1480     if (fTitle == NULL) return;
1481
1482     /* find out if audio track 1 or 2 was changed - this is passed to us in the tag of the sender */
1483     /* the sender will have been either fAudLang1PopUp (tag = 0) or fAudLang2PopUp (tag = 1) */
1484     int thisAudio = [sender tag];
1485
1486     /* get the index of the selected audio */
1487     int thisAudioIndex = [sender indexOfSelectedItem] - 1;
1488
1489     /* Handbrake can't currently cope with ripping the same source track twice */
1490     /* So, if this audio is also selected in the other audio track popup, set that popup's selection to "none" */
1491     /* get a reference to the two audio track popups */
1492     NSPopUpButton * thisAudioPopUp  = (thisAudio == 1 ? fAudLang2PopUp : fAudLang1PopUp);
1493     NSPopUpButton * otherAudioPopUp = (thisAudio == 1 ? fAudLang1PopUp : fAudLang2PopUp);
1494     /* if the same track is selected in the other audio popup, then select "none" in that popup */
1495     /* unless, of course, both are selected as "none!" */
1496     if ([thisAudioPopUp indexOfSelectedItem] != 0 && [thisAudioPopUp indexOfSelectedItem] == [otherAudioPopUp indexOfSelectedItem]) {
1497         [otherAudioPopUp selectItemAtIndex: 0];
1498         [self AudioTrackPopUpChanged: otherAudioPopUp];
1499     }
1500
1501     /* pointer for the hb_audio_s struct we will use later on */
1502     hb_audio_t * audio;
1503
1504     /* find out what the currently-selected output audio codec is */
1505     int format = [fDstFormatPopUp indexOfSelectedItem];
1506     int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1507     int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
1508
1509     /* pointer to this track's mixdown NSPopUpButton */
1510     NSTextField   * mixdownTextField;
1511     NSPopUpButton * mixdownPopUp;
1512
1513     /* find our mixdown NSTextField and NSPopUpButton */
1514     if (thisAudio == 0)
1515     {
1516         mixdownTextField = fAudTrack1MixLabel;
1517         mixdownPopUp = fAudTrack1MixPopUp;
1518     }
1519     else
1520     {
1521         mixdownTextField = fAudTrack2MixLabel;
1522         mixdownPopUp = fAudTrack2MixPopUp;
1523     }
1524
1525     /* delete the previous audio mixdown options */
1526     [mixdownPopUp removeAllItems];
1527
1528     /* check if the audio mixdown controls need their enabled state changing */
1529     [self SetEnabledStateOfAudioMixdownControls: NULL];
1530
1531     if (thisAudioIndex != -1)
1532     {
1533
1534         /* get the audio */
1535         audio = (hb_audio_t *) hb_list_item( fTitle->list_audio, thisAudioIndex );
1536         if (audio != NULL)
1537         {
1538
1539             /* find out if our selected output audio codec supports mono and / or 6ch */
1540             /* we also check for an input codec of AC3 or DCA,
1541                as they are the only libraries able to do the mixdown to mono / conversion to 6-ch */
1542             /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,
1543                but this may change in the future, so they are separated for flexibility */
1544             int audioCodecsSupportMono = ((audio->codec == HB_ACODEC_AC3 ||
1545                 audio->codec == HB_ACODEC_DCA) && acodec == HB_ACODEC_FAAC);
1546             int audioCodecsSupport6Ch =  ((audio->codec == HB_ACODEC_AC3 ||
1547                 audio->codec == HB_ACODEC_DCA) && acodec == HB_ACODEC_FAAC);
1548
1549             /* check for AC-3 passthru */
1550             if (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3)
1551             {
1552                     [[mixdownPopUp menu] addItemWithTitle:
1553                         [NSString stringWithCString: "AC3 Passthru"]
1554                         action: NULL keyEquivalent: @""];
1555             }
1556             else
1557             {
1558
1559                 /* add the appropriate audio mixdown menuitems to the popupbutton */
1560                 /* in each case, we set the new menuitem's tag to be the amixdown value for that mixdown,
1561                    so that we can reference the mixdown later */
1562
1563                 /* keep a track of the min and max mixdowns we used, so we can select the best match later */
1564                 int minMixdownUsed = 0;
1565                 int maxMixdownUsed = 0;
1566                 
1567                 /* get the input channel layout without any lfe channels */
1568                 int layout = audio->input_channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
1569
1570                 /* do we want to add a mono option? */
1571                 if (audioCodecsSupportMono == 1) {
1572                     id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1573                         [NSString stringWithCString: hb_audio_mixdowns[0].human_readable_name]
1574                         action: NULL keyEquivalent: @""];
1575                     [menuItem setTag: hb_audio_mixdowns[0].amixdown];
1576                     if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[0].amixdown;
1577                     maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[0].amixdown);
1578                 }
1579
1580                 /* do we want to add a stereo option? */
1581                 /* offer stereo if we have a mono source and non-mono-supporting codecs, as otherwise we won't have a mixdown at all */
1582                 /* also offer stereo if we have a stereo-or-better source */
1583                 if ((layout == HB_INPUT_CH_LAYOUT_MONO && audioCodecsSupportMono == 0) || layout >= HB_INPUT_CH_LAYOUT_STEREO) {
1584                     id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1585                         [NSString stringWithCString: hb_audio_mixdowns[1].human_readable_name]
1586                         action: NULL keyEquivalent: @""];
1587                     [menuItem setTag: hb_audio_mixdowns[1].amixdown];
1588                     if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[1].amixdown;
1589                     maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[1].amixdown);
1590                 }
1591
1592                 /* do we want to add a dolby surround (DPL1) option? */
1593                 if (layout == HB_INPUT_CH_LAYOUT_3F1R || layout == HB_INPUT_CH_LAYOUT_3F2R || layout == HB_INPUT_CH_LAYOUT_DOLBY) {
1594                     id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1595                         [NSString stringWithCString: hb_audio_mixdowns[2].human_readable_name]
1596                         action: NULL keyEquivalent: @""];
1597                     [menuItem setTag: hb_audio_mixdowns[2].amixdown];
1598                     if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[2].amixdown;
1599                     maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[2].amixdown);
1600                 }
1601
1602                 /* do we want to add a dolby pro logic 2 (DPL2) option? */
1603                 if (layout == HB_INPUT_CH_LAYOUT_3F2R) {
1604                     id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1605                         [NSString stringWithCString: hb_audio_mixdowns[3].human_readable_name]
1606                         action: NULL keyEquivalent: @""];
1607                     [menuItem setTag: hb_audio_mixdowns[3].amixdown];
1608                     if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[3].amixdown;
1609                     maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[3].amixdown);
1610                 }
1611
1612                 /* do we want to add a 6-channel discrete option? */
1613                 if (audioCodecsSupport6Ch == 1 && layout == HB_INPUT_CH_LAYOUT_3F2R && (audio->input_channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE)) {
1614                     id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1615                         [NSString stringWithCString: hb_audio_mixdowns[4].human_readable_name]
1616                         action: NULL keyEquivalent: @""];
1617                     [menuItem setTag: hb_audio_mixdowns[4].amixdown];
1618                     if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[4].amixdown;
1619                     maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[4].amixdown);
1620                 }
1621
1622                 /* auto-select the best mixdown based on our saved mixdown preference */
1623                 
1624                 /* for now, this is hard-coded to a "best" mixdown of HB_AMIXDOWN_DOLBYPLII */
1625                 /* ultimately this should be a prefs option */
1626                 int useMixdown;
1627                 
1628                 /* if we passed in a mixdown to use - in order to load a preset - then try and use it */
1629                 if (mixdownToUse > 0)
1630                 {
1631                     useMixdown = mixdownToUse;
1632                 }
1633                 else
1634                 {
1635                     useMixdown = HB_AMIXDOWN_DOLBYPLII;
1636                 }
1637                 
1638                 /* if useMixdown > maxMixdownUsed, then use maxMixdownUsed */
1639                 if (useMixdown > maxMixdownUsed) useMixdown = maxMixdownUsed;
1640
1641                 /* if useMixdown < minMixdownUsed, then use minMixdownUsed */
1642                 if (useMixdown < minMixdownUsed) useMixdown = minMixdownUsed;
1643
1644                 /* select the (possibly-amended) preferred mixdown */
1645                 [mixdownPopUp selectItemWithTag: useMixdown];
1646                                 
1647                                 /* lets call the AudioTrackMixdownChanged method here to determine appropriate bitrates, etc. */
1648                 [self AudioTrackMixdownChanged: NULL];
1649             }
1650
1651         }
1652         
1653     }
1654
1655         /* see if the new audio track choice will change the bitrate we need */
1656     [self CalculateBitrate: sender];    
1657
1658 }
1659 - (IBAction) AudioTrackMixdownChanged: (id) sender
1660 {
1661
1662     /* find out what the currently-selected output audio codec is */
1663     int format = [fDstFormatPopUp indexOfSelectedItem];
1664     int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1665     int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
1666     
1667     /* storage variable for the min and max bitrate allowed for this codec */
1668     int minbitrate;
1669     int maxbitrate;
1670     
1671     switch( acodec )
1672     {
1673         case HB_ACODEC_FAAC:
1674             /* check if we have a 6ch discrete conversion in either audio track */
1675             if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
1676             {
1677                 /* FAAC is happy using our min bitrate of 32 kbps, even for 6ch */
1678                 minbitrate = 32;
1679                 /* If either mixdown popup includes 6-channel discrete, then allow up to 384 kbps */
1680                 maxbitrate = 384;
1681                 break;
1682             }
1683             else
1684             {
1685                 /* FAAC is happy using our min bitrate of 32 kbps for stereo or mono */
1686                 minbitrate = 32;
1687                 /* FAAC won't honour anything more than 160 for stereo, so let's not offer it */
1688                 /* note: haven't dealt with mono separately here, FAAC will just use the max it can */
1689                 maxbitrate = 160;
1690                 break;
1691             }
1692
1693         case HB_ACODEC_LAME:
1694             /* Lame is happy using our min bitrate of 32 kbps */
1695             minbitrate = 32;
1696             /* Lame won't encode if the bitrate is higher than 320 kbps */
1697             maxbitrate = 320;
1698             break;
1699
1700         case HB_ACODEC_VORBIS:
1701             /* Vorbis causes a crash if we use a bitrate below 48 kbps */
1702             minbitrate = 48;
1703             /* Vorbis can cope with 384 kbps quite happily, even for stereo */
1704             maxbitrate = 384;
1705             break;
1706
1707         default:
1708             /* AC3 passthru disables the bitrate dropdown anyway, so we might as well just use the min and max bitrate */
1709             minbitrate = 32;
1710             maxbitrate = 384;
1711         
1712     }
1713
1714     [fAudBitratePopUp removeAllItems];
1715
1716     for( int i = 0; i < hb_audio_bitrates_count; i++ )
1717     {
1718         if (hb_audio_bitrates[i].rate >= minbitrate && hb_audio_bitrates[i].rate <= maxbitrate)
1719         {
1720             /* add a new menuitem for this bitrate */
1721             id<NSMenuItem> menuItem = [[fAudBitratePopUp menu] addItemWithTitle:
1722                 [NSString stringWithCString: hb_audio_bitrates[i].string]
1723                 action: NULL keyEquivalent: @""];
1724             /* set its tag to be the actual bitrate as an integer, so we can retrieve it later */
1725             [menuItem setTag: hb_audio_bitrates[i].rate];
1726         }
1727     }
1728
1729     /* select the default bitrate (but use 384 for 6-ch AAC) */
1730     if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
1731     {
1732         [fAudBitratePopUp selectItemWithTag: 384];
1733     }
1734     else
1735     {
1736         [fAudBitratePopUp selectItemWithTag: hb_audio_bitrates[hb_audio_bitrates_default].rate];
1737     }
1738
1739 }
1740 /* lets set the picture size back to the max from right after title scan
1741    Lets use an IBAction here as down the road we could always use a checkbox
1742    in the gui to easily take the user back to max. Remember, the compiler
1743    resolves IBActions down to -(void) during compile anyway */
1744 - (IBAction) RevertPictureSizeToMax: (id) sender
1745 {
1746          hb_job_t * job = fTitle->job;
1747         /* We use the output picture width and height
1748         as calculated from libhb right after title is set
1749         in TitlePopUpChanged */
1750         job->width = PicOrigOutputWidth;
1751         job->height = PicOrigOutputHeight;
1752
1753
1754     
1755         [self CalculatePictureSizing: sender];
1756         /* We call method method to change UI to reflect whether a preset is used or not*/    
1757     [self CustomSettingUsed: sender];
1758 }
1759
1760
1761 /* Get and Display Current Pic Settings in main window */
1762 - (IBAction) CalculatePictureSizing: (id) sender
1763 {
1764         
1765
1766         [fPicSettingWidth setStringValue: [NSString stringWithFormat:
1767                 @"%d", fTitle->job->width]];
1768         [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1769                 @"%d", fTitle->job->height]];
1770         [fPicSettingARkeep setStringValue: [NSString stringWithFormat:
1771                 @"%d", fTitle->job->keep_ratio]];                
1772         [fPicSettingDeinterlace setStringValue: [NSString stringWithFormat:
1773                 @"%d", fTitle->job->deinterlace]];
1774         [fPicSettingPAR setStringValue: [NSString stringWithFormat:
1775                 @"%d", fTitle->job->pixel_ratio]];
1776                 
1777         if (fTitle->job->pixel_ratio == 1)
1778         {
1779         int titlewidth = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3];
1780         int arpwidth = fTitle->job->pixel_aspect_width;
1781         int arpheight = fTitle->job->pixel_aspect_height;
1782         int displayparwidth = titlewidth * arpwidth / arpheight;
1783         int displayparheight = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1];
1784         [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1785                 @"%d", displayparheight]];
1786         [fPicLabelPAROutp setStringValue: @"Anamorphic Output:"];
1787         [fPicLabelPAROutputX setStringValue: @"x"];
1788     [fPicSettingPARWidth setStringValue: [NSString stringWithFormat:
1789         @"%d", displayparwidth]];
1790         [fPicSettingPARHeight setStringValue: [NSString stringWithFormat:
1791         @"%d", displayparheight]];
1792
1793         fTitle->job->keep_ratio = 0;
1794         }
1795         else
1796         {
1797         [fPicLabelPAROutp setStringValue: @""];
1798         [fPicLabelPAROutputX setStringValue: @""];
1799         [fPicSettingPARWidth setStringValue: @""];
1800         [fPicSettingPARHeight setStringValue:  @""];
1801         }
1802                 
1803         /* Set ON/Off values for the deinterlace/keep aspect ratio according to boolean */      
1804         if (fTitle->job->keep_ratio > 0)
1805                 {
1806                 [fPicSettingARkeepDsply setStringValue: @"On"];
1807         }
1808                 else
1809                 {
1810                 [fPicSettingARkeepDsply setStringValue: @"Off"];
1811                 }       
1812         if (fTitle->job->deinterlace > 0)
1813                 {
1814                 [fPicSettingDeinterlaceDsply setStringValue: @"On"];
1815         }
1816                 else
1817                 {
1818                 [fPicSettingDeinterlaceDsply setStringValue: @"Off"];
1819                 }
1820         if (fTitle->job->pixel_ratio > 0)
1821                 {
1822                 [fPicSettingPARDsply setStringValue: @"On"];
1823         }
1824                 else
1825                 {
1826                 [fPicSettingPARDsply setStringValue: @"Off"];
1827                 }       
1828         /* below will trigger the preset, if selected, to be
1829         changed to "Custom". Lets comment out for now until
1830         we figure out a way to determine if the picture values
1831         changed modify the preset values */     
1832         //[self CustomSettingUsed: sender];
1833 }
1834
1835 - (IBAction) CalculateBitrate: (id) sender
1836 {
1837     if( !fHandle || [fVidQualityMatrix selectedRow] != 0 )
1838     {
1839         return;
1840     }
1841
1842     hb_list_t  * list  = hb_get_titles( fHandle );
1843     hb_title_t * title = (hb_title_t *) hb_list_item( list,
1844             [fSrcTitlePopUp indexOfSelectedItem] );
1845     hb_job_t * job = title->job;
1846
1847     [self PrepareJob];
1848
1849     [fVidBitrateField setIntValue: hb_calc_bitrate( job,
1850             [fVidTargetSizeField intValue] )];
1851                         
1852                         
1853 }
1854
1855 /* Method to determine if we should change the UI
1856 To reflect whether or not a Preset is being used or if
1857 the user is using "Custom" settings by determining the sender*/
1858 - (IBAction) CustomSettingUsed: (id) sender
1859 {
1860         if ([sender stringValue] != NULL)
1861         {
1862                 /* Deselect the currently selected Preset if there is one*/
1863                 [tableView deselectRow:[tableView selectedRow]];
1864                 /* Change UI to show "Custom" settings are being used */
1865                 [fPresetSelectedDisplay setStringValue: @"Custom"];
1866                 
1867                 curUserPresetChosenNum = nil;
1868                 /* If we have MP4, AVC H.264 and x264 Main then we look to see
1869                         if there are any x264 options from the preferences to use */
1870                 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1)
1871                 {
1872                     /* Lets check to see there is a specified string in the prefs, and use that if need be */
1873                         if ([[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] != @"")
1874                         {
1875                                 [fDisplayX264Options setStringValue: [NSString stringWithFormat:[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"]]];
1876                         }
1877                 }
1878                 else
1879                 {
1880                         /* Empty the field to display custom x264 preset options*/
1881                         [fDisplayX264Options setStringValue: @""];
1882                 }
1883                 
1884         }
1885         [self X264AdvancedOptionsSet:NULL];
1886 }
1887
1888 - (IBAction) X264AdvancedOptionsSet: (id) sender
1889 {
1890     /*Set opt widget values here*/
1891     
1892     /*B-Frames fX264optBframesPopUp*/
1893     int i;
1894     [fX264optBframesPopUp removeAllItems];
1895     [fX264optBframesPopUp addItemWithTitle:@"Default (0)"];
1896     for (i=0; i<17;i++)
1897     {
1898         [fX264optBframesPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1899     }
1900     
1901     /*Reference Frames fX264optRefPopUp*/
1902     [fX264optRefPopUp removeAllItems];
1903     [fX264optRefPopUp addItemWithTitle:@"Default (1)"];
1904     for (i=0; i<17;i++)
1905     {
1906         [fX264optRefPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1907     }
1908     
1909     /*No Fast P-Skip fX264optNfpskipPopUp BOOLEAN*/
1910     [fX264optNfpskipPopUp removeAllItems];
1911     [fX264optNfpskipPopUp addItemWithTitle:@"Default (No)"];
1912     for (i=0; i<2;i++)
1913     {
1914         if (i==0)
1915         {
1916             [fX264optNfpskipPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
1917         }
1918         else
1919         {
1920             [fX264optNfpskipPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
1921         }
1922     }
1923     
1924     /*No Dict Decimate fX264optNodctdcmtPopUp BOOLEAN*/
1925     [fX264optNodctdcmtPopUp removeAllItems];
1926     [fX264optNodctdcmtPopUp addItemWithTitle:@"Default (No)"];
1927     for (i=0; i<2;i++)
1928     {
1929         if (i==0)
1930         {
1931             [fX264optNodctdcmtPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
1932         }
1933         else
1934         {
1935             [fX264optNodctdcmtPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
1936         }
1937     }
1938     
1939     /*Sub Me fX264optSubmePopUp*/
1940     [fX264optSubmePopUp removeAllItems];
1941     [fX264optSubmePopUp addItemWithTitle:@"Default (4)"];
1942     for (i=0; i<8;i++)
1943     {
1944         [fX264optSubmePopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1945     }
1946     
1947     /*Trellis fX264optTrellisPopUp*/
1948     [fX264optTrellisPopUp removeAllItems];
1949     [fX264optTrellisPopUp addItemWithTitle:@"Default (0)"];
1950     for (i=0; i<3;i++)
1951     {
1952         [fX264optTrellisPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1953     }
1954     
1955     /*Mixed-references fX264optMixedRefsPopUp BOOLEAN*/
1956     [fX264optMixedRefsPopUp removeAllItems];
1957     [fX264optMixedRefsPopUp addItemWithTitle:@"Default (No)"];
1958     for (i=0; i<2;i++)
1959     {
1960         if (i==0)
1961         {
1962             [fX264optMixedRefsPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
1963         }
1964         else
1965         {
1966             [fX264optMixedRefsPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
1967         }
1968     }
1969     
1970     /*Motion Estimation fX264optMotionEstPopUp*/
1971     [fX264optMotionEstPopUp removeAllItems];
1972     [fX264optMotionEstPopUp addItemWithTitle:@"Default (Hexagon)"];
1973     [fX264optMotionEstPopUp addItemWithTitle:@"Diamond"];
1974     [fX264optMotionEstPopUp addItemWithTitle:@"Hexagon"];
1975     [fX264optMotionEstPopUp addItemWithTitle:@"Uneven Multi-Hexagon"];
1976     [fX264optMotionEstPopUp addItemWithTitle:@"Exhaustive"];
1977     
1978     /*Motion Estimation range fX264optMERangePopUp*/
1979     [fX264optMERangePopUp removeAllItems];
1980     [fX264optMERangePopUp addItemWithTitle:@"Default (16)"];
1981     for (i=4; i<65;i++)
1982     {
1983         [fX264optMERangePopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1984     }
1985     
1986     /*Weighted B-Frame Prediction fX264optWeightBPopUp BOOLEAN*/
1987     [fX264optWeightBPopUp removeAllItems];
1988     [fX264optWeightBPopUp addItemWithTitle:@"Default (No)"];
1989     for (i=0; i<2;i++)
1990     {
1991         if (i==0)
1992         {
1993             [fX264optWeightBPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
1994         }
1995         else
1996         {
1997             [fX264optWeightBPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
1998         }
1999     }
2000     
2001     /*B-Frame Rate Distortion Optimization fX264optBRDOPopUp BOOLEAN*/
2002     [fX264optBRDOPopUp removeAllItems];
2003     [fX264optBRDOPopUp addItemWithTitle:@"Default (No)"];
2004     for (i=0; i<2;i++)
2005     {
2006         if (i==0)
2007         {
2008             [fX264optBRDOPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
2009         }
2010         else
2011         {
2012             [fX264optBRDOPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
2013         }
2014     }
2015     
2016     /*B-frame Pyramids fX264optBPyramidPopUp BOOLEAN*/
2017     [fX264optBPyramidPopUp removeAllItems];
2018     [fX264optBPyramidPopUp addItemWithTitle:@"Default (No)"];
2019     for (i=0; i<2;i++)
2020     {
2021         if (i==0)
2022         {
2023             [fX264optBPyramidPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
2024         }
2025         else
2026         {
2027             [fX264optBPyramidPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
2028         }
2029     }
2030     
2031     /* Standardize the option string */
2032     [self X264AdvancedOptionsStandardizeOptString: NULL];
2033     /* Set Current GUI Settings based on newly standardized string */
2034     [self X264AdvancedOptionsSetCurrentSettings: NULL];
2035 }
2036
2037 - (IBAction) X264AdvancedOptionsStandardizeOptString: (id) sender
2038 {
2039     /* Set widgets depending on the opt string in field */
2040     NSString * thisOpt; // The separated option such as "bframes=3"
2041     NSString * optName = @""; // The option name such as "bframes"
2042     NSString * optValue = @"";// The option value such as "3"
2043     NSString * changedOptString = @"";
2044     NSArray *currentOptsArray;
2045
2046     /*First, we get an opt string to process */
2047     NSString *currentOptString = [fDisplayX264Options stringValue];
2048
2049     /*verify there is an opt string to process */
2050     NSRange currentOptRange = [currentOptString rangeOfString:@"="];
2051     if (currentOptRange.location != NSNotFound)
2052     {
2053         /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2054         currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2055
2056         /*iterate through the array and get <opts> and <values*/
2057         //NSEnumerator * enumerator = [currentOptsArray objectEnumerator];
2058         int loopcounter;
2059         int currentOptsArrayCount = [currentOptsArray count];
2060         for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2061         {
2062             thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2063             
2064             NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2065             if (splitOptRange.location != NSNotFound)
2066             {
2067                 optName = [thisOpt substringToIndex:splitOptRange.location];
2068                 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2069                 
2070                 /* Standardize the names here depending on whats in the string */
2071                 optName = [self X264AdvancedOptionsStandardizeOptNames:optName];
2072                 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,optValue];        
2073             }
2074             else // No value given so we use a default of "1"
2075             {
2076                 optName = thisOpt;
2077                 /* Standardize the names here depending on whats in the string */
2078                 optName = [self X264AdvancedOptionsStandardizeOptNames:optName];
2079                 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,1];
2080             }
2081             
2082             /* Construct New String for opts here */
2083             if ([thisOpt isEqualToString:@""])
2084             {
2085                 changedOptString = [NSString stringWithFormat:@"%@%@",changedOptString,thisOpt];
2086             }
2087             else
2088             {
2089                 if ([changedOptString isEqualToString:@""])
2090                 {
2091                     changedOptString = [NSString stringWithFormat:@"%@",thisOpt];
2092                 }
2093                 else
2094                 {
2095                     changedOptString = [NSString stringWithFormat:@"%@:%@",changedOptString,thisOpt];
2096                 }
2097             }
2098         }
2099     }
2100     
2101     /* Change the option string to reflect the new standardized option string */
2102     [fDisplayX264Options setStringValue:[NSString stringWithFormat:changedOptString]];
2103 }
2104
2105 - (NSString *) X264AdvancedOptionsStandardizeOptNames:(NSString *) cleanOptNameString
2106 {
2107     if ([cleanOptNameString isEqualToString:@"ref"] || [cleanOptNameString isEqualToString:@"frameref"])
2108     {
2109         cleanOptNameString = @"ref";
2110     }
2111     
2112     /*No Fast PSkip nofast_pskip*/
2113     if ([cleanOptNameString isEqualToString:@"no-fast-pskip"] || [cleanOptNameString isEqualToString:@"no_fast_pskip"] || [cleanOptNameString isEqualToString:@"nofast_pskip"])
2114     {
2115         cleanOptNameString = @"no-fast-pskip";
2116     }
2117     
2118     /*No Dict Decimate*/
2119     if ([cleanOptNameString isEqualToString:@"no-dct-decimate"] || [cleanOptNameString isEqualToString:@"no_dct_decimate"] || [cleanOptNameString isEqualToString:@"nodct_decimate"])
2120     {
2121         cleanOptNameString = @"no-dct-decimate";
2122     }
2123     
2124     /*Subme*/
2125     if ([cleanOptNameString isEqualToString:@"subme"])
2126     {
2127         cleanOptNameString = @"subq";
2128     }
2129     
2130     /*ME Range*/
2131     if ([cleanOptNameString isEqualToString:@"me-range"] || [cleanOptNameString isEqualToString:@"me_range"])
2132         cleanOptNameString = @"merange";
2133     
2134     /*WeightB*/
2135     if ([cleanOptNameString isEqualToString:@"weight-b"] || [cleanOptNameString isEqualToString:@"weight_b"])
2136     {
2137         cleanOptNameString = @"weightb";
2138     }
2139     
2140     /*BRDO*/
2141     if ([cleanOptNameString isEqualToString:@"b-rdo"] || [cleanOptNameString isEqualToString:@"b_rdo"])
2142     {
2143         cleanOptNameString = @"brdo";
2144     }
2145     
2146     /*B Pyramid*/
2147     if ([cleanOptNameString isEqualToString:@"b_pyramid"])
2148     {
2149         cleanOptNameString = @"b-pyramid";
2150     }
2151     
2152     return cleanOptNameString;  
2153 }
2154
2155 - (IBAction) X264AdvancedOptionsSetCurrentSettings: (id) sender
2156 {
2157     /* Set widgets depending on the opt string in field */
2158     NSString * thisOpt; // The separated option such as "bframes=3"
2159     NSString * optName = @""; // The option name such as "bframes"
2160     NSString * optValue = @"";// The option value such as "3"
2161     NSArray *currentOptsArray;
2162     
2163     /*First, we get an opt string to process */
2164     //NSString *currentOptString = @"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2";
2165     NSString *currentOptString = [fDisplayX264Options stringValue];
2166     
2167     /*verify there is an opt string to process */
2168     NSRange currentOptRange = [currentOptString rangeOfString:@"="];
2169     if (currentOptRange.location != NSNotFound)
2170     {
2171         /* lets clean the opt string here to standardize any names*/
2172         /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2173         currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2174         
2175         /*iterate through the array and get <opts> and <values*/
2176         //NSEnumerator * enumerator = [currentOptsArray objectEnumerator];
2177         int loopcounter;
2178         int currentOptsArrayCount = [currentOptsArray count];
2179         
2180         /*iterate through the array and get <opts> and <values*/
2181         for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2182         {
2183             thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2184             NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2185             
2186             if (splitOptRange.location != NSNotFound)
2187             {
2188                 optName = [thisOpt substringToIndex:splitOptRange.location];
2189                 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2190            
2191                 /*Run through the available widgets for x264 opts and set them, as you add widgets, 
2192                 they need to be added here. This should be moved to its own method probably*/
2193            
2194                 /*bframes NSPopUpButton*/
2195                 if ([optName isEqualToString:@"bframes"])
2196                 {
2197                     [fX264optBframesPopUp selectItemAtIndex:[optValue intValue]+1];
2198                 }
2199                 /*ref NSPopUpButton*/
2200                 if ([optName isEqualToString:@"ref"])
2201                 {
2202                    [fX264optRefPopUp selectItemAtIndex:[optValue intValue]+1];
2203                 }
2204                 /*No Fast PSkip NSPopUpButton*/
2205                 if ([optName isEqualToString:@"no-fast-pskip"])
2206                 {
2207                     [fX264optNfpskipPopUp selectItemAtIndex:[optValue intValue]+1];
2208                 }
2209                 /*No Dict Decimate NSPopUpButton*/
2210                 if ([optName isEqualToString:@"no-dct-decimate"])
2211                 {
2212                     [fX264optNodctdcmtPopUp selectItemAtIndex:[optValue intValue]+1];
2213                 }
2214                 /*Sub Me NSPopUpButton*/
2215                 if ([optName isEqualToString:@"subq"])
2216                 {
2217                     [fX264optSubmePopUp selectItemAtIndex:[optValue intValue]+1];
2218                 }
2219                 /*Trellis NSPopUpButton*/
2220                 if ([optName isEqualToString:@"trellis"])
2221                 {
2222                     [fX264optTrellisPopUp selectItemAtIndex:[optValue intValue]+1];
2223                 }
2224                 /*Mixed Refs NSPopUpButton*/
2225                 if ([optName isEqualToString:@"mixed-refs"])
2226                 {
2227                     [fX264optMixedRefsPopUp selectItemAtIndex:[optValue intValue]+1];
2228                 }
2229                 /*Motion Estimation NSPopUpButton*/
2230                 if ([optName isEqualToString:@"me"])
2231                 {
2232                     if ([optValue isEqualToString:@"dia"])
2233                         [fX264optMotionEstPopUp selectItemAtIndex:1];
2234                     else if ([optValue isEqualToString:@"hex"])
2235                         [fX264optMotionEstPopUp selectItemAtIndex:2];
2236                     else if ([optValue isEqualToString:@"umh"])
2237                         [fX264optMotionEstPopUp selectItemAtIndex:3];
2238                     else if ([optValue isEqualToString:@"esa"])
2239                         [fX264optMotionEstPopUp selectItemAtIndex:4];                        
2240                 }
2241                 /*ME Range NSPopUpButton*/
2242                 if ([optName isEqualToString:@"merange"])
2243                 {
2244                     [fX264optMERangePopUp selectItemAtIndex:[optValue intValue]-3];
2245                 }
2246                 /*Weighted B-Frames NSPopUpButton*/
2247                 if ([optName isEqualToString:@"weightb"])
2248                 {
2249                     [fX264optWeightBPopUp selectItemAtIndex:[optValue intValue]+1];
2250                 }
2251                 /*BRDO NSPopUpButton*/
2252                 if ([optName isEqualToString:@"brdo"])
2253                 {
2254                     [fX264optBRDOPopUp selectItemAtIndex:[optValue intValue]+1];
2255                 }
2256                 /*B Pyramid NSPopUpButton*/
2257                 if ([optName isEqualToString:@"b-pyramid"])
2258                 {
2259                     [fX264optBPyramidPopUp selectItemAtIndex:[optValue intValue]+1];
2260                 }
2261                 
2262                                                 
2263             }
2264         }
2265     }
2266 }
2267
2268 - (IBAction) X264AdvancedOptionsChanged: (id) sender
2269 {
2270     /*Determine which outlet is being used and set optName to process accordingly */
2271     NSString * optNameToChange = @""; // The option name such as "bframes"
2272
2273     if (sender == fX264optBframesPopUp)
2274     {
2275         optNameToChange = @"bframes";
2276     }
2277     if (sender == fX264optRefPopUp)
2278     {
2279         optNameToChange = @"ref";
2280     }
2281     if (sender == fX264optNfpskipPopUp)
2282     {
2283         optNameToChange = @"no-fast-pskip";
2284     }
2285     if (sender == fX264optNodctdcmtPopUp)
2286     {
2287         optNameToChange = @"no-dct-decimate";
2288     }
2289     if (sender == fX264optSubmePopUp)
2290     {
2291         optNameToChange = @"subq";
2292     }
2293     if (sender == fX264optTrellisPopUp)
2294     {
2295         optNameToChange = @"trellis";
2296     }
2297     if (sender == fX264optMixedRefsPopUp)
2298     {
2299         optNameToChange = @"mixed-refs";
2300     }
2301     if (sender == fX264optMotionEstPopUp)
2302     {
2303         optNameToChange = @"me";
2304     }
2305     if (sender == fX264optMERangePopUp)
2306     {
2307         optNameToChange = @"merange";
2308     }
2309     if (sender == fX264optWeightBPopUp)
2310     {
2311         optNameToChange = @"weightb";
2312     }
2313     if (sender == fX264optBRDOPopUp)
2314     {
2315         optNameToChange = @"brdo";
2316     }
2317     if (sender == fX264optBPyramidPopUp)
2318     {
2319         optNameToChange = @"b-pyramid";
2320     }
2321     
2322     /* Set widgets depending on the opt string in field */
2323     NSString * thisOpt; // The separated option such as "bframes=3"
2324     NSString * optName = @""; // The option name such as "bframes"
2325     NSString * optValue = @"";// The option value such as "3"
2326     NSArray *currentOptsArray;
2327
2328     /*First, we get an opt string to process */
2329     //EXAMPLE: NSString *currentOptString = @"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2";
2330     NSString *currentOptString = [fDisplayX264Options stringValue];
2331
2332     /*verify there is an occurrence of the opt specified by the sender to change */
2333     /*take care of any multi-value opt names here. This is extremely kludgy, but test for functionality
2334     and worry about pretty later */
2335         
2336         /*First, we create a pattern to check for ":"optNameToChange"=" to modify the option if the name falls after
2337         the first character of the opt string (hence the ":") */
2338         NSString *checkOptNameToChange = [NSString stringWithFormat:@":%@=",optNameToChange];
2339     NSRange currentOptRange = [currentOptString rangeOfString:checkOptNameToChange];
2340         /*Then we create a pattern to check for "<beginning of line>"optNameToChange"=" to modify the option to
2341         see if the name falls at the beginning of the line, where we would not have the ":" as a pattern to test against*/
2342         NSString *checkOptNameToChangeBeginning = [NSString stringWithFormat:@"%@=",optNameToChange];
2343     NSRange currentOptRangeBeginning = [currentOptString rangeOfString:checkOptNameToChangeBeginning];
2344     if (currentOptRange.location != NSNotFound || currentOptRangeBeginning.location == 0)
2345     {
2346         /* Create new empty opt string*/
2347         NSString *changedOptString = @"";
2348
2349         /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2350         currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2351
2352         /*iterate through the array and get <opts> and <values*/
2353         int loopcounter;
2354         int currentOptsArrayCount = [currentOptsArray count];
2355         for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2356         {
2357             thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2358             NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2359
2360             if (splitOptRange.location != NSNotFound)
2361             {
2362                 optName = [thisOpt substringToIndex:splitOptRange.location];
2363                 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2364                 
2365                 /*Run through the available widgets for x264 opts and set them, as you add widgets, 
2366                 they need to be added here. This should be moved to its own method probably*/
2367                 
2368                 /*If the optNameToChange is found, appropriately change the value or delete it if
2369                 "Unspecified" is set.*/
2370                 if ([optName isEqualToString:optNameToChange])
2371                 {
2372                     if ([sender indexOfSelectedItem] == 0) // means that "unspecified" is chosen, lets then remove it from the string
2373                     {
2374                         thisOpt = @"";
2375                     }
2376                     else if ([optNameToChange isEqualToString:@"me"])
2377                     {
2378                         switch ([sender indexOfSelectedItem])
2379                         {   
2380                             case 1:
2381                                thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"dia"];
2382                                break;
2383  
2384                             case 2:
2385                                thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"hex"];
2386                                break;
2387  
2388                             case 3:
2389                                thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"umh"];
2390                                break;
2391  
2392                             case 4:
2393                                thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"esa"];
2394                                break;
2395                             
2396                             default:
2397                                 break;
2398                         }
2399                     }
2400                     else if ([optNameToChange isEqualToString:@"merange"])
2401                     {
2402                         thisOpt = [NSString stringWithFormat:@"%@=%d",optName,[sender indexOfSelectedItem]+3];
2403                     }
2404                     else // we have a valid value to change, so change it
2405                     {
2406                         thisOpt = [NSString stringWithFormat:@"%@=%d",optName,[sender indexOfSelectedItem]-1];
2407                     }
2408                 }
2409             }
2410
2411             /* Construct New String for opts here */
2412             if ([thisOpt isEqualToString:@""])
2413             {
2414                 changedOptString = [NSString stringWithFormat:@"%@%@",changedOptString,thisOpt];
2415             }
2416             else
2417             {
2418                 if ([changedOptString isEqualToString:@""])
2419                 {
2420                     changedOptString = [NSString stringWithFormat:@"%@",thisOpt];
2421                 }
2422                 else
2423                 {
2424                     changedOptString = [NSString stringWithFormat:@"%@:%@",changedOptString,thisOpt];
2425                 }
2426             }
2427         }
2428
2429         /* Change the option string to reflect the new mod settings */
2430         [fDisplayX264Options setStringValue:[NSString stringWithFormat:changedOptString]];      
2431     }
2432     else // if none exists, add it to the string
2433     {
2434         if ([[fDisplayX264Options stringValue] isEqualToString: @""])
2435         {
2436             if ([optNameToChange isEqualToString:@"me"])
2437             {
2438                 switch ([sender indexOfSelectedItem])
2439                 {   
2440                     case 1:
2441                         [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@", 
2442                             [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"dia"]]];
2443                         break;
2444                
2445                     case 2:
2446                         [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@", 
2447                             [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"hex"]]];
2448                         break;
2449                
2450                    case 3:
2451                         [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@", 
2452                             [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"umh"]]];
2453                         break;
2454                
2455                    case 4:
2456                         [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@", 
2457                             [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"esa"]]];
2458                         break;
2459                    
2460                    default:
2461                         break;
2462                 }
2463             }
2464             else if ([optNameToChange isEqualToString:@"merange"])
2465             {
2466                 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@", 
2467                     [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]+3]]];
2468             }
2469             else
2470             {
2471                 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@", 
2472                     [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]-1]]];
2473             }
2474         }
2475         else
2476         {
2477             if ([optNameToChange isEqualToString:@"me"])
2478             {
2479                 switch ([sender indexOfSelectedItem])
2480                 {   
2481                     case 1:
2482                          [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@", 
2483                              [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2484                              [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"dia"]]];
2485                          break;
2486
2487                     case 2:
2488                          [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@", 
2489                              [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2490                              [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"hex"]]];
2491                          break;
2492
2493                     case 3:
2494                          [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@", 
2495                              [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2496                              [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"umh"]]];
2497                          break;
2498
2499                     case 4:
2500                          [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@", 
2501                              [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2502                              [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"esa"]]];
2503                          break;
2504
2505                     default:
2506                          break;
2507                 }
2508             }
2509             else if ([optNameToChange isEqualToString:@"merange"])
2510             {
2511                 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]], 
2512                     [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]+3]]];
2513             }
2514             else
2515             {
2516                 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]], 
2517                     [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]-1]]];
2518             }
2519         }
2520     }
2521
2522     /* We now need to reset the opt widgets since we changed some stuff */              
2523     [self X264AdvancedOptionsSet:NULL];         
2524 }
2525
2526
2527    /* We use this method to recreate new, updated factory
2528    presets */
2529 - (IBAction)AddFactoryPresets:(id)sender
2530 {
2531     /* First, we delete any existing built in presets */
2532     [self DeleteFactoryPresets: sender];
2533     /* Then, we re-create new built in presets programmatically CreatePSPPreset*/
2534         [UserPresets addObject:[self CreateIpodPreset]];
2535         [UserPresets addObject:[self CreateAppleTVPreset]];
2536         [UserPresets addObject:[self CreatePSThreePreset]];
2537         [UserPresets addObject:[self CreatePSPPreset]];
2538     [self AddPreset];
2539 }
2540 - (IBAction)DeleteFactoryPresets:(id)sender
2541 {
2542     //int status;
2543     NSEnumerator *enumerator = [UserPresets objectEnumerator];
2544         id tempObject;
2545     
2546         //NSNumber *index;
2547     NSMutableArray *tempArray;
2548
2549
2550         tempArray = [NSMutableArray array];
2551         /* we look here to see if the preset is we move on to the next one */
2552         while ( tempObject = [enumerator nextObject] )  
2553                 {
2554                         /* if the preset is "Factory" then we put it in the array of
2555                         presets to delete */
2556                         if ([[tempObject objectForKey:@"Type"] intValue] == 0)
2557                         {
2558                                 [tempArray addObject:tempObject];
2559                         }
2560         }
2561         
2562         [UserPresets removeObjectsInArray:tempArray];
2563         [tableView reloadData];
2564         [self savePreset];   
2565
2566 }
2567
2568 - (IBAction) ShowAddPresetPanel: (id) sender
2569 {
2570     /* Deselect the currently selected Preset if there is one*/
2571                 [tableView deselectRow:[tableView selectedRow]];
2572
2573         /* Populate the preset picture settings popup here */
2574         [fPresetNewPicSettingsPopUp removeAllItems];
2575         [fPresetNewPicSettingsPopUp addItemWithTitle:@"None"];
2576         [fPresetNewPicSettingsPopUp addItemWithTitle:@"Current"];
2577         [fPresetNewPicSettingsPopUp addItemWithTitle:@"Source Maximum (post source scan)"];
2578         [fPresetNewPicSettingsPopUp selectItemAtIndex: 0];      
2579         
2580                 /* Erase info from the input fields */
2581         [fPresetNewName setStringValue: @""];
2582         /* Show the panel */
2583         [NSApp beginSheet: fAddPresetPanel modalForWindow: fWindow
2584         modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
2585     [NSApp runModalForWindow: fAddPresetPanel];
2586     [NSApp endSheet: fAddPresetPanel];
2587     [fAddPresetPanel orderOut: self];
2588         
2589         
2590 }
2591 - (IBAction) CloseAddPresetPanel: (id) sender
2592 {
2593         [NSApp stopModal];
2594 }
2595
2596
2597 - (IBAction)AddUserPreset:(id)sender
2598 {
2599
2600     /* Here we create a custom user preset */
2601         [UserPresets addObject:[self CreatePreset]];
2602         /* Erase info from the input fields */
2603         [fPresetNewName setStringValue: @""];
2604         /* We stop the modal window for the new preset */
2605         [NSApp stopModal];
2606     [self AddPreset];
2607         
2608
2609 }
2610 - (void)AddPreset
2611 {
2612
2613         
2614         /* We Sort the Presets By Factory or Custom */
2615         NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type" 
2616                                                     ascending:YES] autorelease];
2617         /* We Sort the Presets Alphabetically by name */
2618         NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName" 
2619                                                     ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
2620         NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
2621         NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
2622         [UserPresets setArray:sortedArray];
2623         
2624         
2625         /* We Reload the New Table data for presets */
2626     [tableView reloadData];
2627    /* We save all of the preset data here */
2628     [self savePreset];
2629 }
2630
2631 - (IBAction)InsertPreset:(id)sender
2632 {
2633     int index = [tableView selectedRow];
2634     [UserPresets insertObject:[self CreatePreset] atIndex:index];
2635     [tableView reloadData];
2636     [self savePreset];
2637 }
2638
2639 - (NSDictionary *)CreatePreset
2640 {
2641     NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2642         /* Get the New Preset Name from the field in the AddPresetPanel */
2643     [preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"];
2644         /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
2645         [preset setObject:[NSNumber numberWithInt:1] forKey:@"Type"];
2646         /*Set whether or not this is default, at creation set to 0*/
2647         [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2648         /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2649         [preset setObject:[NSNumber numberWithInt:[fPresetNewPicSettingsPopUp indexOfSelectedItem]] forKey:@"UsesPictureSettings"];
2650         /* File Format */
2651     [preset setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
2652         /* Chapter Markers fCreateChapterMarkers*/
2653         [preset setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"];
2654         /* Codecs */
2655         [preset setObject:[fDstCodecsPopUp titleOfSelectedItem] forKey:@"FileCodecs"];
2656         /* Video encoder */
2657         [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
2658         /* x264 Option String */
2659         [preset setObject:[fDisplayX264Options stringValue] forKey:@"x264Option"];
2660         
2661         [preset setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"];
2662         [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2663         [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
2664         [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2665         
2666         /* Video framerate */
2667         [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
2668         /* GrayScale */
2669         [preset setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"];
2670         /* 2 Pass Encoding */
2671         [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
2672         
2673         /*Picture Settings*/
2674         hb_job_t * job = fTitle->job;
2675         /* Basic Picture Settings */
2676         /* Use Max Picture settings for whatever the dvd is.*/
2677         [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
2678         [preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
2679         [preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
2680         [preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
2681         [preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
2682         [preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
2683         /* Set crop settings here */
2684         /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2685         [preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
2686     [preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
2687         [preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
2688         [preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
2689         
2690         /*Audio*/
2691         /* Audio Sample Rate*/
2692         [preset setObject:[fAudRatePopUp titleOfSelectedItem] forKey:@"AudioSampleRate"];
2693         /* Audio Bitrate Rate*/
2694         [preset setObject:[fAudBitratePopUp titleOfSelectedItem] forKey:@"AudioBitRate"];
2695         /* Subtitles*/
2696         [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"];
2697         
2698
2699     [preset autorelease];
2700     return preset;
2701
2702 }
2703
2704 - (NSDictionary *)CreateIpodPreset
2705 {
2706     NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2707         /* Get the New Preset Name from the field in the AddPresetPanel */
2708     [preset setObject:@"HB-iPod" forKey:@"PresetName"];
2709         /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
2710         [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
2711         /*Set whether or not this is default, at creation set to 0*/
2712         [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2713         /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2714         [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesPictureSettings"];
2715         /* File Format */
2716     [preset setObject:@"MP4 file" forKey:@"FileFormat"];
2717         /* Chapter Markers*/
2718          [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
2719     /* Codecs */
2720         [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
2721         /* Video encoder */
2722         [preset setObject:@"x264 (h.264 iPod)" forKey:@"VideoEncoder"];
2723         /* x264 Option String */
2724         [preset setObject:@"frameref=1:bframes=0:nofast_pskip:subq=6:partitions=p8x8,p8x4,p4x8,i4x4:qcomp=0:me=umh:nodct_decimate" forKey:@"x264Option"];
2725         /* Video quality */
2726         [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
2727         [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2728         [preset setObject:@"1500" forKey:@"VideoAvgBitrate"];
2729         [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2730         
2731         /* Video framerate */
2732         [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
2733         /* GrayScale */
2734         [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
2735         /* 2 Pass Encoding */
2736         [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
2737         
2738         /*Picture Settings*/
2739         //hb_job_t * job = fTitle->job;
2740         /* Basic Picture Settings */
2741         /* Use Max Picture settings for whatever the dvd is.*/
2742         [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
2743         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureWidth"];
2744         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
2745         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
2746         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
2747         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PicturePAR"];
2748         /* Set crop settings here */
2749         /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2750         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
2751     [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
2752         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
2753         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
2754         
2755         /*Audio*/
2756         /* Audio Sample Rate*/
2757         [preset setObject:@"48" forKey:@"AudioSampleRate"];
2758         /* Audio Bitrate Rate*/
2759         [preset setObject:@"160" forKey:@"AudioBitRate"];
2760         /* Subtitles*/
2761         [preset setObject:@"None" forKey:@"Subtitles"];
2762         
2763
2764     [preset autorelease];
2765     return preset;
2766
2767 }
2768
2769 - (NSDictionary *)CreateAppleTVPreset
2770 {
2771     NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2772         /* Get the New Preset Name from the field in the AddPresetPanel */
2773     [preset setObject:@"HB-AppleTV" forKey:@"PresetName"];
2774         /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
2775         [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
2776         /*Set whether or not this is default, at creation set to 0*/
2777         [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2778         /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2779         [preset setObject:[NSNumber numberWithInt:2] forKey:@"UsesPictureSettings"];
2780         /* File Format */
2781     [preset setObject:@"MP4 file" forKey:@"FileFormat"];
2782         /* Chapter Markers*/
2783          [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
2784         /* Codecs */
2785         [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
2786         /* Video encoder */
2787         [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
2788         /* x264 Option String (We can use this to tweak the appleTV output)*/
2789         [preset setObject:@"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2" forKey:@"x264Option"];
2790         /* Video quality */
2791         [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
2792         [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2793         [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
2794         [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2795         
2796         /* Video framerate */
2797         [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
2798         /* GrayScale */
2799         [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
2800         /* 2 Pass Encoding */
2801         [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
2802         
2803         /*Picture Settings*/
2804         /* For AppleTV we only want to retain UsesMaxPictureSettings
2805         which depend on the source dvd picture settings, so we don't
2806         record the current dvd's picture info since it will vary from
2807         source to source*/
2808         //hb_job_t * job = fTitle->job;
2809         //hb_job_t * job = title->job;
2810         /* Basic Picture Settings */
2811         /* Use Max Picture settings for whatever the dvd is.*/
2812         [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
2813         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureWidth"];
2814         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
2815         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
2816         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
2817         [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
2818         /* Set crop settings here */
2819         /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2820         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
2821     [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
2822         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
2823         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
2824         
2825         /*Audio*/
2826         /* Audio Sample Rate*/
2827         [preset setObject:@"48" forKey:@"AudioSampleRate"];
2828         /* Audio Bitrate Rate*/
2829         [preset setObject:@"160" forKey:@"AudioBitRate"];
2830         /* Subtitles*/
2831         [preset setObject:@"None" forKey:@"Subtitles"];
2832         
2833
2834     [preset autorelease];
2835     return preset;
2836
2837 }
2838
2839 - (NSDictionary *)CreatePSThreePreset
2840 {
2841     NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2842         /* Get the New Preset Name from the field in the AddPresetPanel */
2843     [preset setObject:@"HB-PS3" forKey:@"PresetName"];
2844         /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
2845         [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
2846         /*Set whether or not this is default, at creation set to 0*/
2847         [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2848         /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2849         [preset setObject:[NSNumber numberWithInt:2] forKey:@"UsesPictureSettings"];
2850         /* File Format */
2851     [preset setObject:@"MP4 file" forKey:@"FileFormat"];
2852         /* Chapter Markers*/
2853          [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
2854         /* Codecs */
2855         [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
2856         /* Video encoder */
2857         [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
2858         /* x264 Option String (We can use this to tweak the appleTV output)*/
2859         [preset setObject:@"level=41" forKey:@"x264Option"];
2860         /* Video quality */
2861         [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
2862         [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2863         [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
2864         [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2865         
2866         /* Video framerate */
2867         [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
2868         /* GrayScale */
2869         [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
2870         /* 2 Pass Encoding */
2871         [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
2872         
2873         /*Picture Settings*/
2874         /* For PS3 we only want to retain UsesMaxPictureSettings
2875         which depend on the source dvd picture settings, so we don't
2876         record the current dvd's picture info since it will vary from
2877         source to source*/
2878         /* Use Max Picture settings for whatever the dvd is.*/
2879         [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
2880         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureWidth"];
2881         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
2882         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
2883         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
2884         [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
2885         /* Set crop settings here */
2886         /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2887         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
2888     [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
2889         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
2890         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
2891         
2892         /*Audio*/
2893         /* Audio Sample Rate*/
2894         [preset setObject:@"48" forKey:@"AudioSampleRate"];
2895         /* Audio Bitrate Rate*/
2896         [preset setObject:@"160" forKey:@"AudioBitRate"];
2897         /* Subtitles*/
2898         [preset setObject:@"None" forKey:@"Subtitles"];
2899         
2900
2901     [preset autorelease];
2902     return preset;
2903
2904 }
2905 - (NSDictionary *)CreatePSPPreset
2906 {
2907     NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2908         /* Get the New Preset Name from the field in the AddPresetPanel */
2909     [preset setObject:@"HB-PSP" forKey:@"PresetName"];
2910         /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
2911         [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
2912         /*Set whether or not this is default, at creation set to 0*/
2913         [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2914         /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2915         [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
2916         /* File Format */
2917     [preset setObject:@"MP4 file" forKey:@"FileFormat"];
2918         /* Chapter Markers*/
2919          [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
2920         /* Codecs */
2921         [preset setObject:@"MPEG-4 Video / AAC Audio" forKey:@"FileCodecs"];
2922         /* Video encoder */
2923         [preset setObject:@"FFmpeg" forKey:@"VideoEncoder"];
2924         /* x264 Option String (We can use this to tweak the appleTV output)*/
2925         [preset setObject:@"" forKey:@"x264Option"];
2926         /* Video quality */
2927         [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
2928         [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2929         [preset setObject:@"1024" forKey:@"VideoAvgBitrate"];
2930         [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2931         
2932         /* Video framerate */
2933         [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
2934         /* GrayScale */
2935         [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
2936         /* 2 Pass Encoding */
2937         [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
2938         
2939         /*Picture Settings*/
2940         /* For PS3 we only want to retain UsesMaxPictureSettings
2941         which depend on the source dvd picture settings, so we don't
2942         record the current dvd's picture info since it will vary from
2943         source to source*/
2944         /* Use Max Picture settings for whatever the dvd is.*/
2945         [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
2946         [preset setObject:@"368" forKey:@"PictureWidth"];
2947         [preset setObject:@"208" forKey:@"PictureHeight"];
2948         [preset setObject:[NSNumber numberWithInt:1] forKey:@"PictureKeepRatio"];
2949         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
2950         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PicturePAR"];
2951         /* Set crop settings here */
2952         /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2953         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
2954     [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
2955         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
2956         [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
2957         
2958         /*Audio*/
2959         /* Audio Sample Rate*/
2960         [preset setObject:@"48" forKey:@"AudioSampleRate"];
2961         /* Audio Bitrate Rate*/
2962         [preset setObject:@"128" forKey:@"AudioBitRate"];
2963         /* Subtitles*/
2964         [preset setObject:@"None" forKey:@"Subtitles"];
2965         
2966
2967     [preset autorelease];
2968     return preset;
2969
2970 }
2971
2972
2973 - (IBAction)DeletePreset:(id)sender
2974 {
2975     int status;
2976     NSEnumerator *enumerator;
2977     NSNumber *index;
2978     NSMutableArray *tempArray;
2979     id tempObject;
2980     
2981     if ( [tableView numberOfSelectedRows] == 0 )
2982         return;
2983     /* Alert user before deleting preset */
2984         /* Comment out for now, tie to user pref eventually */
2985
2986     //NSBeep();
2987     status = NSRunAlertPanel(@"Warning!", @"Are you sure that you want to delete the selected preset?", @"OK", @"Cancel", nil);
2988     
2989     if ( status == NSAlertDefaultReturn ) {
2990         enumerator = [tableView selectedRowEnumerator];
2991         tempArray = [NSMutableArray array];
2992         
2993         while ( (index = [enumerator nextObject]) ) {
2994             tempObject = [UserPresets objectAtIndex:[index intValue]];
2995             [tempArray addObject:tempObject];
2996         }
2997         
2998         [UserPresets removeObjectsInArray:tempArray];
2999         [tableView reloadData];
3000         [self savePreset];   
3001     }
3002 }
3003 - (IBAction)tableViewSelected:(id)sender
3004 {
3005     /* Since we cannot disable the presets tableView in terms of clickability
3006            we will use the enabled state of the add presets button to determine whether
3007            or not clicking on a preset will do anything */
3008         if ([fPresetsAdd isEnabled])
3009         {
3010                 
3011                 /* we get the chosen preset from the UserPresets array */
3012                 chosenPreset = [UserPresets objectAtIndex:[sender selectedRow]];
3013                 curUserPresetChosenNum = [sender selectedRow];
3014                 /* we set the preset display field in main window here */
3015                 [fPresetSelectedDisplay setStringValue: [NSString stringWithFormat: @"%@",[chosenPreset valueForKey:@"PresetName"]]];
3016                 /* File Format */
3017                 [fDstFormatPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileFormat"]]];
3018                 [self FormatPopUpChanged: NULL];
3019                 /* Chapter Markers*/
3020                 [fCreateChapterMarkers setState:[[chosenPreset objectForKey:@"ChapterMarkers"] intValue]];
3021             /* Codecs */
3022                 [fDstCodecsPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileCodecs"]]];
3023                 [self CodecsPopUpChanged: NULL];
3024                 /* Video encoder */
3025                 [fVidEncoderPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoEncoder"]]];
3026                 
3027                 /* We can show the preset options here in the gui if we want to
3028                         so we check to see it the user has specified it in the prefs */
3029                 [fDisplayX264Options setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"x264Option"]]];
3030
3031                 [self X264AdvancedOptionsSet:NULL];
3032                 
3033                 /* Lets run through the following functions to get variables set there */
3034                 [self EncoderPopUpChanged: NULL];
3035                 [self CalculateBitrate: NULL];
3036                 
3037                 /* Video quality */
3038                 [fVidQualityMatrix selectCellAtRow:[[chosenPreset objectForKey:@"VideoQualityType"] intValue] column:0];
3039                 
3040                 [fVidTargetSizeField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoTargetSize"]]];
3041                 [fVidBitrateField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoAvgBitrate"]]];
3042                 
3043                 [fVidQualitySlider setFloatValue: [[chosenPreset valueForKey:@"VideoQualitySlider"] floatValue]];
3044                 [self VideoMatrixChanged: NULL];
3045                 
3046                 /* Video framerate */
3047                 [fVidRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoFramerate"]]];
3048
3049                 /* GrayScale */
3050                 [fVidGrayscaleCheck setState:[[chosenPreset objectForKey:@"VideoGrayScale"] intValue]];
3051                 
3052                 /* 2 Pass Encoding */
3053                 [fVidTwoPassCheck setState:[[chosenPreset objectForKey:@"VideoTwoPass"] intValue]];
3054                 
3055                 
3056                 /*Audio*/
3057                 
3058                 /* Audio Sample Rate*/
3059                 [fAudRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioSampleRate"]]];
3060                 /* Audio Bitrate Rate*/
3061                 [fAudBitratePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioBitRate"]]];
3062                 /*Subtitles*/
3063                 [fSubPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"Subtitles"]]];
3064                 
3065                 /* Picture Settings */
3066                 /* Look to see if we apply these here in objectForKey:@"UsesPictureSettings"] */
3067                 if ([[chosenPreset objectForKey:@"UsesPictureSettings"]  intValue] > 0)
3068                 {
3069                         hb_job_t * job = fTitle->job;
3070                         /* Check to see if we should use the max picture setting for the current title*/
3071                         if ([[chosenPreset objectForKey:@"UsesPictureSettings"]  intValue] == 2 || [[chosenPreset objectForKey:@"UsesMaxPictureSettings"]  intValue] == 1)
3072                         {
3073                                 /* Use Max Picture settings for whatever the dvd is.*/
3074                                 [self RevertPictureSizeToMax: NULL];
3075                                 job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"]  intValue];
3076                                 if (job->keep_ratio == 1)
3077                                 {
3078                                         hb_fix_aspect( job, HB_KEEP_WIDTH );
3079                                 }
3080                                 job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"]  intValue];
3081                         }
3082                         else
3083                         {
3084                                 job->width = [[chosenPreset objectForKey:@"PictureWidth"]  intValue];
3085                                 job->height = [[chosenPreset objectForKey:@"PictureHeight"]  intValue];
3086                                 job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"]  intValue];
3087                                 if (job->keep_ratio == 1)
3088                                 {
3089                                         hb_fix_aspect( job, HB_KEEP_WIDTH );
3090                                 }
3091                                 job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"]  intValue];
3092                                 job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"]  intValue];
3093                                 job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"]  intValue];
3094                                 job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"]  intValue];
3095                                 job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"]  intValue];
3096                         }
3097                         [self CalculatePictureSizing: NULL]; 
3098                 }
3099                 
3100
3101
3102
3103 }
3104 }
3105
3106
3107
3108 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
3109 {
3110     return [UserPresets count];
3111 }
3112
3113 /* we use this to determine display characteristics for
3114 each table cell based on content currently only used to
3115 show the built in presets in a blue font. */
3116 - (void)tableView:(NSTableView *)aTableView
3117  willDisplayCell:(id)aCell 
3118  forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
3119 {
3120     NSDictionary *userPresetDict = [UserPresets objectAtIndex:rowIndex];
3121    if ([[userPresetDict objectForKey:@"Type"] intValue] == 0)
3122         {
3123                 [aCell setTextColor:[NSColor blueColor]];
3124         }
3125         else
3126         {
3127                 [aCell setTextColor:[NSColor blackColor]];
3128         }
3129
3130 }
3131
3132 - (id)tableView:(NSTableView *)aTableView
3133       objectValueForTableColumn:(NSTableColumn *)aTableColumn
3134       row:(int)rowIndex
3135 {
3136 id theRecord, theValue;
3137     
3138     theRecord = [UserPresets objectAtIndex:rowIndex];
3139     theValue = [theRecord objectForKey:[aTableColumn identifier]];
3140     return theValue;
3141 }
3142
3143 // NSTableDataSource method that we implement to edit values directly in the table...
3144 - (void)tableView:(NSTableView *)aTableView
3145         setObjectValue:(id)anObject
3146         forTableColumn:(NSTableColumn *)aTableColumn
3147         row:(int)rowIndex
3148 {
3149     id theRecord;
3150     
3151     theRecord = [UserPresets objectAtIndex:rowIndex];
3152     [theRecord setObject:anObject forKey:@"PresetName"];
3153     /* We Sort the Presets By Factory or Custom */
3154         NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type" 
3155                                                     ascending:YES] autorelease];
3156                 /* We Sort the Presets Alphabetically by name */
3157         NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName" 
3158                                                     ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
3159         NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
3160     NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
3161         [UserPresets setArray:sortedArray];
3162         /* We Reload the New Table data for presets */
3163     [tableView reloadData];
3164    /* We save all of the preset data here */
3165     [self savePreset];
3166 }
3167
3168
3169 - (void)savePreset
3170 {
3171     [UserPresets writeToFile:UserPresetsFile atomically:YES];
3172
3173 }
3174
3175
3176
3177 - (void) controlTextDidBeginEditing: (NSNotification *) notification
3178 {
3179     [self CalculateBitrate: NULL];
3180 }
3181
3182 - (void) controlTextDidEndEditing: (NSNotification *) notification
3183 {
3184     [self CalculateBitrate: NULL];
3185 }
3186
3187 - (void) controlTextDidChange: (NSNotification *) notification
3188 {
3189     [self CalculateBitrate: NULL];
3190 }
3191
3192 - (IBAction) OpenHomepage: (id) sender
3193 {
3194     [[NSWorkspace sharedWorkspace] openURL: [NSURL
3195         URLWithString:@"http://handbrake.m0k.org/"]];
3196 }
3197
3198 - (IBAction) OpenForums: (id) sender
3199 {
3200     [[NSWorkspace sharedWorkspace] openURL: [NSURL
3201         URLWithString:@"http://handbrake.m0k.org/forum/"]];
3202 }
3203 - (IBAction) OpenUserGuide: (id) sender
3204 {
3205     [[NSWorkspace sharedWorkspace] openURL: [NSURL
3206         URLWithString:@"http://handbrake.m0k.org/trac/wiki/HandBrakeGuide"]];
3207 }
3208
3209
3210 @end