OSDN Git Service

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