OSDN Git Service

MacGui: Thinine's custom file size and x264 fix.
[handbrake-jp/handbrake-jp-git.git] / macosx / Controller.mm
index 8f6e94d..499ae83 100644 (file)
-/* $Id: Controller.mm,v 1.30 2004/03/12 14:22:19 titer Exp $
+/* $Id: Controller.mm,v 1.79 2005/11/04 19:41:32 titer Exp $
 
    This file is part of the HandBrake source code.
    Homepage: <http://handbrake.m0k.org/>.
    It may be used under the terms of the GNU General Public License. */
 
-#include <paths.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOBSD.h>
-#include <IOKit/storage/IOMedia.h>
-#include <IOKit/storage/IODVDMedia.h>
-
 #include "Controller.h"
 
-#define _(a) NSLocalizedString(a,nil)
-
-static void _Scanning( void * data, int title, int titleCount );
-static void _ScanDone( void * data, HBList * titleList );
-static void _Encoding( void * data, float position, int pass,
-                      int passCount, float curFrameRate,
-                      float avgFrameRate, int remainingTime );
-static void _RipDone( void * data, int result );
+#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,
+      0,
+      0 },
+    { HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
+      HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_AC3,
+      HB_MUX_AVI | HB_VCODEC_X264   | HB_ACODEC_LAME,
+      HB_MUX_AVI | HB_VCODEC_X264   | HB_ACODEC_AC3 },
+    { HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_VORBIS,
+      HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
+      0,
+      0 } };
 
 /*******************************
  * HBController implementation *
  *******************************/
 @implementation HBController
 
+- init
+{
+    self    = [super init];
+    fHandle = NULL;
+    return self;
+}
+
 - (void) applicationDidFinishLaunching: (NSNotification *) notification
 {
-    /* Init libhb */
-    HBCallbacks callbacks;
-    callbacks.data     = self;
-    callbacks.scanning = _Scanning;
-    callbacks.scanDone = _ScanDone;
-    callbacks.encoding = _Encoding;
-    callbacks.ripDone  = _RipDone;
+    int    build;
+    char * version;
 
-    fHandle = HBInit( 1, 0 );
-    HBSetCallbacks( fHandle, callbacks );
+    /* Init libhb */
+    fHandle = hb_init( HB_DEBUG_NONE, [[NSUserDefaults
+        standardUserDefaults] boolForKey:@"CheckForUpdates"] );
+    
+    /* Init others controllers */
+    [fScanController    SetHandle: fHandle];
+    [fPictureController SetHandle: fHandle];
+    [fQueueController   SetHandle: fHandle];
+       
+
+     /* Call UpdateUI every 2/10 sec */
+    [[NSRunLoop currentRunLoop] addTimer: [NSTimer
+        scheduledTimerWithTimeInterval: 0.2 target: self
+        selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
+        forMode: NSModalPanelRunLoopMode];
+
+    if( ( build = hb_check_update( fHandle, &version ) ) > -1 )
+    {
+        /* Update available - tell the user */
+       
+        NSBeginInformationalAlertSheet( _( @"Update is available" ),
+            _( @"Go get it!" ), _( @"Discard" ), NULL, fWindow, self,
+            @selector( UpdateAlertDone:returnCode:contextInfo: ),
+            NULL, NULL, [NSString stringWithFormat:
+            _( @"HandBrake %s (build %d) is now available for download." ),
+            version, build] );
+        return;
 
-    [fPictureGLView SetHandle: fHandle];
+    }
 
-    /* Detect drives mounted after the app is started */
-    [[[NSWorkspace sharedWorkspace] notificationCenter]
-        addObserver: self selector: @selector( DetectDrives: )
-        name: NSWorkspaceDidMountNotification object: nil];
+    /* Show scan panel ASAP */
+    [self performSelectorOnMainThread: @selector(ShowScanPanel:)
+        withObject: NULL waitUntilDone: NO];
 }
 
 - (NSApplicationTerminateReply) applicationShouldTerminate:
     (NSApplication *) app
 {
-    if( [[fRipRipButton title] compare: _( @"Cancel" ) ]
-            == NSOrderedSame )
+    if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
     {
-        [self Cancel: self];
+        [self Cancel: NULL];
         return NSTerminateCancel;
     }
     
     /* Clean up */
-    HBClose( &fHandle );
-
+    hb_close( &fHandle );
     return NSTerminateNow;
 }
 
 - (void) awakeFromNib
 {
-    /* Strings for the Scan view */
-    [fScWelcomeField  setStringValue: _( @"Welcome to HandBrake" )];
-    [fScSelectField   setStringValue: _( @"Select a DVD:" )];
-    [fScDetectedCell  setTitle: _( @"Detected volume" )];
-    [fScDetectedPopUp removeAllItems];
-    [fScFolderCell    setTitle: _( @"DVD Folder" )];
-    [fScBrowseButton  setTitle: _( @"Browse" )];
-    [fScStatusField   setStringValue: @""];
-    [fScOpenButton    setTitle: _( @"Open" )];
-
-    /* Strings for the Rip view */
-    /* General box */
-    [fRipGeneralField setStringValue: _( @"General" )];
-    [fRipTitleField   setStringValue: _( @"DVD title" )];
-    [fRipTitlePopUp   removeAllItems];
-    [fRipFormatField  setStringValue: _( @"Output format" )];
-    [fRipFormatPopUp  removeAllItems];
-    [fRipFormatPopUp  addItemWithTitle:
-        _( @"MP4 file / MPEG-4 video / AAC audio" )];
-    [fRipFormatPopUp  addItemWithTitle:
-        _( @"AVI file / MPEG-4 video / MP3 audio" )];
-    [fRipFormatPopUp  addItemWithTitle:
-        _( @"AVI file / H264 video / MP3 audio" )];
-    [fRipFormatPopUp  addItemWithTitle:
-        _( @"OGM file / MPEG-4 video / Vorbis audio" )];
-    [fRipFileField1   setStringValue: _( @"File" )];
-    [fRipFileField2   setStringValue: [NSString stringWithFormat:
+    [fWindow center];
+
+    [self TranslateStrings];
+
+       /* 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];
+  }
+  /* 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" )];
+    [fDstFormatPopUp addItemWithTitle: _( @"OGM file" )];
+    [fDstFormatPopUp selectItemAtIndex: 0];
+
+    [self FormatPopUpChanged: NULL];
+
+    [fDstFile2Field setStringValue: [NSString stringWithFormat:
         @"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
-    [fRipBrowseButton setTitle: _( @"Browse" )];
-
-    /* Video box */
-    [fRipVideoField   setStringValue: _( @"Video" )];
-    [fRipEncoderField setStringValue: _( @"MPEG-4 encoder" )];
-    [fRipEncoderPopUp removeAllItems];
-    [fRipEncoderPopUp addItemWithTitle: @"FFmpeg"];
-    [fRipEncoderPopUp addItemWithTitle: @"XviD"];
-    [fRipBitrateField setStringValue: _( @"Bitrate" )];
-    [fRipCustomCell   setTitle: _( @"Custom (kbps)" )];
-    [fRipCustomField  setIntValue: 1024];
-    [fRipTargetCell   setTitle: _( @"Target size (MB)" )];
-    [fRipTargetField  setIntValue: 700];
-    [fRipTwoPassCheck setTitle: _( @"2-pass encoding" )];
-    [fRipCropButton   setTitle: _( @"Crop & Scale..." )];
-
-    /* Audio box */
-    [fRipAudioField  setStringValue: _( @"Audio" )];
-    [fRipLang1Field  setStringValue: _( @"Language 1" )];
-    [fRipLang1PopUp  removeAllItems];
-    [fRipLang2Field  setStringValue: _( @"Language 2 (optional)" )];
-    [fRipLang2PopUp  removeAllItems];
-    [fRipAudBitField setStringValue: _( @"Bitrate (kbps)" )];
-    [fRipAudBitPopUp removeAllItems];
-    [fRipAudBitPopUp addItemWithTitle: @"32"];
-    [fRipAudBitPopUp addItemWithTitle: @"40"];
-    [fRipAudBitPopUp addItemWithTitle: @"48"];
-    [fRipAudBitPopUp addItemWithTitle: @"56"];
-    [fRipAudBitPopUp addItemWithTitle: @"64"];
-    [fRipAudBitPopUp addItemWithTitle: @"80"];
-    [fRipAudBitPopUp addItemWithTitle: @"96"];
-    [fRipAudBitPopUp addItemWithTitle: @"112"];
-    [fRipAudBitPopUp addItemWithTitle: @"128"];
-    [fRipAudBitPopUp addItemWithTitle: @"160"];
-    [fRipAudBitPopUp addItemWithTitle: @"192"];
-    [fRipAudBitPopUp addItemWithTitle: @"224"];
-    [fRipAudBitPopUp addItemWithTitle: @"256"];
-    [fRipAudBitPopUp addItemWithTitle: @"320"];
-    [fRipAudBitPopUp selectItemWithTitle: @"128"];
+
+    /* Video encoder */
+    [fVidEncoderPopUp removeAllItems];
+    [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
+    [fVidEncoderPopUp addItemWithTitle: @"XviD"];
+
+    /* Video quality */
+    [fVidTargetSizeField setIntValue: 700];
+       [fVidBitrateField    setIntValue: 1000];
+       /* Do we want to force the quality settings if PAR is on ?
+       if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
+    {
+       [fVidBitrateField    setIntValue: 1500];
+       [fVidTwoPassCheck    setState: NSOnState];
+    }
+       else
+       {
+       [fVidBitrateField    setIntValue: 1000];
+    }
+       */
+    [fVidQualityMatrix   selectCell: fVidBitrateCell];
+    [self VideoMatrixChanged: NULL];
+
+    /* Video framerate */
+    [fVidRatePopUp removeAllItems];
+    [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++ )
+    {
+        [fAudBitratePopUp addItemWithTitle:
+            [NSString stringWithCString: hb_audio_bitrates[i].string]];
+    }
+    [fAudBitratePopUp selectItemAtIndex: hb_audio_bitrates_default];
+
+    /* Audio samplerate */
+    [fAudRatePopUp removeAllItems];
+    for( int i = 0; i < hb_audio_rates_count; i++ )
+    {
+        [fAudRatePopUp addItemWithTitle:
+            [NSString stringWithCString: hb_audio_rates[i].string]];
+    }
+    [fAudRatePopUp selectItemAtIndex: hb_audio_rates_default];
 
     /* Bottom */
-    [fRipStatusField setStringValue: @""];
-    [fRipInfoField   setStringValue: @""];
-    [fRipPauseButton setTitle: _( @"Pause" )];
-    [fRipRipButton   setTitle: _( @"Rip" )];
-
-    /* Strings for the crop panel */
-    [fWidthField1      setStringValue: _( @"Picture width" )];
-    [fDeinterlaceCheck setTitle: _( @"Deinterlace picture" )];
-    [fTopField1        setStringValue: _( @"Top cropping" )];
-    [fBottomField1     setStringValue: _( @"Bottom cropping" )];
-    [fLeftField1       setStringValue: _( @"Left cropping" )];
-    [fRightField1      setStringValue: _( @"Right cropping" )];
-    [fPreviousButton   setTitle: _( @"Previous" )];
-    [fNextButton       setTitle: _( @"Next" )];
-    [fAutocropButton   setTitle: _( @"Autocrop" )];
-    [fOpenGLCheck      setTitle: _( @"Useless OpenGL effects" )];
-    [fInfoField        setStringValue: @""];
-    [fCloseButton      setTitle: _( @"Close" )];
-
-    [self VideoMatrixChanged: self];
-
-    /* Show the scan view */
-    [fWindow setContentSize: [fScView frame].size];
-    [fWindow setContentView: fScView];
-    [fWindow center];
+    [fStatusField setStringValue: @""];
+
+    [self EnableUI: NO];
+    [fPauseButton setEnabled: NO];
+    [fRipButton setEnabled: NO];
+
+
 
-    /* Detect DVD drives */
-    [self DetectDrives: nil];
-    [self ScanMatrixChanged: self];
 }
 
-- (BOOL) windowShouldClose: (id) sender
+
+- (void) TranslateStrings
 {
-    if( [[fRipRipButton title] compare: _( @"Cancel" ) ]
-            == NSOrderedSame )
+    [fSrcDVD1Field      setStringValue: _( @"DVD:" )];
+    [fSrcTitleField     setStringValue: _( @"Title:" )];
+    [fSrcChapterField   setStringValue: _( @"Chapters:" )];
+    [fSrcChapterToField setStringValue: _( @"to" )];
+    [fSrcDuration1Field setStringValue: _( @"Duration:" )];
+
+    [fDstFormatField    setStringValue: _( @"File format:" )];
+    [fDstCodecsField    setStringValue: _( @"Codecs:" )];
+    [fDstFile1Field     setStringValue: _( @"File:" )];
+    [fDstBrowseButton   setTitle:       _( @"Browse" )];
+
+    [fVidRateField      setStringValue: _( @"Framerate (fps):" )];
+    [fVidEncoderField   setStringValue: _( @"Encoder:" )];
+    [fVidQualityField   setStringValue: _( @"Quality:" )];
+}
+
+/***********************************************************************
+ * UpdateDockIcon
+ ***********************************************************************
+ * Shows a progression bar on the dock icon, filled according to
+ * 'progress' (0.0 <= progress <= 1.0).
+ * Called with progress < 0.0 or progress > 1.0, restores the original
+ * icon.
+ **********************************************************************/
+- (void) UpdateDockIcon: (float) progress
+{
+    NSImage * icon;
+    NSData * tiff;
+    NSBitmapImageRep * bmp;
+    uint32_t * pen;
+    uint32_t black = htonl( 0x000000FF );
+    uint32_t red   = htonl( 0xFF0000FF );
+    uint32_t white = htonl( 0xFFFFFFFF );
+    int row_start, row_end;
+    int i, j;
+
+    /* Get application original icon */
+    icon = [NSImage imageNamed: @"NSApplicationIcon"];
+
+    if( progress < 0.0 || progress > 1.0 )
     {
-        [self Cancel: self];
-        return NO;
+        [NSApp setApplicationIconImage: icon];
+        return;
     }
 
-    /* Stop the application when the user closes the window */
-    [NSApp terminate: self];
-    return YES;
+    /* Get it in a raw bitmap form */
+    tiff = [icon TIFFRepresentationUsingCompression:
+            NSTIFFCompressionNone factor: 1.0];
+    bmp = [NSBitmapImageRep imageRepWithData: tiff];
+    
+    /* Draw the progression bar */
+    /* It's pretty simple (ugly?) now, but I'm no designer */
+
+    row_start = 3 * (int) [bmp size].height / 4;
+    row_end   = 7 * (int) [bmp size].height / 8;
+
+    for( i = row_start; i < row_start + 2; i++ )
+    {
+        pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
+        for( j = 0; j < (int) [bmp size].width; j++ )
+        {
+            pen[j] = black;
+        }
+    }
+    for( i = row_start + 2; i < row_end - 2; i++ )
+    {
+        pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
+        pen[0] = black;
+        pen[1] = black;
+        for( j = 2; j < (int) [bmp size].width - 2; j++ )
+        {
+            if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) )
+            {
+                pen[j] = red;
+            }
+            else
+            {
+                pen[j] = white;
+            }
+        }
+        pen[j]   = black;
+        pen[j+1] = black;
+    }
+    for( i = row_end - 2; i < row_end; i++ )
+    {
+        pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
+        for( j = 0; j < (int) [bmp size].width; j++ )
+        {
+            pen[j] = black;
+        }
+    }
+
+    /* Now update the dock icon */
+    tiff = [bmp TIFFRepresentationUsingCompression:
+            NSTIFFCompressionNone factor: 1.0];
+    icon = [[NSImage alloc] initWithData: tiff];
+    [NSApp setApplicationIconImage: icon];
+    [icon release];
 }
 
-- (IBAction) BrowseDVD: (id) sender
+- (void) UpdateUI: (NSTimer *) timer
 {
-    /* Open a panel to let the user choose and update the text field */
-    NSOpenPanel * panel = [NSOpenPanel openPanel];
 
-    [panel setAllowsMultipleSelection: NO];
-    [panel setCanChooseFiles: NO];
-    [panel setCanChooseDirectories: YES ];
+    hb_state_t s;
+    hb_get_state( fHandle, &s );
 
-    [panel beginSheetForDirectory: nil file: nil types: nil
-        modalForWindow: fWindow modalDelegate: self
-        didEndSelector: @selector( BrowseDVDDone:returnCode:contextInfo: )
-        contextInfo: nil];
+    switch( s.state )
+    {
+        case HB_STATE_IDLE:
+            break;
+
+        case HB_STATE_SCANNING:
+            [fScanController UpdateUI: &s];
+            break;
+
+#define p s.param.scandone
+        case HB_STATE_SCANDONE:
+        {
+            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];
+
+            list = hb_get_titles( fHandle );
+
+            if( !hb_list_count( list ) )
+            {
+                break;
+            }
+
+
+            [fSrcTitlePopUp removeAllItems];
+            for( int i = 0; i < hb_list_count( list ); i++ )
+            {
+                title = (hb_title_t *) hb_list_item( list, i );
+                /*Set DVD Name at top of window*/
+                               [fSrcDVD2Field setStringValue: [NSString
+                  stringWithUTF8String: title->name]]; 
+                               
+                               /* 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",
+                    title->index, title->hours, title->minutes,
+                    title->seconds]];
+                       
+            }
+            // Select the longuest title
+                       [fSrcTitlePopUp selectItemAtIndex: indxpri];
+                       
+            [self TitlePopUpChanged: NULL];
+            [self EnableUI: YES];
+            [fPauseButton setEnabled: NO];
+            [fRipButton   setEnabled: YES];
+            break;
+        }
+#undef p
+
+#define p s.param.working
+        case HB_STATE_WORKING:
+        {
+            float progress_total;
+            NSMutableString * string;
+
+            /* Update text field */
+            string = [NSMutableString stringWithFormat:
+                _( @"Encoding: task %d of %d, %.2f %%" ),
+                p.job_cur, p.job_count, 100.0 * p.progress];
+            if( p.seconds > -1 )
+            {
+                [string appendFormat:
+                    _( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)" ),
+                    p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds];
+            }
+            [fStatusField setStringValue: string];
+
+            /* 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 */
+            [self UpdateDockIcon: progress_total];
+
+            [fPauseButton setEnabled: YES];
+            [fPauseButton setTitle: _( @"Pause" )];
+            [fRipButton setEnabled: YES];
+            [fRipButton setTitle: _( @"Cancel" )];
+            break;
+        }
+#undef p
+
+#define p s.param.muxing
+        case HB_STATE_MUXING:
+        {
+            NSMutableString * string;
+                       
+            /* Update text field */
+            string = [NSMutableString stringWithFormat:
+                _( @"Muxing..." )];
+            [fStatusField setStringValue: string];
+                       
+            /* Update slider */
+            [fRipIndicator setIndeterminate: YES];
+            [fRipIndicator startAnimation: nil];
+                       
+            /* Update dock icon */
+            [self UpdateDockIcon: 1.0];
+                       
+            [fPauseButton setEnabled: YES];
+            [fPauseButton setTitle: _( @"Pause" )];
+            [fRipButton setEnabled: YES];
+            [fRipButton setTitle: _( @"Cancel" )];
+            break;
+        }
+#undef p
+                       
+        case HB_STATE_PAUSED:
+            [fStatusField setStringValue: _( @"Paused" )];
+            [fPauseButton setEnabled: YES];
+            [fPauseButton setTitle: _( @"Resume" )];
+            [fRipButton setEnabled: YES];
+            [fRipButton setTitle: _( @"Cancel" )];
+            break;
+
+        case HB_STATE_WORKDONE:
+        {
+            [self EnableUI: YES];
+            [fStatusField setStringValue: _( @"Done." )];
+            [fRipIndicator setIndeterminate: NO];
+            [fRipIndicator setDoubleValue: 0.0];
+            [fRipButton setTitle: _( @"Rip" )];
+
+            /* Restore dock icon */
+            [self UpdateDockIcon: -1.0];
+
+            [fPauseButton setEnabled: NO];
+            [fPauseButton setTitle: _( @"Pause" )];
+            [fRipButton setEnabled: YES];
+            [fRipButton setTitle: _( @"Rip" )];
+
+            /* FIXME */
+            hb_job_t * job;
+            while( ( job = hb_job( fHandle, 0 ) ) )
+            {
+                hb_rem( fHandle, job );
+            }
+            break;
+        }
+    }
+
+    /* FIXME: we should only do that when necessary */
+    if( [fQueueCheck state] == NSOnState )
+    {
+        int count = hb_count( fHandle );
+        if( count )
+        {
+            [fQueueCheck setTitle: [NSString stringWithFormat:
+                @"Enable queue (%d task%s in queue)",
+                count, ( count > 1 ) ? "s" : ""]];
+        }
+        else
+        {
+            [fQueueCheck setTitle: @"Enable queue (no task in queue)"];
+        }
+    }
+
+    [[NSRunLoop currentRunLoop] addTimer: [NSTimer
+        scheduledTimerWithTimeInterval: 0.2 target: self
+        selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
+        forMode: NSModalPanelRunLoopMode];
 }
 
-- (void) BrowseDVDDone: (NSOpenPanel *) sheet
-    returnCode: (int) returnCode contextInfo: (void *) contextInfo
+- (void) EnableUI: (bool) b
 {
-    if( returnCode == NSOKButton )
+    NSControl * controls[] =
+      { fSrcDVD1Field, fSrcDVD2Field, fSrcTitleField, fSrcTitlePopUp,
+        fSrcChapterField, fSrcChapterStartPopUp, fSrcChapterToField,
+        fSrcChapterEndPopUp, fSrcDuration1Field, fSrcDuration2Field,
+        fDstFormatField, fDstFormatPopUp, fDstCodecsField,
+        fDstCodecsPopUp, fDstFile1Field, fDstFile2Field,
+        fDstBrowseButton, fVidRateField, fVidRatePopUp,
+        fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
+        fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp,
+        fAudLang1Field, fAudLang1PopUp, fAudLang2Field, fAudLang2PopUp,
+        fAudRateField, fAudRatePopUp, fAudBitrateField,
+        fAudBitratePopUp, fPictureButton, fQueueCheck, 
+               fPicSrcWidth,fPicSrcHeight,fPicSettingWidth,fPicSettingHeight,
+               fPicSettingARkeep,fPicSettingDeinterlace,fPicSettingARkeepDsply,
+               fPicSettingDeinterlaceDsply,fPicLabelSettings,fPicLabelSrc,fPicLabelOutp,
+               fPicLabelAr,fPicLabelDeinter,fPicLabelSrcX,fPicLabelOutputX,
+               fPicLabelPAROutp,fPicLabelPAROutputX,fPicSettingPARWidth,fPicSettingPARHeight,
+               fPicSettingPARDsply,fPicLabelAnamorphic,tableView,fPresetsAdd,fPresetsDelete};
+
+    for( unsigned i = 0;
+         i < sizeof( controls ) / sizeof( NSControl * ); i++ )
     {
-        [fScFolderField setStringValue:
-            [[sheet filenames] objectAtIndex: 0]];
+        if( [[controls[i] className] isEqualToString: @"NSTextField"] )
+        {
+            NSTextField * tf = (NSTextField *) controls[i];
+            if( ![tf isBezeled] )
+            {
+                [tf setTextColor: b ? [NSColor controlTextColor] :
+                    [NSColor disabledControlTextColor]];
+                continue;
+            }
+        }
+        [controls[i] setEnabled: b];
+
     }
+
+       /* Temporarily disable Lang2 until crash is fixed */
+       [fAudLang2PopUp setEnabled: NO];
+       [fAudLang2Field setEnabled: NO];
+       
+       if (b) {
+               /* if we're enabling the interface, check if we should / should't offer 6-channel AAC extraction */
+               [self Check6ChannelAACExtraction: NULL];
+       } else {
+               /* if we're disabling the interface, turn it off */
+               [fAudLang1SurroundCheck setEnabled: NO];
+       }
+
+    [self VideoMatrixChanged: NULL];
+}
+
+- (IBAction) ShowScanPanel: (id) sender
+{
+    [fScanController Show];
+}
+
+- (BOOL) windowShouldClose: (id) sender
+{
+    /* Stop the application when the user closes the window */
+    [NSApp terminate: self];
+    return YES;
 }
 
 - (IBAction) VideoMatrixChanged: (id) sender;
 {
-    if( ![fRipVideoMatrix isEnabled] )
-    {
-        [fRipCustomField setEnabled: NO];
-        [fRipTargetField setEnabled: NO];
-        return;
-    }
-    
-    if( ![fRipVideoMatrix selectedRow] )
+    bool target, bitrate, quality;
+
+    target = bitrate = quality = false;
+    if( [fVidQualityMatrix isEnabled] )
     {
-        [fRipCustomField setEnabled: YES];
-        [fRipTargetField setEnabled: NO];
+        switch( [fVidQualityMatrix selectedRow] )
+        {
+            case 0:
+                target = true;
+                break;
+            case 1:
+                bitrate = true;
+                break;
+            case 2:
+                quality = true;
+                break;
+        }
     }
-    else
+    [fVidTargetSizeField  setEnabled: target];
+    [fVidBitrateField     setEnabled: bitrate];
+    [fVidQualitySlider    setEnabled: quality];
+    [fVidTwoPassCheck     setEnabled: !quality &&
+        [fVidQualityMatrix isEnabled]];
+    if( quality )
     {
-        [fRipCustomField setEnabled: NO];
-        [fRipTargetField setEnabled: YES];
-        [fRipTargetField UpdateBitrate];
+        [fVidTwoPassCheck setState: NSOffState];
     }
+
+    [self QualitySliderChanged: sender];
+    [self CalculateBitrate:     sender];
+}
+
+- (IBAction) QualitySliderChanged: (id) sender
+{
+    [fVidConstantCell setTitle: [NSString stringWithFormat:
+        _( @"Constant quality: %.0f %%" ), 100.0 *
+        [fVidQualitySlider floatValue]]];
 }
 
 - (IBAction) BrowseFile: (id) sender
 {
     /* Open a panel to let the user choose and update the text field */
     NSSavePanel * panel = [NSSavePanel savePanel];
-
-    [panel beginSheetForDirectory: nil file: nil
-        modalForWindow: fWindow modalDelegate: self
-        didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
-        contextInfo: nil];
+       /* 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
@@ -242,150 +688,249 @@ static void _RipDone( void * data, int result );
 {
     if( returnCode == NSOKButton )
     {
-        [fRipFileField2 setStringValue: [sheet filename]];
-        [self FormatPopUpChanged: self];
-    }
-}
-
-- (IBAction) Scan: (id) sender
-{
-    [fScMatrix       setEnabled: NO];
-    [fScDetectedPopUp         setEnabled: NO];
-    [fScFolderField   setEnabled: NO];
-    [fScBrowseButton setEnabled: NO];
-    [fScProgress     setIndeterminate: YES];
-    [fScProgress     startAnimation: self];
-    [fScOpenButton       setEnabled: NO];
-    [fScStatusField setStringValue: _( @"Opening device..." )];
-
-    /* Ask libhb to start scanning the specified volume */
-    if( ![fScMatrix selectedRow] )
-    {
-        /* DVD drive */
-        HBScanDVD( fHandle,
-                   [[fScDetectedPopUp titleOfSelectedItem] cString], 0 );
-    }
-    else
-    {
-        /* DVD folder */
-        HBScanDVD( fHandle,
-                   [[fScFolderField stringValue] cString], 0 );
+        [fDstFile2Field setStringValue: [sheet filename]];
+               [self FormatPopUpChanged: NULL];
     }
 }
 
 - (IBAction) ShowPicturePanel: (id) sender
 {
-    HBTitle * title = (HBTitle*)
-        HBListItemAt( fTitleList, [fRipTitlePopUp indexOfSelectedItem] );
-
-    [fPictureGLView SetTitle: title];
-
-    fPicture = 0;
-    [fPictureGLView ShowPicture: fPicture animate: HB_ANIMATE_NONE];
-
-    [fWidthStepper  setValueWraps: NO];
-    [fWidthStepper  setIncrement: 16];
-    [fWidthStepper  setMinValue: 16];
-    [fWidthStepper  setMaxValue: title->outWidthMax];
-    [fWidthStepper  setIntValue: title->outWidth];
-    [fWidthField2   setIntValue: title->outWidth];
-    [fDeinterlaceCheck setState:
-        title->deinterlace ? NSOnState : NSOffState];
-    [fTopStepper    setValueWraps: NO];
-    [fTopStepper    setIncrement: 2];
-    [fTopStepper    setMinValue: 0];
-    [fTopStepper    setMaxValue: title->inHeight / 4];
-    [fTopStepper    setIntValue: title->topCrop];
-    [fTopField2     setIntValue: title->topCrop];
-    [fBottomStepper setValueWraps: NO];
-    [fBottomStepper setIncrement: 2];
-    [fBottomStepper setMinValue: 0];
-    [fBottomStepper setMaxValue: title->inHeight / 4];
-    [fBottomStepper setIntValue: title->bottomCrop];
-    [fBottomField2  setIntValue: title->bottomCrop];
-    [fLeftStepper   setValueWraps: NO];
-    [fLeftStepper   setIncrement: 2];
-    [fLeftStepper   setMinValue: 0];
-    [fLeftStepper   setMaxValue: title->inWidth / 4];
-    [fLeftStepper   setIntValue: title->leftCrop];
-    [fLeftField2    setIntValue: title->leftCrop];
-    [fRightStepper  setValueWraps: NO];
-    [fRightStepper  setIncrement: 2];
-    [fRightStepper  setMinValue: 0];
-    [fRightStepper  setMaxValue: title->inWidth / 4];
-    [fRightStepper  setIntValue: title->rightCrop];
-    [fRightField2   setIntValue: title->rightCrop];
-
-    [fPreviousButton setEnabled: NO];
-    [fNextButton     setEnabled: YES];
-
-    [fInfoField setStringValue: [NSString stringWithFormat:
-        _( @"Final size: %dx%d" ), title->outWidth, title->outHeight] ];
+    hb_list_t  * list  = hb_get_titles( fHandle );
+    hb_title_t * title = (hb_title_t *) hb_list_item( list,
+            [fSrcTitlePopUp indexOfSelectedItem] );
 
     /* Resize the panel */
     NSSize newSize;
-    newSize.width  = 42 +  MAX( 720, title->outWidthMax );
-    newSize.height = 165 + title->outHeightMax;
+    newSize.width  = 246 + title->width;
+    newSize.height = 80 + title->height;
     [fPicturePanel setContentSize: newSize];
 
+    [fPictureController SetTitle: title];
+
     [NSApp beginSheet: fPicturePanel modalForWindow: fWindow
-        modalDelegate: nil didEndSelector: nil contextInfo: nil];
+        modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
     [NSApp runModalForWindow: fPicturePanel];
     [NSApp endSheet: fPicturePanel];
     [fPicturePanel orderOut: self];
+       [self CalculatePictureSizing: sender];
 }
 
-- (IBAction) ClosePanel: (id) sender
+- (IBAction) ShowQueuePanel: (id) sender
 {
-    [NSApp stopModal];
+    /* Update the OutlineView */
+    [fQueueController Update: sender];
+
+    /* Show the panel */
+    [NSApp beginSheet: fQueuePanel modalForWindow: fWindow
+        modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
+    [NSApp runModalForWindow: fQueuePanel];
+    [NSApp endSheet: fQueuePanel];
+    [fQueuePanel orderOut: self];
 }
 
-- (IBAction) Rip: (id) sender
+- (void) PrepareJob
 {
-    /* Rip or Cancel ? */
-    if( [[fRipRipButton title] compare: _( @"Cancel" ) ]
-            == NSOrderedSame )
+    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;
+
+    /* 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;
+
+    if( ( job->vcodec & HB_VCODEC_FFMPEG ) &&
+        [fVidEncoderPopUp indexOfSelectedItem] > 0 )
     {
-        [self Cancel: self];
-        return;
+        job->vcodec = HB_VCODEC_XVID;
+    }
+    if( job->vcodec & HB_VCODEC_X264 )
+    {
+        if ([fVidEncoderPopUp indexOfSelectedItem] > 0 )
+           {
+               /* Just use new Baseline Level 3.0 
+               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 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;
+               }
+               
+               /* Sends x264 options to the core library*/
+               job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
+               
+               
+        job->h264_13 = [fVidEncoderPopUp indexOfSelectedItem];
     }
 
-    if( [fRipCustomField intValue] < 64 )
+    /* Video settings */
+    if( [fVidRatePopUp indexOfSelectedItem] > 0 )
     {
-        NSBeginCriticalAlertSheet( _( @"Invalid video bitrate" ),
-            _( @"Ooops" ), nil, nil, fWindow, self, nil, nil, nil,
-            _( @"Video bitrate is too low." ) );
-        return;
+        job->vrate      = 27000000;
+        job->vrate_base = hb_video_rates[[fVidRatePopUp
+            indexOfSelectedItem]-1].rate;
     }
-    if( [fRipCustomField intValue] > 8192 )
+    else
     {
-        NSBeginCriticalAlertSheet( _( @"Invalid video bitrate" ),
-            _( @"Ooops" ), nil, nil, fWindow, self, nil, nil, nil,
-            _( @"Video bitrate is too high." ) );
-        return;
+        job->vrate      = title->rate;
+        job->vrate_base = title->rate_base;
+    }
+
+    switch( [fVidQualityMatrix selectedRow] )
+    {
+        case 0:
+            /* Target size.
+               Bitrate should already have been calculated and displayed
+               in fVidBitrateField, so let's just use it */
+        case 1:
+            job->vquality = -1.0;
+            job->vbitrate = [fVidBitrateField intValue];
+            break;
+        case 2:
+            job->vquality = [fVidQualitySlider floatValue];
+            job->vbitrate = 0;
+            break;
     }
-    if( [fRipLang1PopUp indexOfSelectedItem] ==
-            [fRipLang2PopUp indexOfSelectedItem] )
+
+    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 settings */
+    job->arate = hb_audio_rates[[fAudRatePopUp
+                     indexOfSelectedItem]].rate;
+    job->abitrate = hb_audio_bitrates[[fAudBitratePopUp
+                        indexOfSelectedItem]].rate;
+       /* have we selected that 5.1 should be extracted as AAC? */
+       if (job->acodec == HB_ACODEC_FAAC && [fAudLang1SurroundCheck isEnabled] && [fAudLang1SurroundCheck state] == NSOnState) {
+               job->surround = 1;
+       } else {
+               job->surround = 0;
+       }
+
+}
+
+- (IBAction) EnableQueue: (id) sender
+{
+    bool e = ( [fQueueCheck state] == NSOnState );
+    [fQueueAddButton  setHidden: !e];
+    [fQueueShowButton setHidden: !e];
+    [fRipButton       setTitle: e ? @"Start" : @"Rip"];
+}
+
+- (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;
+                       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
+{
+   
+    
+    /* Rip or Cancel ? */
+    if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
     {
-        NSBeginCriticalAlertSheet( _( @"Invalid secondary language" ),
-            _( @"Ooops" ), nil, nil, fWindow, self, nil, nil, nil,
-            _( @"You can't encode the same audio track twice." ) );
+        [self Cancel: sender];
         return;
     }
 
-    if( [[NSFileManager defaultManager] fileExistsAtPath:
-            [fRipFileField2 stringValue]] )
+    if( [fQueueCheck state] == NSOffState )
+    {
+
+                       [self AddToQueue: sender];
+
+               
+
+    }
+
+    /* We check for duplicate name here */
+       if( [[NSFileManager defaultManager] fileExistsAtPath:
+            [fDstFile2Field stringValue]] )
     {
         NSBeginCriticalAlertSheet( _( @"File already exists" ),
-            _( @"No" ), _( @"Yes" ), nil, fWindow, self,
+            _( @"Cancel" ), _( @"Overwrite" ), NULL, fWindow, self,
             @selector( OverwriteAlertDone:returnCode:contextInfo: ),
-            nil, nil, [NSString stringWithFormat:
+            NULL, NULL, [NSString stringWithFormat:
             _( @"Do you want to overwrite %@?" ),
-            [fRipFileField2 stringValue]] );
+            [fDstFile2Field stringValue]] );
         return;
     }
+       /* 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
+       {
+       [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
+               [self _Rip];
+       }
+       
+
 
-    [self _Rip];
 }
 
 - (void) OverwriteAlertDone: (NSWindow *) sheet
@@ -397,70 +942,38 @@ static void _RipDone( void * data, int result );
     }
 }
 
-- (void) _Rip
+- (void) UpdateAlertDone: (NSWindow *) sheet
+    returnCode: (int) returnCode contextInfo: (void *) contextInfo
 {
-    /* Get the specified title & audio track(s) */
-    HBTitle * title = (HBTitle*) HBListItemAt( fTitleList,
-            [fRipTitlePopUp indexOfSelectedItem] );
-    HBAudio * audio1 = (HBAudio*) HBListItemAt( title->audioList,
-            [fRipLang1PopUp indexOfSelectedItem] );
-    HBAudio * audio2 = (HBAudio*) HBListItemAt( title->audioList,
-            [fRipLang2PopUp indexOfSelectedItem] );
-
-    /* Use user settings */
-    title->file    = strdup( [[fRipFileField2 stringValue] cString] );
-    title->bitrate = [fRipCustomField intValue];
-    title->twoPass = ( [fRipTwoPassCheck state] == NSOnState );
-
-    int format = [fRipFormatPopUp indexOfSelectedItem];
-    int codec  = [fRipEncoderPopUp indexOfSelectedItem];
-    title->mux = ( !format ) ? HB_MUX_MP4 : ( ( format == 3 ) ?
-            HB_MUX_OGM : HB_MUX_AVI );
-    title->codec = ( format == 2 ) ? HB_CODEC_X264 : ( ( !codec ) ?
-            HB_CODEC_FFMPEG : HB_CODEC_XVID );
-
-    audio1->outBitrate = [[fRipAudBitPopUp titleOfSelectedItem]
-                              intValue];
-    audio1->outCodec = ( !format ) ? HB_CODEC_AAC : ( ( format == 3 ) ?
-            HB_CODEC_VORBIS : HB_CODEC_MP3 );;
-    HBListAdd( title->ripAudioList, audio1 );
-    if( audio2 )
-    {
-        audio2->outBitrate = [[fRipAudBitPopUp
-            titleOfSelectedItem] intValue];
-        audio2->outCodec = ( !format ) ? HB_CODEC_AAC : ( ( format == 3 ) ?
-                HB_CODEC_VORBIS : HB_CODEC_MP3 );
-        HBListAdd( title->ripAudioList, audio2 );
+    if( returnCode == NSAlertAlternateReturn )
+    {
+        /* Show scan panel */
+        [self performSelectorOnMainThread: @selector(ShowScanPanel:)
+            withObject: NULL waitUntilDone: NO];
+        return;
     }
 
-    /* Disable interface */
-    [fRipTitlePopUp   setEnabled: NO];
-    [fRipFormatPopUp  setEnabled: NO];
-    [fRipVideoMatrix  setEnabled: NO];
-    [fRipCustomField  setEnabled: NO];
-    [fRipTargetField  setEnabled: NO];
-    [fRipTwoPassCheck setEnabled: NO];
-    [fRipCropButton   setEnabled: NO];
-    [fRipLang1PopUp   setEnabled: NO];
-    [fRipLang2PopUp   setEnabled: NO];
-    [fRipAudBitPopUp  setEnabled: NO];
-    [fRipFileField2   setEnabled: NO];
-    [fRipEncoderPopUp setEnabled: NO];
-    [fRipBrowseButton setEnabled: NO];
-    [fRipPauseButton  setEnabled: YES];
-    [fRipRipButton    setTitle: _( @"Cancel" )];
-    [fRipProgress     setIndeterminate: YES];
-    [fRipProgress     startAnimation: self];;
+    /* Go to HandBrake homepage and exit */
+    [self OpenHomepage: NULL];
+    [NSApp terminate: self];
+}
 
+- (void) _Rip
+{
     /* Let libhb do the job */
-    HBStartRip( fHandle, title );
+    hb_start( fHandle );
+
+    /* Disable interface */
+   [self EnableUI: NO];
+    [fPauseButton setEnabled: NO];
+    [fRipButton   setEnabled: NO];
 }
 
 - (IBAction) Cancel: (id) sender
 {
     NSBeginCriticalAlertSheet( _( @"Cancel - Are you sure?" ),
-        _( @"No" ), _( @"Yes" ), nil, fWindow, self,
-        @selector( _Cancel:returnCode:contextInfo: ), nil, nil,
+        _( @"Keep working" ), _( @"Cancel encoding" ), NULL, fWindow, self,
+        @selector( _Cancel:returnCode:contextInfo: ), NULL, NULL,
         _( @"Encoding won't be recoverable." ) );
 }
 
@@ -469,500 +982,765 @@ static void _RipDone( void * data, int result );
 {
     if( returnCode == NSAlertAlternateReturn )
     {
-        if( [[fRipPauseButton title] compare: _( @"Resume" ) ]
-                == NSOrderedSame )
-        {
-            HBResumeRip( fHandle );
-        }
-        HBStopRip( fHandle );
+        hb_stop( fHandle );
+        [fPauseButton setEnabled: NO];
+        [fRipButton   setEnabled: NO];
     }
 }
 
 - (IBAction) Pause: (id) sender
 {
-    if( [[fRipPauseButton title] compare: _( @"Resume" ) ]
-            == NSOrderedSame )
+    [fPauseButton setEnabled: NO];
+    [fRipButton   setEnabled: NO];
+
+    if( [[fPauseButton title] isEqualToString: _( @"Resume" )] )
     {
-        [self Resume: self];
-        return;
+        hb_resume( fHandle );
+    }
+    else
+    {
+        hb_pause( fHandle );
     }
-
-    [fRipPauseButton setTitle: _( @"Resume" )];
-    HBPauseRip( fHandle );
 }
 
-- (IBAction) Resume: (id) sender
+- (IBAction) TitlePopUpChanged: (id) sender
 {
-    [fRipPauseButton setTitle: _( @"Pause" )];
-    HBResumeRip( fHandle );
-}
+    hb_list_t  * list  = hb_get_titles( fHandle );
+    hb_title_t * title = (hb_title_t*)
+        hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
 
-- (IBAction) PreviousPicture: (id) sender
-{
-    fPicture--;
-    if( [fOpenGLCheck state] == NSOnState )
+
+    /* Update chapter popups */
+    [fSrcChapterStartPopUp removeAllItems];
+    [fSrcChapterEndPopUp   removeAllItems];
+    for( int i = 0; i < hb_list_count( title->list_chapter ); i++ )
     {
-        [fPictureGLView ShowPicture: fPicture
-            animate: HB_ANIMATE_LEFT];
+        [fSrcChapterStartPopUp addItemWithTitle: [NSString
+            stringWithFormat: @"%d", i + 1]];
+        [fSrcChapterEndPopUp addItemWithTitle: [NSString
+            stringWithFormat: @"%d", i + 1]];
     }
-    else
+    [fSrcChapterStartPopUp selectItemAtIndex: 0];
+    [fSrcChapterEndPopUp   selectItemAtIndex:
+        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; 
+       /*Set Source Size Fields Here */
+       [fPicSrcWidth setStringValue: [NSString stringWithFormat:
+                                                        @"%d", fTitle->width]];
+       [fPicSrcHeight setStringValue: [NSString stringWithFormat:
+                                                        @"%d", fTitle->height]];
+       /* 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"])
     {
-        [fPictureGLView ShowPicture: fPicture
-            animate: HB_ANIMATE_NONE];
-    }
-
-    [fPreviousButton setEnabled: ( fPicture > 0 )];
-    [fNextButton     setEnabled: YES];
-}
 
-- (IBAction) NextPicture: (id) sender
-{
-    fPicture++;
-    if( [fOpenGLCheck state] == NSOnState )
+               job->pixel_ratio = 1 ;
+       }
+       else
+       {
+               job->pixel_ratio = 0 ;
+       }
+       /* 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];
+    [fSubPopUp addItemWithTitle: @"None"];
+    for( int i = 0; i < hb_list_count( title->list_subtitle ); i++ )
     {
-        [fPictureGLView ShowPicture: fPicture
-            animate: HB_ANIMATE_RIGHT];
+        subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, i );
+
+        /* We cannot use NSPopUpButton's addItemWithTitle because
+           it checks for duplicate entries */
+        [[fSubPopUp menu] addItemWithTitle: [NSString stringWithCString:
+            subtitle->lang] action: NULL keyEquivalent: @""];
     }
-    else
+    [fSubPopUp selectItemAtIndex: 0];
+
+    /* START pri */
+       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];
+       /* Disable second audio language until crashing is resolved*/
+       [fAudLang2Field setEnabled: NO];
+       [fAudLang2PopUp setEnabled: NO];
+    [fAudLang2PopUp removeAllItems];
+    [fAudLang1PopUp addItemWithTitle: _( @"None" )];
+       /* Display Currently Unavailable until crash is fixed */
+    [fAudLang2PopUp addItemWithTitle: _( @"Currently Unavailable" )];
+       //[fAudLang2PopUp addItemWithTitle: _( @"None" )];
+    for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
     {
-        [fPictureGLView ShowPicture: fPicture
-            animate: HB_ANIMATE_NONE];
+        audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
+       // PRI CHANGES 02/12/06
+               if (audiosearchpri!= NULL) 
+               {
+                       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];
+       
+       /* END pri */
+
+       /* changing the title may have changed the audio channels on offer, so */
+       /* check if this change means we should / should't offer 6-channel AAC extraction */
+       [self Check6ChannelAACExtraction: sender];
 
-    [fPreviousButton setEnabled: YES];
-    [fNextButton     setEnabled: ( fPicture < 9 )];
 }
 
-- (IBAction) UpdatePicture: (id) sender
+- (IBAction) ChapterPopUpChanged: (id) sender
 {
-    HBTitle * title = (HBTitle*)
-        HBListItemAt( fTitleList, [fRipTitlePopUp indexOfSelectedItem] );
-    title->outWidth    = [fWidthStepper intValue];
-    title->deinterlace = ( [fDeinterlaceCheck state] == NSOnState );
-    title->topCrop     = [fTopStepper intValue];
-    title->bottomCrop  = [fBottomStepper intValue];
-    title->leftCrop    = [fLeftStepper intValue];
-    title->rightCrop   = [fRightStepper intValue];
-
-    [fPictureGLView ShowPicture: fPicture animate: HB_ANIMATE_NONE];
-
-    [fWidthStepper  setIntValue: title->outWidth];
-    [fTopStepper    setIntValue: title->topCrop];
-    [fBottomStepper setIntValue: title->bottomCrop];
-    [fLeftStepper   setIntValue: title->leftCrop];
-    [fRightStepper  setIntValue: title->rightCrop];
-    [fWidthField2   setIntValue: [fWidthStepper intValue]];
-    [fTopField2     setIntValue: [fTopStepper intValue]];
-    [fBottomField2  setIntValue: [fBottomStepper intValue]];
-    [fLeftField2    setIntValue: [fLeftStepper intValue]];
-    [fRightField2   setIntValue: [fRightStepper intValue]];
+    hb_list_t  * list  = hb_get_titles( fHandle );
+    hb_title_t * title = (hb_title_t *)
+        hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
+
+    hb_chapter_t * chapter;
+    int64_t        duration = 0;
+    for( int i = [fSrcChapterStartPopUp indexOfSelectedItem];
+         i <= [fSrcChapterEndPopUp indexOfSelectedItem]; i++ )
+    {
+        chapter = (hb_chapter_t *) hb_list_item( title->list_chapter, i );
+        duration += chapter->duration;
+    }
+    
+    duration /= 90000; /* pts -> seconds */
+    [fSrcDuration2Field setStringValue: [NSString stringWithFormat:
+        @"%02lld:%02lld:%02lld", duration / 3600, ( duration / 60 ) % 60,
+        duration % 60]];
 
-    [fInfoField setStringValue: [NSString stringWithFormat:
-        _( @"Final size: %dx%d" ), title->outWidth, title->outHeight]];
+    [self CalculateBitrate: sender];
 }
 
-- (IBAction) AutoCrop: (id) sender
+- (IBAction) FormatPopUpChanged: (id) sender
 {
-    HBTitle * title = (HBTitle*)
-        HBListItemAt( fTitleList, [fRipTitlePopUp indexOfSelectedItem] );
-    title->topCrop     = title->autoTopCrop;
-    title->bottomCrop  = title->autoBottomCrop;
-    title->leftCrop    = title->autoLeftCrop;
-    title->rightCrop   = title->autoRightCrop;
+    NSString * string = [fDstFile2Field stringValue];
+    int format = [fDstFormatPopUp indexOfSelectedItem];
+    char * ext = NULL;
 
-    [fPictureGLView ShowPicture: fPicture animate: HB_ANIMATE_NONE];
+    /* Update the codecs popup */
+    [fDstCodecsPopUp removeAllItems];
+    switch( format )
+    {
+        case 0:
+                               /*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;
+        case 1: 
+            ext = "avi";
+            [fDstCodecsPopUp addItemWithTitle:
+                _( @"MPEG-4 Video / MP3 Audio" )];
+            [fDstCodecsPopUp addItemWithTitle:
+                _( @"MPEG-4 Video / AC-3 Audio" )];
+            [fDstCodecsPopUp addItemWithTitle:
+                _( @"AVC/H.264 Video / MP3 Audio" )];
+            [fDstCodecsPopUp addItemWithTitle:
+                _( @"AVC/H.264 Video / AC-3 Audio" )];
+            break;
+        case 2:
+            ext = "ogm";
+            [fDstCodecsPopUp addItemWithTitle:
+                _( @"MPEG-4 Video / Vorbis Audio" )];
+            [fDstCodecsPopUp addItemWithTitle:
+                _( @"MPEG-4 Video / MP3 Audio" )];
+            break;
+    }
+    [self CodecsPopUpChanged: NULL];
 
-    [fWidthStepper  setIntValue: title->outWidth];
-    [fTopStepper    setIntValue: title->topCrop];
-    [fBottomStepper setIntValue: title->bottomCrop];
-    [fLeftStepper   setIntValue: title->leftCrop];
-    [fRightStepper  setIntValue: title->rightCrop];
-    [fWidthField2   setIntValue: [fWidthStepper intValue]];
-    [fTopField2     setIntValue: [fTopStepper intValue]];
-    [fBottomField2  setIntValue: [fBottomStepper intValue]];
-    [fLeftField2    setIntValue: [fLeftStepper intValue]];
-    [fRightField2   setIntValue: [fRightStepper intValue]];
+    /* Add/replace 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]];
+    }
+
+       /* changing the codecs on offer may mean that we are/aren't now offering AAC, so */
+       /* check if this change means we should / should't offer 6-channel AAC extraction */
+       [self Check6ChannelAACExtraction: sender];
 
-    [fInfoField setStringValue: [NSString stringWithFormat:
-        _( @"Final size: %dx%d" ), title->outWidth, title->outHeight]];
 }
 
-- (void) DetectDrives: (NSNotification *) notification
+- (IBAction) CodecsPopUpChanged: (id) sender
 {
-    /* Scan DVD drives (stolen from VLC) */
-    io_object_t next_media;
-    mach_port_t master_port;
-    kern_return_t kern_result;
-    io_iterator_t media_iterator;
-    CFMutableDictionaryRef classes_to_match;
+    int format = [fDstFormatPopUp indexOfSelectedItem];
+    int codecs = [fDstCodecsPopUp indexOfSelectedItem];
 
-    kern_result = IOMasterPort( MACH_PORT_NULL, &master_port );
-    if( kern_result != KERN_SUCCESS )
+    /* Update the encoder popup */
+    if( ( FormatSettings[format][codecs] & HB_VCODEC_X264 ) )
     {
-        return;
+        /* MPEG-4 -> H.264 */
+        [fVidEncoderPopUp removeAllItems];
+               [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 Main)"];
+               [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 iPod)"];
+        
+        
     }
-
-    classes_to_match = IOServiceMatching( kIODVDMediaClass );
-    if( classes_to_match == NULL )
+    else if( ( FormatSettings[format][codecs] & HB_VCODEC_FFMPEG ) )
     {
-        return;
+        /* H.264 -> MPEG-4 */
+        [fVidEncoderPopUp removeAllItems];
+        [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
+        [fVidEncoderPopUp addItemWithTitle: @"XviD"];
+        [fVidEncoderPopUp selectItemAtIndex: 0];
     }
 
-    CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectableKey ),
-                          kCFBooleanTrue );
-
-    kern_result =
-        IOServiceGetMatchingServices( master_port, classes_to_match,
-                                      &media_iterator );
-    if( kern_result != KERN_SUCCESS )
+    if( FormatSettings[format][codecs] & HB_ACODEC_AC3 )
     {
-        return;
+        /* AC-3 pass-through: disable samplerate and bitrate */
+        [fAudRatePopUp    setEnabled: NO];
+        [fAudBitratePopUp setEnabled: NO];
     }
+    else
+    {
+        [fAudRatePopUp    setEnabled: YES];
+        [fAudBitratePopUp setEnabled: YES];
+    }
+
+       /* check if this change means we should / should't offer 6-channel AAC extraction */
+       [self Check6ChannelAACExtraction: sender];
 
-    NSMutableArray * drivesList;
-    drivesList = [NSMutableArray arrayWithCapacity: 1];
+    [self CalculateBitrate: sender];
 
-    next_media = IOIteratorNext( media_iterator );
-    if( next_media != NULL )
+}
+
+- (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)
     {
-        char psz_buf[0x32];
-        size_t dev_path_length;
-        CFTypeRef str_bsd_path;
-        do
-        {
-            str_bsd_path =
-                IORegistryEntryCreateCFProperty( next_media,
-                                                 CFSTR( kIOBSDNameKey ),
-                                                 kCFAllocatorDefault,
-                                                 0 );
-            if( str_bsd_path == NULL )
-            {
-                IOObjectRelease( next_media );
-                continue;
-            }
+       hb_job_t * job = fTitle->job;
+       job->pixel_ratio = 0 ;
+       
+                if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPicSizeAutoiPod"] > 0)
+                {
+                
+                if (fTitle->job->width > 640)
+                               {
+                               fTitle->job->width = 640;
+                               }
+                fTitle->job->keep_ratio = 1;
+                hb_fix_aspect( job, HB_KEEP_WIDTH );
+                
+                }
+
+               /* uncheck the "export 5.1 as 6-channel AAC" checkbox if it is checked */
+               [fAudLang1SurroundCheck setState: NSOffState];
+
+       }
+    
+       [self CalculatePictureSizing: sender];    
+  
+}
 
-            snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' );
-            dev_path_length = strlen( psz_buf );
+- (IBAction) Check6ChannelAACExtraction: (id) sender
+{
 
-            if( CFStringGetCString( (CFStringRef) str_bsd_path,
-                                    (char*)&psz_buf + dev_path_length,
-                                    sizeof(psz_buf) - dev_path_length,
-                                    kCFStringEncodingASCII ) )
-            {
-                [drivesList addObject:
-                    [NSString stringWithCString: psz_buf]];
-            }
+       /* make sure we have a selected title before continuing */
+       if (fTitle == NULL) return;
+
+       /* get the current title's job into a convenience variable */
+       hb_job_t * job = fTitle->job;
+       
+    /* get the current audio tracks */
+       /* this is done in PrepareJob too, but we want them here to check against below */
+    job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
+    job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1;
+    job->audios[2] = -1;
+
+       /* now, let's check if any selected audio track has 5.1 sound */
+       hb_audio_t * audio;
+       bool foundfiveoneaudio = false;
+
+       /* find out what the currently-selected audio codec is */
+    int format = [fDstFormatPopUp indexOfSelectedItem];
+    int codecs = [fDstCodecsPopUp indexOfSelectedItem];
+       int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
+
+       /* we only offer the option to extract 5.1 to 6-channel if the selected audio codec is AAC */
+       if (acodec == HB_ACODEC_FAAC) {
+
+               bool doneaudios = false;
+               int thisaudio = 0;
+               
+               while (!doneaudios) {
+
+                       if (job->audios[thisaudio] == -1) {
+                               doneaudios = true;
+                       } else {
+                               audio = (hb_audio_t *) hb_list_item( fTitle->list_audio, job->audios[thisaudio] );
+                               if (audio != NULL) {
+                                       if (audio->channels == 5 && audio->lfechannels == 1) {
+                                               foundfiveoneaudio = true;
+                                               doneaudios = true; /* as it doesn't matter if we find any more! */
+                                       }
+                               }
+                       }
+
+                       thisaudio++;
+               }
+       }
+
+    /* If we are extracting to AAC, and any of our soundtracks were 5.1, then enable the checkbox  */
+       if (foundfiveoneaudio) {
+               [fAudLang1SurroundCheck setEnabled: YES];
+               /* Check default surround sound pref and if it is YES, lets also check the checkbox */
+               if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultSurroundSound"] > 0)
+               {
+                       [fAudLang1SurroundCheck setState: NSOnState];
+               }
+       } else {
+               [fAudLang1SurroundCheck setEnabled: NO];
+               /* as well as disabling the checkbox, let's uncheck it if it is checked */
+               [fAudLang1SurroundCheck setState: NSOffState];
+       }
 
-            CFRelease( str_bsd_path );
+}
 
-            IOObjectRelease( next_media );
 
-        } while( ( next_media = IOIteratorNext( media_iterator ) ) != NULL );
-    }
+- (IBAction) LanguagePopUpChanged: (id) sender
+{
+       
+       /* selecting a different language may mean we have a different number of channels, so */
+       /* check if this change means we should / should't offer 6-channel AAC extraction */
+       [self Check6ChannelAACExtraction: sender];
+       
+       /* see if the new language setting will change the bitrate we need */
+    [self CalculateBitrate:     sender];       
 
-    IOObjectRelease( media_iterator );
+}
 
-    [fScDetectedPopUp removeAllItems];
-    for( unsigned i = 0; i < [drivesList count]; i++ )
-    {
-        [[fScDetectedPopUp menu] addItemWithTitle:
-            [drivesList objectAtIndex: i] action: nil
-            keyEquivalent: @""];
-    }
-    [self ScanMatrixChanged: self];
+
+/* Get and Display Current Pic Settings in main window */
+- (IBAction) CalculatePictureSizing: (id) sender
+{
+
+       hb_job_t * job = fTitle->job;           
+
+       [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];
+       [fPicLabelPAROutp setStringValue: @"Anamorphic Output:"];
+       [fPicLabelPAROutputX setStringValue: @"x"];
+    [fPicSettingPARWidth setStringValue: [NSString stringWithFormat:
+        @"%d", displayparwidth]];
+       [fPicSettingPARHeight setStringValue: [NSString stringWithFormat:
+        @"%d", displayparheight]];
+       [fPicSettingHeight 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"];
+               }       
+               
+       
 }
 
-- (IBAction) ScanMatrixChanged: (id) sender
+- (IBAction) CalculateBitrate: (id) sender
 {
-    if( ![fScMatrix selectedRow] )
+    if( !fHandle || [fVidQualityMatrix selectedRow] != 0 )
     {
-        [fScDetectedPopUp setEnabled: YES];
-        [fScFolderField setEnabled: NO];
-        [fScBrowseButton setEnabled: NO];
-        [fScOpenButton setEnabled: ( [fScDetectedPopUp selectedItem] != nil )];
-    }
-    else
-    {
-        [fScDetectedPopUp setEnabled: NO];
-        [fScFolderField setEnabled: YES];
-        [fScBrowseButton setEnabled: YES];
-        [fScOpenButton setEnabled: YES];
+        return;
     }
+
+    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];
+
+    [fVidBitrateField setIntValue: hb_calc_bitrate( job,
+            [fVidTargetSizeField intValue] )];
 }
 
-- (IBAction) TitlePopUpChanged: (id) sender
+- (IBAction) ShowAddPresetPanel: (id) sender
+{
+    /* 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
 {
-    HBTitle * title = (HBTitle*)
-        HBListItemAt( fTitleList, [fRipTitlePopUp indexOfSelectedItem] );
+    [NSApp stopModal];
+}
 
-    [fRipLang1PopUp removeAllItems];
-    [fRipLang2PopUp removeAllItems];
+- (IBAction)addPreset:(id)sender
+{
+    [UserPresets addObject:[self CreatePreset]];
+       /* We Sort the Presets Alphabetically by name */
+       NSSortDescriptor * lastNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName" 
+                                                    ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
+       NSArray *sortDescriptors=[NSArray arrayWithObject:lastNameDescriptor];
+       NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
+       [UserPresets setArray:sortedArray];
+       
+       /* We stop the modal window for the new preset */
+       [fPresetNewName    setStringValue: @""];
+       [NSApp stopModal];
+       /* We Reload the New Table data for presets */
+    [tableView reloadData];
+   /* We save all of the preset data here */
+    [self savePreset];
+}
 
-    HBAudio * audio;
-    for( int i = 0; i < HBListCount( title->audioList ); i++ )
-    {
-        audio = (HBAudio*) HBListItemAt( title->audioList, i );
+- (IBAction)insertPreset:(id)sender
+{
+    int index = [tableView selectedRow];
+    [UserPresets insertObject:[self CreatePreset] atIndex:index];
+    [tableView reloadData];
+    [self savePreset];
+}
 
-        /* We cannot use NSPopUpButton's addItemWithTitle because
-           it checks for duplicate entries */
-        [[fRipLang1PopUp menu] addItemWithTitle:
-            [NSString stringWithCString: audio->language]
-            action: nil keyEquivalent: @""];
-        [[fRipLang2PopUp menu] addItemWithTitle:
-            [NSString stringWithCString: audio->language]
-            action: nil keyEquivalent: @""];
-    }
-    [fRipLang2PopUp addItemWithTitle: _( @"None" )];
-    [fRipLang2PopUp selectItemWithTitle: _( @"None" )];
-    [fRipLang2PopUp setEnabled:
-        ( HBListCount( title->audioList ) > 1 )];
+- (NSDictionary *)CreatePreset
+{
+    NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
+       /* Get the New Preset Name from the field in the AddPresetPanel */
+    [preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"];
+       /*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"];
+       /* Codecs */
+       [preset setObject:[fDstCodecsPopUp titleOfSelectedItem] forKey:@"FileCodecs"];
+       /* Video encoder */
+       [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
+       /* Video quality */
+       [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 */
+       [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 Language One*/
+       [preset setObject:[fAudLang1PopUp titleOfSelectedItem] forKey:@"AudioLang1"];
+       /* Audio Language One Surround Sound Checkbox*/
+       [preset setObject:[NSNumber numberWithInt:[fAudLang1SurroundCheck state]] forKey:@"AudioLang1Surround"];
+       /* 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;
 
-    [fRipTargetField SetHBTitle: title];
-    if( [fRipVideoMatrix selectedRow] )
-    {
-        [fRipTargetField UpdateBitrate];
-    }
 }
 
-- (IBAction) FormatPopUpChanged: (id) sender
+- (IBAction)deletePreset:(id)sender
 {
-    /* Headers size changes depending on the format, so let's
-       recalculate the bitrate if necessary */
-    if( [fRipVideoMatrix selectedRow] )
-    {
-        [fRipTargetField UpdateBitrate];
+    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
+{
 
-    /* Add/replace to the correct extension */
-    NSString * string = [fRipFileField2 stringValue];
-    int format = [fRipFormatPopUp indexOfSelectedItem];
-    if( [string characterAtIndex: [string length] - 4] == '.' )
-    {
-        [fRipFileField2 setStringValue: [NSString stringWithFormat:
-            @"%@.%s", [string substringToIndex: [string length] - 4],
-            ( !format ) ? "mp4" : ( ( format == 3 ) ?
-            "ogm" : "avi" )]];
-    }
-    else
-    {
-        [fRipFileField2 setStringValue: [NSString stringWithFormat:
-            @"%@.%s", string, ( !format ) ? "mp4" :
-            ( ( format == 3 ) ? "ogm" : "avi" )]];
-    }
+    /* we get the chosen preset from the UserPresets array */
+       chosenPreset = [UserPresets objectAtIndex:[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];
+    /* Codecs */
+       [fDstCodecsPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileCodecs"]]];
+       [self CodecsPopUpChanged: NULL];
+       /* Video encoder */
+       [fVidEncoderPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoEncoder"]]];
+       /* Lets run through the following functions to get variables set there */
+       [self EncoderPopUpChanged: sender];
+       [self Check6ChannelAACExtraction: sender];
+       [self CalculateBitrate: sender];
+       
+       /* 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: sender];
+       
+       /* 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 Language One*/
+       [fAudLang1PopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioLang1"]]];
+       /* Audio Language One Surround Sound Checkbox*/
+       [fAudLang1SurroundCheck setState:[[chosenPreset objectForKey:@"AudioLang1Surround"] intValue]];
+       [self Check6ChannelAACExtraction: sender];
+       /* 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;
+               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: sender]; 
+       }
+       
+       // Deselect the currently selected table //
+       //[tableView deselectRow:[tableView selectedRow]];
+}
 
-    if( format == 2 )
-    {
-        /* Can't set X264 bitrate */
-        [fRipEncoderPopUp setEnabled: NO];
-        [fRipVideoMatrix  setEnabled: NO];
-        [fRipTwoPassCheck setEnabled: NO];
-    }
-    else if( format == 3 )
-    {
-        [fRipEncoderPopUp setEnabled: YES];
-        [fRipVideoMatrix  setEnabled: YES];
-        [fRipTwoPassCheck setEnabled: YES];
-    }
-    else
-    {
-        [fRipEncoderPopUp setEnabled: YES];
-        [fRipVideoMatrix  setEnabled: YES];
-        [fRipTwoPassCheck setEnabled: YES];
-    }
-    [self VideoMatrixChanged: self];
+- (int)numberOfRowsInTableView:(NSTableView *)aTableView
+{
+    return [UserPresets count];
 }
 
-- (IBAction) AudioPopUpChanged: (id) sender
+- (id)tableView:(NSTableView *)aTableView
+      objectValueForTableColumn:(NSTableColumn *)aTableColumn
+      row:(int)rowIndex
 {
-    /* Recalculate the bitrate */
-    if( [fRipVideoMatrix selectedRow] )
-    {
-        [fRipTargetField UpdateBitrate];
-    }
+
+       
+       
+       id theRecord, theValue;
+    
+    theRecord = [UserPresets objectAtIndex:rowIndex];
+    theValue = [theRecord objectForKey:[aTableColumn identifier]];
+    
+    return theValue;
 }
 
-/*******************
- * libhb callbacks *
- *******************/
-static void _Scanning( void * data, int title, int titleCount )
+// 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
 {
-    HBController * controller = (HBController*) data;
-    controller->fTitle        = title;
-    controller->fTitleCount   = titleCount;
-    [controller performSelectorOnMainThread: @selector(Scanning:)
-        withObject: nil waitUntilDone: YES];
+    id theRecord;
+    
+    theRecord = [UserPresets objectAtIndex:rowIndex];
+    [theRecord setObject:anObject forKey:[aTableColumn identifier]];
+    
+               /* We Sort the Presets Alphabetically by name */
+       NSSortDescriptor * lastNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName" 
+                                                    ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
+       NSArray *sortDescriptors=[NSArray arrayWithObject:lastNameDescriptor];
+       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) Scanning: (id) sender
+
+
+- (void)savePreset
 {
-    [fScProgress stopAnimation: self];
-    [fScProgress setIndeterminate: NO];
-    [fScProgress setDoubleValue: 100.0 * fTitle / fTitleCount];
+    [UserPresets writeToFile:UserPresetsFile atomically:YES];
 
-    [fScStatusField setStringValue: [NSString stringWithFormat:
-        _( @"Scanning title %d of %d..." ), fTitle, fTitleCount]];
 }
 
-static void _ScanDone( void * data, HBList * titleList )
+
+
+- (void) controlTextDidBeginEditing: (NSNotification *) notification
 {
-    HBController * controller = (HBController*) data;
-    controller->fTitleList    = titleList;
-    [controller performSelectorOnMainThread: @selector(ScanDone:)
-        withObject: nil waitUntilDone: YES];
+    [self CalculateBitrate: NULL];
 }
-- (void) ScanDone: (id) sender
+
+- (void) controlTextDidEndEditing: (NSNotification *) notification
 {
-    if( !fTitleList )
-    {
-        [fScMatrix setEnabled: YES];
-        [self ScanMatrixChanged: self];
-        [fScProgress stopAnimation: self];
-        [fScProgress setIndeterminate: NO];
-        [fScOpenButton setEnabled: YES];
-        [fScStatusField setStringValue:
-            _( @"Invalid volume, try again" ) ];
-        return;
-    }
+    [self CalculateBitrate: NULL];
+}
 
-    /* Show a temporary empty view while the window
-       resizing animation */
-    [fWindow setContentView: fTempView ];
-
-    /* Actually resize it */
-    NSRect newFrame;
-    newFrame = [NSWindow contentRectForFrameRect: [fWindow frame]
-                 styleMask: [fWindow styleMask]];
-    newFrame.origin.y    += newFrame.size.height -
-                                [fRipView frame].size.height;
-    newFrame.size.height  = [fRipView frame].size.height;
-    newFrame.size.width   = [fRipView frame].size.width;
-    newFrame = [NSWindow frameRectForContentRect: newFrame
-                 styleMask: [fWindow styleMask]];
-    [fWindow setFrame: newFrame display: YES animate: YES];
-
-    /* Show the new GUI */
-    [fWindow setContentView: fRipView ];
-    [fRipPauseButton setEnabled: NO];
-
-    [fRipTitlePopUp removeAllItems];
-    HBTitle * title;
-    for( int i = 0; i < HBListCount( fTitleList ); i++ )
-    {
-        title = (HBTitle*) HBListItemAt( fTitleList, i );
-        [[fRipTitlePopUp menu] addItemWithTitle:
-            [NSString stringWithFormat: @"%d - %02dh%02dm%02ds",
-            title->index, title->length / 3600, ( title->length % 3600 )
-            / 60, title->length % 60] action: nil keyEquivalent: @""];
-    }
-    [self TitlePopUpChanged: self];
-}
-
-static void _Encoding( void * data, float position, int pass,
-                      int passCount, float curFrameRate,
-                      float avgFrameRate, int remainingTime )
-{
-    HBController * controller  = (HBController*) data;
-    controller->fPosition      = position;
-    controller->fPass          = pass;
-    controller->fPassCount     = passCount;
-    controller->fCurFrameRate  = curFrameRate;
-    controller->fAvgFrameRate  = avgFrameRate;
-    controller->fRemainingTime = remainingTime;
-    [controller performSelectorOnMainThread: @selector(Encoding:)
-        withObject: nil waitUntilDone: YES];
-}
-- (void) Encoding: (id) sender
-{
-    [fRipStatusField setStringValue: [NSString stringWithFormat:
-        _( @"Encoding: %.2f %% (pass %d of %d)" ),
-        100.0 * fPosition, fPass, fPassCount]];
-    [fRipInfoField setStringValue: [NSString stringWithFormat:
-        _( @"Speed: %.2f fps (avg %.2f fps), %02dh%02dm%02ds remaining" ),
-        fCurFrameRate, fAvgFrameRate, fRemainingTime / 3600,
-        ( fRemainingTime / 60 ) % 60, fRemainingTime % 60]];
-
-    [fRipProgress setIndeterminate: NO];
-    [fRipProgress setDoubleValue: 100.0 * fPosition];
-}
-
-static void _RipDone( void * data, int result )
-{
-    HBController * controller = (HBController*) data;
-    controller->fResult       = result;
-    [controller performSelectorOnMainThread: @selector(RipDone:)
-        withObject: nil waitUntilDone: YES];
-}
-- (void) RipDone: (id) sender
-{
-    [fRipTitlePopUp   setEnabled: YES];
-    [fRipFormatPopUp  setEnabled: YES];
-    [fRipVideoMatrix  setEnabled: YES];
-    [fRipTwoPassCheck setEnabled: YES];
-    [fRipCropButton   setEnabled: YES];
-    [fRipLang1PopUp   setEnabled: YES];
-    [fRipLang2PopUp   setEnabled: YES];
-    [fRipAudBitPopUp  setEnabled: YES];
-    [fRipFileField2   setEnabled: YES];
-    [fRipBrowseButton setEnabled: YES];
-    [fRipEncoderPopUp setEnabled: YES];
-    [fRipPauseButton  setEnabled: NO];
-    [fRipPauseButton  setTitle: _( @"Pause" )];
-    [fRipRipButton    setTitle: _( @"Rip" )];
-    [fRipProgress     setIndeterminate: NO];
-    [fRipProgress     setDoubleValue: 0.0];
-    [self VideoMatrixChanged: self];
-
-    switch( fResult )
-    {
-        case HB_SUCCESS:
-            [fRipStatusField setStringValue: _( @"Rip completed." )];
-            [fRipInfoField   setStringValue: @""];
-            NSBeep();
-            [NSApp requestUserAttention: NSInformationalRequest];
-            [NSApp beginSheet: fDonePanel
-                modalForWindow: fWindow modalDelegate: nil
-                didEndSelector: nil contextInfo: nil];
-            [NSApp runModalForWindow: fDonePanel];
-            [NSApp endSheet: fDonePanel];
-            [fDonePanel orderOut: self];
-            break;
-        case HB_CANCELED:
-            [fRipStatusField setStringValue: _( @"Canceled." )];
-            [fRipInfoField   setStringValue: @""];
-            break;
-        case HB_ERROR_A52_SYNC:
-            [fRipStatusField setStringValue: @"Error."];
-            [fRipInfoField   setStringValue: @"Corrupted AC3 data"];
-            break;
-        case HB_ERROR_AVI_WRITE:
-            [fRipStatusField setStringValue: @"Error."];
-            [fRipInfoField   setStringValue: @"Write error"];
-            break;
-        case HB_ERROR_DVD_OPEN:
-            [fRipStatusField setStringValue: @"Error."];
-            [fRipInfoField   setStringValue: @"Could not open the DVD"];
-            break;
-        case HB_ERROR_DVD_READ:
-            [fRipStatusField setStringValue: @"Error."];
-            [fRipInfoField   setStringValue: @"DVD read error"];
-            break;
-        case HB_ERROR_MP3_INIT:
-            [fRipStatusField setStringValue: @"Error."];
-            [fRipInfoField   setStringValue:
-                @"MP3 encoder initialization failed"];
-            break;
-        case HB_ERROR_MP3_ENCODE:
-            [fRipStatusField setStringValue: @"Error."];
-            [fRipInfoField   setStringValue: @"MP3 encoder failed"];
-            break;
-        case HB_ERROR_MPEG4_INIT:
-            [fRipStatusField setStringValue: @"Error."];
-            [fRipInfoField   setStringValue:
-                @"MPEG4 encoder initialization failed"];
-            break;
-        default:
-            [fRipStatusField setStringValue: @"Error."];
-            [fRipInfoField   setStringValue: @"Unknown error"];
-    }
+- (void) controlTextDidChange: (NSNotification *) notification
+{
+    [self CalculateBitrate: NULL];
+}
+
+- (IBAction) OpenHomepage: (id) sender
+{
+    [[NSWorkspace sharedWorkspace] openURL: [NSURL
+        URLWithString:@"http://handbrake.m0k.org/"]];
 }
 
+- (IBAction) OpenForums: (id) sender
+{
+    [[NSWorkspace sharedWorkspace] openURL: [NSURL
+        URLWithString:@"http://handbrake.m0k.org/forum/"]];
+}
+
+
+
 @end