OSDN Git Service

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