OSDN Git Service

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