OSDN Git Service

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