OSDN Git Service

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