OSDN Git Service

macGui: Growl Support initial implementation
[handbrake-jp/handbrake-jp-git.git] / macosx / Controller.mm
index d4242ac..7caaf7f 100644 (file)
@@ -5,9 +5,14 @@
    It may be used under the terms of the GNU General Public License. */
 
 #include "Controller.h"
+#include "a52dec/a52.h"
 
 #define _(a) NSLocalizedString(a,NULL)
 
+
+
+
+
 static int FormatSettings[3][4] =
   { { HB_MUX_MP4 | HB_VCODEC_FFMPEG | HB_ACODEC_FAAC,
       HB_MUX_MP4 | HB_VCODEC_X264   | HB_ACODEC_FAAC,
@@ -36,19 +41,27 @@ static int FormatSettings[3][4] =
 
 - (void) applicationDidFinishLaunching: (NSNotification *) notification
 {
+
+
     int    build;
     char * version;
 
+
     /* Init libhb */
     fHandle = hb_init( HB_DEBUG_NONE, [[NSUserDefaults
         standardUserDefaults] boolForKey:@"CheckForUpdates"] );
-
+       /* Set the Growl Delegate */
+       HBController *hbGrowlDelegate = [[HBController alloc] init];
+       [GrowlApplicationBridge setGrowlDelegate: hbGrowlDelegate];    
     /* Init others controllers */
     [fScanController    SetHandle: fHandle];
     [fPictureController SetHandle: fHandle];
     [fQueueController   SetHandle: fHandle];
+       
+    fChapterTitlesDelegate = [[ChapterTitles alloc] init];
+    [fChapterTable setDataSource:fChapterTitlesDelegate];
 
-    /* Call UpdateUI every 2/10 sec */
+     /* Call UpdateUI every 2/10 sec */
     [[NSRunLoop currentRunLoop] addTimer: [NSTimer
         scheduledTimerWithTimeInterval: 0.2 target: self
         selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
@@ -57,8 +70,7 @@ static int FormatSettings[3][4] =
     if( ( build = hb_check_update( fHandle, &version ) ) > -1 )
     {
         /* Update available - tell the user */
-               /* TEMPORARILY COMMENT OUT AS UPDATE CHECK IS NOT ACCURATE */
-                /*
+       
         NSBeginInformationalAlertSheet( _( @"Update is available" ),
             _( @"Go get it!" ), _( @"Discard" ), NULL, fWindow, self,
             @selector( UpdateAlertDone:returnCode:contextInfo: ),
@@ -66,7 +78,7 @@ static int FormatSettings[3][4] =
             _( @"HandBrake %s (build %d) is now available for download." ),
             version, build] );
         return;
-               */
+
     }
 
     /* Show scan panel ASAP */
@@ -94,7 +106,63 @@ static int FormatSettings[3][4] =
 
     [self TranslateStrings];
 
-    /* Destination box */
+
+//[self registrationDictionaryForGrowl];
+/* Init User Presets .plist */
+       /* We declare the default NSFileManager into fileManager */
+       NSFileManager * fileManager = [NSFileManager defaultManager];
+       //presetPrefs = [[NSUserDefaults standardUserDefaults] retain];
+       /* we set the files and support paths here */
+       AppSupportDirectory = @"~/Library/Application Support/HandBrake";
+    AppSupportDirectory = [AppSupportDirectory stringByExpandingTildeInPath];
+    
+       UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
+    UserPresetsFile = [UserPresetsFile stringByExpandingTildeInPath];
+       
+       x264ProfilesFile = @"~/Library/Application Support/HandBrake/x264Profiles.plist";
+    x264ProfilesFile = [x264ProfilesFile stringByExpandingTildeInPath];
+       /* We check for the app support directory for media fork */
+       if ([fileManager fileExistsAtPath:AppSupportDirectory] == 0) 
+       {
+               // If it doesnt exist yet, we create it here 
+               [fileManager createDirectoryAtPath:AppSupportDirectory attributes:nil];
+       }
+       // We check for the presets.plist here
+       
+       if ([fileManager fileExistsAtPath:UserPresetsFile] == 0) 
+       {
+
+               [fileManager createFileAtPath:UserPresetsFile contents:nil attributes:nil];
+               
+       }
+       // We check for the x264profiles.plist here
+        
+       if ([fileManager fileExistsAtPath:x264ProfilesFile] == 0) 
+       {
+        
+               [fileManager createFileAtPath:x264ProfilesFile contents:nil attributes:nil];
+       }
+    
+       
+  UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
+  UserPresetsFile = [[UserPresetsFile stringByExpandingTildeInPath]retain];
+
+  UserPresets = [[NSMutableArray alloc] initWithContentsOfFile:UserPresetsFile];
+  if (nil == UserPresets) 
+  {
+    UserPresets = [[NSMutableArray alloc] init];
+       [self AddFactoryPresets:NULL];
+  }
+  /* Show/Dont Show Presets drawer upon launch based
+  on user preference DefaultPresetsDrawerShow*/
+  if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0)
+               {
+         [fPresetDrawer open];
+               }
+
+
+
+    /* Destination box*/
     [fDstFormatPopUp removeAllItems];
     [fDstFormatPopUp addItemWithTitle: _( @"MP4 file" )];
     [fDstFormatPopUp addItemWithTitle: _( @"AVI file" )];
@@ -102,7 +170,12 @@ static int FormatSettings[3][4] =
     [fDstFormatPopUp selectItemAtIndex: 0];
 
     [self FormatPopUpChanged: NULL];
-
+    /* We enable the create chapters checkbox here since we are .mp4 */        
+       [fCreateChapterMarkers setEnabled: YES];
+       if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultChapterMarkers"] > 0)
+       {
+               [fCreateChapterMarkers setState: NSOnState];
+       }
     [fDstFile2Field setStringValue: [NSString stringWithFormat:
         @"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
 
@@ -113,20 +186,27 @@ static int FormatSettings[3][4] =
 
     /* Video quality */
     [fVidTargetSizeField setIntValue: 700];
-    [fVidBitrateField    setIntValue: 1000];
+       [fVidBitrateField    setIntValue: 1000];
+
     [fVidQualityMatrix   selectCell: fVidBitrateCell];
     [self VideoMatrixChanged: NULL];
 
     /* Video framerate */
     [fVidRatePopUp removeAllItems];
-    [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
+       [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
     for( int i = 0; i < hb_video_rates_count; i++ )
     {
         [fVidRatePopUp addItemWithTitle:
             [NSString stringWithCString: hb_video_rates[i].string]];
     }
     [fVidRatePopUp selectItemAtIndex: 0];
-
+       
+       /* Picture Settings */
+       [fPicLabelPAROutp setStringValue: @""];
+       [fPicLabelPAROutputX setStringValue: @""];
+       [fPicSettingPARWidth setStringValue: @""];
+       [fPicSettingPARHeight setStringValue:  @""];
+       
     /* Audio bitrate */
     [fAudBitratePopUp removeAllItems];
     for( int i = 0; i < hb_audio_bitrates_count; i++ )
@@ -151,8 +231,23 @@ static int FormatSettings[3][4] =
     [self EnableUI: NO];
     [fPauseButton setEnabled: NO];
     [fRipButton setEnabled: NO];
+
+
+
 }
 
+// register a test notification and make
+// it enabled by default
+#define SERVICE_NAME @"Encode Done"
+- (NSDictionary *)registrationDictionaryForGrowl 
+{ 
+NSDictionary *registrationDictionary = [NSDictionary dictionaryWithObjectsAndKeys: 
+[NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_ALL, 
+[NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_DEFAULT, 
+nil]; 
+
+return registrationDictionary; 
+} 
 - (void) TranslateStrings
 {
     [fSrcDVD1Field      setStringValue: _( @"DVD:" )];
@@ -275,6 +370,8 @@ static int FormatSettings[3][4] =
         {
             hb_list_t  * list;
             hb_title_t * title;
+                       int indxpri=0;    // Used to search the longuest title (default in combobox)
+                       int longuestpri=0; // Used to search the longuest title (default in combobox)
 
             [fScanController UpdateUI: &s];
 
@@ -285,6 +382,7 @@ static int FormatSettings[3][4] =
                 break;
             }
 
+
             [fSrcTitlePopUp removeAllItems];
             for( int i = 0; i < hb_list_count( list ); i++ )
             {
@@ -295,9 +393,67 @@ static int FormatSettings[3][4] =
                                
                                /* Use the dvd name in the default output field here 
                                May want to add code to remove blank spaces for some dvd names*/
+                               /* Check to see if the last destination has been set,use if so, if not, use Desktop */
+                               if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"])
+                               {
+                               [fDstFile2Field setStringValue: [NSString stringWithFormat:
+                @"%@/%@.mp4", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[NSString
+                  stringWithUTF8String: title->name]]];
+                               }
+                               else
+                               {
                                [fDstFile2Field setStringValue: [NSString stringWithFormat:
                 @"%@/Desktop/%@.mp4", NSHomeDirectory(),[NSString
                   stringWithUTF8String: title->name]]];
+                               }
+
+                  
+                if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds)
+                {
+                       longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds;
+                       indxpri=i;
+                }
+                
+                               
+                int format = [fDstFormatPopUp indexOfSelectedItem];
+                               char * ext = NULL;
+                               switch( format )
+                {
+                 case 0:
+                                        
+                                        /*Get Default MP4 File Extension for mpeg4 (.mp4 or .m4v) from prefs*/
+                                        if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
+                                        {
+                                        ext = "m4v";
+                                        }
+                                    else
+                                    {
+                                        ext = "mp4";
+                                        }
+                                       break;
+                               case 1: 
+                     ext = "avi";
+                               case 2:
+                                  break;
+                     ext = "ogm";
+                              break;
+                                  }
+                               
+                               
+                               NSString * string = [fDstFile2Field stringValue];
+                               /* Add/replace File Output name to the correct extension*/
+                               if( [string characterAtIndex: [string length] - 4] == '.' )
+                               {
+                                       [fDstFile2Field setStringValue: [NSString stringWithFormat:
+                                               @"%@.%s", [string substringToIndex: [string length] - 4],
+                                               ext]];
+                               }
+                               else
+                               {
+                                       [fDstFile2Field setStringValue: [NSString stringWithFormat:
+                                               @"%@.%s", string, ext]];
+                               }
+
                                
                            [fSrcTitlePopUp addItemWithTitle: [NSString
                     stringWithFormat: @"%d - %02dh%02dm%02ds",
@@ -305,7 +461,12 @@ static int FormatSettings[3][4] =
                     title->seconds]];
                        
             }
-
+            // Select the longuest title
+                       [fSrcTitlePopUp selectItemAtIndex: indxpri];
+            /* We set the Settings Display to "Default" here
+                       until we get default presets implemented */
+                       [fPresetSelectedDisplay setStringValue: @"Default"];
+                       
             [self TitlePopUpChanged: NULL];
             [self EnableUI: YES];
             [fPauseButton setEnabled: NO];
@@ -334,6 +495,7 @@ static int FormatSettings[3][4] =
 
             /* Update slider */
             progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
+            [fRipIndicator setIndeterminate: NO];
             [fRipIndicator setDoubleValue: 100.0 * progress_total];
 
             /* Update dock icon */
@@ -350,19 +512,19 @@ static int FormatSettings[3][4] =
 #define p s.param.muxing
         case HB_STATE_MUXING:
         {
-            float progress_total;
             NSMutableString * string;
                        
             /* Update text field */
             string = [NSMutableString stringWithFormat:
-                _( @"Muxing: %.2f %%" ), 100.0 * p.progress];
+                _( @"Muxing..." )];
             [fStatusField setStringValue: string];
                        
             /* Update slider */
-            [fRipIndicator setDoubleValue: 100.0 * p.progress];
+            [fRipIndicator setIndeterminate: YES];
+            [fRipIndicator startAnimation: nil];
                        
             /* Update dock icon */
-            [self UpdateDockIcon: 100.0 * p.progress];
+            [self UpdateDockIcon: 1.0];
                        
             [fPauseButton setEnabled: YES];
             [fPauseButton setTitle: _( @"Pause" )];
@@ -373,7 +535,7 @@ static int FormatSettings[3][4] =
 #undef p
                        
         case HB_STATE_PAUSED:
-            [fStatusField setStringValue: _( @"Paused" )];
+                   [fStatusField setStringValue: _( @"Paused" )];
             [fPauseButton setEnabled: YES];
             [fPauseButton setTitle: _( @"Resume" )];
             [fRipButton setEnabled: YES];
@@ -382,44 +544,65 @@ static int FormatSettings[3][4] =
 
         case HB_STATE_WORKDONE:
         {
-            [self EnableUI: YES];
+            //[self EnableUI: YES];
             [fStatusField setStringValue: _( @"Done." )];
+            [fRipIndicator setIndeterminate: NO];
             [fRipIndicator setDoubleValue: 0.0];
-            [fRipButton setTitle: _( @"Rip" )];
-
+            [fRipButton setTitle: _( @"Start" )];
+                       
             /* Restore dock icon */
             [self UpdateDockIcon: -1.0];
-
+                       
             [fPauseButton setEnabled: NO];
             [fPauseButton setTitle: _( @"Pause" )];
             [fRipButton setEnabled: YES];
-            [fRipButton setTitle: _( @"Rip" )];
-
+            [fRipButton setTitle: _( @"Start" )];
+                       
             /* FIXME */
             hb_job_t * job;
             while( ( job = hb_job( fHandle, 0 ) ) )
             {
                 hb_rem( fHandle, job );
             }
+            
+                       if (fEncodeState != 2) // if the encode has not been cancelled
+                       {
+                               /* Lets alert the user that the encode has finished */
+                               /*Growl Notification*/
+                               [self showGrowlDoneNotification: NULL];
+                               /*On Screen Notification*/
+                               int status;
+                               NSBeep();
+                               status = NSRunAlertPanel(@"Put down that cocktail...",@"your HandBrake encode is done!", @"OK", nil, nil);
+                               //[NSApp requestUserAttention:NSInformationalRequest];
+                               [NSApp requestUserAttention:NSCriticalRequest];
+                               if ( status == NSAlertDefaultReturn ) 
+                               {
+                                       [self EnableUI: YES];
+                               }
+                       }
+                       else
+                       {
+                       [self EnableUI: YES];
+                       }
             break;
         }
     }
 
-    /* FIXME: we should only do that when necessary */
-    if( [fQueueCheck state] == NSOnState )
-    {
+    /* Lets show the queue status
+       here in the main window*/
+
         int count = hb_count( fHandle );
         if( count )
         {
-            [fQueueCheck setTitle: [NSString stringWithFormat:
-                @"Enable queue (%d task%s in queue)",
+            [fQueueStatus setStringValue: [NSString stringWithFormat:
+                @"%d task%s in the queue",
                 count, ( count > 1 ) ? "s" : ""]];
         }
         else
         {
-            [fQueueCheck setTitle: @"Enable queue (no task in queue)"];
+            [fQueueStatus setStringValue: @""];
         }
-    }
 
     [[NSRunLoop currentRunLoop] addTimer: [NSTimer
         scheduledTimerWithTimeInterval: 0.2 target: self
@@ -427,6 +610,20 @@ static int FormatSettings[3][4] =
         forMode: NSModalPanelRunLoopMode];
 }
 
+-(IBAction)showGrowlDoneNotification:(id)sender
+{
+
+  
+  [GrowlApplicationBridge 
+          notifyWithTitle:@"Put down that cocktail..." 
+              description:@"Thank You for using HandBrake" 
+         notificationName:SERVICE_NAME
+                 iconData:nil 
+                 priority:0 
+                 isSticky:1 
+             clickContext:nil];
+}
+
 - (void) EnableUI: (bool) b
 {
     NSControl * controls[] =
@@ -439,8 +636,16 @@ static int FormatSettings[3][4] =
         fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
         fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp,
         fAudLang1Field, fAudLang1PopUp, fAudLang2Field, fAudLang2PopUp,
+        fAudTrack1MixLabel, fAudTrack1MixPopUp, fAudTrack2MixLabel, fAudTrack2MixPopUp,
         fAudRateField, fAudRatePopUp, fAudBitrateField,
-        fAudBitratePopUp, fPictureButton, fQueueCheck };
+        fAudBitratePopUp, fPictureButton,fQueueStatus, 
+               fPicSrcWidth,fPicSrcHeight,fPicSettingWidth,fPicSettingHeight,
+               fPicSettingARkeep,fPicSettingDeinterlace,fPicSettingARkeepDsply,
+               fPicSettingDeinterlaceDsply,fPicLabelSettings,fPicLabelSrc,fPicLabelOutp,
+               fPicLabelAr,fPicLabelDeinter,fPicLabelSrcX,fPicLabelOutputX,
+               fPicLabelPAROutp,fPicLabelPAROutputX,fPicSettingPARWidth,fPicSettingPARHeight,
+               fPicSettingPARDsply,fPicLabelAnamorphic,tableView,fPresetsAdd,fPresetsDelete,
+               fCreateChapterMarkers,fPresetNewX264OptLabel,fDisplayX264Options};
 
     for( unsigned i = 0;
          i < sizeof( controls ) / sizeof( NSControl * ); i++ )
@@ -456,7 +661,20 @@ static int FormatSettings[3][4] =
             }
         }
         [controls[i] setEnabled: b];
+
     }
+       
+       if (b) {
+
+        /* if we're enabling the interface, check if the audio mixdown controls need to be enabled or not */
+        /* these will have been enabled by the mass control enablement above anyway, so we're sense-checking it here */
+        [self SetEnabledStateOfAudioMixdownControls: NULL];
+       
+       } else {
+
+               [tableView setEnabled: NO];
+       
+       }
 
     [self VideoMatrixChanged: NULL];
 }
@@ -505,6 +723,7 @@ static int FormatSettings[3][4] =
 
     [self QualitySliderChanged: sender];
     [self CalculateBitrate:     sender];
+       [self CustomSettingUsed: sender];
 }
 
 - (IBAction) QualitySliderChanged: (id) sender
@@ -512,17 +731,18 @@ static int FormatSettings[3][4] =
     [fVidConstantCell setTitle: [NSString stringWithFormat:
         _( @"Constant quality: %.0f %%" ), 100.0 *
         [fVidQualitySlider floatValue]]];
+               [self CustomSettingUsed: sender];
 }
 
 - (IBAction) BrowseFile: (id) sender
 {
     /* Open a panel to let the user choose and update the text field */
     NSSavePanel * panel = [NSSavePanel savePanel];
-
-    [panel beginSheetForDirectory: NULL file: NULL
-        modalForWindow: fWindow modalDelegate: self
-        didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
-        contextInfo: NULL];
+       /* We get the current file name and path from the destination field here */
+       [panel beginSheetForDirectory: [[fDstFile2Field stringValue] stringByDeletingLastPathComponent] file: [[fDstFile2Field stringValue] lastPathComponent]
+                                  modalForWindow: fWindow modalDelegate: self
+                                  didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
+                                         contextInfo: NULL];
 }
 
 - (void) BrowseFileDone: (NSSavePanel *) sheet
@@ -531,7 +751,7 @@ static int FormatSettings[3][4] =
     if( returnCode == NSOKButton )
     {
         [fDstFile2Field setStringValue: [sheet filename]];
-        [self FormatPopUpChanged: NULL];
+               
     }
 }
 
@@ -554,6 +774,7 @@ static int FormatSettings[3][4] =
     [NSApp runModalForWindow: fPicturePanel];
     [NSApp endSheet: fPicturePanel];
     [fPicturePanel orderOut: self];
+       [self CalculatePictureSizing: sender];
 }
 
 - (IBAction) ShowQueuePanel: (id) sender
@@ -575,18 +796,28 @@ static int FormatSettings[3][4] =
     hb_title_t * title = (hb_title_t *) hb_list_item( list,
             [fSrcTitlePopUp indexOfSelectedItem] );
     hb_job_t * job = title->job;
+    //int i;
 
     /* Chapter selection */
     job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;
     job->chapter_end   = [fSrcChapterEndPopUp   indexOfSelectedItem] + 1;
-
+       
     /* Format and codecs */
     int format = [fDstFormatPopUp indexOfSelectedItem];
     int codecs = [fDstCodecsPopUp indexOfSelectedItem];
     job->mux    = FormatSettings[format][codecs] & HB_MUX_MASK;
     job->vcodec = FormatSettings[format][codecs] & HB_VCODEC_MASK;
     job->acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
-
+    /* We set the chapter marker extraction here based on the format being
+       mpeg4 and the checkbox being checked */
+       if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fCreateChapterMarkers state] == NSOnState)
+       {
+        job->chapter_markers = 1;
+       }
+       else
+       {
+       job->chapter_markers = 0;
+       }
     if( ( job->vcodec & HB_VCODEC_FFMPEG ) &&
         [fVidEncoderPopUp indexOfSelectedItem] > 0 )
     {
@@ -600,10 +831,39 @@ static int FormatSettings[3][4] =
                Lets Deprecate Baseline Level 1.3*/
                job->h264_level = 30;
                job->mux = HB_MUX_IPOD;
+        /* move sanity check for iPod Encoding here */
+               job->pixel_ratio = 0 ;
+
                }
                
-               /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor */
-               // job->crf = 1;
+               /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake
+               Currently only used with Constant Quality setting*/
+               if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2)
+               {
+               /* Can only be used with svn rev >= 89 */
+                       job->crf = 1;
+               }
+               
+               /* Below Sends x264 options to the core library if x264 is selected*/
+               /* First we look to see if a user preset has been selected that contains a x264 optional string CurUserPresetChosenNum = nil */
+               if (curUserPresetChosenNum != nil)
+               {
+                       
+                       /* Lets use this as per Nyx, Thanks Nyx! */
+                       job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */  
+                       strcpy(job->x264opts, [[chosenPreset valueForKey:@"x264Option"] UTF8String]);
+                       //job->x264opts = [[chosenPreset valueForKey:@"x264Option"] cString];
+               }
+               else
+               {
+                   /* if not, then we check to see if there is a x264 opt in the preferences and use that if we want */
+                       //job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
+                       /* Lets use this as per Nyx, Thanks Nyx! */
+                       job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */  
+                       strcpy(job->x264opts, [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String]);
+               } 
+               
+               
                
         job->h264_13 = [fVidEncoderPopUp indexOfSelectedItem];
     }
@@ -638,54 +898,96 @@ static int FormatSettings[3][4] =
     }
 
     job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState );
+    
+
 
     /* Subtitle settings */
     job->subtitle = [fSubPopUp indexOfSelectedItem] - 1;
 
-    /* Audio tracks */
-    job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
-    job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1;
-    job->audios[2] = -1;
+    /* Audio tracks and mixdowns */
+    /* check for the condition where track 2 has an audio selected, but track 1 does not */
+    /* we will use track 2 as track 1 in this scenario */
+    if ([fAudLang1PopUp indexOfSelectedItem] > 0)
+    {
+        job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
+        job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1; /* will be -1 if "none" is selected */
+        job->audios[2] = -1;
+        job->audio_mixdowns[0] = [[fAudTrack1MixPopUp selectedItem] tag];
+        job->audio_mixdowns[1] = [[fAudTrack2MixPopUp selectedItem] tag];
+    }
+    else if ([fAudLang2PopUp indexOfSelectedItem] > 0)
+    {
+        job->audios[0] = [fAudLang2PopUp indexOfSelectedItem] - 1;
+        job->audio_mixdowns[0] = [[fAudTrack2MixPopUp selectedItem] tag];
+        job->audios[1] = -1;
+    }
+    else
+    {
+        job->audios[0] = -1;
+    }
 
     /* Audio settings */
     job->arate = hb_audio_rates[[fAudRatePopUp
                      indexOfSelectedItem]].rate;
-    job->abitrate = hb_audio_bitrates[[fAudBitratePopUp
-                        indexOfSelectedItem]].rate;
-}
+    job->abitrate = [[fAudBitratePopUp selectedItem] tag];
 
-- (IBAction) EnableQueue: (id) sender
-{
-    bool e = ( [fQueueCheck state] == NSOnState );
-    [fQueueAddButton  setHidden: !e];
-    [fQueueShowButton setHidden: !e];
-    [fRipButton       setTitle: e ? @"Start" : @"Rip"];
 }
 
-- (IBAction) AddToQueue: (id) sender
-{
-    hb_list_t  * list  = hb_get_titles( fHandle );
-    hb_title_t * title = (hb_title_t *) hb_list_item( list,
-            [fSrcTitlePopUp indexOfSelectedItem] );
-    hb_job_t * job = title->job;
-
-    [self PrepareJob];
 
-    /* Destination file */
-    job->file = strdup( [[fDstFile2Field stringValue] UTF8String] );
 
-    if( [fVidTwoPassCheck state] == NSOnState )
-    {
-        job->pass = 1;
-        hb_add( fHandle, job );
-        job->pass = 2;
-        hb_add( fHandle, job );
-    }
-    else
-    {
-        job->pass = 0;
-        hb_add( fHandle, job );
-    }
+- (IBAction) AddToQueue: (id) sender
+{
+/* We get the destination directory from the destingation field here */
+       NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
+       /* We check for a valid destination here */
+       if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0) 
+       {
+               NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
+       }
+       else
+       {
+               
+               hb_list_t  * list  = hb_get_titles( fHandle );
+               hb_title_t * title = (hb_title_t *) hb_list_item( list,
+                                                                                                                 [fSrcTitlePopUp indexOfSelectedItem] );
+               hb_job_t * job = title->job;
+               
+               [self PrepareJob];
+               
+               /* Destination file */
+               job->file = [[fDstFile2Field stringValue] UTF8String];
+               
+               if( [fVidTwoPassCheck state] == NSOnState )
+               {
+                       job->pass = 1;
+                       hb_add( fHandle, job );
+                       job->pass = 2;
+                       /* First we look to see if a user preset has been selected that contains a x264 optional string CurUserPresetChosenNum = nil */
+                       if (curUserPresetChosenNum != nil)
+                       {
+                               
+                               /* Lets use this as per Nyx, Thanks Nyx! */
+                               job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */  
+                               strcpy(job->x264opts, [[chosenPreset valueForKey:@"x264Option"] UTF8String]);
+                               //job->x264opts = [[chosenPreset valueForKey:@"x264Option"] cString];
+                       }
+                       else
+                       {
+                               //job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
+                               /* Lets use this as per Nyx, Thanks Nyx! */
+                               job->x264opts = (char *)calloc(1024,1); /* Fixme, this just leaks */ 
+                               strcpy(job->x264opts, [[[NSUserDefaults standardUserDefaults]stringForKey:@"DefAdvancedx264Flags"] UTF8String]);
+                       } 
+                       hb_add( fHandle, job );
+               }
+               else
+               {
+                       job->pass = 0;
+                       hb_add( fHandle, job );
+               }
+       
+       [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
+       }
 }
 
 - (IBAction) Rip: (id) sender
@@ -696,13 +998,16 @@ static int FormatSettings[3][4] =
         [self Cancel: sender];
         return;
     }
-
-    if( [fQueueCheck state] == NSOffState )
-    {
-        [self AddToQueue: sender];
-    }
-
-    if( [[NSFileManager defaultManager] fileExistsAtPath:
+       /* if there is no job in the queue, then add it to the queue and rip 
+       otherwise, there are already jobs in queue, so just rip the queue */
+       int count = hb_count( fHandle );
+       if( count < 1 )
+        {
+               [self AddToQueue: sender];
+               }
+    
+           /* We check for duplicate name here */
+       if( [[NSFileManager defaultManager] fileExistsAtPath:
             [fDstFile2Field stringValue]] )
     {
         NSBeginCriticalAlertSheet( _( @"File already exists" ),
@@ -713,8 +1018,21 @@ static int FormatSettings[3][4] =
             [fDstFile2Field stringValue]] );
         return;
     }
+       /* We get the destination directory from the destination field here */
+       NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
+       /* We check for a valid destination here */
+       if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0) 
+       {
+               NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
+       }
+       else
+       {
+       [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
+               [self _Rip];
+       }
+       
+
 
-    [self _Rip];
 }
 
 - (void) OverwriteAlertDone: (NSWindow *) sheet
@@ -746,9 +1064,11 @@ static int FormatSettings[3][4] =
 {
     /* Let libhb do the job */
     hb_start( fHandle );
+       /*set the fEncodeState State */
+       fEncodeState = 1;
 
     /* Disable interface */
-    [self EnableUI: NO];
+   [self EnableUI: NO];
     [fPauseButton setEnabled: NO];
     [fRipButton   setEnabled: NO];
 }
@@ -769,6 +1089,8 @@ static int FormatSettings[3][4] =
         hb_stop( fHandle );
         [fPauseButton setEnabled: NO];
         [fRipButton   setEnabled: NO];
+               /*set the fEncodeState State */
+            fEncodeState = 2;
     }
 }
 
@@ -792,6 +1114,17 @@ static int FormatSettings[3][4] =
     hb_list_t  * list  = hb_get_titles( fHandle );
     hb_title_t * title = (hb_title_t*)
         hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
+               
+               
+    /* If Auto Naming is on. We create an output filename of dvd name - title number */
+    if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"] > 0)
+       {
+               [fDstFile2Field setStringValue: [NSString stringWithFormat:
+                       @"%@/%@-%d.%@", [[fDstFile2Field stringValue] stringByDeletingLastPathComponent],
+                       [NSString stringWithUTF8String: title->name],
+                       [fSrcTitlePopUp indexOfSelectedItem] + 1,
+                       [[fDstFile2Field stringValue] pathExtension]]]; 
+       }
 
     /* Update chapter popups */
     [fSrcChapterStartPopUp removeAllItems];
@@ -808,6 +1141,52 @@ static int FormatSettings[3][4] =
         hb_list_count( title->list_chapter ) - 1];
     [self ChapterPopUpChanged: NULL];
 
+/* Start Get and set the initial pic size for display */
+       hb_job_t * job = title->job;
+       fTitle = title; 
+       /* Turn Deinterlace on/off depending on the preference */
+       if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultDeinterlaceOn"] > 0)
+       {
+               job->deinterlace = 1;
+       }
+       else
+       {
+               job->deinterlace = 0;
+       }
+       
+       /* Pixel Ratio Setting */
+       if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
+    {
+
+               job->pixel_ratio = 1 ;
+       }
+       else
+       {
+               job->pixel_ratio = 0 ;
+       }
+       /*Set Source Size Fields Here */
+       [fPicSrcWidth setStringValue: [NSString stringWithFormat:
+                                                        @"%d", fTitle->width]];
+       [fPicSrcHeight setStringValue: [NSString stringWithFormat:
+                                                        @"%d", fTitle->height]];
+       /* We get the originial output picture width and height and put them
+       in variables for use with some presets later on */
+       PicOrigOutputWidth = job->width;
+       PicOrigOutputHeight = job->height;
+       /* we test getting the max output value for pic sizing here to be used later*/
+       [fPicSettingWidth setStringValue: [NSString stringWithFormat:
+               @"%d", PicOrigOutputWidth]];
+       [fPicSettingHeight setStringValue: [NSString stringWithFormat:
+               @"%d", PicOrigOutputHeight]];
+       /* we run the picture size values through
+       CalculatePictureSizing to get all picture size
+       information*/
+       [self CalculatePictureSizing: NULL];
+       /* Run Through EncoderPopUpChanged to see if there
+               needs to be any pic value modifications based on encoder settings */
+       //[self EncoderPopUpChanged: NULL];
+       /* END Get and set the initial pic size for display */ 
+
     /* Update subtitle popups */
     hb_subtitle_t * subtitle;
     [fSubPopUp removeAllItems];
@@ -822,42 +1201,24 @@ static int FormatSettings[3][4] =
             subtitle->lang] action: NULL keyEquivalent: @""];
     }
     [fSubPopUp selectItemAtIndex: 0];
+    
+    /* Update chapter table */
+    [fChapterTitlesDelegate resetWithTitle:title];
+    [fChapterTable reloadData];
+
+    /* Update audio popups */
+    [self AddAllAudioTracksToPopUp: fAudLang1PopUp];
+    [self AddAllAudioTracksToPopUp: fAudLang2PopUp];
+    /* search for the first instance of our prefs default language for track 1, and set track 2 to "none" */
+       NSString * audioSearchPrefix = [[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
+    [self SelectAudioTrackInPopUp: fAudLang1PopUp searchPrefixString: audioSearchPrefix selectIndexIfNotFound: 1];
+    [self SelectAudioTrackInPopUp: fAudLang2PopUp searchPrefixString: NULL selectIndexIfNotFound: 0];
+       
+       /* changing the title may have changed the audio channels on offer, */
+       /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
+       [self AudioTrackPopUpChanged: fAudLang1PopUp];
+       [self AudioTrackPopUpChanged: fAudLang2PopUp];
 
-    /* Update lang popups */
-    hb_audio_t * audio;
-       // PRI CHANGES 02/12/06
-       NSString * audiotmppri;
-       NSString * audiosearchpri=[[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
-       int indxpri=0;
-       // End of pri changes 02/12/06
-    [fAudLang1PopUp removeAllItems];
-    [fAudLang2PopUp removeAllItems];
-    [fAudLang1PopUp addItemWithTitle: _( @"None" )];
-    [fAudLang2PopUp addItemWithTitle: _( @"None" )];
-    for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
-    {
-        audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
-       // PRI CHANGES 02/12/06
-               audiotmppri=(NSString *) [NSString stringWithCString: audio->lang];
-               // Try to find the desired default language
-          if ([audiotmppri hasPrefix:audiosearchpri] && indxpri==0)
-               {
-                       indxpri=i+1;
-               }
-       // End of pri changes 02/12/06
-
-        [[fAudLang1PopUp menu] addItemWithTitle:
-            [NSString stringWithCString: audio->lang]
-            action: NULL keyEquivalent: @""];
-        [[fAudLang2PopUp menu] addItemWithTitle:
-            [NSString stringWithCString: audio->lang]
-            action: NULL keyEquivalent: @""];
-    }
-       // PRI CHANGES 02/12/06
-       if (indxpri==0) { indxpri=1; }
-    [fAudLang1PopUp selectItemAtIndex: indxpri];
-       // End of pri changes 02/12/06
-    [fAudLang2PopUp selectItemAtIndex: 0];
 }
 
 - (IBAction) ChapterPopUpChanged: (id) sender
@@ -894,12 +1255,22 @@ static int FormatSettings[3][4] =
     switch( format )
     {
         case 0:
-            ext = "mp4";
+                               /*Get Default MP4 File Extension*/
+                               if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
+                               {
+                               ext = "m4v";
+                               }
+                               else
+                               {
+                               ext = "mp4";
+                               }
             [fDstCodecsPopUp addItemWithTitle:
                 _( @"MPEG-4 Video / AAC Audio" )];
             [fDstCodecsPopUp addItemWithTitle:
                 _( @"AVC/H.264 Video / AAC Audio" )];
-            break;
+                       /* We enable the create chapters checkbox here since we are .mp4*/
+                       [fCreateChapterMarkers setEnabled: YES];
+                       break;
         case 1: 
             ext = "avi";
             [fDstCodecsPopUp addItemWithTitle:
@@ -910,6 +1281,10 @@ static int FormatSettings[3][4] =
                 _( @"AVC/H.264 Video / MP3 Audio" )];
             [fDstCodecsPopUp addItemWithTitle:
                 _( @"AVC/H.264 Video / AC-3 Audio" )];
+                       /* We disable the create chapters checkbox here since we are NOT .mp4 
+                       and make sure it is unchecked*/
+                       [fCreateChapterMarkers setEnabled: NO];
+                       [fCreateChapterMarkers setState: NSOffState];
             break;
         case 2:
             ext = "ogm";
@@ -917,7 +1292,11 @@ static int FormatSettings[3][4] =
                 _( @"MPEG-4 Video / Vorbis Audio" )];
             [fDstCodecsPopUp addItemWithTitle:
                 _( @"MPEG-4 Video / MP3 Audio" )];
-            break;
+            /* We disable the create chapters checkbox here since we are NOT .mp4 
+                       and make sure it is unchecked*/
+                       [fCreateChapterMarkers setEnabled: NO];
+                       [fCreateChapterMarkers setState: NSOffState];
+                       break;
     }
     [self CodecsPopUpChanged: NULL];
 
@@ -933,6 +1312,15 @@ static int FormatSettings[3][4] =
         [fDstFile2Field setStringValue: [NSString stringWithFormat:
             @"%@.%s", string, ext]];
     }
+
+       /* changing the format may mean that we can / can't offer mono or 6ch, */
+       /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
+       [self AudioTrackPopUpChanged: fAudLang1PopUp];
+       [self AudioTrackPopUpChanged: fAudLang2PopUp];
+
+       /* We call method method to change UI to reflect whether a preset is used or not*/
+       [self CustomSettingUsed: sender];       
+       
 }
 
 - (IBAction) CodecsPopUpChanged: (id) sender
@@ -971,7 +1359,490 @@ static int FormatSettings[3][4] =
         [fAudBitratePopUp setEnabled: YES];
     }
 
+       /* changing the codecs on offer may mean that we can / can't offer mono or 6ch, */
+       /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
+       [self AudioTrackPopUpChanged: fAudLang1PopUp];
+       [self AudioTrackPopUpChanged: fAudLang2PopUp];
+
     [self CalculateBitrate: sender];
+    /* We call method method to change UI to reflect whether a preset is used or not*/
+       [self CustomSettingUsed: sender];
+}
+
+- (IBAction) EncoderPopUpChanged: (id) sender
+{
+    
+       /* Check to see if we need to modify the job pic values based on x264 (iPod) encoder selection */
+    if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1 && [fVidEncoderPopUp indexOfSelectedItem] == 1)
+    {
+       hb_job_t * job = fTitle->job;
+       job->pixel_ratio = 0 ;
+       
+                if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPicSizeAutoiPod"] > 0)
+                {
+                
+                if (job->width > 640)
+                               {
+                               job->width = 640;
+                               }
+                job->keep_ratio = 1;
+                hb_fix_aspect( job, HB_KEEP_WIDTH );
+                
+                }
+
+       }
+    
+       [self CalculatePictureSizing: sender];
+       /* We call method method to change UI to reflect whether a preset is used or not*/    
+    [self CustomSettingUsed: sender];
+}
+
+- (IBAction) SetEnabledStateOfAudioMixdownControls: (id) sender
+{
+
+    /* enable/disable the mixdown text and popupbutton for audio track 1 */
+    [fAudTrack1MixPopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
+    [fAudTrack1MixLabel setTextColor: ([fAudLang1PopUp indexOfSelectedItem] == 0) ?
+        [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
+
+    /* enable/disable the mixdown text and popupbutton for audio track 2 */
+    [fAudTrack2MixPopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
+    [fAudTrack2MixLabel setTextColor: ([fAudLang2PopUp indexOfSelectedItem] == 0) ?
+        [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
+
+}
+
+- (IBAction) AddAllAudioTracksToPopUp: (id) sender
+{
+
+    hb_list_t  * list  = hb_get_titles( fHandle );
+    hb_title_t * title = (hb_title_t*)
+        hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
+
+       hb_audio_t * audio;
+
+    [sender removeAllItems];
+    [sender addItemWithTitle: _( @"None" )];
+    for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
+    {
+        audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
+        [[sender menu] addItemWithTitle:
+            [NSString stringWithCString: audio->lang]
+            action: NULL keyEquivalent: @""];
+    }
+    [sender selectItemAtIndex: 0];
+
+}
+
+- (IBAction) SelectAudioTrackInPopUp: (id) sender searchPrefixString: (NSString *) searchPrefixString selectIndexIfNotFound: (int) selectIndexIfNotFound
+{
+
+    /* this method can be used to find a language, or a language-and-source-format combination, by passing in the appropriate string */
+    /* e.g. to find the first French track, pass in an NSString * of "Francais" */
+    /* e.g. to find the first English 5.1 AC3 track, pass in an NSString * of "English (AC3) (5.1 ch)" */
+    /* if no matching track is found, then selectIndexIfNotFound is used to choose which track to select instead */
+    
+       if (searchPrefixString != NULL) 
+       {
+
+        for( int i = 0; i < [sender numberOfItems]; i++ )
+        {
+            /* Try to find the desired search string */
+            if ([[[sender itemAtIndex: i] title] hasPrefix:searchPrefixString])
+            {
+                [sender selectItemAtIndex: i];
+                return;
+            }
+        }
+        /* couldn't find the string, so select the requested "search string not found" item */
+        /* index of 0 means select the "none" item */
+        /* index of 1 means select the first audio track */
+        [sender selectItemAtIndex: selectIndexIfNotFound];
+       }
+    else
+    {
+        /* if no search string is provided, then select the selectIndexIfNotFound item */
+        [sender selectItemAtIndex: selectIndexIfNotFound];
+    }
+
+}
+
+- (IBAction) AudioTrackPopUpChanged: (id) sender
+{
+    /* utility function to call AudioTrackPopUpChanged without passing in a mixdown-to-use */
+    [self AudioTrackPopUpChanged: sender mixdownToUse: 0];
+}
+
+- (IBAction) AudioTrackPopUpChanged: (id) sender mixdownToUse: (int) mixdownToUse
+{
+
+    /* make sure we have a selected title before continuing */
+    if (fTitle == NULL) return;
+
+    /* find out if audio track 1 or 2 was changed - this is passed to us in the tag of the sender */
+    /* the sender will have been either fAudLang1PopUp (tag = 0) or fAudLang2PopUp (tag = 1) */
+    int thisAudio = [sender tag];
+
+    /* get the index of the selected audio */
+    int thisAudioIndex = [sender indexOfSelectedItem] - 1;
+
+    /* Handbrake can't currently cope with ripping the same source track twice */
+    /* So, if this audio is also selected in the other audio track popup, set that popup's selection to "none" */
+    /* get a reference to the two audio track popups */
+    NSPopUpButton * thisAudioPopUp  = (thisAudio == 1 ? fAudLang2PopUp : fAudLang1PopUp);
+    NSPopUpButton * otherAudioPopUp = (thisAudio == 1 ? fAudLang1PopUp : fAudLang2PopUp);
+    /* if the same track is selected in the other audio popup, then select "none" in that popup */
+    /* unless, of course, both are selected as "none!" */
+    if ([thisAudioPopUp indexOfSelectedItem] != 0 && [thisAudioPopUp indexOfSelectedItem] == [otherAudioPopUp indexOfSelectedItem]) {
+        [otherAudioPopUp selectItemAtIndex: 0];
+        [self AudioTrackPopUpChanged: otherAudioPopUp];
+    }
+
+    /* pointer for the hb_audio_s struct we will use later on */
+    hb_audio_t * audio;
+
+    /* find out what the currently-selected output audio codec is */
+    int format = [fDstFormatPopUp indexOfSelectedItem];
+    int codecs = [fDstCodecsPopUp indexOfSelectedItem];
+    int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
+
+    /* pointer to this track's mixdown NSPopUpButton */
+    NSTextField   * mixdownTextField;
+    NSPopUpButton * mixdownPopUp;
+
+    /* find our mixdown NSTextField and NSPopUpButton */
+    if (thisAudio == 0)
+    {
+        mixdownTextField = fAudTrack1MixLabel;
+        mixdownPopUp = fAudTrack1MixPopUp;
+    }
+    else
+    {
+        mixdownTextField = fAudTrack2MixLabel;
+        mixdownPopUp = fAudTrack2MixPopUp;
+    }
+
+    /* delete the previous audio mixdown options */
+    [mixdownPopUp removeAllItems];
+
+    /* check if the audio mixdown controls need their enabled state changing */
+    [self SetEnabledStateOfAudioMixdownControls: NULL];
+
+    if (thisAudioIndex != -1)
+    {
+
+        /* get the audio */
+        audio = (hb_audio_t *) hb_list_item( fTitle->list_audio, thisAudioIndex );
+        if (audio != NULL)
+        {
+
+            /* find out if our selected output audio codec supports mono and / or 6ch */
+            /* we also check for an input codec of AC3,
+               as it is the only library able to do the mixdown to mono / conversion to 6-ch */
+            /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,
+               but this may change in the future, so they are separated for flexibility */
+            int audioCodecsSupportMono = (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_FAAC);
+            int audioCodecsSupport6Ch = (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_FAAC);
+
+            /* check for AC-3 passthru */
+            if (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3)
+            {
+                    [[mixdownPopUp menu] addItemWithTitle:
+                        [NSString stringWithCString: "AC3 Passthru"]
+                        action: NULL keyEquivalent: @""];
+            }
+            else
+            {
+
+                /* find out the audio channel layout for our input audio */
+                /* we'll cheat and use the liba52 layouts, even if the source isn't AC3 */
+                int channel_layout;
+                int audio_has_lfe;
+                if (audio->codec == HB_ACODEC_AC3)
+                {
+                    channel_layout = (audio->ac3flags & A52_CHANNEL_MASK);
+                    audio_has_lfe = (audio->ac3flags & A52_LFE);
+                }
+                else
+                {
+                    /* assume a stereo input for all other input codecs */
+                    /* we're cheating and using liba52's A52_STEREO layout here, even though the source isn't AC3 */
+                    channel_layout = A52_STEREO;
+                    audio_has_lfe = 0;
+                }
+
+                /* add the appropriate audio mixdown menuitems to the popupbutton */
+                /* in each case, we set the new menuitem's tag to be the amixdown value for that mixdown,
+                   so that we can reference the mixdown later */
+
+                /* keep a track of the min and max mixdowns we used, so we can select the best match later */
+                int minMixdownUsed = 0;
+                int maxMixdownUsed = 0;
+
+                /* do we want to add a mono option? */
+                if (audioCodecsSupportMono == 1) {
+                    id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
+                        [NSString stringWithCString: hb_audio_mixdowns[0].human_readable_name]
+                        action: NULL keyEquivalent: @""];
+                    [menuItem setTag: hb_audio_mixdowns[0].amixdown];
+                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[0].amixdown;
+                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[0].amixdown);
+                }
+
+                /* do we want to add a stereo option? */
+                /* offer stereo if we have a mono source and non-mono-supporting codecs, as otherwise we won't have a mixdown at all */
+                /* also offer stereo if we have a stereo-or-better source */
+                if (((channel_layout == A52_MONO || channel_layout == A52_CHANNEL1 || channel_layout == A52_CHANNEL2) && audioCodecsSupportMono == 0) ||
+                    (channel_layout >= A52_STEREO && channel_layout != A52_CHANNEL1 && channel_layout != A52_CHANNEL2)) {
+                    id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
+                        [NSString stringWithCString: hb_audio_mixdowns[1].human_readable_name]
+                        action: NULL keyEquivalent: @""];
+                    [menuItem setTag: hb_audio_mixdowns[1].amixdown];
+                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[1].amixdown;
+                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[1].amixdown);
+                }
+
+                /* do we want to add a dolby surround (DPL1) option? */
+                if (channel_layout == A52_3F1R || channel_layout == A52_3F2R || channel_layout == A52_DOLBY) {
+                    id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
+                        [NSString stringWithCString: hb_audio_mixdowns[2].human_readable_name]
+                        action: NULL keyEquivalent: @""];
+                    [menuItem setTag: hb_audio_mixdowns[2].amixdown];
+                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[2].amixdown;
+                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[2].amixdown);
+                }
+
+                /* do we want to add a dolby pro logic 2 (DPL2) option? */
+                if (channel_layout == A52_3F2R) {
+                    id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
+                        [NSString stringWithCString: hb_audio_mixdowns[3].human_readable_name]
+                        action: NULL keyEquivalent: @""];
+                    [menuItem setTag: hb_audio_mixdowns[3].amixdown];
+                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[3].amixdown;
+                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[3].amixdown);
+                }
+
+                /* do we want to add a 6-channel discrete option? */
+                if (audioCodecsSupport6Ch == 1 && channel_layout == A52_3F2R && audio_has_lfe == A52_LFE) {
+                    id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
+                        [NSString stringWithCString: hb_audio_mixdowns[4].human_readable_name]
+                        action: NULL keyEquivalent: @""];
+                    [menuItem setTag: hb_audio_mixdowns[4].amixdown];
+                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[4].amixdown;
+                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[4].amixdown);
+                }
+
+                /* auto-select the best mixdown based on our saved mixdown preference */
+                
+                /* for now, this is hard-coded to a "best" mixdown of HB_AMIXDOWN_DOLBYPLII */
+                /* ultimately this should be a prefs option */
+                int useMixdown;
+                
+                /* if we passed in a mixdown to use - in order to load a preset - then try and use it */
+                if (mixdownToUse > 0)
+                {
+                    useMixdown = mixdownToUse;
+                }
+                else
+                {
+                    useMixdown = HB_AMIXDOWN_DOLBYPLII;
+                }
+                
+                /* if useMixdown > maxMixdownUsed, then use maxMixdownUsed */
+                if (useMixdown > maxMixdownUsed) useMixdown = maxMixdownUsed;
+
+                /* if useMixdown < minMixdownUsed, then use minMixdownUsed */
+                if (useMixdown < minMixdownUsed) useMixdown = minMixdownUsed;
+
+                /* select the (possibly-amended) preferred mixdown */
+                [mixdownPopUp selectItemWithTag: useMixdown];
+                               
+                               /* lets call the AudioTrackMixdownChanged method here to determine appropriate bitrates, etc. */
+                [self AudioTrackMixdownChanged: NULL];
+            }
+
+        }
+        
+    }
+
+       /* see if the new audio track choice will change the bitrate we need */
+    [self CalculateBitrate: sender];   
+
+}
+- (IBAction) AudioTrackMixdownChanged: (id) sender
+{
+
+    /* find out what the currently-selected output audio codec is */
+    int format = [fDstFormatPopUp indexOfSelectedItem];
+    int codecs = [fDstCodecsPopUp indexOfSelectedItem];
+    int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
+    
+    /* storage variable for the min and max bitrate allowed for this codec */
+    int minbitrate;
+    int maxbitrate;
+    
+    switch( acodec )
+    {
+        case HB_ACODEC_FAAC:
+            /* check if we have a 6ch discrete conversion in either audio track */
+            if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
+            {
+                /* FAAC is happy using our min bitrate of 32 kbps, even for 6ch */
+                minbitrate = 32;
+                /* If either mixdown popup includes 6-channel discrete, then allow up to 384 kbps */
+                maxbitrate = 384;
+                break;
+            }
+            else
+            {
+                /* FAAC is happy using our min bitrate of 32 kbps for stereo or mono */
+                minbitrate = 32;
+                /* FAAC won't honour anything more than 160 for stereo, so let's not offer it */
+                /* note: haven't dealt with mono separately here, FAAC will just use the max it can */
+                maxbitrate = 160;
+                break;
+            }
+
+        case HB_ACODEC_LAME:
+            /* Lame is happy using our min bitrate of 32 kbps */
+            minbitrate = 32;
+            /* Lame won't encode if the bitrate is higher than 320 kbps */
+            maxbitrate = 320;
+            break;
+
+        case HB_ACODEC_VORBIS:
+            /* Vorbis causes a crash if we use a bitrate below 48 kbps */
+            minbitrate = 48;
+            /* Vorbis can cope with 384 kbps quite happily, even for stereo */
+            maxbitrate = 384;
+            break;
+
+        default:
+            /* AC3 passthru disables the bitrate dropdown anyway, so we might as well just use the min and max bitrate */
+            minbitrate = 32;
+            maxbitrate = 384;
+        
+    }
+
+    [fAudBitratePopUp removeAllItems];
+
+    for( int i = 0; i < hb_audio_bitrates_count; i++ )
+    {
+        if (hb_audio_bitrates[i].rate >= minbitrate && hb_audio_bitrates[i].rate <= maxbitrate)
+        {
+            /* add a new menuitem for this bitrate */
+            id<NSMenuItem> menuItem = [[fAudBitratePopUp menu] addItemWithTitle:
+                [NSString stringWithCString: hb_audio_bitrates[i].string]
+                action: NULL keyEquivalent: @""];
+            /* set its tag to be the actual bitrate as an integer, so we can retrieve it later */
+            [menuItem setTag: hb_audio_bitrates[i].rate];
+        }
+    }
+
+    /* select the default bitrate (but use 384 for 6-ch AAC) */
+    if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
+    {
+        [fAudBitratePopUp selectItemWithTag: 384];
+    }
+    else
+    {
+        [fAudBitratePopUp selectItemWithTag: hb_audio_bitrates[hb_audio_bitrates_default].rate];
+    }
+
+}
+/* lets set the picture size back to the max from right after title scan
+   Lets use an IBAction here as down the road we could always use a checkbox
+   in the gui to easily take the user back to max. Remember, the compiler
+   resolves IBActions down to -(void) during compile anyway */
+- (IBAction) RevertPictureSizeToMax: (id) sender
+{
+        hb_job_t * job = fTitle->job;
+       /* We use the output picture width and height
+       as calculated from libhb right after title is set
+       in TitlePopUpChanged */
+       job->width = PicOrigOutputWidth;
+       job->height = PicOrigOutputHeight;
+
+
+    
+       [self CalculatePictureSizing: sender];
+       /* We call method method to change UI to reflect whether a preset is used or not*/    
+    [self CustomSettingUsed: sender];
+}
+
+
+/* Get and Display Current Pic Settings in main window */
+- (IBAction) CalculatePictureSizing: (id) sender
+{
+       
+
+       [fPicSettingWidth setStringValue: [NSString stringWithFormat:
+               @"%d", fTitle->job->width]];
+       [fPicSettingHeight setStringValue: [NSString stringWithFormat:
+               @"%d", fTitle->job->height]];
+       [fPicSettingARkeep setStringValue: [NSString stringWithFormat:
+               @"%d", fTitle->job->keep_ratio]];                
+       [fPicSettingDeinterlace setStringValue: [NSString stringWithFormat:
+               @"%d", fTitle->job->deinterlace]];
+       [fPicSettingPAR setStringValue: [NSString stringWithFormat:
+               @"%d", fTitle->job->pixel_ratio]];
+               
+       if (fTitle->job->pixel_ratio == 1)
+       {
+       int titlewidth = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3];
+       int arpwidth = fTitle->job->pixel_aspect_width;
+       int arpheight = fTitle->job->pixel_aspect_height;
+       int displayparwidth = titlewidth * arpwidth / arpheight;
+       int displayparheight = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1];
+       [fPicSettingHeight setStringValue: [NSString stringWithFormat:
+               @"%d", displayparheight]];
+       [fPicLabelPAROutp setStringValue: @"Anamorphic Output:"];
+       [fPicLabelPAROutputX setStringValue: @"x"];
+    [fPicSettingPARWidth setStringValue: [NSString stringWithFormat:
+        @"%d", displayparwidth]];
+       [fPicSettingPARHeight setStringValue: [NSString stringWithFormat:
+        @"%d", displayparheight]];
+
+       fTitle->job->keep_ratio = 0;
+       }
+       else
+       {
+       [fPicLabelPAROutp setStringValue: @""];
+       [fPicLabelPAROutputX setStringValue: @""];
+       [fPicSettingPARWidth setStringValue: @""];
+       [fPicSettingPARHeight setStringValue:  @""];
+       }
+               
+       /* Set ON/Off values for the deinterlace/keep aspect ratio according to boolean */      
+       if (fTitle->job->keep_ratio > 0)
+               {
+               [fPicSettingARkeepDsply setStringValue: @"On"];
+        }
+               else
+               {
+               [fPicSettingARkeepDsply setStringValue: @"Off"];
+               }       
+       if (fTitle->job->deinterlace > 0)
+               {
+               [fPicSettingDeinterlaceDsply setStringValue: @"On"];
+        }
+               else
+               {
+               [fPicSettingDeinterlaceDsply setStringValue: @"Off"];
+               }
+       if (fTitle->job->pixel_ratio > 0)
+               {
+               [fPicSettingPARDsply setStringValue: @"On"];
+        }
+               else
+               {
+               [fPicSettingPARDsply setStringValue: @"Off"];
+               }       
+       /* below will trigger the preset, if selected, to be
+       changed to "Custom". Lets comment out for now until
+       we figure out a way to determine if the picture values
+       changed modify the preset values */     
+       //[self CustomSettingUsed: sender];
 }
 
 - (IBAction) CalculateBitrate: (id) sender
@@ -990,8 +1861,697 @@ static int FormatSettings[3][4] =
 
     [fVidBitrateField setIntValue: hb_calc_bitrate( job,
             [fVidTargetSizeField intValue] )];
+                       
+                       
+}
+
+/* Method to determine if we should change the UI
+To reflect whether or not a Preset is being used or if
+the user is using "Custom" settings by determining the sender*/
+- (IBAction) CustomSettingUsed: (id) sender
+{
+       if ([sender stringValue] != NULL)
+       {
+               /* Deselect the currently selected Preset if there is one*/
+               [tableView deselectRow:[tableView selectedRow]];
+               /* Change UI to show "Custom" settings are being used */
+               [fPresetSelectedDisplay setStringValue: @"Custom"];
+               /* Empty the field to display custom x264 preset options*/
+               [fDisplayX264Options setStringValue: @""];
+               curUserPresetChosenNum = nil;
+               /* If we have MP4, AVC H.264 and x264 Main then we look to see
+                       if there are any x264 options from the preferences to use */
+               if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1)
+               {
+                   /* Lets check to see if the user wants them displayed from the preferences */
+                       if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefAdvancedx264FlagsShow"] > 0)
+                       {
+                               [fDisplayX264Options setStringValue: [NSString stringWithFormat:[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"]]];
+                       }
+               }
+               
+       }
+}
+
+
+   /* We use this method to recreate new, updated factory
+   presets */
+- (IBAction)AddFactoryPresets:(id)sender
+{
+    /* First, we delete any existing built in presets */
+    [self DeleteFactoryPresets: sender];
+    /* Then, we re-create new built in presets programmatically CreatePSPPreset*/
+       [UserPresets addObject:[self CreateIpodPreset]];
+       [UserPresets addObject:[self CreateAppleTVPreset]];
+       [UserPresets addObject:[self CreatePSThreePreset]];
+       [UserPresets addObject:[self CreatePSPPreset]];
+    [self AddPreset];
+}
+- (IBAction)DeleteFactoryPresets:(id)sender
+{
+    //int status;
+    NSEnumerator *enumerator = [UserPresets objectEnumerator];
+       id tempObject;
+    
+       //NSNumber *index;
+    NSMutableArray *tempArray;
+
+
+        tempArray = [NSMutableArray array];
+        /* we look here to see if the preset is we move on to the next one */
+        while ( tempObject = [enumerator nextObject] )  
+               {
+                       /* if the preset is "Factory" then we put it in the array of
+                       presets to delete */
+                       if ([[tempObject objectForKey:@"Type"] intValue] == 0)
+                       {
+                               [tempArray addObject:tempObject];
+                       }
+        }
+        
+        [UserPresets removeObjectsInArray:tempArray];
+        [tableView reloadData];
+        [self savePreset];   
+
+}
+
+- (IBAction) ShowAddPresetPanel: (id) sender
+{
+    /* Deselect the currently selected Preset if there is one*/
+               [tableView deselectRow:[tableView selectedRow]];
+    /* If we have MP4, AVC H.264 and Main then we enable the x264 Options field for the
+        Add Preset window we are about to open. We do this before we actually open the panel,
+        as doing it after causes it to stick from the last selection for some reason. */
+       if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1)
+       {
+               [fPresetNewX264Opt setEditable: YES];
+               [fPresetNewX264OptLabel setEnabled: YES];
+       }
+       else
+       {
+               [fPresetNewX264Opt setEditable: NO];
+               [fPresetNewX264OptLabel setEnabled: NO];
+       }
+               /* Erase info from the input fields */
+       [fPresetNewName setStringValue: @""];
+       [fPresetNewX264Opt setStringValue:@""];
+       /* Show the panel */
+       [NSApp beginSheet: fAddPresetPanel modalForWindow: fWindow
+        modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
+    [NSApp runModalForWindow: fAddPresetPanel];
+    [NSApp endSheet: fAddPresetPanel];
+    [fAddPresetPanel orderOut: self];
+       
+       
+}
+- (IBAction) CloseAddPresetPanel: (id) sender
+{
+       [NSApp stopModal];
+}
+
+
+- (IBAction)AddUserPreset:(id)sender
+{
+
+    /* Here we create a custom user preset */
+       [UserPresets addObject:[self CreatePreset]];
+       /* Erase info from the input fields */
+       [fPresetNewName setStringValue: @""];
+       [fPresetNewX264Opt setStringValue:@""];
+       /* We stop the modal window for the new preset */
+       [NSApp stopModal];
+    [self AddPreset];
+       
+
+}
+- (void)AddPreset
+{
+
+       
+       /* We Sort the Presets By Factory or Custom */
+       NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type" 
+                                                    ascending:YES] autorelease];
+       /* We Sort the Presets Alphabetically by name */
+       NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName" 
+                                                    ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
+       NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
+       NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
+       [UserPresets setArray:sortedArray];
+       
+       
+       /* We Reload the New Table data for presets */
+    [tableView reloadData];
+   /* We save all of the preset data here */
+    [self savePreset];
+}
+
+- (IBAction)InsertPreset:(id)sender
+{
+    int index = [tableView selectedRow];
+    [UserPresets insertObject:[self CreatePreset] atIndex:index];
+    [tableView reloadData];
+    [self savePreset];
+}
+
+- (NSDictionary *)CreatePreset
+{
+    NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
+       /* Get the New Preset Name from the field in the AddPresetPanel */
+    [preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"];
+       /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"Type"];
+       /*Set whether or not this is default, at creation set to 0*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+       /*Get the whether or not to apply pic settings in the AddPresetPanel*/
+       [preset setObject:[NSNumber numberWithInt:[fPresetNewPicSettingsApply state]] forKey:@"UsesPictureSettings"];
+       /* File Format */
+    [preset setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
+       /* Chapter Markers fCreateChapterMarkers*/
+       [preset setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"];
+       /* Codecs */
+       [preset setObject:[fDstCodecsPopUp titleOfSelectedItem] forKey:@"FileCodecs"];
+       /* Video encoder */
+       [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
+       /* x264 Option String */
+       [preset setObject:[fPresetNewX264Opt stringValue] forKey:@"x264Option"];
+       
+       [preset setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"];
+       [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
+       [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
+       [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+       
+       /* Video framerate */
+       [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
+       /* GrayScale */
+       [preset setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"];
+       /* 2 Pass Encoding */
+       [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
+       
+       /*Picture Settings*/
+       hb_job_t * job = fTitle->job;
+       /* Basic Picture Settings */
+       /* Use Max Picture settings for whatever the dvd is.*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
+       [preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
+       [preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
+       [preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
+       [preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
+       [preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
+       /* Set crop settings here */
+       /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
+       [preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
+    [preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
+       [preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
+       [preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
+       
+       /*Audio*/
+       /* Audio Sample Rate*/
+       [preset setObject:[fAudRatePopUp titleOfSelectedItem] forKey:@"AudioSampleRate"];
+       /* Audio Bitrate Rate*/
+       [preset setObject:[fAudBitratePopUp titleOfSelectedItem] forKey:@"AudioBitRate"];
+       /* Subtitles*/
+       [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"];
+       
+
+    [preset autorelease];
+    return preset;
+
+}
+
+- (NSDictionary *)CreateIpodPreset
+{
+    NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
+       /* Get the New Preset Name from the field in the AddPresetPanel */
+    [preset setObject:@"HB-iPod" forKey:@"PresetName"];
+       /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
+       /*Set whether or not this is default, at creation set to 0*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+       /*Get the whether or not to apply pic settings in the AddPresetPanel*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesPictureSettings"];
+       /* File Format */
+    [preset setObject:@"MP4 file" forKey:@"FileFormat"];
+       /* Chapter Markers*/
+        [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
+    /* Codecs */
+       [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
+       /* Video encoder */
+       [preset setObject:@"x264 (h.264 iPod)" forKey:@"VideoEncoder"];
+       /* x264 Option String */
+       [preset setObject:@"frameref=1:bframes=0:nofast_pskip:subq=6:partitions=p8x8,p8x4,p4x8,i4x4:qcomp=0:me=umh:nodct_decimate" forKey:@"x264Option"];
+       /* Video quality */
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
+       [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
+       [preset setObject:@"1500" forKey:@"VideoAvgBitrate"];
+       [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+       
+       /* Video framerate */
+       [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
+       /* GrayScale */
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
+       /* 2 Pass Encoding */
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
+       
+       /*Picture Settings*/
+       //hb_job_t * job = fTitle->job;
+       /* Basic Picture Settings */
+       /* Use Max Picture settings for whatever the dvd is.*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
+       //[preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
+       //[preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
+       //[preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
+       //[preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
+       //[preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
+       /* Set crop settings here */
+       /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
+       //[preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
+    //[preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
+       //[preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
+       //[preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
+       
+       /*Audio*/
+       /* Audio Sample Rate*/
+       [preset setObject:@"48" forKey:@"AudioSampleRate"];
+       /* Audio Bitrate Rate*/
+       [preset setObject:@"160" forKey:@"AudioBitRate"];
+       /* Subtitles*/
+       [preset setObject:@"None" forKey:@"Subtitles"];
+       
+
+    [preset autorelease];
+    return preset;
+
+}
+
+- (NSDictionary *)CreateAppleTVPreset
+{
+    NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
+       /* Get the New Preset Name from the field in the AddPresetPanel */
+    [preset setObject:@"HB-AppleTV" forKey:@"PresetName"];
+       /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
+       /*Set whether or not this is default, at creation set to 0*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+       /*Get the whether or not to apply pic settings in the AddPresetPanel*/
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
+       /* File Format */
+    [preset setObject:@"MP4 file" forKey:@"FileFormat"];
+       /* Chapter Markers*/
+        [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
+       /* Codecs */
+       [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
+       /* Video encoder */
+       [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
+       /* x264 Option String (We can use this to tweak the appleTV output)*/
+       [preset setObject:@"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2" forKey:@"x264Option"];
+       /* Video quality */
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
+       [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
+       [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
+       [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+       
+       /* Video framerate */
+       [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
+       /* GrayScale */
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
+       /* 2 Pass Encoding */
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
+       
+       /*Picture Settings*/
+       /* For AppleTV we only want to retain UsesMaxPictureSettings
+       which depend on the source dvd picture settings, so we don't
+       record the current dvd's picture info since it will vary from
+       source to source*/
+       //hb_job_t * job = fTitle->job;
+       //hb_job_t * job = title->job;
+       /* Basic Picture Settings */
+       /* Use Max Picture settings for whatever the dvd is.*/
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
+       //[preset setObject:[NSNumber numberWithInt:PicOrigOutputWidth] forKey:@"PictureWidth"];
+       //[preset setObject:[NSNumber numberWithInt:PicOrigOutputHeight] forKey:@"PictureHeight"];
+       //[preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
+       //[preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
+       /* Set crop settings here */
+       /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
+       //[preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
+    //[preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
+       //[preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
+       //[preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
+       
+       /*Audio*/
+       /* Audio Sample Rate*/
+       [preset setObject:@"48" forKey:@"AudioSampleRate"];
+       /* Audio Bitrate Rate*/
+       [preset setObject:@"160" forKey:@"AudioBitRate"];
+       /* Subtitles*/
+       [preset setObject:@"None" forKey:@"Subtitles"];
+       
+
+    [preset autorelease];
+    return preset;
+
 }
 
+- (NSDictionary *)CreatePSThreePreset
+{
+    NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
+       /* Get the New Preset Name from the field in the AddPresetPanel */
+    [preset setObject:@"HB-PS3" forKey:@"PresetName"];
+       /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
+       /*Set whether or not this is default, at creation set to 0*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+       /*Get the whether or not to apply pic settings in the AddPresetPanel*/
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
+       /* File Format */
+    [preset setObject:@"MP4 file" forKey:@"FileFormat"];
+       /* Chapter Markers*/
+        [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
+       /* Codecs */
+       [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
+       /* Video encoder */
+       [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
+       /* x264 Option String (We can use this to tweak the appleTV output)*/
+       [preset setObject:@"level=41" forKey:@"x264Option"];
+       /* Video quality */
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
+       [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
+       [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
+       [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+       
+       /* Video framerate */
+       [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
+       /* GrayScale */
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
+       /* 2 Pass Encoding */
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
+       
+       /*Picture Settings*/
+       /* For PS3 we only want to retain UsesMaxPictureSettings
+       which depend on the source dvd picture settings, so we don't
+       record the current dvd's picture info since it will vary from
+       source to source*/
+       /* Use Max Picture settings for whatever the dvd is.*/
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
+       //[preset setObject:[NSNumber numberWithInt:PicOrigOutputWidth] forKey:@"PictureWidth"];
+       //[preset setObject:[NSNumber numberWithInt:PicOrigOutputHeight] forKey:@"PictureHeight"];
+       //[preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
+       //[preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
+       /* Set crop settings here */
+       /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
+       //[preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
+    //[preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
+       //[preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
+       //[preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
+       
+       /*Audio*/
+       /* Audio Sample Rate*/
+       [preset setObject:@"48" forKey:@"AudioSampleRate"];
+       /* Audio Bitrate Rate*/
+       [preset setObject:@"160" forKey:@"AudioBitRate"];
+       /* Subtitles*/
+       [preset setObject:@"None" forKey:@"Subtitles"];
+       
+
+    [preset autorelease];
+    return preset;
+
+}
+- (NSDictionary *)CreatePSPPreset
+{
+    NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
+       /* Get the New Preset Name from the field in the AddPresetPanel */
+    [preset setObject:@"HB-PSP" forKey:@"PresetName"];
+       /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
+       /*Set whether or not this is default, at creation set to 0*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+       /*Get the whether or not to apply pic settings in the AddPresetPanel*/
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
+       /* File Format */
+    [preset setObject:@"MP4 file" forKey:@"FileFormat"];
+       /* Chapter Markers*/
+        [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
+       /* Codecs */
+       [preset setObject:@"MPEG-4 Video / AAC Audio" forKey:@"FileCodecs"];
+       /* Video encoder */
+       [preset setObject:@"FFmpeg" forKey:@"VideoEncoder"];
+       /* x264 Option String (We can use this to tweak the appleTV output)*/
+       [preset setObject:@"" forKey:@"x264Option"];
+       /* Video quality */
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
+       [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
+       [preset setObject:@"1024" forKey:@"VideoAvgBitrate"];
+       [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+       
+       /* Video framerate */
+       [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
+       /* GrayScale */
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
+       /* 2 Pass Encoding */
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
+       
+       /*Picture Settings*/
+       /* For PS3 we only want to retain UsesMaxPictureSettings
+       which depend on the source dvd picture settings, so we don't
+       record the current dvd's picture info since it will vary from
+       source to source*/
+       /* Use Max Picture settings for whatever the dvd is.*/
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
+       [preset setObject:@"368" forKey:@"PictureWidth"];
+       [preset setObject:@"208" forKey:@"PictureHeight"];
+       [preset setObject:[NSNumber numberWithInt:1] forKey:@"PictureKeepRatio"];
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
+       [preset setObject:[NSNumber numberWithInt:0] forKey:@"PicturePAR"];
+       /* Set crop settings here */
+       /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
+       //[preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
+    //[preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
+       //[preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
+       //[preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
+       
+       /*Audio*/
+       /* Audio Sample Rate*/
+       [preset setObject:@"48" forKey:@"AudioSampleRate"];
+       /* Audio Bitrate Rate*/
+       [preset setObject:@"128" forKey:@"AudioBitRate"];
+       /* Subtitles*/
+       [preset setObject:@"None" forKey:@"Subtitles"];
+       
+
+    [preset autorelease];
+    return preset;
+
+}
+
+
+- (IBAction)DeletePreset:(id)sender
+{
+    int status;
+    NSEnumerator *enumerator;
+    NSNumber *index;
+    NSMutableArray *tempArray;
+    id tempObject;
+    
+    if ( [tableView numberOfSelectedRows] == 0 )
+        return;
+    /* Alert user before deleting preset */
+       /* Comment out for now, tie to user pref eventually */
+
+    //NSBeep();
+    status = NSRunAlertPanel(@"Warning!", @"Are you sure that you want to delete the selected preset?", @"OK", @"Cancel", nil);
+    
+    if ( status == NSAlertDefaultReturn ) {
+        enumerator = [tableView selectedRowEnumerator];
+        tempArray = [NSMutableArray array];
+        
+        while ( (index = [enumerator nextObject]) ) {
+            tempObject = [UserPresets objectAtIndex:[index intValue]];
+            [tempArray addObject:tempObject];
+        }
+        
+        [UserPresets removeObjectsInArray:tempArray];
+        [tableView reloadData];
+        [self savePreset];   
+    }
+}
+- (IBAction)tableViewSelected:(id)sender
+{
+    /* Since we cannot disable the presets tableView in terms of clickability
+          we will use the enabled state of the add presets button to determine whether
+          or not clicking on a preset will do anything */
+       if ([fPresetsAdd isEnabled])
+       {
+               
+               /* we get the chosen preset from the UserPresets array */
+               chosenPreset = [UserPresets objectAtIndex:[sender selectedRow]];
+               curUserPresetChosenNum = [sender selectedRow];
+               /* we set the preset display field in main window here */
+               [fPresetSelectedDisplay setStringValue: [NSString stringWithFormat: @"%@",[chosenPreset valueForKey:@"PresetName"]]];
+               /* File Format */
+               [fDstFormatPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileFormat"]]];
+               [self FormatPopUpChanged: NULL];
+               /* Chapter Markers*/
+               [fCreateChapterMarkers setState:[[chosenPreset objectForKey:@"ChapterMarkers"] intValue]];
+           /* Codecs */
+               [fDstCodecsPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileCodecs"]]];
+               [self CodecsPopUpChanged: NULL];
+               /* Video encoder */
+               [fVidEncoderPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoEncoder"]]];
+               
+               /* We can show the preset options here in the gui if we want to
+                       so we check to see it the user has specified it in the prefs */
+               if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefAdvancedx264FlagsShow"] > 0)
+               {
+                       [fDisplayX264Options setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"x264Option"]]];
+               }
+               
+               /* Lets run through the following functions to get variables set there */
+               [self EncoderPopUpChanged: NULL];
+               [self CalculateBitrate: NULL];
+               
+               /* Video quality */
+               [fVidQualityMatrix selectCellAtRow:[[chosenPreset objectForKey:@"VideoQualityType"] intValue] column:0];
+               
+               [fVidTargetSizeField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoTargetSize"]]];
+               [fVidBitrateField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoAvgBitrate"]]];
+               
+               [fVidQualitySlider setFloatValue: [[chosenPreset valueForKey:@"VideoQualitySlider"] floatValue]];
+               [self VideoMatrixChanged: NULL];
+               
+               /* Video framerate */
+               [fVidRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoFramerate"]]];
+
+               /* GrayScale */
+               [fVidGrayscaleCheck setState:[[chosenPreset objectForKey:@"VideoGrayScale"] intValue]];
+               
+               /* 2 Pass Encoding */
+               [fVidTwoPassCheck setState:[[chosenPreset objectForKey:@"VideoTwoPass"] intValue]];
+               
+               
+               /*Audio*/
+               
+               /* Audio Sample Rate*/
+               [fAudRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioSampleRate"]]];
+               /* Audio Bitrate Rate*/
+               [fAudBitratePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioBitRate"]]];
+               /*Subtitles*/
+               [fSubPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"Subtitles"]]];
+               
+               /* Picture Settings */
+               /* Look to see if we apply these here in objectForKey:@"UsesPictureSettings"] */
+               if ([[chosenPreset objectForKey:@"UsesPictureSettings"]  intValue] == 1)
+               {
+                       hb_job_t * job = fTitle->job;
+                       /* Check to see if we should use the max picture setting for the current title*/
+                       if ([[chosenPreset objectForKey:@"UsesMaxPictureSettings"]  intValue] == 1)
+                       {
+                               /* Use Max Picture settings for whatever the dvd is.*/
+                               [self RevertPictureSizeToMax: NULL];
+                               job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"]  intValue];
+                               if (job->keep_ratio == 1)
+                               {
+                                       hb_fix_aspect( job, HB_KEEP_WIDTH );
+                               }
+                               job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"]  intValue];
+                       }
+                       else
+                       {
+                               job->width = [[chosenPreset objectForKey:@"PictureWidth"]  intValue];
+                               job->height = [[chosenPreset objectForKey:@"PictureHeight"]  intValue];
+                               job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"]  intValue];
+                               if (job->keep_ratio == 1)
+                               {
+                                       hb_fix_aspect( job, HB_KEEP_WIDTH );
+                               }
+                               job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"]  intValue];
+                               job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"]  intValue];
+                               job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"]  intValue];
+                               job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"]  intValue];
+                               job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"]  intValue];
+                       }
+                       [self CalculatePictureSizing: NULL]; 
+               }
+               
+
+
+
+}
+}
+
+
+
+- (int)numberOfRowsInTableView:(NSTableView *)aTableView
+{
+    return [UserPresets count];
+}
+
+/* we use this to determine display characteristics for
+each table cell based on content currently only used to
+show the built in presets in a blue font. */
+- (void)tableView:(NSTableView *)aTableView
+ willDisplayCell:(id)aCell 
+ forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
+{
+    NSDictionary *userPresetDict = [UserPresets objectAtIndex:rowIndex];
+   if ([[userPresetDict objectForKey:@"Type"] intValue] == 0)
+       {
+               [aCell setTextColor:[NSColor blueColor]];
+       }
+       else
+       {
+               [aCell setTextColor:[NSColor blackColor]];
+       }
+
+}
+
+- (id)tableView:(NSTableView *)aTableView
+      objectValueForTableColumn:(NSTableColumn *)aTableColumn
+      row:(int)rowIndex
+{
+id theRecord, theValue;
+    
+    theRecord = [UserPresets objectAtIndex:rowIndex];
+    theValue = [theRecord objectForKey:[aTableColumn identifier]];
+    return theValue;
+}
+
+// NSTableDataSource method that we implement to edit values directly in the table...
+- (void)tableView:(NSTableView *)aTableView
+        setObjectValue:(id)anObject
+        forTableColumn:(NSTableColumn *)aTableColumn
+        row:(int)rowIndex
+{
+    id theRecord;
+    
+    theRecord = [UserPresets objectAtIndex:rowIndex];
+    [theRecord setObject:anObject forKey:@"PresetName"];
+    /* We Sort the Presets By Factory or Custom */
+       NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type" 
+                                                    ascending:YES] autorelease];
+               /* We Sort the Presets Alphabetically by name */
+       NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName" 
+                                                    ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
+       NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
+    NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
+       [UserPresets setArray:sortedArray];
+       /* We Reload the New Table data for presets */
+    [tableView reloadData];
+   /* We save all of the preset data here */
+    [self savePreset];
+}
+
+
+- (void)savePreset
+{
+    [UserPresets writeToFile:UserPresetsFile atomically:YES];
+
+}
+
+
+
 - (void) controlTextDidBeginEditing: (NSNotification *) notification
 {
     [self CalculateBitrate: NULL];
@@ -1018,5 +2578,11 @@ static int FormatSettings[3][4] =
     [[NSWorkspace sharedWorkspace] openURL: [NSURL
         URLWithString:@"http://handbrake.m0k.org/forum/"]];
 }
+- (IBAction) OpenUserGuide: (id) sender
+{
+    [[NSWorkspace sharedWorkspace] openURL: [NSURL
+        URLWithString:@"http://handbrake.m0k.org/trac/wiki/HandBrakeGuide"]];
+}
+
 
 @end