OSDN Git Service

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