OSDN Git Service

MacGui: Audio ... Add an "Add All Tracks" button to the audio tab.
[handbrake-jp/handbrake-jp-git.git] / macosx / Controller.m
index 013de25..92d31a8 100644 (file)
@@ -4,6 +4,7 @@
    Homepage: <http://handbrake.fr/>.
    It may be used under the terms of the GNU General Public License. */
 
+#include <dlfcn.h>
 #import "Controller.h"
 #import "HBOutputPanelController.h"
 #import "HBPreferencesController.h"
 #import "HBPresets.h"
 #import "HBPreviewController.h"
 
+unsigned int maximumNumberOfAllowedAudioTracks = 24;
+NSString *HBContainerChangedNotification = @"HBContainerChangedNotification";
+NSString *keyContainerTag = @"keyContainerTag";
+NSString *HBTitleChangedNotification = @"HBTitleChangedNotification";
+NSString *keyTitleTag = @"keyTitleTag";
+
 #define DragDropSimplePboardType       @"MyCustomOutlineViewPboardType"
 
 /* We setup the toolbar values here ShowPreviewIdentifier */
@@ -30,6 +37,8 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
  *******************************/
 @implementation HBController
 
++ (unsigned int) maximumNumberOfAllowedAudioTracks     {       return maximumNumberOfAllowedAudioTracks;       }
+
 - (id)init
 {
     self = [super init];
@@ -82,7 +91,7 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
     fPreferencesController = [[HBPreferencesController alloc] init];
     /* Lets report the HandBrake version number here to the activity log and text log file */
     NSString *versionStringFull = [[NSString stringWithFormat: @"Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]];
-    [self writeToActivityLog: "%s", [versionStringFull UTF8String]];    
+    [self writeToActivityLog: "%s", [versionStringFull UTF8String]];
     
     return self;
 }
@@ -117,16 +126,58 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
     [fSubtitlesTable setDelegate:fSubtitlesDelegate];
     [fSubtitlesTable setRowHeight:25.0];
     
+       /* setup the audio controller */
+       [fAudioDelegate setHBController: self];
+       [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(autoSetM4vExtension:) name: HBMixdownChangedNotification object: nil];
+
     [fPresetsOutlineView setAutosaveName:@"Presets View"];
     [fPresetsOutlineView setAutosaveExpandedItems:YES];
     
     dockIconProgress = 0;
-
+    
+    /* Init QueueFile .plist */
+    [self loadQueueFile];
+    /* Run hbInstances to get any info on other instances as well as set the
+     * pid number for this instance in the case of multi-instance encoding. */ 
+    hbInstanceNum = [self hbInstances];
+    
+    /* If we are a single instance it is safe to clean up the previews if there are any
+     * left over. This is a bit of a kludge but will prevent a build up of old instance
+     * live preview cruft. No danger of removing an active preview directory since they
+     * are created later in HBPreviewController if they don't exist at the moment a live
+     * preview encode is initiated. */
+    if (hbInstanceNum == 1)
+    {
+        NSString *PreviewDirectory = [NSString stringWithFormat:@"~/Library/Application Support/HandBrake/Previews"];
+        PreviewDirectory = [PreviewDirectory stringByExpandingTildeInPath];
+        NSError *error;
+        NSArray *files = [ [NSFileManager defaultManager]  contentsOfDirectoryAtPath: PreviewDirectory error: &error ];
+        for( NSString *file in files ) 
+        {
+            if( file != @"." && file != @".." ) 
+            {
+                [ [NSFileManager defaultManager] removeItemAtPath: [ PreviewDirectory stringByAppendingPathComponent: file ] error: &error ];
+                if( error ) 
+                { 
+                    //an error occurred...
+                    [self writeToActivityLog: "Could not remove existing preview at : %s",[file UTF8String] ];
+                }
+            }    
+        }
+        
+    }
+    
+     
+    
     /* Call UpdateUI every 1/2 sec */
+    
     [[NSRunLoop currentRunLoop] addTimer:[NSTimer
-                                          scheduledTimerWithTimeInterval:0.5 target:self
-                                          selector:@selector(updateUI:) userInfo:nil repeats:YES]
-                                 forMode:NSDefaultRunLoopMode];
+                                          scheduledTimerWithTimeInterval:0.5 
+                                          target:self
+                                          selector:@selector(updateUI:) 
+                                          userInfo:nil repeats:YES]
+                                          forMode:NSDefaultRunLoopMode];
+                             
 
     // Open debug output window now if it was visible when HB was closed
     if ([[NSUserDefaults standardUserDefaults] boolForKey:@"OutputPanelIsOpen"])
@@ -164,11 +215,11 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
         /* We check to see if there is already another instance of hb running.
          * Note: hbInstances == 1 means we are the only instance of HandBrake.app
          */
-        if ([self hbInstances] > 1)
+        if (hbInstanceNum > 1)
         {
-        alertTitle = [NSString stringWithFormat:
-                         NSLocalizedString(@"There is already an instance of HandBrake running.", @"")];
-        NSBeginCriticalAlertSheet(
+            alertTitle = [NSString stringWithFormat:
+                          NSLocalizedString(@"There is already an instance of HandBrake running.", @"")];
+            NSBeginCriticalAlertSheet(
                                       alertTitle,
                                       NSLocalizedString(@"Reload Queue", nil),
                                       nil,
@@ -179,29 +230,48 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
         }
         else
         {
-            if (fWorkingCount > 0)
+            if (fWorkingCount > 0 || fPendingCount > 0)
             {
-                alertTitle = [NSString stringWithFormat:
-                              NSLocalizedString(@"HandBrake Has Detected %d Previously Encoding Item and %d Pending Item(s) In Your Queue.", @""),
-                              fWorkingCount,fPendingCount];
+                if (fWorkingCount > 0)
+                {
+                    alertTitle = [NSString stringWithFormat:
+                                  NSLocalizedString(@"HandBrake Has Detected %d Previously Encoding Item(s) and %d Pending Item(s) In Your Queue.", @""),
+                                  fWorkingCount,fPendingCount];
+                }
+                else
+                {
+                    alertTitle = [NSString stringWithFormat:
+                                  NSLocalizedString(@"HandBrake Has Detected %d Pending Item(s) In Your Queue.", @""),
+                                  fPendingCount];
+                }
+                
+                NSBeginCriticalAlertSheet(
+                                          alertTitle,
+                                          NSLocalizedString(@"Reload Queue", nil),
+                                          nil,
+                                          NSLocalizedString(@"Empty Queue", nil),
+                                          fWindow, self,
+                                          nil, @selector(didDimissReloadQueue:returnCode:contextInfo:), nil,
+                                          NSLocalizedString(@" Do you want to reload them ?", nil));
             }
             else
             {
-                alertTitle = [NSString stringWithFormat:
-                              NSLocalizedString(@"HandBrake Has Detected %d Pending Item(s) In Your Queue.", @""),
-                              fPendingCount];
+                /* Since we addressed any pending or previously encoding items above, we go ahead and make sure the queue
+                 * is empty of any finished items or cancelled items */
+                [self clearQueueAllItems];
+                /* We show whichever open source window specified in LaunchSourceBehavior preference key */
+                if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source"])
+                {
+                    [self browseSources:nil];
+                }
+                
+                if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source (Title Specific)"])
+                {
+                    [self browseSources:(id)fOpenSourceTitleMMenu];
+                }
             }
             
-            NSBeginCriticalAlertSheet(
-                                      alertTitle,
-                                      NSLocalizedString(@"Reload Queue", nil),
-                                      nil,
-                                      NSLocalizedString(@"Empty Queue", nil),
-                                      fWindow, self,
-                                      nil, @selector(didDimissReloadQueue:returnCode:contextInfo:), nil,
-                                      NSLocalizedString(@" Do you want to reload them ?", nil));
         }
-        
     }
     else
     {
@@ -216,29 +286,67 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
             [self browseSources:(id)fOpenSourceTitleMMenu];
         }
     }
+    currentQueueEncodeNameString = @"";
 }
 
+#pragma mark -
+#pragma mark Multiple Instances
+
+/* hbInstances checks to see if other instances of HB are running and also sets the pid for this instance for multi-instance queue encoding */
+ /* Note for now since we are in early phases of multi-instance I have put in quite a bit of logging. Can be removed as we see fit. */
 - (int) hbInstances
 {
     /* check to see if another instance of HandBrake.app is running */
     NSArray *runningAppDictionaries = [[NSWorkspace sharedWorkspace] launchedApplications];
-    NSDictionary *aDictionary;
+    NSDictionary *runningAppsDictionary;
     int hbInstances = 0;
-    for (aDictionary in runningAppDictionaries)
+    NSString * thisInstanceAppPath = [[NSBundle mainBundle] bundlePath];
+    NSString * runningInstanceAppPath;
+    int runningInstancePidNum;
+    [self writeToActivityLog: "hbInstances path to this instance: %s", [thisInstanceAppPath UTF8String]];
+    for (runningAppsDictionary in runningAppDictionaries)
        {
-        if ([[aDictionary valueForKey:@"NSApplicationName"] isEqualToString:@"HandBrake"])
+        if ([[runningAppsDictionary valueForKey:@"NSApplicationName"] isEqualToString:@"HandBrake"])
                {
+            /*Report the path to each active instances app path */
+            runningInstancePidNum = [[runningAppsDictionary valueForKey:@"NSApplicationProcessIdentifier"] intValue];
+            runningInstanceAppPath = [runningAppsDictionary valueForKey:@"NSApplicationPath"];
+            [self writeToActivityLog: "hbInstance found instance pidnum:%d at path: %s", runningInstancePidNum, [runningInstanceAppPath UTF8String]];
+            /* see if this is us by comparing the app path */
+            if ([runningInstanceAppPath isEqualToString: thisInstanceAppPath])
+            {
+                /* If so this is our pidnum */
+                [self writeToActivityLog: "hbInstance MATCH FOUND, our pidnum is:%d", runningInstancePidNum];
+                /* Get the PID number for this hb instance, used in multi instance encoding */
+                pidNum = runningInstancePidNum;
+                /* Report this pid to the activity log */
+                [self writeToActivityLog: "Pid for this instance:%d", pidNum];
+                /* Tell fQueueController what our pidNum is */
+                [fQueueController setPidNum:pidNum];
+            }
             hbInstances++;
-               }
-       }
+        }
+    }
     return hbInstances;
 }
 
+- (int) getPidnum
+{
+    return pidNum;
+}
+
+#pragma mark -
+
 - (void) didDimissReloadQueue: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo
 {
+    
+    [self writeToActivityLog: "didDimissReloadQueue number of hb instances:%d", hbInstanceNum];
     if (returnCode == NSAlertOtherReturn)
     {
+        [self writeToActivityLog: "didDimissReloadQueue NSAlertOtherReturn Chosen"];
         [self clearQueueAllItems];
+        
         /* We show whichever open source window specified in LaunchSourceBehavior preference key */
         if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source"])
         {
@@ -252,8 +360,10 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
     }
     else
     {
-        if ([self hbInstances] == 1)
+        [self writeToActivityLog: "didDimissReloadQueue First Button Chosen"];
+        if (hbInstanceNum == 1)
         {
+            
             [self setQueueEncodingItemsAsPending];
         }
         [self showQueueWindow:NULL];
@@ -262,15 +372,7 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
 
 - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) app
 {
-    /* if we are in preview full screen mode, we need to go to
-     * windowed mode and release the display before we terminate.
-     * We do it here (instead of applicationWillTerminate) so we 
-     * release the displays and can then see the alerts below.
-     */
-    if ([fPictureController previewFullScreenMode] == YES)
-    {
-        [fPictureController previewGoWindowed:nil];
-    }
+
     
     hb_state_t s;
     hb_get_state( fQueueEncodeLibhb, &s );
@@ -309,7 +411,7 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
 
 - (void)applicationWillTerminate:(NSNotification *)aNotification
 {
-    
+    [currentQueueEncodeNameString release];
     [browsedSourceDisplayName release];
     [outputPanel release];
        [fQueueController release];
@@ -317,15 +419,18 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
     [fPictureController release];
     [fApplicationIcon release];
 
-       hb_close(&fHandle);
+    hb_close(&fHandle);
     hb_close(&fQueueEncodeLibhb);
+    hb_global_close();
+
 }
 
 
 - (void) awakeFromNib
 {
     [fWindow center];
-    [fWindow setExcludedFromWindowsMenu:YES];
+    [fWindow setExcludedFromWindowsMenu:NO];
+    
     [fAdvancedOptions setView:fAdvancedView];
     
     /* lets setup our presets drawer for drag and drop here */
@@ -340,9 +445,6 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
     
     /* Init UserPresets .plist */
        [self loadPresets];
-    
-    /* Init QueueFile .plist */
-    [self loadQueueFile];
        
     fRipIndicatorShown = NO;  // initially out of view in the nib
     
@@ -459,26 +561,7 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
        
        /* Set Auto Crop to On at launch */
     [fPictureController setAutoCrop:YES];
-       
-       /* Audio bitrate */
-    [fAudTrack1BitratePopUp removeAllItems];
-    for( int i = 0; i < hb_audio_bitrates_count; i++ )
-    {
-        [fAudTrack1BitratePopUp addItemWithTitle:
-         [NSString stringWithUTF8String: hb_audio_bitrates[i].string]];
-        
-    }
-    [fAudTrack1BitratePopUp selectItemAtIndex: hb_audio_bitrates_default];
-       
-    /* Audio samplerate */
-    [fAudTrack1RatePopUp removeAllItems];
-    for( int i = 0; i < hb_audio_rates_count; i++ )
-    {
-        [fAudTrack1RatePopUp addItemWithTitle:
-         [NSString stringWithUTF8String: hb_audio_rates[i].string]];
-    }
-    [fAudTrack1RatePopUp selectItemAtIndex: hb_audio_rates_default];
-       
+               
     /* Bottom */
     [fStatusField setStringValue: @""];
     
@@ -494,8 +577,6 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
        [self getDefaultPresets:nil];
        /* lets initialize the current successful scancount here to 0 */
        currentSuccessfulScanCount = 0;
-    
-    
 }
 
 - (void) enableUI: (bool) b
@@ -507,19 +588,11 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
         fDstFormatField, fDstFormatPopUp, fDstFile1Field, fDstFile2Field,
         fDstBrowseButton, fVidRateField, fVidRatePopUp,fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
         fPictureSizeField,fPictureCroppingField, fVideoFiltersField,fVidQualityMatrix, fSubField, fSubPopUp,
-        fAudSourceLabel, fAudCodecLabel, fAudMixdownLabel, fAudSamplerateLabel, fAudBitrateLabel,
-        fAudTrack1Label, fAudTrack2Label, fAudTrack3Label, fAudTrack4Label,
-        fAudLang1PopUp, fAudLang2PopUp, fAudLang3PopUp, fAudLang4PopUp,
-        fAudTrack1CodecPopUp, fAudTrack2CodecPopUp, fAudTrack3CodecPopUp, fAudTrack4CodecPopUp,
-        fAudTrack1MixPopUp, fAudTrack2MixPopUp, fAudTrack3MixPopUp, fAudTrack4MixPopUp,
-        fAudTrack1RatePopUp, fAudTrack2RatePopUp, fAudTrack3RatePopUp, fAudTrack4RatePopUp,
-        fAudTrack1BitratePopUp, fAudTrack2BitratePopUp, fAudTrack3BitratePopUp, fAudTrack4BitratePopUp,
-        fAudDrcLabel, fAudTrack1DrcSlider, fAudTrack1DrcField, fAudTrack2DrcSlider,
-        fAudTrack2DrcField, fAudTrack3DrcSlider, fAudTrack3DrcField, fAudTrack4DrcSlider,fAudTrack4DrcField,
         fQueueStatus,fPresetsAdd,fPresetsDelete,fSrcAngleLabel,fSrcAnglePopUp,
                fCreateChapterMarkers,fVidTurboPassCheck,fDstMp4LargeFileCheck,fSubForcedCheck,fPresetsOutlineView,
-        fAudDrcLabel,fDstMp4HttpOptFileCheck,fDstMp4iPodFileCheck,fVidQualityRFField,fVidQualityRFLabel,
-        fEncodeStartStopPopUp,fSrcTimeStartEncodingField,fSrcTimeEndEncodingField,fSrcFrameStartEncodingField,fSrcFrameEndEncodingField};
+        fDstMp4HttpOptFileCheck,fDstMp4iPodFileCheck,fVidQualityRFField,fVidQualityRFLabel,
+        fEncodeStartStopPopUp,fSrcTimeStartEncodingField,fSrcTimeEndEncodingField,fSrcFrameStartEncodingField,
+        fSrcFrameEndEncodingField, fLoadChaptersButton, fSaveChaptersButton, fFrameratePfrCheck};
     
     for( unsigned i = 0;
         i < sizeof( controls ) / sizeof( NSControl * ); i++ )
@@ -538,19 +611,20 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
         
     }
     
-       if (b) {
+       if (b) 
+    {
         
-        /* if we're enabling the interface, check if the audio mixdown controls need to be enabled or not */
-        /* these will have been enabled by the mass control enablement above anyway, so we're sense-checking it here */
-        [self setEnabledStateOfAudioMixdownControls:nil];
         /* we also call calculatePictureSizing here to sense check if we already have vfr selected */
         [self calculatePictureSizing:nil];
-        
-       } else {
+        /* Also enable the preview window hud controls */
+        [fPictureController enablePreviewHudControls];
+    }
+    else 
+    {
         
                [fPresetsOutlineView setEnabled: NO];
-        
-       }
+        [fPictureController disablePreviewHudControls];
+    }
     
     [self videoMatrixChanged:nil];
     [fAdvancedOptions enableUI:b];
@@ -761,10 +835,10 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
                        break;
         }
 #undef p
-
+            
             
 #define p s.param.working
-        
+            
         case HB_STATE_SEARCHING:
                {
             NSMutableString * string;
@@ -811,7 +885,7 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
             break;  
         }
             
-
+            
         case HB_STATE_WORKING:
         {
             NSMutableString * string;
@@ -833,7 +907,7 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
                 pass_desc = @"";
             }
             
-                       string = [NSMutableString stringWithFormat: NSLocalizedString( @"Encoding: pass %d %@ of %d, %.2f %%", @"" ), p.job_cur, pass_desc, p.job_count, 100.0 * p.progress];
+                       string = [NSMutableString stringWithFormat: NSLocalizedString( @"Encoding: %@ \nPass %d %@ of %d, %.2f %%", @"" ), currentQueueEncodeNameString, p.job_cur, pass_desc, p.job_count, 100.0 * p.progress];
             
                        if( p.seconds > -1 )
             {
@@ -841,10 +915,9 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
                  NSLocalizedString( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)", @"" ),
                  p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds];
             }
-            
             [fStatusField setStringValue: string];
-            /* Set the status string in fQueueController as well */
-            [fQueueController setQueueStatusString: string];
+            [fQueueController setQueueStatusString:string];
+            
             /* Update slider */
             CGFloat progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
             [fRipIndicator setIndeterminate: NO];
@@ -865,14 +938,14 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
                 fRipIndicatorShown = YES;
                 
             }
-
+            
             /* Update dock icon */
             if( dockIconProgress < 100.0 * progress_total )
             {
                 [self UpdateDockIcon: progress_total];
                 dockIconProgress += 5;
             }
-
+            
             break;
         }
 #undef p
@@ -943,62 +1016,39 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
                 pathOfFinishedEncode = [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"DestinationPath"];
                 
                 /* Both the Growl Alert and Sending to MetaX can be done as encodes roll off the queue */
-                /* Growl alert */
-                [self showGrowlDoneNotification:pathOfFinishedEncode];
-                /* Send to MetaX */
-                [self sendToMetaX:pathOfFinishedEncode];
-                
-                /* since we have successfully completed an encode, we increment the queue counter */
-                [self incrementQueueItemDone:nil]; 
-                
-                /* all end of queue actions below need to be done after all queue encodes have finished 
-                 * and there are no pending jobs left to process
-                 */
-                if (fPendingCount == 0)
+                if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Growl Notification"] || 
+                    [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Alert Window And Growl"])
                 {
-                    /* If Alert Window or Window and Growl has been selected */
-                    if( [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Alert Window"] ||
-                       [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Alert Window And Growl"] )
+                    /* If Play System Alert has been selected in Preferences */
+                    if( [[NSUserDefaults standardUserDefaults] boolForKey:@"AlertWhenDoneSound"] == YES )
                     {
-                        /*On Screen Notification*/
-                        int status;
                         NSBeep();
-                        status = NSRunAlertPanel(@"Put down that cocktail...",@"Your HandBrake queue is done!", @"OK", nil, nil);
-                        [NSApp requestUserAttention:NSCriticalRequest];
-                    }
-                    
-                    /* If sleep has been selected */
-                    if( [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Put Computer To Sleep"] )
-                    {
-                        /* Sleep */
-                        NSDictionary* errorDict;
-                        NSAppleEventDescriptor* returnDescriptor = nil;
-                        NSAppleScript* scriptObject = [[NSAppleScript alloc] initWithSource:
-                                                       @"tell application \"Finder\" to sleep"];
-                        returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
-                        [scriptObject release];
-                    }
-                    /* If Shutdown has been selected */
-                    if( [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Shut Down Computer"] )
-                    {
-                        /* Shut Down */
-                        NSDictionary* errorDict;
-                        NSAppleEventDescriptor* returnDescriptor = nil;
-                        NSAppleScript* scriptObject = [[NSAppleScript alloc] initWithSource:
-                                                       @"tell application \"Finder\" to shut down"];
-                        returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
-                        [scriptObject release];
                     }
-                    
+                    [self showGrowlDoneNotification:pathOfFinishedEncode];
                 }
                 
+                /* Send to MetaX */
+                [self sendToMetaX:pathOfFinishedEncode];
                 
+                /* since we have successfully completed an encode, we increment the queue counter */
+                [self incrementQueueItemDone:currentQueueEncodeIndex]; 
+
             }
             
             break;
         }
     }
     
+    /* Since we can use multiple instance off of the same queue file it is imperative that we keep the QueueFileArray updated off of the QueueFile.plist
+     * so we go ahead and do it in this existing timer as opposed to using a new one */
+    
+    NSMutableArray * tempQueueArray = [[NSMutableArray alloc] initWithContentsOfFile:QueueFile];
+    [QueueFileArray setArray:tempQueueArray];
+    [tempQueueArray release]; 
+    /* Send Fresh QueueFileArray to fQueueController to update queue window */
+    [fQueueController setQueueArray: QueueFileArray];
+    [self getQueueStats];
+    
 }
 
 /* We use this to write messages to stderr from the macgui which show up in the activity window and log*/
@@ -1354,23 +1404,19 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
 -(void)showGrowlDoneNotification:(NSString *) filePath
 {
     /* This end of encode action is called as each encode rolls off of the queue */
+    /* Setup the Growl stuff ... */
     NSString * finishedEncode = filePath;
     /* strip off the path to just show the file name */
     finishedEncode = [finishedEncode lastPathComponent];
-    if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Growl Notification"] || 
-        [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Alert Window And Growl"])
-    {
-        NSString * growlMssg = [NSString stringWithFormat: @"your HandBrake encode %@ is done!",finishedEncode];
-        [GrowlApplicationBridge 
-         notifyWithTitle:@"Put down that cocktail..." 
-         description:growlMssg 
-         notificationName:SERVICE_NAME
-         iconData:nil 
-         priority:0 
-         isSticky:1 
-         clickContext:nil];
-    }
-    
+    NSString * growlMssg = [NSString stringWithFormat: @"your HandBrake encode %@ is done!",finishedEncode];
+    [GrowlApplicationBridge 
+     notifyWithTitle:@"Put down that cocktail..." 
+     description:growlMssg 
+     notificationName:SERVICE_NAME
+     iconData:nil 
+     priority:0 
+     isSticky:1 
+     clickContext:nil];
 }
 -(void)sendToMetaX:(NSString *) filePath
 {
@@ -1388,6 +1434,49 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
         
     }
 }
+
+- (void) queueCompletedAlerts
+{
+    /* If Play System Alert has been selected in Preferences */
+    if( [[NSUserDefaults standardUserDefaults] boolForKey:@"AlertWhenDoneSound"] == YES )
+    {
+        NSBeep();
+    }
+    
+    /* If Alert Window or Window and Growl has been selected */
+    if( [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Alert Window"] ||
+       [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Alert Window And Growl"] )
+    {
+        /*On Screen Notification*/
+        int status;
+        status = NSRunAlertPanel(@"Put down that cocktail...",@"Your HandBrake queue is done!", @"OK", nil, nil);
+        [NSApp requestUserAttention:NSCriticalRequest];
+    }
+    
+    /* If sleep has been selected */
+    if( [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Put Computer To Sleep"] )
+    {
+        /* Sleep */
+        NSDictionary* errorDict;
+        NSAppleEventDescriptor* returnDescriptor = nil;
+        NSAppleScript* scriptObject = [[NSAppleScript alloc] initWithSource:
+                                       @"tell application \"Finder\" to sleep"];
+        returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
+        [scriptObject release];
+    }
+    /* If Shutdown has been selected */
+    if( [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Shut Down Computer"] )
+    {
+        /* Shut Down */
+        NSDictionary* errorDict;
+        NSAppleEventDescriptor* returnDescriptor = nil;
+        NSAppleScript* scriptObject = [[NSAppleScript alloc] initWithSource:
+                                       @"tell application \"Finder\" to shut down"];
+        returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
+        [scriptObject release];
+    }
+}
+
 #pragma mark -
 #pragma mark Get New Source
 
@@ -1615,35 +1704,32 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
     [fSubtitlesDelegate resetWithTitle:nil];
     [fSubtitlesTable reloadData];
     
+       //      Notify anyone interested (audio controller) that there's no title
+       [[NSNotificationCenter defaultCenter] postNotification:
+        [NSNotification notificationWithName: HBTitleChangedNotification
+                                                                  object: self
+                                                                userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
+                                                                                       [NSData dataWithBytesNoCopy: &fTitle length: sizeof(fTitle) freeWhenDone: NO], keyTitleTag,
+                                                                                       nil]]];
+
     [self enableUI: NO];
     
     if( [detector isVideoDVD] )
     {
-        int hb_arch;
-#if defined( __LP64__ )
-        /* we are 64 bit */
-        hb_arch = 64;
-#else
-        /* we are 32 bit */
-        hb_arch = 32;
-#endif 
-        
-        
         // The chosen path was actually on a DVD, so use the raw block
         // device path instead.
         path = [detector devicePath];
         [self writeToActivityLog: "trying to open a physical dvd at: %s", [scanPath UTF8String]];
         
         /* lets check for vlc here to make sure we have a dylib available to use for decrypting */
-        NSString *vlcPath = @"/Applications/VLC.app/Contents/MacOS/lib/libdvdcss.2.dylib";
-        NSFileManager * fileManager = [NSFileManager defaultManager];
-           if ([fileManager fileExistsAtPath:vlcPath] == 0) 
-           {
-            /*vlc not found in /Applications so we set the bool to cancel scanning to 1 */
+        void *dvdcss = dlopen("libdvdcss.2.dylib", RTLD_LAZY);
+        if (dvdcss == NULL) 
+        {
+            /*compatible vlc not found, so we set the bool to cancel scanning to 1 */
             cancelScanDecrypt = 1;
             [self writeToActivityLog: "VLC app not found for decrypting physical dvd"];
             int status;
-            status = NSRunAlertPanel(@"HandBrake could not find VLC or your VLC is out of date.",@"Please download and install VLC media player in your /Applications folder if you wish to read encrypted DVDs.", @"Get VLC", @"Cancel Scan", @"Attempt Scan Anyway");
+            status = NSRunAlertPanel(@"HandBrake could not find VLC or your VLC is incompatible (Note: 32 bit vlc is not compatible with 64 bit HandBrake and vice-versa).",@"Please download and install VLC media player if you wish to read encrypted DVDs.", @"Get VLC", @"Cancel Scan", @"Attempt Scan Anyway");
             [NSApp requestUserAttention:NSCriticalRequest];
             
             if (status == NSAlertDefaultReturn)
@@ -1669,111 +1755,8 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
             /* VLC was found in /Applications so all is well, we can carry on using vlc's libdvdcss.dylib for decrypting if needed */
             [self writeToActivityLog: "VLC app found for decrypting physical dvd"];
             vlcFound = 1;
+            dlclose(dvdcss);
         }
-        /* test for architecture of the vlc app */
-        NSArray *vlc_architecturesArray = [[NSBundle bundleWithPath:@"/Applications/VLC.app"] executableArchitectures];
-        BOOL vlcIntel32bit = NO;
-        BOOL vlcIntel64bit = NO;
-        BOOL vlcPPC32bit = NO;
-        BOOL vlcPPC64bit = NO;
-        /* check the available architectures for vlc and note accordingly */
-        NSEnumerator *enumerator = [vlc_architecturesArray objectEnumerator];
-        id tempObject;
-        while (tempObject = [enumerator nextObject])
-        {
-            
-            if ([tempObject intValue] == NSBundleExecutableArchitectureI386)
-            {
-                vlcIntel32bit = YES;   
-            }
-            if ([tempObject intValue] == NSBundleExecutableArchitectureX86_64)
-            {
-                vlcIntel64bit = YES;   
-            }
-            if ([tempObject intValue] == NSBundleExecutableArchitecturePPC)
-            {
-                vlcPPC32bit = YES;   
-            }
-            if ([tempObject intValue] == NSBundleExecutableArchitecturePPC64)
-            {
-                vlcPPC64bit = YES;   
-            }
-            
-        }
-        /* Write vlc architecture findings to activity window */
-        if (vlcIntel32bit)
-        {
-            [self writeToActivityLog: " 32-Bit VLC app found for decrypting physical dvd"];
-        }
-        if (vlcIntel64bit)
-        {
-            [self writeToActivityLog: " 64-Bit VLC app found for decrypting physical dvd"];
-        }
-        
-        
-        
-        if (vlcFound && hb_arch == 64 && !vlcIntel64bit && cancelScanDecrypt != 1)
-        {
-            
-            /* we are 64 bit */
-            
-            /* Appropriate VLC not found, so cancel */
-            cancelScanDecrypt = 1;
-            [self writeToActivityLog: "This version of HandBrake is 64 bit, 64 bit version of vlc not found, scan cancelled"];
-            /*On Screen Notification*/
-            int status;
-            NSBeep();
-            status = NSRunAlertPanel(@"This version of HandBrake is 64 bit, VLC found but not 64 bit!",@"", @"Cancel Scan", @"Attempt Scan Anyway", @"Get 64 bit VLC", nil);
-            [NSApp requestUserAttention:NSCriticalRequest];
-            
-            if (status == NSAlertDefaultReturn)
-            {
-                /* User chose to cancel the scan */
-                [self writeToActivityLog: "cannot open physical dvd VLC found but not 64 bit, scan cancelled"];
-                cancelScanDecrypt = 1;
-            }
-            else if (status == NSAlertAlternateReturn)
-            {
-                [self writeToActivityLog: "user overrode 64-bit warning trying to open physical dvd without proper decryption"];
-                cancelScanDecrypt = 0;
-            }
-            else
-            {
-                /* User chose to go download vlc (as they rightfully should) so we send them to the vlc site */
-                [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.videolan.org/vlc/download-macosx.html"]];
-            }
-            
-        }    
-        else if (vlcFound && hb_arch == 32 && !vlcIntel32bit && cancelScanDecrypt != 1)
-        {
-            /* we are 32 bit */
-            /* Appropriate VLC not found, so cancel */
-            cancelScanDecrypt = 1;
-            [self writeToActivityLog: "This version of HandBrake is 32 bit, 32 bit version of vlc not found, scan cancelled"];
-            /*On Screen Notification*/
-            int status;
-            NSBeep();
-            status = NSRunAlertPanel(@"This version of HandBrake is 32 bit, VLC found but not 32 bit!",@"", @"Cancel Scan", @"Attempt Scan Anyway", @"Get 32 bit VLC", nil);
-            [NSApp requestUserAttention:NSCriticalRequest];
-            
-            if (status == NSAlertDefaultReturn)
-            {
-                /* User chose to cancel the scan */
-                [self writeToActivityLog: "cannot open physical dvd VLC found but not 32 bit, scan cancelled"];
-                cancelScanDecrypt = 1;
-            }
-            else if (status == NSAlertAlternateReturn)
-            {
-                [self writeToActivityLog: "user overrode 32-bit warning trying to open physical dvd without proper decryption"];
-                cancelScanDecrypt = 0;
-            }
-            else
-            {
-                /* User chose to go download vlc (as they rightfully should) so we send them to the vlc site */
-                [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://www.videolan.org/vlc/download-macosx.html"]];
-            }
-            
-        } 
     }
     
     if (cancelScanDecrypt == 0)
@@ -1790,11 +1773,14 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
         {
             [self writeToActivityLog: "scanning specifically for title: %d", scanTitleNum];
         }
-        /* We use our advance pref to determine how many previews to scan */
+        /* We use our advanced pref to determine how many previews to scan */
         int hb_num_previews = [[[NSUserDefaults standardUserDefaults] objectForKey:@"PreviewsNumber"] intValue];
+        /* We use our advanced pref to determine the minimum title length to use in seconds*/
+        uint64_t min_title_duration_seconds = 90000L * [[[NSUserDefaults standardUserDefaults] objectForKey:@"MinTitleScanSeconds"] intValue];
         /* set title to NULL */
         fTitle = NULL;
-        hb_scan( fHandle, [path UTF8String], scanTitleNum, hb_num_previews, 1 );
+        [self writeToActivityLog: "Minimum length of title for scan: %d", min_title_duration_seconds];
+        hb_scan( fHandle, [path UTF8String], scanTitleNum, hb_num_previews, 1 , min_title_duration_seconds );
         [fSrcDVD2Field setStringValue:@"Scanning new source ..."];
     }
 }
@@ -1807,10 +1793,8 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
 - (IBAction) showNewScan:(id)sender
 {
     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)
-    
+       hb_title_t * title = NULL;
+       int feature_title=0; // Used to store the main feature title
 
         list = hb_get_titles( fHandle );
         
@@ -1827,6 +1811,14 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
             // Notify Subtitles that there's no title
             [fChapterTitlesDelegate resetWithTitle:nil];
             [fChapterTable reloadData];
+
+                       //      Notify anyone interested (audio controller) that there's no title
+                       [[NSNotificationCenter defaultCenter] postNotification:
+                        [NSNotification notificationWithName: HBTitleChangedNotification
+                                                                                  object: self
+                                                                                userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
+                                                                                                       [NSData dataWithBytesNoCopy: &fTitle length: sizeof(fTitle) freeWhenDone: NO], keyTitleTag,
+                                                                                                       nil]]];
         }
         else
         {
@@ -1884,11 +1876,10 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
                                                      @"%@/Desktop/%@.mp4", NSHomeDirectory(),[browsedSourceDisplayName stringByDeletingPathExtension]]];
                 }
                 
-                
-                if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds)
+                /* See if this is the main feature according to libhb */
+                if (title->index == title->job->feature)
                 {
-                    longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds;
-                    indxpri=i;
+                    feature_title = i;
                 }
                 
                 [fSrcTitlePopUp addItemWithTitle: [NSString
@@ -1904,8 +1895,8 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
             }
             else
             {
-                /* if not then select the longest title (dvd) */
-                [fSrcTitlePopUp selectItemAtIndex: indxpri];
+                /* if not then select the main feature title */
+                [fSrcTitlePopUp selectItemAtIndex: feature_title];
             }
             [self titlePopUpChanged:nil];
             
@@ -1985,12 +1976,9 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
 - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
 {
     if( !flag ) {
-        [fWindow  makeKeyAndOrderFront:nil];
-                
-        return YES;
+        [fWindow makeKeyAndOrderFront:nil];
     }
-    
-    return NO;
+    return YES;
 }
 
 - (NSSize) drawerWillResizeContents:(NSDrawer *) drawer toSize:(NSSize) contentSize {
@@ -2007,53 +1995,38 @@ static NSString *        ChooseSourceIdentifier             = @"Choose Source It
        /*We define the location of the user presets file */
     QueueFile = @"~/Library/Application Support/HandBrake/Queue.plist";
        QueueFile = [[QueueFile stringByExpandingTildeInPath]retain];
-    /* We check for the presets.plist */
+    /* We check for the Queue.plist */
        if ([fileManager fileExistsAtPath:QueueFile] == 0)
        {
                [fileManager createFileAtPath:QueueFile contents:nil attributes:nil];
        }
-
+    
        QueueFileArray = [[NSMutableArray alloc] initWithContentsOfFile:QueueFile];
        /* lets check to see if there is anything in the queue file .plist */
     if (nil == QueueFileArray)
        {
         /* if not, then lets initialize an empty array */
                QueueFileArray = [[NSMutableArray alloc] init];
-        
-     /* Initialize our curQueueEncodeIndex to 0
-     * so we can use it to track which queue
-     * item is to be used to track our encodes */
-     /* NOTE: this should be changed if and when we
-      * are able to get the last unfinished encode
-      * in the case of a crash or shutdown */
-    
-       }
+    }
     else
     {
-    [self clearQueueEncodedItems];
+        /* ONLY clear out encoded items if we are single instance */
+        if (hbInstanceNum == 1)
+        {
+            [self clearQueueEncodedItems];
+        }
     }
-    currentQueueEncodeIndex = 0;
 }
 
 - (void)addQueueFileItem
 {
-        [QueueFileArray addObject:[self createQueueFileItem]];
-        [self saveQueueFileItem];
-
+    [QueueFileArray addObject:[self createQueueFileItem]];
+    [self saveQueueFileItem];
+    
 }
 
 - (void) removeQueueFileItem:(int) queueItemToRemove
 {
-   
-   /* Find out if the item we are removing is a cancelled (3) or a finished (0) item*/
-   if ([[[QueueFileArray objectAtIndex:queueItemToRemove] objectForKey:@"Status"] intValue] == 3 || [[[QueueFileArray objectAtIndex:queueItemToRemove] objectForKey:@"Status"] intValue] == 0)
-    {
-    /* Since we are removing a cancelled or finished item, WE need to decrement the currentQueueEncodeIndex
-     * by one to keep in sync with the queue array
-     */
-    currentQueueEncodeIndex--;
-    [self writeToActivityLog: "removeQueueFileItem: Removing a cancelled/finished encode, decrement currentQueueEncodeIndex to %d", currentQueueEncodeIndex];
-    }
     [QueueFileArray removeObjectAtIndex:queueItemToRemove];
     [self saveQueueFileItem];
 
@@ -2097,7 +2070,13 @@ fWorkingCount = 0;
                if ([[thisQueueDict objectForKey:@"Status"] intValue] == 1) // being encoded
                {
                        fWorkingCount++;
-            fEncodingQueueItem = i;    
+            fEncodingQueueItem = i;
+            /* check to see if we are the instance doing this encoding */
+            if ([thisQueueDict objectForKey:@"EncodingPID"] && [[thisQueueDict objectForKey:@"EncodingPID"] intValue] == pidNum)
+            {
+                currentQueueEncodeIndex = i;
+            }
+               
                }
         if ([[thisQueueDict objectForKey:@"Status"] intValue] == 2) // pending         
         {
@@ -2114,15 +2093,39 @@ fWorkingCount = 0;
     NSMutableString * string;
     if (fPendingCount == 1)
     {
-        string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode pending in the queue", @"" ), fPendingCount];
+        string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode pending", @"" ), fPendingCount];
     }
     else
     {
-        string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode(s) pending in the queue", @"" ), fPendingCount];
+        string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode(s) pending", @"" ), fPendingCount];
     }
     [fQueueStatus setStringValue:string];
 }
 
+/* Used to get the next pending queue item index and return it if found */
+- (int)getNextPendingQueueIndex
+{
+    /* initialize nextPendingIndex to -1, this value tells incrementQueueItemDone that there are no pending items in the queue */
+    int nextPendingIndex = -1;
+       BOOL nextPendingFound = NO;
+    NSEnumerator *enumerator = [QueueFileArray objectEnumerator];
+       id tempObject;
+    int i = 0;
+       while (tempObject = [enumerator nextObject])
+       {
+               NSDictionary *thisQueueDict = tempObject;
+        if ([[thisQueueDict objectForKey:@"Status"] intValue] == 2 && nextPendingFound == NO) // pending               
+        {
+                       nextPendingFound = YES;
+            nextPendingIndex = [QueueFileArray indexOfObject: tempObject];
+            [self writeToActivityLog: "getNextPendingQueueIndex next pending encod index is:%d", nextPendingIndex];
+               }
+        i++;
+       }
+    return nextPendingIndex;
+}
+
+
 /* This method will set any item marked as encoding back to pending
  * currently used right after a queue reload
  */
@@ -2135,15 +2138,19 @@ fWorkingCount = 0;
     /* we look here to see if the preset is we move on to the next one */
     while ( tempObject = [enumerator nextObject] )  
     {
-        /* If the queue item is marked as "encoding" (1)
-         * then change its status back to pending (2) which effectively
-         * puts it back into the queue to be encoded
-         */
-        if ([[tempObject objectForKey:@"Status"] intValue] == 1)
+        /* We want to keep any queue item that is pending or was previously being encoded */
+        if ([[tempObject objectForKey:@"Status"] intValue] == 1 || [[tempObject objectForKey:@"Status"] intValue] == 2)
         {
-            [tempObject setObject:[NSNumber numberWithInt: 2] forKey:@"Status"];
+            /* If the queue item is marked as "encoding" (1)
+             * then change its status back to pending (2) which effectively
+             * puts it back into the queue to be encoded
+             */
+            if ([[tempObject objectForKey:@"Status"] intValue] == 1)
+            {
+                [tempObject setObject:[NSNumber numberWithInt: 2] forKey:@"Status"];
+            }
+            [tempArray addObject:tempObject];
         }
-        [tempArray addObject:tempObject];
     }
     
     [QueueFileArray setArray:tempArray];
@@ -2249,7 +2256,7 @@ fWorkingCount = 0;
     
     
     /* The number of seek points equals the number of seconds announced in the title as that is our current granularity */
-        int title_duration_seconds = (title->hours * 3600) + (title->minutes * 60) + (title->seconds);
+    int title_duration_seconds = (title->hours * 3600) + (title->minutes * 60) + (title->seconds);
     [queueFileJob setObject:[NSNumber numberWithInt:title_duration_seconds] forKey:@"SourceTotalSeconds"];
     
     [queueFileJob setObject:[fDstFile2Field stringValue] forKey:@"DestinationPath"];
@@ -2307,6 +2314,7 @@ fWorkingCount = 0;
        [queueFileJob setObject:[NSNumber numberWithFloat:[fVidQualityRFField floatValue]] forKey:@"VideoQualitySlider"];
     /* Framerate */
     [queueFileJob setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
+    [queueFileJob setObject:[NSNumber numberWithInt:[fFrameratePfrCheck state]] forKey:@"VideoFrameratePFR"];
     
        /* 2 Pass Encoding */
        [queueFileJob setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
@@ -2365,46 +2373,7 @@ fWorkingCount = 0;
     [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController grayscale]] forKey:@"VideoGrayScale"];
     
     /*Audio*/
-    if ([fAudLang1PopUp indexOfSelectedItem] > 0)
-    {
-        [queueFileJob setObject:[NSNumber numberWithInt:[fAudLang1PopUp indexOfSelectedItem]] forKey:@"Audio1Track"];
-        [queueFileJob setObject:[fAudLang1PopUp titleOfSelectedItem] forKey:@"Audio1TrackDescription"];
-        [queueFileJob setObject:[fAudTrack1CodecPopUp titleOfSelectedItem] forKey:@"Audio1Encoder"];
-        [queueFileJob setObject:[fAudTrack1MixPopUp titleOfSelectedItem] forKey:@"Audio1Mixdown"];
-        [queueFileJob setObject:[fAudTrack1RatePopUp titleOfSelectedItem] forKey:@"Audio1Samplerate"];
-        [queueFileJob setObject:[fAudTrack1BitratePopUp titleOfSelectedItem] forKey:@"Audio1Bitrate"];
-        [queueFileJob setObject:[NSNumber numberWithFloat:[fAudTrack1DrcSlider floatValue]] forKey:@"Audio1TrackDRCSlider"];
-    }
-    if ([fAudLang2PopUp indexOfSelectedItem] > 0)
-    {
-        [queueFileJob setObject:[NSNumber numberWithInt:[fAudLang2PopUp indexOfSelectedItem]] forKey:@"Audio2Track"];
-        [queueFileJob setObject:[fAudLang2PopUp titleOfSelectedItem] forKey:@"Audio2TrackDescription"];
-        [queueFileJob setObject:[fAudTrack2CodecPopUp titleOfSelectedItem] forKey:@"Audio2Encoder"];
-        [queueFileJob setObject:[fAudTrack2MixPopUp titleOfSelectedItem] forKey:@"Audio2Mixdown"];
-        [queueFileJob setObject:[fAudTrack2RatePopUp titleOfSelectedItem] forKey:@"Audio2Samplerate"];
-        [queueFileJob setObject:[fAudTrack2BitratePopUp titleOfSelectedItem] forKey:@"Audio2Bitrate"];
-        [queueFileJob setObject:[NSNumber numberWithFloat:[fAudTrack2DrcSlider floatValue]] forKey:@"Audio2TrackDRCSlider"];
-    }
-    if ([fAudLang3PopUp indexOfSelectedItem] > 0)
-    {
-        [queueFileJob setObject:[NSNumber numberWithInt:[fAudLang3PopUp indexOfSelectedItem]] forKey:@"Audio3Track"];
-        [queueFileJob setObject:[fAudLang3PopUp titleOfSelectedItem] forKey:@"Audio3TrackDescription"];
-        [queueFileJob setObject:[fAudTrack3CodecPopUp titleOfSelectedItem] forKey:@"Audio3Encoder"];
-        [queueFileJob setObject:[fAudTrack3MixPopUp titleOfSelectedItem] forKey:@"Audio3Mixdown"];
-        [queueFileJob setObject:[fAudTrack3RatePopUp titleOfSelectedItem] forKey:@"Audio3Samplerate"];
-        [queueFileJob setObject:[fAudTrack3BitratePopUp titleOfSelectedItem] forKey:@"Audio3Bitrate"];
-        [queueFileJob setObject:[NSNumber numberWithFloat:[fAudTrack3DrcSlider floatValue]] forKey:@"Audio3TrackDRCSlider"];
-    }
-    if ([fAudLang4PopUp indexOfSelectedItem] > 0)
-    {
-        [queueFileJob setObject:[NSNumber numberWithInt:[fAudLang4PopUp indexOfSelectedItem]] forKey:@"Audio4Track"];
-        [queueFileJob setObject:[fAudLang4PopUp titleOfSelectedItem] forKey:@"Audio4TrackDescription"];
-        [queueFileJob setObject:[fAudTrack4CodecPopUp titleOfSelectedItem] forKey:@"Audio4Encoder"];
-        [queueFileJob setObject:[fAudTrack4MixPopUp titleOfSelectedItem] forKey:@"Audio4Mixdown"];
-        [queueFileJob setObject:[fAudTrack4RatePopUp titleOfSelectedItem] forKey:@"Audio4Samplerate"];
-        [queueFileJob setObject:[fAudTrack4BitratePopUp titleOfSelectedItem] forKey:@"Audio4Bitrate"];
-        [queueFileJob setObject:[NSNumber numberWithFloat:[fAudTrack4DrcSlider floatValue]] forKey:@"Audio4TrackDRCSlider"];
-    }
+       [fAudioDelegate prepareAudioForQueueFileJob: queueFileJob];     
     
        /* Subtitles*/
     NSMutableArray *subtitlesArray = [[NSMutableArray alloc] initWithArray:[fSubtitlesDelegate getSubtitleArray] copyItems:YES];
@@ -2445,41 +2414,7 @@ fWorkingCount = 0;
        [queueFileJob setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
     
     
-    /*Audio*/
-    if ([fAudLang1PopUp indexOfSelectedItem] > 0)
-    {
-        //[queueFileJob setObject:[fAudTrack1CodecPopUp indexOfSelectedItem] forKey:@"JobAudio1Encoder"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack1CodecPopUp selectedItem] tag]] forKey:@"JobAudio1Encoder"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack1MixPopUp selectedItem] tag]] forKey:@"JobAudio1Mixdown"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack1RatePopUp selectedItem] tag]] forKey:@"JobAudio1Samplerate"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack1BitratePopUp selectedItem] tag]] forKey:@"JobAudio1Bitrate"];
-     }
-    if ([fAudLang2PopUp indexOfSelectedItem] > 0)
-    {
-        //[queueFileJob setObject:[fAudTrack1CodecPopUp indexOfSelectedItem] forKey:@"JobAudio2Encoder"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack2CodecPopUp selectedItem] tag]] forKey:@"JobAudio2Encoder"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack2MixPopUp selectedItem] tag]] forKey:@"JobAudio2Mixdown"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack2RatePopUp selectedItem] tag]] forKey:@"JobAudio2Samplerate"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack2BitratePopUp selectedItem] tag]] forKey:@"JobAudio2Bitrate"];
-    }
-    if ([fAudLang3PopUp indexOfSelectedItem] > 0)
-    {
-        //[queueFileJob setObject:[fAudTrack1CodecPopUp indexOfSelectedItem] forKey:@"JobAudio3Encoder"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack3CodecPopUp selectedItem] tag]] forKey:@"JobAudio3Encoder"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack3MixPopUp selectedItem] tag]] forKey:@"JobAudio3Mixdown"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack3RatePopUp selectedItem] tag]] forKey:@"JobAudio3Samplerate"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack3BitratePopUp selectedItem] tag]] forKey:@"JobAudio3Bitrate"];
-    }
-    if ([fAudLang4PopUp indexOfSelectedItem] > 0)
-    {
-        //[queueFileJob setObject:[fAudTrack1CodecPopUp indexOfSelectedItem] forKey:@"JobAudio4Encoder"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack4CodecPopUp selectedItem] tag]] forKey:@"JobAudio4Encoder"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack4MixPopUp selectedItem] tag]] forKey:@"JobAudio4Mixdown"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack4RatePopUp selectedItem] tag]] forKey:@"JobAudio4Samplerate"];
-        [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack4BitratePopUp selectedItem] tag]] forKey:@"JobAudio4Bitrate"];
-    }
 
     /* we need to auto relase the queueFileJob and return it */
     [queueFileJob autorelease];
     return queueFileJob;
@@ -2525,46 +2460,58 @@ fWorkingCount = 0;
 
 - (void) incrementQueueItemDone:(int) queueItemDoneIndexNum
 {
-    int i = currentQueueEncodeIndex;
-    [[QueueFileArray objectAtIndex:i] setObject:[NSNumber numberWithInt:0] forKey:@"Status"];
+    /* Mark the encode just finished as done (status 0)*/
+    [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:0] forKey:@"Status"];
        
     /* We save all of the Queue data here */
     [self saveQueueFileItem];
-       /* We Reload the New Table data for presets */
-    //[fPresetsOutlineView reloadData];
 
     /* Since we have now marked a queue item as done
      * we can go ahead and increment currentQueueEncodeIndex 
      * so that if there is anything left in the queue we can
      * go ahead and move to the next item if we want to */
-    currentQueueEncodeIndex++ ;
-    [self writeToActivityLog: "incrementQueueItemDone currentQueueEncodeIndex is incremented to: %d", currentQueueEncodeIndex];
     int queueItems = [QueueFileArray count];
-    /* If we still have more items in our queue, lets go to the next one */
-    if (currentQueueEncodeIndex < queueItems)
-    {
-    [self writeToActivityLog: "incrementQueueItemDone currentQueueEncodeIndex is incremented to: %d", currentQueueEncodeIndex];
-    [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]];
+    /* Check to see if there are any more pending items in the queue */
+    int newQueueItemIndex = [self getNextPendingQueueIndex];
+    /* If we still have more pending items in our queue, lets go to the next one */
+    if (newQueueItemIndex >= 0 && newQueueItemIndex < queueItems)
+    {
+        /*Set our currentQueueEncodeIndex now to the newly found Pending encode as we own it */
+        currentQueueEncodeIndex = newQueueItemIndex;
+        /* now we mark the queue item as Status = 1 ( being encoded ) so another instance can not come along and try to scan it while we are scanning */
+        [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:1] forKey:@"Status"];
+        [self writeToActivityLog: "incrementQueueItemDone new pending items found: %d", currentQueueEncodeIndex];
+        [self saveQueueFileItem];
+        /* now we can go ahead and scan the new pending queue item */
+        [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]];
+
     }
     else
     {
-        [self writeToActivityLog: "incrementQueueItemDone the %d item queue is complete", currentQueueEncodeIndex - 1];
+        [self writeToActivityLog: "incrementQueueItemDone there are no more pending encodes"];
+        /*Since there are no more items to encode, go to queueCompletedAlerts for user specified alerts after queue completed*/
+        [self queueCompletedAlerts];
     }
 }
 
 /* Here we actually tell hb_scan to perform the source scan, using the path to source and title number*/
 - (void) performNewQueueScan:(NSString *) scanPath scanTitleNum: (int) scanTitleNum
 {
-   /* Tell HB to output a new activity log file for this encode */
+    /* Tell HB to output a new activity log file for this encode */
     [outputPanel startEncodeLog:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"DestinationPath"]];
     
+    /* We now flag the queue item as being owned by this instance of HB using the PID */
+    [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:pidNum] forKey:@"EncodingPID"];
+    /* Get the currentQueueEncodeNameString from the queue item to display in the status field */
+    currentQueueEncodeNameString = [[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"DestinationPath"] lastPathComponent]retain];
+    /* We save all of the Queue data here */
+    [self saveQueueFileItem];
     
-     /* use a bool to determine whether or not we can decrypt using vlc */
+    /* use a bool to determine whether or not we can decrypt using vlc */
     BOOL cancelScanDecrypt = 0;
     /* set the bool so that showNewScan knows to apply the appropriate queue
-    * settings as this is a queue rescan
-    */
-    //applyQueueToScan = YES;
+     * settings as this is a queue rescan
+     */
     NSString *path = scanPath;
     HBDVDDetector *detector = [HBDVDDetector detectorForPath:path];
     
@@ -2576,10 +2523,9 @@ fWorkingCount = 0;
         [self writeToActivityLog: "trying to open a physical dvd at: %s", [scanPath UTF8String]];
 
         /* lets check for vlc here to make sure we have a dylib available to use for decrypting */
-        NSString *vlcPath = @"/Applications/VLC.app";
-        NSFileManager * fileManager = [NSFileManager defaultManager];
-           if ([fileManager fileExistsAtPath:vlcPath] == 0) 
-           {
+        void *dvdcss = dlopen("libdvdcss.2.dylib", RTLD_LAZY);
+        if (dvdcss == NULL) 
+        {
             /*vlc not found in /Applications so we set the bool to cancel scanning to 1 */
             cancelScanDecrypt = 1;
             [self writeToActivityLog: "VLC app not found for decrypting physical dvd"];
@@ -2608,6 +2554,7 @@ fWorkingCount = 0;
         else
         {
             /* VLC was found in /Applications so all is well, we can carry on using vlc's libdvdcss.dylib for decrypting if needed */
+            dlclose(dvdcss);
             [self writeToActivityLog: "VLC app found for decrypting physical dvd"];
         }
     }
@@ -2627,10 +2574,9 @@ fWorkingCount = 0;
             [self writeToActivityLog: "scanning specifically for title: %d", scanTitleNum];
         }
         
-        [self writeToActivityLog: "performNewQueueScan currentQueueEncodeIndex is: %d", currentQueueEncodeIndex];
-        /* We use our advance pref to determine how many previews to scan */
+         /* We use our advance pref to determine how many previews to scan */
         int hb_num_previews = [[[NSUserDefaults standardUserDefaults] objectForKey:@"PreviewsNumber"] intValue];
-        hb_scan( fQueueEncodeLibhb, [path UTF8String], scanTitleNum, hb_num_previews, 0 );
+        hb_scan( fQueueEncodeLibhb, [path UTF8String], scanTitleNum, hb_num_previews, 0 , 0 );
     }
 }
 
@@ -2650,7 +2596,6 @@ fWorkingCount = 0;
     [self writeToActivityLog: "Preset: %s", [[queueToApply objectForKey:@"PresetName"] UTF8String]];
     [self writeToActivityLog: "processNewQueueEncode number of passes expected is: %d", ([[queueToApply objectForKey:@"VideoTwoPass"] intValue] + 1)];
     job->file = [[queueToApply objectForKey:@"DestinationPath"] UTF8String];
-    //[self writeToActivityLog: "processNewQueueEncode sending to prepareJob"];
     [self prepareJob];
     
     /*
@@ -2725,13 +2670,10 @@ fWorkingCount = 0;
         free(subtitle);
     }
     
-    
     /* We should be all setup so let 'er rip */   
     [self doRip];
 }
 
-
-
 #pragma mark -
 #pragma mark Queue Item Editing
 
@@ -2822,7 +2764,7 @@ fWorkingCount = 0;
     }
     
     [self videoMatrixChanged:nil];
-    [self writeToActivityLog: "applyQueueSettingsToMainWindow: video matrix changed"];    
+        
     /* Video framerate */
     /* For video preset video framerate, we want to make sure that Same as source does not conflict with the
      detected framerate in the fVidRatePopUp so we use index 0*/
@@ -2845,88 +2787,8 @@ fWorkingCount = 0;
     
     
     /* Now lets add our new tracks to the audio list here */
-    if ([[queueToApply objectForKey:@"Audio1Track"] intValue] > 0)
-    {
-        [fAudLang1PopUp selectItemAtIndex: [[queueToApply objectForKey:@"Audio1Track"] intValue]];
-        [self audioTrackPopUpChanged: fAudLang1PopUp];
-        [fAudTrack1CodecPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio1Encoder"]];
-        [self audioTrackPopUpChanged: fAudTrack1CodecPopUp];
-        
-        [fAudTrack1MixPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio1Mixdown"]];
-        
-        [fAudTrack1RatePopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio1Samplerate"]];
-        [fAudTrack1BitratePopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio1Bitrate"]];
-        
-        [fAudTrack1DrcSlider setFloatValue:[[queueToApply objectForKey:@"Audio1TrackDRCSlider"] floatValue]];
-        [self audioDRCSliderChanged: fAudTrack1DrcSlider];
-    }
-    else
-    {
-        [fAudLang1PopUp selectItemAtIndex: 0];
-        [self audioTrackPopUpChanged: fAudLang1PopUp];
-    }
-    if ([[queueToApply objectForKey:@"Audio2Track"] intValue] > 0)
-    {
-        [fAudLang2PopUp selectItemAtIndex: [[queueToApply objectForKey:@"Audio2Track"] intValue]];
-        [self audioTrackPopUpChanged: fAudLang2PopUp];
-        [fAudTrack2CodecPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio2Encoder"]];
-        [self audioTrackPopUpChanged: fAudTrack2CodecPopUp];
-        
-        [fAudTrack2MixPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio2Mixdown"]];
-        
-        [fAudTrack2RatePopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio2Samplerate"]];
-        [fAudTrack2BitratePopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio2Bitrate"]];
-        
-        [fAudTrack2DrcSlider setFloatValue:[[queueToApply objectForKey:@"Audio2TrackDRCSlider"] floatValue]];
-        [self audioDRCSliderChanged: fAudTrack2DrcSlider];
-    }
-    else
-    {
-        [fAudLang2PopUp selectItemAtIndex: 0];
-        [self audioTrackPopUpChanged: fAudLang2PopUp];
-    }
-    if ([[queueToApply objectForKey:@"Audio3Track"] intValue] > 0)
-    {
-        [fAudLang3PopUp selectItemAtIndex: [[queueToApply objectForKey:@"Audio3Track"] intValue]];
-        [self audioTrackPopUpChanged: fAudLang3PopUp];
-        [fAudTrack3CodecPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio3Encoder"]];
-        [self audioTrackPopUpChanged: fAudTrack3CodecPopUp];
-        
-        [fAudTrack3MixPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio3Mixdown"]];
-        
-        [fAudTrack3RatePopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio3Samplerate"]];
-        [fAudTrack3BitratePopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio3Bitrate"]];
-        
-        [fAudTrack3DrcSlider setFloatValue:[[queueToApply objectForKey:@"Audio3TrackDRCSlider"] floatValue]];
-        [self audioDRCSliderChanged: fAudTrack3DrcSlider];
-    }
-    else
-    {
-        [fAudLang3PopUp selectItemAtIndex: 0];
-        [self audioTrackPopUpChanged: fAudLang3PopUp];
-    }
-    if ([[queueToApply objectForKey:@"Audio4Track"] intValue] > 0)
-    {
-        [fAudLang4PopUp selectItemAtIndex: [[queueToApply objectForKey:@"Audio4Track"] intValue]];
-        [self audioTrackPopUpChanged: fAudLang4PopUp];
-        [fAudTrack4CodecPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio4Encoder"]];
-        [self audioTrackPopUpChanged: fAudTrack4CodecPopUp];
-        
-        [fAudTrack4MixPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio4Mixdown"]];
-        
-        [fAudTrack4RatePopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio4Samplerate"]];
-        [fAudTrack4BitratePopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio4Bitrate"]];
-        
-        [fAudTrack4DrcSlider setFloatValue:[[queueToApply objectForKey:@"Audio4TrackDRCSlider"] floatValue]];
-        [self audioDRCSliderChanged: fAudTrack4DrcSlider];
-    }
-    else
-    {
-        [fAudLang4PopUp selectItemAtIndex: 0];
-        [self audioTrackPopUpChanged: fAudLang4PopUp];
-    }
+       [fAudioDelegate addTracksFromQueue: queueToApply];
     
-    [self writeToActivityLog: "applyQueueSettingsToMainWindow: audio set up"];
     /*Subtitles*/
     /* Crashy crashy right now, working on it */
     [fSubtitlesDelegate setNewSubtitles:[queueToApply objectForKey:@"SubtitleList"]];
@@ -2986,9 +2848,6 @@ fWorkingCount = 0;
     job->anamorphic.mode = [[queueToApply objectForKey:@"PicturePAR"]  intValue];
     job->modulus = [[queueToApply objectForKey:@"PictureModulus"]  intValue];
     
-    [self writeToActivityLog: "applyQueueSettingsToMainWindow: picture sizing set up"];
-    
-    
     /* Filters */
     
     /* We only allow *either* Decomb or Deinterlace. So check for the PictureDecombDeinterlace key.
@@ -3086,10 +2945,9 @@ fWorkingCount = 0;
     [fPictureController SetTitle:fTitle];
     [self calculatePictureSizing:nil];
     
-    [self writeToActivityLog: "applyQueueSettingsToMainWindow: picture filters set up"];
     /* somehow we need to figure out a way to tie the queue item to a preset if it used one */
     //[queueFileJob setObject:[fPresetSelectedDisplay stringValue] forKey:@"PresetName"];
-    //    [queueFileJob setObject:[NSNumber numberWithInt:[fPresetsOutlineView selectedRow]] forKey:@"PresetIndexNum"];
+    //[queueFileJob setObject:[NSNumber numberWithInt:[fPresetsOutlineView selectedRow]] forKey:@"PresetIndexNum"];
     if ([queueToApply objectForKey:@"PresetIndexNum"]) // This item used a preset so insert that info
        {
                /* Deselect the currently selected Preset if there is one*/
@@ -3172,7 +3030,14 @@ fWorkingCount = 0;
         /* We are not same as source so we set job->cfr to 1 
          * to enable constant frame rate since user has specified
          * a specific framerate*/
-        job->cfr = 1;
+        if ([fFrameratePfrCheck state] == 1)
+        {
+            job->cfr = 2;
+        }
+        else
+        {
+            job->cfr = 1;
+        }
     }
     else
     {
@@ -3248,23 +3113,18 @@ bool one_burned = FALSE;
                 [self writeToActivityLog: "Foreign Language Search: %d", 1];
                 
                 job->indepth_scan = 1;
-                if (burned == 1 || job->mux != HB_MUX_MP4)
+                
+                if (burned != 1)
                 {
-                    if (burned != 1 && job->mux == HB_MUX_MKV)
-                    {
-                        job->select_subtitle_config.dest = PASSTHRUSUB;
-                    }
-                    else
-                    {
-                        job->select_subtitle_config.dest = RENDERSUB;
-                    }
-                    
-                    job->select_subtitle_config.force = force;
-                    job->select_subtitle_config.default_track = def;
-                    
+                    job->select_subtitle_config.dest = PASSTHRUSUB;
+                }
+                else
+                {
+                    job->select_subtitle_config.dest = RENDERSUB;
                 }
                 
-                
+                job->select_subtitle_config.force = force;
+                job->select_subtitle_config.default_track = def;
             }
             else
             {
@@ -3312,17 +3172,10 @@ bool one_burned = FALSE;
                 {
                     hb_subtitle_config_t sub_config = subt->config;
                     
-                    if (!burned && job->mux == HB_MUX_MKV && 
-                        subt->format == PICTURESUB)
+                    if ( !burned && subt->format == PICTURESUB )
                     {
                         sub_config.dest = PASSTHRUSUB;
                     }
-                    else if (!burned && job->mux == HB_MUX_MP4 && 
-                             subt->format == PICTURESUB)
-                    {
-                        // Skip any non-burned vobsubs when output is mp4
-                        continue;
-                    }
                     else if ( burned && subt->format == PICTURESUB )
                     {
                         // Only allow one subtitle to be burned into the video
@@ -3346,83 +3199,7 @@ bool one_burned = FALSE;
     
     
     /* Audio tracks and mixdowns */
-    /* Lets make sure there arent any erroneous audio tracks in the job list, so lets make sure its empty*/
-    int audiotrack_count = hb_list_count(job->list_audio);
-    for( int i = 0; i < audiotrack_count;i++)
-    {
-        hb_audio_t * temp_audio = (hb_audio_t*) hb_list_item( job->list_audio, 0 );
-        hb_list_rem(job->list_audio, temp_audio);
-    }
-    /* Now lets add our new tracks to the audio list here */
-    if ([fAudLang1PopUp indexOfSelectedItem] > 0)
-    {
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [fAudLang1PopUp indexOfSelectedItem] - 1;
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [fAudLang1PopUp indexOfSelectedItem] - 1;
-        audio->out.codec = [[fAudTrack1CodecPopUp selectedItem] tag];
-        audio->out.mixdown = [[fAudTrack1MixPopUp selectedItem] tag];
-        audio->out.bitrate = [[fAudTrack1BitratePopUp selectedItem] tag];
-        audio->out.samplerate = [[fAudTrack1RatePopUp selectedItem] tag];
-        audio->out.dynamic_range_compression = [fAudTrack1DrcField floatValue];
-        
-        hb_audio_add( job, audio );
-        free(audio);
-    }  
-    if ([fAudLang2PopUp indexOfSelectedItem] > 0)
-    {
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [fAudLang2PopUp indexOfSelectedItem] - 1;
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [fAudLang2PopUp indexOfSelectedItem] - 1;
-        audio->out.codec = [[fAudTrack2CodecPopUp selectedItem] tag];
-        audio->out.mixdown = [[fAudTrack2MixPopUp selectedItem] tag];
-        audio->out.bitrate = [[fAudTrack2BitratePopUp selectedItem] tag];
-        audio->out.samplerate = [[fAudTrack2RatePopUp selectedItem] tag];
-        audio->out.dynamic_range_compression = [fAudTrack2DrcField floatValue];
-        
-        hb_audio_add( job, audio );
-        free(audio);
-        
-    }
-    
-    if ([fAudLang3PopUp indexOfSelectedItem] > 0)
-    {
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [fAudLang3PopUp indexOfSelectedItem] - 1;
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [fAudLang3PopUp indexOfSelectedItem] - 1;
-        audio->out.codec = [[fAudTrack3CodecPopUp selectedItem] tag];
-        audio->out.mixdown = [[fAudTrack3MixPopUp selectedItem] tag];
-        audio->out.bitrate = [[fAudTrack3BitratePopUp selectedItem] tag];
-        audio->out.samplerate = [[fAudTrack3RatePopUp selectedItem] tag];
-        audio->out.dynamic_range_compression = [fAudTrack3DrcField floatValue];
-        
-        hb_audio_add( job, audio );
-        free(audio);
-        
-    }
-
-    if ([fAudLang4PopUp indexOfSelectedItem] > 0)
-    {
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [fAudLang4PopUp indexOfSelectedItem] - 1;
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [fAudLang4PopUp indexOfSelectedItem] - 1;
-        audio->out.codec = [[fAudTrack4CodecPopUp selectedItem] tag];
-        audio->out.mixdown = [[fAudTrack4MixPopUp selectedItem] tag];
-        audio->out.bitrate = [[fAudTrack4BitratePopUp selectedItem] tag];
-        audio->out.samplerate = [[fAudTrack4RatePopUp selectedItem] tag];
-        audio->out.dynamic_range_compression = [fAudTrack4DrcField floatValue];
-        
-        hb_audio_add( job, audio );
-        free(audio);
-        
-    }
+       [fAudioDelegate prepareAudioForJob: job];
 
     
     
@@ -3449,6 +3226,7 @@ bool one_burned = FALSE;
     */
     
        /* Detelecine */
+    hb_filter_detelecine.settings = NULL;
     if ([fPictureController detelecine] == 1)
     {
         /* use a custom detelecine string */
@@ -3467,6 +3245,7 @@ bool one_burned = FALSE;
     {
         /* Decomb */
         /* we add the custom string if present */
+        hb_filter_decomb.settings = NULL;
         if ([fPictureController decomb] == 1)
         {
             /* use a custom decomb string */
@@ -3577,51 +3356,28 @@ bool one_burned = FALSE;
         /* we are pts based start / stop */
         [self writeToActivityLog: "Start / Stop set to seconds ..."];
         
-        /* Point A to Point B. Since we cannot get frame accurate start times, attempt to glean a semi-accurate start time based on a percentage of the
-         * scanned title time as per live preview, while in some cases inaccurate its the best I can do with what I have barring a pre-scan index afaik.
-         */
-        /* Attempt to bastardize the live preview code to get a roughly 1 second accurate point a to point b encode ... */
+        /* Point A to Point B. Time to time in seconds.*/
         /* get the start seconds from the start seconds field */
         int start_seconds = [[queueToApply objectForKey:@"StartSeconds"] intValue];
-        //job->start_at_preview = start_seconds;
-        /* The number of seek points equals the number of seconds announced in the title as that is our current granularity */
-        //job->seek_points = [[queueToApply objectForKey:@"SourceTotalSeconds"] intValue];
         job->pts_to_start = start_seconds * 90000LL;
         /* Stop seconds is actually the duration of encode, so subtract the end seconds from the start seconds */
         int stop_seconds = [[queueToApply objectForKey:@"StopSeconds"] intValue];
         job->pts_to_stop = stop_seconds * 90000LL;
-
-        /* A bunch of verbose activity log messages to check on what should be expected */
-        [self writeToActivityLog: "point a to b should start at: %d seconds", start_seconds];
-        [self writeToActivityLog: "point a to b should start at (hh:mm:ss): %d:%d:%d", start_seconds / 3600, ( start_seconds / 60 ) % 60,start_seconds % 60];
-        [self writeToActivityLog: "point a to b duration: %d seconds", stop_seconds];
-        [self writeToActivityLog: "point a to b duration (hh:mm:ss): %d:%d:%d", stop_seconds / 3600, ( stop_seconds / 60 ) % 60,stop_seconds % 60];
-        [self writeToActivityLog: "point a to b should end at: %d seconds", start_seconds + stop_seconds];
-        [self writeToActivityLog: "point a to b should end at (hh:mm:ss): %d:%d:%d", (start_seconds + stop_seconds) / 3600, ( (start_seconds + stop_seconds) / 60 ) % 60,(start_seconds + stop_seconds) % 60];
+        
     }
     else if ([[queueToApply objectForKey:@"fEncodeStartStop"] intValue] == 2)
     {
         /* we are frame based start / stop */
         [self writeToActivityLog: "Start / Stop set to frames ..."];
         
-        /* Point A to Point B. Since we cannot get frame accurate start times, attempt to glean a semi-accurate start time based on a percentage of the
-         * scanned title time as per live preview, while in some cases inaccurate its the best I can do with what I have barring a pre-scan index afaik.
-         */
-        /* Attempt to bastardize the live preview code to get a roughly 1 second accurate point a to point b encode ... */
-        /* get the start seconds from the start seconds field */
+        /* Point A to Point B. Frame to frame */
+        /* get the start frame from the start frame field */
         int start_frame = [[queueToApply objectForKey:@"StartFrame"] intValue];
-        //job->start_at_preview = start_seconds;
-        /* The number of seek points equals the number of seconds announced in the title as that is our current granularity */
-        //job->seek_points = [[queueToApply objectForKey:@"SourceTotalSeconds"] intValue];
         job->frame_to_start = start_frame;
-        /* Stop seconds is actually the duration of encode, so subtract the end seconds from the start seconds */
+        /* get the frame to stop on from the end frame field */
         int stop_frame = [[queueToApply objectForKey:@"StopFrame"] intValue];
         job->frame_to_stop = stop_frame;
-
-        /* A bunch of verbose activity log messages to check on what should be expected */
-        [self writeToActivityLog: "point a to b should start at frame %d", start_frame];
-        [self writeToActivityLog: "point a to b duration: %d frames", stop_frame];
-        [self writeToActivityLog: "point a to b should end at frame %d", start_frame + stop_frame];
+        
     }
 
        
@@ -3762,7 +3518,15 @@ bool one_burned = FALSE;
         /* We are not same as source so we set job->cfr to 1 
          * to enable constant frame rate since user has specified
          * a specific framerate*/
-        job->cfr = 1;
+        
+        if ([[queueToApply objectForKey:@"VideoFrameratePFR"] intValue] == 1)
+        {
+            job->cfr = 2;
+        }
+        else
+        {
+            job->cfr = 1;
+        }
     }
     else
     {
@@ -3844,22 +3608,18 @@ bool one_burned = FALSE;
                 [self writeToActivityLog: "Foreign Language Search: %d", 1];
                 
                 job->indepth_scan = 1;
-                if (burned == 1 || job->mux != HB_MUX_MP4)
+                
+                if (burned != 1)
                 {
-                    if (burned != 1 && job->mux == HB_MUX_MKV)
-                    {
-                        job->select_subtitle_config.dest = PASSTHRUSUB;
-                    }
-                    else
-                    {
-                        job->select_subtitle_config.dest = RENDERSUB;
-                    }
-                    
-                    job->select_subtitle_config.force = force;
-                    job->select_subtitle_config.default_track = def;
+                    job->select_subtitle_config.dest = PASSTHRUSUB;
+                }
+                else
+                {
+                    job->select_subtitle_config.dest = RENDERSUB;
                 }
                 
-                
+                job->select_subtitle_config.force = force;
+                job->select_subtitle_config.default_track = def;
             }
             else
             {
@@ -3908,17 +3668,10 @@ bool one_burned = FALSE;
                 {
                     hb_subtitle_config_t sub_config = subt->config;
                     
-                    if (!burned && job->mux == HB_MUX_MKV && 
-                        subt->format == PICTURESUB)
+                    if ( !burned && subt->format == PICTURESUB )
                     {
                         sub_config.dest = PASSTHRUSUB;
                     }
-                    else if (!burned && job->mux == HB_MUX_MP4 && 
-                             subt->format == PICTURESUB)
-                    {
-                        // Skip any non-burned vobsubs when output is mp4
-                        continue;
-                    }
                     else if ( burned && subt->format == PICTURESUB )
                     {
                         // Only allow one subtitle to be burned into the video
@@ -3948,75 +3701,25 @@ bool one_burned = FALSE;
         hb_list_rem(job->list_audio, temp_audio);
     }
     /* Now lets add our new tracks to the audio list here */
-    if ([[queueToApply objectForKey:@"Audio1Track"] intValue] > 0)
-    {
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [[queueToApply objectForKey:@"Audio1Track"] intValue] - 1;
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [[queueToApply objectForKey:@"Audio1Track"] intValue] - 1;
-        audio->out.codec = [[queueToApply objectForKey:@"JobAudio1Encoder"] intValue];
-        audio->out.mixdown = [[queueToApply objectForKey:@"JobAudio1Mixdown"] intValue];
-        audio->out.bitrate = [[queueToApply objectForKey:@"JobAudio1Bitrate"] intValue];
-        audio->out.samplerate = [[queueToApply objectForKey:@"JobAudio1Samplerate"] intValue];
-        audio->out.dynamic_range_compression = [[queueToApply objectForKey:@"Audio1TrackDRCSlider"] floatValue];
-        
-        hb_audio_add( job, audio );
-        free(audio);
-    }  
-    if ([[queueToApply objectForKey:@"Audio2Track"] intValue] > 0)
-    {
-        
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [[queueToApply objectForKey:@"Audio2Track"] intValue] - 1;
-        [self writeToActivityLog: "prepareJob audiotrack 2 is: %d", audio->in.track];
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [[queueToApply objectForKey:@"Audio2Track"] intValue] - 1;
-        audio->out.codec = [[queueToApply objectForKey:@"JobAudio2Encoder"] intValue];
-        audio->out.mixdown = [[queueToApply objectForKey:@"JobAudio2Mixdown"] intValue];
-        audio->out.bitrate = [[queueToApply objectForKey:@"JobAudio2Bitrate"] intValue];
-        audio->out.samplerate = [[queueToApply objectForKey:@"JobAudio2Samplerate"] intValue];
-        audio->out.dynamic_range_compression = [[queueToApply objectForKey:@"Audio2TrackDRCSlider"] floatValue];
-        
-        hb_audio_add( job, audio );
-        free(audio);
-    }
-    
-    if ([[queueToApply objectForKey:@"Audio3Track"] intValue] > 0)
-    {
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [[queueToApply objectForKey:@"Audio3Track"] intValue] - 1;
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [[queueToApply objectForKey:@"Audio3Track"] intValue] - 1;
-        audio->out.codec = [[queueToApply objectForKey:@"JobAudio3Encoder"] intValue];
-        audio->out.mixdown = [[queueToApply objectForKey:@"JobAudio3Mixdown"] intValue];
-        audio->out.bitrate = [[queueToApply objectForKey:@"JobAudio3Bitrate"] intValue];
-        audio->out.samplerate = [[queueToApply objectForKey:@"JobAudio3Samplerate"] intValue];
-        audio->out.dynamic_range_compression = [[queueToApply objectForKey:@"Audio3TrackDRCSlider"] floatValue];
-        
-        hb_audio_add( job, audio );
-        free(audio);        
-    }
-    
-    if ([[queueToApply objectForKey:@"Audio4Track"] intValue] > 0)
-    {
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [[queueToApply objectForKey:@"Audio4Track"] intValue] - 1;
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [[queueToApply objectForKey:@"Audio4Track"] intValue] - 1;
-        audio->out.codec = [[queueToApply objectForKey:@"JobAudio4Encoder"] intValue];
-        audio->out.mixdown = [[queueToApply objectForKey:@"JobAudio4Mixdown"] intValue];
-        audio->out.bitrate = [[queueToApply objectForKey:@"JobAudio4Bitrate"] intValue];
-        audio->out.samplerate = [[queueToApply objectForKey:@"JobAudio4Samplerate"] intValue];
-        audio->out.dynamic_range_compression = [[queueToApply objectForKey:@"Audio4TrackDRCSlider"] floatValue];
-        
-        hb_audio_add( job, audio );
-        
-
-    }
+       for (unsigned int counter = 0; counter < maximumNumberOfAllowedAudioTracks; counter++) {
+               NSString *prefix = [NSString stringWithFormat: @"Audio%d", counter + 1];
+               if ([[queueToApply objectForKey: [prefix stringByAppendingString: @"Track"]] intValue] > 0) {
+                       audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
+                       hb_audio_config_init(audio);
+                       audio->in.track = [[queueToApply objectForKey: [prefix stringByAppendingString: @"Track"]] intValue] - 1;
+                       /* We go ahead and assign values to our audio->out.<properties> */
+                       audio->out.track = audio->in.track;
+                       audio->out.dynamic_range_compression = [[queueToApply objectForKey: [prefix stringByAppendingString: @"TrackDRCSlider"]] floatValue];
+                       prefix = [NSString stringWithFormat: @"JobAudio%d", counter + 1];
+                       audio->out.codec = [[queueToApply objectForKey: [prefix stringByAppendingString: @"Encoder"]] intValue];
+                       audio->out.mixdown = [[queueToApply objectForKey: [prefix stringByAppendingString: @"Mixdown"]] intValue];
+                       audio->out.bitrate = [[queueToApply objectForKey: [prefix stringByAppendingString: @"Bitrate"]] intValue];
+                       audio->out.samplerate = [[queueToApply objectForKey: [prefix stringByAppendingString: @"Samplerate"]] intValue];
+                       
+                       hb_audio_add( job, audio );
+                       free(audio);
+               }
+       }
     
     /* Filters */ 
     job->filters = hb_list_init();
@@ -4025,6 +3728,7 @@ bool one_burned = FALSE;
      * The order of the filters is critical
      */
     /* Detelecine */
+    hb_filter_detelecine.settings = NULL;
     if ([[queueToApply objectForKey:@"PictureDetelecine"] intValue] == 1)
     {
         /* use a custom detelecine string */
@@ -4041,6 +3745,7 @@ bool one_burned = FALSE;
     {
         /* Decomb */
         /* we add the custom string if present */
+        hb_filter_decomb.settings = NULL;
         if ([[queueToApply objectForKey:@"PictureDecomb"] intValue] == 1)
         {
             /* use a custom decomb string */
@@ -4125,7 +3830,7 @@ bool one_burned = FALSE;
 
 
 /* addToQueue: puts up an alert before ultimately calling doAddToQueue
-*/
+ */
 - (IBAction) addToQueue: (id) sender
 {
        /* We get the destination directory from the destination field here */
@@ -4175,7 +3880,7 @@ bool one_burned = FALSE;
     }
     else if (fileExistsInQueue == YES)
     {
-    NSBeginCriticalAlertSheet( NSLocalizedString( @"There is already a queue item for this destination.", @"" ),
+        NSBeginCriticalAlertSheet( NSLocalizedString( @"There is already a queue item for this destination.", @"" ),
                                   NSLocalizedString( @"Cancel", @"" ), NSLocalizedString( @"Overwrite", @"" ), nil, fWindow, self,
                                   @selector( overwriteAddToQueueAlertDone:returnCode:contextInfo: ),
                                   NULL, NULL, [NSString stringWithFormat:
@@ -4227,6 +3932,7 @@ bool one_burned = FALSE;
     // If there are pending jobs in the queue, then this is a rip the queue
     if (fPendingCount > 0)
     {
+        currentQueueEncodeIndex = [self getNextPendingQueueIndex];
         /* here lets start the queue with the first pending item */
         [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; 
         
@@ -4264,6 +3970,7 @@ bool one_burned = FALSE;
         }
         
         /* go right to processing the new queue encode */
+        currentQueueEncodeIndex = [self getNextPendingQueueIndex];
         [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; 
         
     }
@@ -4401,23 +4108,29 @@ bool one_burned = FALSE;
     // and as always, save it in the queue .plist...
     /* We save all of the Queue data here */
     [self saveQueueFileItem];
-    // so now lets move to 
-    currentQueueEncodeIndex++ ;
+    
     // ... and see if there are more items left in our queue
     int queueItems = [QueueFileArray count];
     /* If we still have more items in our queue, lets go to the next one */
-    if (currentQueueEncodeIndex < queueItems)
-    {
-    [self writeToActivityLog: "doCancelCurrentJob currentQueueEncodeIndex is incremented to: %d", currentQueueEncodeIndex];
-    [self writeToActivityLog: "doCancelCurrentJob moving to the next job"];
-    
-    [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]];
+    /* Check to see if there are any more pending items in the queue */
+    int newQueueItemIndex = [self getNextPendingQueueIndex];
+    /* If we still have more pending items in our queue, lets go to the next one */
+    if (newQueueItemIndex >= 0 && newQueueItemIndex < queueItems)
+    {
+        /*Set our currentQueueEncodeIndex now to the newly found Pending encode as we own it */
+        currentQueueEncodeIndex = newQueueItemIndex;
+        /* now we mark the queue item as Status = 1 ( being encoded ) so another instance can not come along and try to scan it while we are scanning */
+        [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:1] forKey:@"Status"];
+        [self writeToActivityLog: "incrementQueueItemDone new pending items found: %d", currentQueueEncodeIndex];
+        [self saveQueueFileItem];
+        /* now we can go ahead and scan the new pending queue item */
+        [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]];
+
     }
     else
     {
-        [self writeToActivityLog: "doCancelCurrentJob the item queue is complete"];
+        [self writeToActivityLog: "incrementQueueItemDone there are no more pending encodes"];
     }
-
 }
 
 - (void) doCancelCurrentJobAndStop
@@ -4465,19 +4178,17 @@ bool one_burned = FALSE;
     hb_title_t * title = (hb_title_t*)
         hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
 
-    /* If we are a stream type, grok the output file name from title->name upon title change */
-    if (title->type == HB_STREAM_TYPE)
+    /* If we are a stream type and a batch scan, grok the output file name from title->name upon title change */
+    if (title->type == HB_STREAM_TYPE && hb_list_count( list ) > 1 )
     {
         /* we set the default name according to the new title->name */
         [fDstFile2Field setStringValue: [NSString stringWithFormat:
                                          @"%@/%@.%@", [[fDstFile2Field stringValue] stringByDeletingLastPathComponent],
                                          [NSString stringWithUTF8String: title->name],
                                          [[fDstFile2Field stringValue] pathExtension]]];
-        /* If we have more than one title and are stream then we have a batch, change the source to read out the parent folder also */
-        if ( hb_list_count( list ) > 1 )
-        {                                  
-            [fSrcDVD2Field setStringValue:[NSString stringWithFormat:@"%@/%@", browsedSourceDisplayName,[NSString stringWithUTF8String: title->name]]];
-        }
+        
+        /* Change the source to read out the parent folder also */
+        [fSrcDVD2Field setStringValue:[NSString stringWithFormat:@"%@/%@", browsedSourceDisplayName,[NSString stringWithUTF8String: title->name]]];
     }
     
     /* For point a to point b pts encoding, set the start and end fields to 0 and the title duration in seconds respectively */
@@ -4566,7 +4277,15 @@ bool one_burned = FALSE;
     [fChapterTitlesDelegate resetWithTitle:title];
     [fChapterTable reloadData];
 
-   /* Lets make sure there arent any erroneous audio tracks in the job list, so lets make sure its empty*/
+       /* Update audio table */
+       [[NSNotificationCenter defaultCenter] postNotification:
+        [NSNotification notificationWithName: HBTitleChangedNotification
+                                                                  object: self
+                                                                userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
+                                                                                       [NSData dataWithBytesNoCopy: &fTitle length: sizeof(fTitle) freeWhenDone: NO], keyTitleTag,
+                                                                                       nil]]];
+       
+       /* Lets make sure there arent any erroneous audio tracks in the job list, so lets make sure its empty*/
     int audiotrack_count = hb_list_count(job->list_audio);
     for( int i = 0; i < audiotrack_count;i++)
     {
@@ -4574,25 +4293,7 @@ bool one_burned = FALSE;
         hb_list_rem(job->list_audio, temp_audio);
     }
 
-    /* Update audio popups */
-    [self addAllAudioTracksToPopUp: fAudLang1PopUp];
-    [self addAllAudioTracksToPopUp: fAudLang2PopUp];
-    [self addAllAudioTracksToPopUp: fAudLang3PopUp];
-    [self addAllAudioTracksToPopUp: fAudLang4PopUp];
-    /* search for the first instance of our prefs default language for track 1, and set track 2 to "none" */
-       NSString * audioSearchPrefix = [[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
-        [self selectAudioTrackInPopUp: fAudLang1PopUp searchPrefixString: audioSearchPrefix selectIndexIfNotFound: 1];
-    [self selectAudioTrackInPopUp:fAudLang2PopUp searchPrefixString:nil selectIndexIfNotFound:0];
-    [self selectAudioTrackInPopUp:fAudLang3PopUp searchPrefixString:nil selectIndexIfNotFound:0];
-    [self selectAudioTrackInPopUp:fAudLang4PopUp searchPrefixString:nil selectIndexIfNotFound:0];
-
-       /* changing the title may have changed the audio channels on offer, */
-       /* so call audioTrackPopUpChanged for both audio tracks to update the mixdown popups */
-       [self audioTrackPopUpChanged: fAudLang1PopUp];
-       [self audioTrackPopUpChanged: fAudLang2PopUp];
-    [self audioTrackPopUpChanged: fAudLang3PopUp];
-    [self audioTrackPopUpChanged: fAudLang4PopUp];
-
+       
     [fVidRatePopUp selectItemAtIndex: 0];
 
     /* we run the picture size values through calculatePictureSizing to get all picture setting        information*/
@@ -4782,6 +4483,15 @@ bool one_burned = FALSE;
     
     [fSubtitlesDelegate containerChanged:[[fDstFormatPopUp selectedItem] tag]];
     [fSubtitlesTable reloadData];
+       
+       /* post a notification for any interested observers to indicate that our video container has changed */
+       [[NSNotificationCenter defaultCenter] postNotification:
+        [NSNotification notificationWithName: HBContainerChangedNotification
+                                                                  object: self
+                                                                userInfo: [NSDictionary dictionaryWithObjectsAndKeys:
+                                                                                       [NSNumber numberWithInt: [[fDstFormatPopUp selectedItem] tag]], keyContainerTag,
+                                                                                       nil]]];
+       
     /* if we have a previously selected vid encoder tag, then try to select it */
     if (selectedVidEncoderTag)
     {
@@ -4792,10 +4502,6 @@ bool one_burned = FALSE;
         [fVidEncoderPopUp selectItemAtIndex: 0];
     }
 
-    [self audioAddAudioTrackCodecs: fAudTrack1CodecPopUp];
-    [self audioAddAudioTrackCodecs: fAudTrack2CodecPopUp];
-    [self audioAddAudioTrackCodecs: fAudTrack3CodecPopUp];
-    [self audioAddAudioTrackCodecs: fAudTrack4CodecPopUp];
 
     if( format == 0 )
         [self autoSetM4vExtension: sender];
@@ -4805,10 +4511,6 @@ bool one_burned = FALSE;
     if( SuccessfulScan )
     {
         /* Add/replace to the correct extension */
-        [self audioTrackPopUpChanged: fAudLang1PopUp];
-        [self audioTrackPopUpChanged: fAudLang2PopUp];
-        [self audioTrackPopUpChanged: fAudLang3PopUp];
-        [self audioTrackPopUpChanged: fAudLang4PopUp];
 
         if( [fVidEncoderPopUp selectedItem] == nil )
         {
@@ -4834,9 +4536,8 @@ bool one_burned = FALSE;
 
     NSString * extension = @"mp4";
 
-    if( [[fAudTrack1CodecPopUp selectedItem] tag] == HB_ACODEC_AC3 || [[fAudTrack2CodecPopUp selectedItem] tag] == HB_ACODEC_AC3 ||
-                                                        [[fAudTrack3CodecPopUp selectedItem] tag] == HB_ACODEC_AC3 ||
-                                                        [[fAudTrack4CodecPopUp selectedItem] tag] == HB_ACODEC_AC3 ||
+       BOOL anyCodecAC3 = [fAudioDelegate anyCodecMatches: HB_ACODEC_AC3];
+       if (YES == anyCodecAC3 ||
                                                         [fCreateChapterMarkers state] == NSOnState ||
                                                         [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0 )
     {
@@ -4935,6 +4636,17 @@ the user is using "Custom" settings by determining the sender*/
 
 - (IBAction ) videoFrameRateChanged: (id) sender
 {
+    /* Hide and set the PFR Checkbox to OFF if we are set to Same as Source */
+    if ([fVidRatePopUp indexOfSelectedItem] == 0)
+    {
+        [fFrameratePfrCheck setHidden:YES];
+        [fFrameratePfrCheck setState:0];
+    }
+    else
+    {
+        [fFrameratePfrCheck setHidden:NO];
+    }
+    
     /* We call method method to calculatePictureSizing to error check detelecine*/
     [self calculatePictureSizing: sender];
 
@@ -5086,82 +4798,7 @@ the user is using "Custom" settings by determining the sender*/
     job->mux = [[fDstFormatPopUp selectedItem] tag];
     
     /* Audio goes here */
-    int audiotrack_count = hb_list_count(job->list_audio);
-    for( int i = 0; i < audiotrack_count;i++)
-    {
-        hb_audio_t * temp_audio = (hb_audio_t*) hb_list_item( job->list_audio, 0 );
-        hb_list_rem(job->list_audio, temp_audio);
-    }
-    /* Now we need our audio info here for each track if applicable */
-    if ([fAudLang1PopUp indexOfSelectedItem] > 0)
-    {
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [fAudLang1PopUp indexOfSelectedItem] - 1;
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [fAudLang1PopUp indexOfSelectedItem] - 1;
-        audio->out.codec = [[fAudTrack1CodecPopUp selectedItem] tag];
-        audio->out.mixdown = [[fAudTrack1MixPopUp selectedItem] tag];
-        audio->out.bitrate = [[fAudTrack1BitratePopUp selectedItem] tag];
-        audio->out.samplerate = [[fAudTrack1RatePopUp selectedItem] tag];
-        audio->out.dynamic_range_compression = [fAudTrack1DrcField floatValue];
-        
-        hb_audio_add( job, audio );
-        free(audio);
-    }  
-    if ([fAudLang2PopUp indexOfSelectedItem] > 0)
-    {
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [fAudLang2PopUp indexOfSelectedItem] - 1;
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [fAudLang2PopUp indexOfSelectedItem] - 1;
-        audio->out.codec = [[fAudTrack2CodecPopUp selectedItem] tag];
-        audio->out.mixdown = [[fAudTrack2MixPopUp selectedItem] tag];
-        audio->out.bitrate = [[fAudTrack2BitratePopUp selectedItem] tag];
-        audio->out.samplerate = [[fAudTrack2RatePopUp selectedItem] tag];
-        audio->out.dynamic_range_compression = [fAudTrack2DrcField floatValue];
-        
-        hb_audio_add( job, audio );
-        free(audio);
-        
-    }
-    
-    if ([fAudLang3PopUp indexOfSelectedItem] > 0)
-    {
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [fAudLang3PopUp indexOfSelectedItem] - 1;
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [fAudLang3PopUp indexOfSelectedItem] - 1;
-        audio->out.codec = [[fAudTrack3CodecPopUp selectedItem] tag];
-        audio->out.mixdown = [[fAudTrack3MixPopUp selectedItem] tag];
-        audio->out.bitrate = [[fAudTrack3BitratePopUp selectedItem] tag];
-        audio->out.samplerate = [[fAudTrack3RatePopUp selectedItem] tag];
-        audio->out.dynamic_range_compression = [fAudTrack3DrcField floatValue];
-        
-        hb_audio_add( job, audio );
-        free(audio);
-        
-    }
-
-    if ([fAudLang4PopUp indexOfSelectedItem] > 0)
-    {
-        audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
-        hb_audio_config_init(audio);
-        audio->in.track = [fAudLang4PopUp indexOfSelectedItem] - 1;
-        /* We go ahead and assign values to our audio->out.<properties> */
-        audio->out.track = [fAudLang4PopUp indexOfSelectedItem] - 1;
-        audio->out.codec = [[fAudTrack4CodecPopUp selectedItem] tag];
-        audio->out.mixdown = [[fAudTrack4MixPopUp selectedItem] tag];
-        audio->out.bitrate = [[fAudTrack4BitratePopUp selectedItem] tag];
-        audio->out.samplerate = [[fAudTrack4RatePopUp selectedItem] tag];
-        audio->out.dynamic_range_compression = [fAudTrack4DrcField floatValue];
-        
-        hb_audio_add( job, audio );
-        free(audio);
-        
-    }
+       [fAudioDelegate prepareAudioForJob: job];
        
 [fVidBitrateField setIntValue: hb_calc_bitrate( job, [fVidTargetSizeField intValue] )];
 }
@@ -5317,914 +4954,31 @@ the user is using "Custom" settings by determining the sender*/
 
 #pragma mark -
 #pragma mark - Audio and Subtitles
-- (IBAction) audioCodecsPopUpChanged: (id) sender
-{
-    
-    NSPopUpButton * audiotrackPopUp;
-    NSPopUpButton * sampleratePopUp;
-    NSPopUpButton * bitratePopUp;
-    NSPopUpButton * audiocodecPopUp;
-    if (sender == fAudTrack1CodecPopUp)
-    {
-        audiotrackPopUp = fAudLang1PopUp;
-        audiocodecPopUp = fAudTrack1CodecPopUp;
-        sampleratePopUp = fAudTrack1RatePopUp;
-        bitratePopUp = fAudTrack1BitratePopUp;
-    }
-    else if (sender == fAudTrack2CodecPopUp)
-    {
-        audiotrackPopUp = fAudLang2PopUp;
-        audiocodecPopUp = fAudTrack2CodecPopUp;
-        sampleratePopUp = fAudTrack2RatePopUp;
-        bitratePopUp = fAudTrack2BitratePopUp;
-    }
-    else if (sender == fAudTrack3CodecPopUp)
-    {
-        audiotrackPopUp = fAudLang3PopUp;
-        audiocodecPopUp = fAudTrack3CodecPopUp;
-        sampleratePopUp = fAudTrack3RatePopUp;
-        bitratePopUp = fAudTrack3BitratePopUp;
-    }
-    else
-    {
-        audiotrackPopUp = fAudLang4PopUp;
-        audiocodecPopUp = fAudTrack4CodecPopUp;
-        sampleratePopUp = fAudTrack4RatePopUp;
-        bitratePopUp = fAudTrack4BitratePopUp;
-    }
-       
-    /* changing the codecs on offer may mean that we can / can't offer mono or 6ch, */
-       /* so call audioTrackPopUpChanged for both audio tracks to update the mixdown popups */
-    [self audioTrackPopUpChanged: audiotrackPopUp];
-    
-}
-
-- (IBAction) setEnabledStateOfAudioMixdownControls: (id) sender
-{
-    /* We will be setting the enabled/disabled state of each tracks audio controls based on
-     * the settings of the source audio for that track. We leave the samplerate and bitrate
-     * to audiotrackMixdownChanged
-     */
-    
-    /* We will first verify that a lower track number has been selected before enabling each track
-     * for example, make sure a track is selected for track 1 before enabling track 2, etc.
-     */
-    if ([fAudLang1PopUp indexOfSelectedItem] == 0)
-    {
-        [fAudLang2PopUp setEnabled: NO];
-        [fAudLang2PopUp selectItemAtIndex: 0];
-    }
-    else
-    {
-        [fAudLang2PopUp setEnabled: YES];
-    }
-    
-    if ([fAudLang2PopUp indexOfSelectedItem] == 0)
-    {
-        [fAudLang3PopUp setEnabled: NO];
-        [fAudLang3PopUp selectItemAtIndex: 0];
-    }
-    else
-    {
-        [fAudLang3PopUp setEnabled: YES];
-    }
-    if ([fAudLang3PopUp indexOfSelectedItem] == 0)
-    {
-        [fAudLang4PopUp setEnabled: NO];
-        [fAudLang4PopUp selectItemAtIndex: 0];
-    }
-    else
-    {
-        [fAudLang4PopUp setEnabled: YES];
-    }
-    /* enable/disable the mixdown text and popupbutton for audio track 1 */
-    [fAudTrack1CodecPopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack1MixPopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack1RatePopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack1BitratePopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack1DrcSlider setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack1DrcField setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    if ([fAudLang1PopUp indexOfSelectedItem] == 0)
-    {
-        [fAudTrack1CodecPopUp removeAllItems];
-        [fAudTrack1MixPopUp removeAllItems];
-        [fAudTrack1RatePopUp removeAllItems];
-        [fAudTrack1BitratePopUp removeAllItems];
-        [fAudTrack1DrcSlider setFloatValue: 0.00];
-        [self audioDRCSliderChanged: fAudTrack1DrcSlider];
-    }
-    else if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_ACODEC_AC3 || [[fAudTrack1MixPopUp selectedItem] tag] == HB_ACODEC_DCA)
-    {
-        [fAudTrack1RatePopUp setEnabled: NO];
-        [fAudTrack1BitratePopUp setEnabled: NO];
-        [fAudTrack1DrcSlider setEnabled: NO];
-        [fAudTrack1DrcField setEnabled: NO];
-    }
-    
-    /* enable/disable the mixdown text and popupbutton for audio track 2 */
-    [fAudTrack2CodecPopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack2MixPopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack2RatePopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack2BitratePopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack2DrcSlider setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack2DrcField setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    if ([fAudLang2PopUp indexOfSelectedItem] == 0)
-    {
-        [fAudTrack2CodecPopUp removeAllItems];
-        [fAudTrack2MixPopUp removeAllItems];
-        [fAudTrack2RatePopUp removeAllItems];
-        [fAudTrack2BitratePopUp removeAllItems];
-        [fAudTrack2DrcSlider setFloatValue: 0.00];
-        [self audioDRCSliderChanged: fAudTrack2DrcSlider];
-    }
-    else if ([[fAudTrack2MixPopUp selectedItem] tag] == HB_ACODEC_AC3 || [[fAudTrack2MixPopUp selectedItem] tag] == HB_ACODEC_DCA)
-    {
-        [fAudTrack2RatePopUp setEnabled: NO];
-        [fAudTrack2BitratePopUp setEnabled: NO];
-        [fAudTrack2DrcSlider setEnabled: NO];
-        [fAudTrack2DrcField setEnabled: NO];
-    }
-    
-    /* enable/disable the mixdown text and popupbutton for audio track 3 */
-    [fAudTrack3CodecPopUp setEnabled: ([fAudLang3PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack3MixPopUp setEnabled: ([fAudLang3PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack3RatePopUp setEnabled: ([fAudLang3PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack3BitratePopUp setEnabled: ([fAudLang3PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack3DrcSlider setEnabled: ([fAudLang3PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack3DrcField setEnabled: ([fAudLang3PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    if ([fAudLang3PopUp indexOfSelectedItem] == 0)
-    {
-        [fAudTrack3CodecPopUp removeAllItems];
-        [fAudTrack3MixPopUp removeAllItems];
-        [fAudTrack3RatePopUp removeAllItems];
-        [fAudTrack3BitratePopUp removeAllItems];
-        [fAudTrack3DrcSlider setFloatValue: 0.00];
-        [self audioDRCSliderChanged: fAudTrack3DrcSlider];
-    }
-    else if ([[fAudTrack3MixPopUp selectedItem] tag] == HB_ACODEC_AC3 || [[fAudTrack3MixPopUp selectedItem] tag] == HB_ACODEC_DCA)
-    {
-        [fAudTrack3RatePopUp setEnabled: NO];
-        [fAudTrack3BitratePopUp setEnabled: NO];
-        [fAudTrack3DrcSlider setEnabled: NO];
-        [fAudTrack3DrcField setEnabled: NO];
-    }
-    
-    /* enable/disable the mixdown text and popupbutton for audio track 4 */
-    [fAudTrack4CodecPopUp setEnabled: ([fAudLang4PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack4MixPopUp setEnabled: ([fAudLang4PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack4RatePopUp setEnabled: ([fAudLang4PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack4BitratePopUp setEnabled: ([fAudLang4PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack4DrcSlider setEnabled: ([fAudLang4PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    [fAudTrack4DrcField setEnabled: ([fAudLang4PopUp indexOfSelectedItem] == 0) ? NO : YES];
-    if ([fAudLang4PopUp indexOfSelectedItem] == 0)
-    {
-        [fAudTrack4CodecPopUp removeAllItems];
-        [fAudTrack4MixPopUp removeAllItems];
-        [fAudTrack4RatePopUp removeAllItems];
-        [fAudTrack4BitratePopUp removeAllItems];
-        [fAudTrack4DrcSlider setFloatValue: 0.00];
-        [self audioDRCSliderChanged: fAudTrack4DrcSlider];
-    }
-    else if ([[fAudTrack4MixPopUp selectedItem] tag] == HB_ACODEC_AC3 || [[fAudTrack4MixPopUp selectedItem] tag] == HB_ACODEC_DCA)
-    {
-        [fAudTrack4RatePopUp setEnabled: NO];
-        [fAudTrack4BitratePopUp setEnabled: NO];
-        [fAudTrack4DrcSlider setEnabled: NO];
-        [fAudTrack4DrcField setEnabled: NO];
-    }
-    
-}
 
-- (IBAction) addAllAudioTracksToPopUp: (id) sender
-{
 
-    hb_list_t  * list  = hb_get_titles( fHandle );
-    hb_title_t * title = (hb_title_t*)
-        hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
+#pragma mark -
 
-       hb_audio_config_t * audio;
+@synthesize hasValidPresetSelected;
 
-    [sender removeAllItems];
-    [sender addItemWithTitle: NSLocalizedString( @"None", @"" )];
-    for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
-    {
-        audio = (hb_audio_config_t *) hb_list_audio_config_item( title->list_audio, i );
-        [[sender menu] addItemWithTitle:
-            [NSString stringWithUTF8String: audio->lang.description]
-            action: NULL keyEquivalent: @""];
-    }
-    [sender selectItemAtIndex: 0];
+//     This causes all audio tracks from the title to be used based on the current preset
+- (IBAction) addAllAudioTracks: (id) sender
 
+{
+       [fAudioDelegate addAllTracksFromPreset: [fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]]];
+       return;
 }
 
-- (IBAction) selectAudioTrackInPopUp: (id) sender searchPrefixString: (NSString *) searchPrefixString selectIndexIfNotFound: (int) selectIndexIfNotFound
+- (IBAction) browseImportSrtFile: (id) sender
 {
 
-    /* this method can be used to find a language, or a language-and-source-format combination, by passing in the appropriate string */
-    /* e.g. to find the first French track, pass in an NSString * of "Francais" */
-    /* e.g. to find the first English 5.1 AC3 track, pass in an NSString * of "English (AC3) (5.1 ch)" */
-    /* if no matching track is found, then selectIndexIfNotFound is used to choose which track to select instead */
-
-       if (searchPrefixString)
-       {
-
-        for( int i = 0; i < [sender numberOfItems]; i++ )
-        {
-            /* Try to find the desired search string */
-            if ([[[sender itemAtIndex: i] title] hasPrefix:searchPrefixString])
-            {
-                [sender selectItemAtIndex: i];
-                return;
-            }
-        }
-        /* couldn't find the string, so select the requested "search string not found" item */
-        /* index of 0 means select the "none" item */
-        /* index of 1 means select the first audio track */
-        [sender selectItemAtIndex: selectIndexIfNotFound];
-       }
-    else
-    {
-        /* if no search string is provided, then select the selectIndexIfNotFound item */
-        [sender selectItemAtIndex: selectIndexIfNotFound];
-    }
-
-}
-- (IBAction) audioAddAudioTrackCodecs: (id)sender
-{
-    int format = [fDstFormatPopUp indexOfSelectedItem];
-    
-    /* setup pointers to the appropriate popups for the correct track */
-    NSPopUpButton * audiocodecPopUp;
-    NSPopUpButton * audiotrackPopUp;
-    if (sender == fAudTrack1CodecPopUp)
-    {
-        audiotrackPopUp = fAudLang1PopUp;
-        audiocodecPopUp = fAudTrack1CodecPopUp;
-    }
-    else if (sender == fAudTrack2CodecPopUp)
-    {
-        audiotrackPopUp = fAudLang2PopUp;
-        audiocodecPopUp = fAudTrack2CodecPopUp;
-    }
-    else if (sender == fAudTrack3CodecPopUp)
-    {
-        audiotrackPopUp = fAudLang3PopUp;
-        audiocodecPopUp = fAudTrack3CodecPopUp;
-    }
-    else
-    {
-        audiotrackPopUp = fAudLang4PopUp;
-        audiocodecPopUp = fAudTrack4CodecPopUp;
-    }
-    
-    [audiocodecPopUp removeAllItems];
-    /* Make sure "None" isnt selected in the source track */
-    if ([audiotrackPopUp indexOfSelectedItem] > 0)
-    {
-        [audiocodecPopUp setEnabled:YES];
-        NSMenuItem *menuItem;
-        /* We setup our appropriate popups for codecs and put the int value in the popup tag for easy retrieval */
-        switch( format )
-        {
-            case 0:
-                /* MP4 */
-                // FAAC
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (faac)" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_FAAC];
-
-                // CA_AAC
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (CoreAudio)" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_CA_AAC];
-
-                // AC3 Passthru
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AC3 Passthru" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_AC3];
-                break;
-                
-            case 1:
-                /* MKV */
-                // FAAC
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (faac)" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_FAAC];
-                // CA_AAC
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (CoreAudio)" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_CA_AAC];
-                // AC3 Passthru
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AC3 Passthru" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_AC3];
-                // DTS Passthru
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"DTS Passthru" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_DCA];
-                // MP3
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"MP3 (lame)" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_LAME];
-                // Vorbis
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"Vorbis (vorbis)" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_VORBIS];
-                break;
-                
-            case 2: 
-                /* AVI */
-                // MP3
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"MP3 (lame)" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_LAME];
-                // AC3 Passthru
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AC3 Passthru" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_AC3];
-                break;
-                
-            case 3:
-                /* OGM */
-                // Vorbis
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"Vorbis (vorbis)" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_VORBIS];
-                // MP3
-                menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"MP3 (lame)" action: NULL keyEquivalent: @""];
-                [menuItem setTag: HB_ACODEC_LAME];
-                break;
-        }
-        [audiocodecPopUp selectItemAtIndex:0];
-    }
-    else
-    {
-        [audiocodecPopUp setEnabled:NO];
-    }
-}
-
-- (IBAction) audioTrackPopUpChanged: (id) sender
-{
-    /* utility function to call audioTrackPopUpChanged without passing in a mixdown-to-use */
-    [self audioTrackPopUpChanged: sender mixdownToUse: 0];
-}
-
-- (IBAction) audioTrackPopUpChanged: (id) sender mixdownToUse: (int) mixdownToUse
-{
-    
-    /* make sure we have a selected title before continuing */
-    if (fTitle == NULL) return;
-    /* if the sender is the lanaguage popup and there is nothing in the codec popup, lets call
-    * audioAddAudioTrackCodecs on the codec popup to populate it properly before moving on
-    */
-    if (sender == fAudLang1PopUp && [[fAudTrack1CodecPopUp menu] numberOfItems] == 0)
-    {
-        [self audioAddAudioTrackCodecs: fAudTrack1CodecPopUp];
-    }
-    if (sender == fAudLang2PopUp && [[fAudTrack2CodecPopUp menu] numberOfItems] == 0)
-    {
-        [self audioAddAudioTrackCodecs: fAudTrack2CodecPopUp];
-    }
-    if (sender == fAudLang3PopUp && [[fAudTrack3CodecPopUp menu] numberOfItems] == 0)
-    {
-        [self audioAddAudioTrackCodecs: fAudTrack3CodecPopUp];
-    }
-    if (sender == fAudLang4PopUp && [[fAudTrack4CodecPopUp menu] numberOfItems] == 0)
-    {
-        [self audioAddAudioTrackCodecs: fAudTrack4CodecPopUp];
-    }
-    
-    /* Now lets make the sender the appropriate Audio Track popup from this point on */
-    if (sender == fAudTrack1CodecPopUp || sender == fAudTrack1MixPopUp)
-    {
-        sender = fAudLang1PopUp;
-    }
-    if (sender == fAudTrack2CodecPopUp || sender == fAudTrack2MixPopUp)
-    {
-        sender = fAudLang2PopUp;
-    }
-    if (sender == fAudTrack3CodecPopUp || sender == fAudTrack3MixPopUp)
-    {
-        sender = fAudLang3PopUp;
-    }
-    if (sender == fAudTrack4CodecPopUp || sender == fAudTrack4MixPopUp)
-    {
-        sender = fAudLang4PopUp;
-    }
-    
-    /* pointer to this track's mixdown, codec, sample rate and bitrate NSPopUpButton's */
-    NSPopUpButton * mixdownPopUp;
-    NSPopUpButton * audiocodecPopUp;
-    NSPopUpButton * sampleratePopUp;
-    NSPopUpButton * bitratePopUp;
-    if (sender == fAudLang1PopUp)
-    {
-        mixdownPopUp = fAudTrack1MixPopUp;
-        audiocodecPopUp = fAudTrack1CodecPopUp;
-        sampleratePopUp = fAudTrack1RatePopUp;
-        bitratePopUp = fAudTrack1BitratePopUp;
-    }
-    else if (sender == fAudLang2PopUp)
-    {
-        mixdownPopUp = fAudTrack2MixPopUp;
-        audiocodecPopUp = fAudTrack2CodecPopUp;
-        sampleratePopUp = fAudTrack2RatePopUp;
-        bitratePopUp = fAudTrack2BitratePopUp;
-    }
-    else if (sender == fAudLang3PopUp)
-    {
-        mixdownPopUp = fAudTrack3MixPopUp;
-        audiocodecPopUp = fAudTrack3CodecPopUp;
-        sampleratePopUp = fAudTrack3RatePopUp;
-        bitratePopUp = fAudTrack3BitratePopUp;
-    }
-    else
-    {
-        mixdownPopUp = fAudTrack4MixPopUp;
-        audiocodecPopUp = fAudTrack4CodecPopUp;
-        sampleratePopUp = fAudTrack4RatePopUp;
-        bitratePopUp = fAudTrack4BitratePopUp;
-    }
-
-    /* get the index of the selected audio Track*/
-    int thisAudioIndex = [sender indexOfSelectedItem] - 1;
-
-    /* pointer for the hb_audio_s struct we will use later on */
-    hb_audio_config_t * audio;
-
-    int acodec;
-    /* check if the audio mixdown controls need their enabled state changing */
-    [self setEnabledStateOfAudioMixdownControls:nil];
-
-    if (thisAudioIndex != -1)
-    {
-
-        /* get the audio */
-        audio = (hb_audio_config_t *) hb_list_audio_config_item( fTitle->list_audio, thisAudioIndex );// Should "fTitle" be title and be setup ?
-
-        /* actually manipulate the proper mixdowns here */
-        /* delete the previous audio mixdown options */
-        [mixdownPopUp removeAllItems];
-
-        acodec = [[audiocodecPopUp selectedItem] tag];
-
-        if (audio != NULL)
-        {
-
-            /* find out if our selected output audio codec supports mono and / or 6ch */
-            /* we also check for an input codec of AC3 or DCA,
-             as they are the only libraries able to do the mixdown to mono / conversion to 6-ch */
-            /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,
-             but this may change in the future, so they are separated for flexibility */
-            int audioCodecsSupportMono =
-                    (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
-                    (acodec != HB_ACODEC_LAME);
-            int audioCodecsSupport6Ch =
-                    (audio->in.codec & (HB_ACODEC_AC3|HB_ACODEC_DCA)) &&
-                    (acodec != HB_ACODEC_LAME);
-            
-            /* check for AC-3 passthru */
-            if (audio->in.codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3)
-            {
-                
-            NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:
-                 [NSString stringWithUTF8String: "AC3 Passthru"]
-                                               action: NULL keyEquivalent: @""];
-             [menuItem setTag: HB_ACODEC_AC3];   
-            }
-            else if (audio->in.codec == HB_ACODEC_DCA && acodec == HB_ACODEC_DCA)
-            {
-            NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:
-                 [NSString stringWithUTF8String: "DTS Passthru"]
-                                               action: NULL keyEquivalent: @""];
-             [menuItem setTag: HB_ACODEC_DCA]; 
-            }
-            else
-            {
-                
-                /* add the appropriate audio mixdown menuitems to the popupbutton */
-                /* in each case, we set the new menuitem's tag to be the amixdown value for that mixdown,
-                 so that we can reference the mixdown later */
-                
-                /* keep a track of the min and max mixdowns we used, so we can select the best match later */
-                int minMixdownUsed = 0;
-                int maxMixdownUsed = 0;
-                
-                /* get the input channel layout without any lfe channels */
-                int layout = audio->in.channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
-                
-                /* do we want to add a mono option? */
-                if (audioCodecsSupportMono == 1)
-                {
-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:
-                                            [NSString stringWithUTF8String: hb_audio_mixdowns[0].human_readable_name]
-                                                                          action: NULL keyEquivalent: @""];
-                    [menuItem setTag: hb_audio_mixdowns[0].amixdown];
-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[0].amixdown;
-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[0].amixdown);
-                }
-                
-                /* do we want to add a stereo option? */
-                /* offer stereo if we have a mono source and non-mono-supporting codecs, as otherwise we won't have a mixdown at all */
-                /* also offer stereo if we have a stereo-or-better source */
-                if ((layout == HB_INPUT_CH_LAYOUT_MONO && audioCodecsSupportMono == 0) || layout >= HB_INPUT_CH_LAYOUT_STEREO)
-                {
-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:
-                                            [NSString stringWithUTF8String: hb_audio_mixdowns[1].human_readable_name]
-                                                                          action: NULL keyEquivalent: @""];
-                    [menuItem setTag: hb_audio_mixdowns[1].amixdown];
-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[1].amixdown;
-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[1].amixdown);
-                }
-                
-                /* do we want to add a dolby surround (DPL1) option? */
-                if (layout == HB_INPUT_CH_LAYOUT_3F1R || layout == HB_INPUT_CH_LAYOUT_3F2R || layout == HB_INPUT_CH_LAYOUT_DOLBY)
-                {
-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:
-                                            [NSString stringWithUTF8String: hb_audio_mixdowns[2].human_readable_name]
-                                                                          action: NULL keyEquivalent: @""];
-                    [menuItem setTag: hb_audio_mixdowns[2].amixdown];
-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[2].amixdown;
-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[2].amixdown);
-                }
-                
-                /* do we want to add a dolby pro logic 2 (DPL2) option? */
-                if (layout == HB_INPUT_CH_LAYOUT_3F2R)
-                {
-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:
-                                            [NSString stringWithUTF8String: hb_audio_mixdowns[3].human_readable_name]
-                                                                          action: NULL keyEquivalent: @""];
-                    [menuItem setTag: hb_audio_mixdowns[3].amixdown];
-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[3].amixdown;
-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[3].amixdown);
-                }
-                
-                /* do we want to add a 6-channel discrete option? */
-                if (audioCodecsSupport6Ch == 1 && layout == HB_INPUT_CH_LAYOUT_3F2R && (audio->in.channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE))
-                {
-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:
-                                            [NSString stringWithUTF8String: hb_audio_mixdowns[4].human_readable_name]
-                                                                          action: NULL keyEquivalent: @""];
-                    [menuItem setTag: hb_audio_mixdowns[4].amixdown];
-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[4].amixdown;
-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[4].amixdown);
-                }
-                
-                /* do we want to add an AC-3 passthrough option? */
-                if (audio->in.codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3) 
-                {
-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:
-                                            [NSString stringWithUTF8String: hb_audio_mixdowns[5].human_readable_name]
-                                                                          action: NULL keyEquivalent: @""];
-                    [menuItem setTag: HB_ACODEC_AC3];
-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[5].amixdown;
-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[5].amixdown);
-                }
-                
-                /* do we want to add a DTS Passthru option ? HB_ACODEC_DCA*/
-                if (audio->in.codec == HB_ACODEC_DCA && acodec == HB_ACODEC_DCA) 
-                {
-                    NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle:
-                                            [NSString stringWithUTF8String: hb_audio_mixdowns[5].human_readable_name]
-                                                                          action: NULL keyEquivalent: @""];
-                    [menuItem setTag: HB_ACODEC_DCA];
-                    if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[5].amixdown;
-                    maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[5].amixdown);
-                }
-                
-                /* auto-select the best mixdown based on our saved mixdown preference */
-                
-                /* for now, this is hard-coded to a "best" mixdown of HB_AMIXDOWN_DOLBYPLII */
-                /* ultimately this should be a prefs option */
-                int useMixdown;
-                
-                /* if we passed in a mixdown to use - in order to load a preset - then try and use it */
-                if (mixdownToUse > 0)
-                {
-                    useMixdown = mixdownToUse;
-                }
-                else
-                {
-                    useMixdown = HB_AMIXDOWN_DOLBYPLII;
-                }
-                
-                /* if useMixdown > maxMixdownUsed, then use maxMixdownUsed */
-                if (useMixdown > maxMixdownUsed)
-                { 
-                    useMixdown = maxMixdownUsed;
-                }
-                
-                /* if useMixdown < minMixdownUsed, then use minMixdownUsed */
-                if (useMixdown < minMixdownUsed)
-                { 
-                    useMixdown = minMixdownUsed;
-                }
-                
-                /* select the (possibly-amended) preferred mixdown */
-                [mixdownPopUp selectItemWithTag: useMixdown];
-
-            }
-            /* In the case of a source track that is not AC3 and the user tries to use AC3 Passthru (which does not work)
-             * we force the Audio Codec choice back to a workable codec. We use MP3 for avi and aac for all
-             * other containers.
-             */
-            if (audio->in.codec != HB_ACODEC_AC3 && [[audiocodecPopUp selectedItem] tag] == HB_ACODEC_AC3)
-            {
-                /* If we are using the avi container, we select MP3 as there is no aac available*/
-                if ([[fDstFormatPopUp selectedItem] tag] == HB_MUX_AVI)
-                {
-                    [audiocodecPopUp selectItemWithTag: HB_ACODEC_LAME];
-                }
-                else
-                {
-                    [audiocodecPopUp selectItemWithTag: HB_ACODEC_FAAC];
-                }
-            }
-            
-            /* In the case of a source track that is not DTS and the user tries to use DTS Passthru (which does not work)
-             * we force the Audio Codec choice back to a workable codec. We use MP3 for avi and aac for all
-             * other containers.
-             */
-            if (audio->in.codec != HB_ACODEC_DCA && [[audiocodecPopUp selectedItem] tag] == HB_ACODEC_DCA)
-            {
-                /* If we are using the avi container, we select MP3 as there is no aac available*/
-                if ([[fDstFormatPopUp selectedItem] tag] == HB_MUX_AVI)
-                {
-                    [audiocodecPopUp selectItemWithTag: HB_ACODEC_LAME];
-                }
-                else
-                {
-                    [audiocodecPopUp selectItemWithTag: HB_ACODEC_FAAC];
-                }
-            }
-            
-            /* Setup our samplerate and bitrate popups we will need based on mixdown */
-            [self audioTrackMixdownChanged: mixdownPopUp];            
-        }
-    
-    }
-    if( [fDstFormatPopUp indexOfSelectedItem] == 0 )
-    {
-        [self autoSetM4vExtension: sender];
-    }
-}
-
-- (IBAction) audioTrackMixdownChanged: (id) sender
-{
-    
-    int acodec;
-    /* setup pointers to all of the other audio track controls
-    * we will need later
-    */
-    NSPopUpButton * mixdownPopUp;
-    NSPopUpButton * sampleratePopUp;
-    NSPopUpButton * bitratePopUp;
-    NSPopUpButton * audiocodecPopUp;
-    NSPopUpButton * audiotrackPopUp;
-    NSSlider * drcSlider;
-    NSTextField * drcField;
-    if (sender == fAudTrack1MixPopUp)
-    {
-        audiotrackPopUp = fAudLang1PopUp;
-        audiocodecPopUp = fAudTrack1CodecPopUp;
-        mixdownPopUp = fAudTrack1MixPopUp;
-        sampleratePopUp = fAudTrack1RatePopUp;
-        bitratePopUp = fAudTrack1BitratePopUp;
-        drcSlider = fAudTrack1DrcSlider;
-        drcField = fAudTrack1DrcField;
-    }
-    else if (sender == fAudTrack2MixPopUp)
-    {
-        audiotrackPopUp = fAudLang2PopUp;
-        audiocodecPopUp = fAudTrack2CodecPopUp;
-        mixdownPopUp = fAudTrack2MixPopUp;
-        sampleratePopUp = fAudTrack2RatePopUp;
-        bitratePopUp = fAudTrack2BitratePopUp;
-        drcSlider = fAudTrack2DrcSlider;
-        drcField = fAudTrack2DrcField;
-    }
-    else if (sender == fAudTrack3MixPopUp)
-    {
-        audiotrackPopUp = fAudLang3PopUp;
-        audiocodecPopUp = fAudTrack3CodecPopUp;
-        mixdownPopUp = fAudTrack3MixPopUp;
-        sampleratePopUp = fAudTrack3RatePopUp;
-        bitratePopUp = fAudTrack3BitratePopUp;
-        drcSlider = fAudTrack3DrcSlider;
-        drcField = fAudTrack3DrcField;
-    }
-    else
-    {
-        audiotrackPopUp = fAudLang4PopUp;
-        audiocodecPopUp = fAudTrack4CodecPopUp;
-        mixdownPopUp = fAudTrack4MixPopUp;
-        sampleratePopUp = fAudTrack4RatePopUp;
-        bitratePopUp = fAudTrack4BitratePopUp;
-        drcSlider = fAudTrack4DrcSlider;
-        drcField = fAudTrack4DrcField;
-    }
-    acodec = [[audiocodecPopUp selectedItem] tag];
-    /* storage variable for the min and max bitrate allowed for this codec */
-    int minbitrate;
-    int maxbitrate;
-    
-    switch( acodec )
-    {
-        case HB_ACODEC_FAAC:
-            /* check if we have a 6ch discrete conversion in either audio track */
-            if ([[mixdownPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
-            {
-                /* FAAC has a minimum of 192 kbps for 6-channel discrete */
-                minbitrate = 192;
-                /* If either mixdown popup includes 6-channel discrete, then allow up to 448 kbps */
-                maxbitrate = 448;
-                break;
-            }
-            else
-            {
-                /* FAAC is happy using our min bitrate of 32 kbps for stereo or mono */
-                minbitrate = 32;
-                /* FAAC won't honour anything more than 160 for stereo, so let's not offer it */
-                /* note: haven't dealt with mono separately here, FAAC will just use the max it can */
-                maxbitrate = 160;
-                break;
-            }
-
-        case HB_ACODEC_CA_AAC:
-            /* check if we have a 6ch discrete conversion in either audio track */
-            if ([[mixdownPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
-            {
-                minbitrate = 128;
-                maxbitrate = 768;
-                break;
-            }
-            else
-            {
-                minbitrate = 64;
-                maxbitrate = 320;
-                break;
-            }
-
-            case HB_ACODEC_LAME:
-            /* Lame is happy using our min bitrate of 32 kbps */
-            minbitrate = 32;
-            /* Lame won't encode if the bitrate is higher than 320 kbps */
-            maxbitrate = 320;
-            break;
-            
-            case HB_ACODEC_VORBIS:
-            if ([[mixdownPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
-            {
-                /* Vorbis causes a crash if we use a bitrate below 192 kbps with 6 channel */
-                minbitrate = 192;
-                /* If either mixdown popup includes 6-channel discrete, then allow up to 384 kbps */
-                maxbitrate = 384;
-                break;
-            }
-            else
-            {
-                /* Vorbis causes a crash if we use a bitrate below 48 kbps */
-                minbitrate = 48;
-                /* Vorbis can cope with 384 kbps quite happily, even for stereo */
-                maxbitrate = 384;
-                break;
-            }
-            
-            default:
-            /* AC3 passthru disables the bitrate dropdown anyway, so we might as well just use the min and max bitrate */
-            minbitrate = 32;
-            maxbitrate = 384;
-            
-    }
-    
-    /* make sure we have a selected title before continuing */
-    if (fTitle == NULL) return;
-    /* get the audio so we can find out what input rates are*/
-    hb_audio_config_t * audio;
-    audio = (hb_audio_config_t *) hb_list_audio_config_item( fTitle->list_audio, [audiotrackPopUp indexOfSelectedItem] - 1 );
-    int inputbitrate = audio->in.bitrate / 1000;
-    int inputsamplerate = audio->in.samplerate;
-    
-    if ([[mixdownPopUp selectedItem] tag] != HB_ACODEC_AC3 && [[mixdownPopUp selectedItem] tag] != HB_ACODEC_DCA)
-    {
-        [bitratePopUp removeAllItems];
-        
-        for( int i = 0; i < hb_audio_bitrates_count; i++ )
-        {
-            if (hb_audio_bitrates[i].rate >= minbitrate && hb_audio_bitrates[i].rate <= maxbitrate)
-            {
-                /* add a new menuitem for this bitrate */
-                NSMenuItem *menuItem = [[bitratePopUp menu] addItemWithTitle:
-                                        [NSString stringWithUTF8String: hb_audio_bitrates[i].string]
-                                                                      action: NULL keyEquivalent: @""];
-                /* set its tag to be the actual bitrate as an integer, so we can retrieve it later */
-                [menuItem setTag: hb_audio_bitrates[i].rate];
-            }
-        }
-        
-        /* select the default bitrate (but use 384 for 6-ch AAC) */
-        if ([[mixdownPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
-        {
-            [bitratePopUp selectItemWithTag: 384];
-        }
-        else
-        {
-            [bitratePopUp selectItemWithTag: hb_audio_bitrates[hb_audio_bitrates_default].rate];
-        }
-    }
-    /* populate and set the sample rate popup */
-    /* Audio samplerate */
-    [sampleratePopUp removeAllItems];
-    /* we create a same as source selection (Auto) so that we can choose to use the input sample rate */
-    NSMenuItem *menuItem = [[sampleratePopUp menu] addItemWithTitle: @"Auto" action: NULL keyEquivalent: @""];
-    [menuItem setTag: inputsamplerate];
-    
-    for( int i = 0; i < hb_audio_rates_count; i++ )
-    {
-        NSMenuItem *menuItem = [[sampleratePopUp menu] addItemWithTitle:
-                                [NSString stringWithUTF8String: hb_audio_rates[i].string]
-                                                                 action: NULL keyEquivalent: @""];
-        [menuItem setTag: hb_audio_rates[i].rate];
-    }
-    /* We use the input sample rate as the default sample rate as downsampling just makes audio worse
-    * and there is no compelling reason to use anything else as default, though the users default
-    * preset will likely override any setting chosen here.
-    */
-    [sampleratePopUp selectItemWithTag: inputsamplerate];
-    
-    
-    /* Since AC3 Pass Thru and DTS Pass Thru uses the input bitrate and sample rate, we get the input tracks
-    * bitrate and display it in the bitrate popup even though libhb happily ignores any bitrate input from
-    * the gui. We do this for better user feedback in the audio tab as well as the queue for the most part
-    */
-    if ([[mixdownPopUp selectedItem] tag] == HB_ACODEC_AC3 || [[mixdownPopUp selectedItem] tag] == HB_ACODEC_DCA)
-    {
-        
-        /* lets also set the bitrate popup to the input bitrate as thats what passthru will use */
-        [bitratePopUp removeAllItems];
-        NSMenuItem *menuItem = [[bitratePopUp menu] addItemWithTitle:
-                                [NSString stringWithFormat:@"%d", inputbitrate]
-                                                              action: NULL keyEquivalent: @""];
-        [menuItem setTag: inputbitrate];
-        /* For ac3 passthru we disable the sample rate and bitrate popups as well as the drc slider*/
-        [bitratePopUp setEnabled: NO];
-        [sampleratePopUp setEnabled: NO];
-        
-        [drcSlider setFloatValue: 0.00];
-        [self audioDRCSliderChanged: drcSlider];
-        [drcSlider setEnabled: NO];
-        [drcField setEnabled: NO];
-    }
-    else
-    {
-        [sampleratePopUp setEnabled: YES];
-        [bitratePopUp setEnabled: YES];
-        [drcSlider setEnabled: YES];
-        [drcField setEnabled: YES];
-    }
-[self calculateBitrate:nil];    
-}
-
-- (IBAction) audioDRCSliderChanged: (id) sender
-{
-    NSSlider * drcSlider;
-    NSTextField * drcField;
-    if (sender == fAudTrack1DrcSlider)
-    {
-        drcSlider = fAudTrack1DrcSlider;
-        drcField = fAudTrack1DrcField;
-    }
-    else if (sender == fAudTrack2DrcSlider)
-    {
-        drcSlider = fAudTrack2DrcSlider;
-        drcField = fAudTrack2DrcField;
-    }
-    else if (sender == fAudTrack3DrcSlider)
-    {
-        drcSlider = fAudTrack3DrcSlider;
-        drcField = fAudTrack3DrcField;
-    }
-    else
-    {
-        drcSlider = fAudTrack4DrcSlider;
-        drcField = fAudTrack4DrcField;
-    }
-    
-    /* If we are between 0.0 and 1.0 on the slider, snap it to 1.0 */
-    if ([drcSlider floatValue] > 0.0 && [drcSlider floatValue] < 1.0)
-    {
-        [drcSlider setFloatValue:1.0];
-    }
-    
-    
-    [drcField setStringValue: [NSString stringWithFormat: @"%.2f", [drcSlider floatValue]]];
-    /* For now, do not call this until we have an intelligent way to determine audio track selections
-    * compared to presets
-    */
-    //[self customSettingUsed: sender];
-}
-
-#pragma mark -
-
-- (IBAction) browseImportSrtFile: (id) sender
-{
-
-    NSOpenPanel * panel;
-       
-    panel = [NSOpenPanel openPanel];
-    [panel setAllowsMultipleSelection: NO];
-    [panel setCanChooseFiles: YES];
-    [panel setCanChooseDirectories: NO ];
-    NSString * sourceDirectory;
-       if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastSrtImportDirectory"])
+    NSOpenPanel * panel;
+       
+    panel = [NSOpenPanel openPanel];
+    [panel setAllowsMultipleSelection: NO];
+    [panel setCanChooseFiles: YES];
+    [panel setCanChooseDirectories: NO ];
+    NSString * sourceDirectory;
+       if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastSrtImportDirectory"])
        {
                sourceDirectory = [[NSUserDefaults standardUserDefaults] stringForKey:@"LastSrtImportDirectory"];
        }
@@ -6270,12 +5024,12 @@ the user is using "Custom" settings by determining the sender*/
 - (IBAction) openForums: (id) sender
 {
     [[NSWorkspace sharedWorkspace] openURL: [NSURL
-        URLWithString:@"http://handbrake.fr/forum/"]];
+        URLWithString:@"http://forum.handbrake.fr/"]];
 }
 - (IBAction) openUserGuide: (id) sender
 {
     [[NSWorkspace sharedWorkspace] openURL: [NSURL
-        URLWithString:@"http://handbrake.fr/trac/wiki/HandBrakeGuide"]];
+        URLWithString:@"http://trac.handbrake.fr/wiki/HandBrakeGuide"]];
 }
 
 /**
@@ -6677,6 +5431,7 @@ return YES;
     
     if ([fPresetsOutlineView selectedRow] >= 0 && [[[fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]] objectForKey:@"Folder"] intValue] != 1)
     {
+               [self setHasValidPresetSelected: YES];
         chosenPreset = [fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]];
         [fPresetSelectedDisplay setStringValue:[chosenPreset objectForKey:@"PresetName"]];
         
@@ -6759,7 +5514,9 @@ return YES;
         {
             [fVidRatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"VideoFramerate"]];
         }
-        
+        /* Set PFR */
+        [fFrameratePfrCheck setState:[[chosenPreset objectForKey:@"VideoFrameratePFR"] intValue]];
+        [self videoFrameRateChanged:nil];
         
         /* 2 Pass Encoding */
         [fVidTwoPassCheck setState:[[chosenPreset objectForKey:@"VideoTwoPass"] intValue]];
@@ -6769,301 +5526,7 @@ return YES;
         [fVidTurboPassCheck setState:[[chosenPreset objectForKey:@"VideoTurboTwoPass"] intValue]];
         
         /*Audio*/
-        /* First we check to see if we are using the current audio track layout based on AudioList array */
-        if ([chosenPreset objectForKey:@"AudioList"])
-        {
-            
-            /* pointer to this track's mixdown, codec, sample rate and bitrate NSPopUpButton's */
-            NSPopUpButton * trackLangPopUp = nil;
-            NSPopUpButton * mixdownPopUp = nil;
-            NSPopUpButton * audiocodecPopUp = nil;
-            NSPopUpButton * sampleratePopUp = nil;
-            NSPopUpButton * bitratePopUp = nil;
-            NSSlider      * drcSlider = nil;
-            
-            
-            /* Populate the audio widgets based on the contents of the AudioList array */
-            int i = 0;
-            NSEnumerator *enumerator = [[chosenPreset objectForKey:@"AudioList"] objectEnumerator];
-            id tempObject;
-            while (tempObject = [enumerator nextObject])
-            {
-                i++;
-                if( i == 1 )
-                {
-                    trackLangPopUp = fAudLang1PopUp;
-                    mixdownPopUp = fAudTrack1MixPopUp;
-                    audiocodecPopUp = fAudTrack1CodecPopUp;
-                    sampleratePopUp = fAudTrack1RatePopUp;
-                    bitratePopUp = fAudTrack1BitratePopUp;
-                    drcSlider = fAudTrack1DrcSlider;
-                }
-                if( i == 2 )
-                {
-                    trackLangPopUp = fAudLang2PopUp;
-                    mixdownPopUp = fAudTrack2MixPopUp;
-                    audiocodecPopUp = fAudTrack2CodecPopUp;
-                    sampleratePopUp = fAudTrack2RatePopUp;
-                    bitratePopUp = fAudTrack2BitratePopUp;
-                    drcSlider = fAudTrack2DrcSlider;
-                }
-                if( i == 3 )
-                {
-                    trackLangPopUp = fAudLang3PopUp;
-                    mixdownPopUp = fAudTrack3MixPopUp;
-                    audiocodecPopUp = fAudTrack3CodecPopUp;
-                    sampleratePopUp = fAudTrack3RatePopUp;
-                    bitratePopUp = fAudTrack3BitratePopUp;
-                    drcSlider = fAudTrack3DrcSlider;
-                }
-                if( i == 4 )
-                {
-                    trackLangPopUp = fAudLang4PopUp;
-                    mixdownPopUp = fAudTrack4MixPopUp;
-                    audiocodecPopUp = fAudTrack4CodecPopUp;
-                    sampleratePopUp = fAudTrack4RatePopUp;
-                    bitratePopUp = fAudTrack4BitratePopUp;
-                    drcSlider = fAudTrack4DrcSlider;
-                }
-                
-                
-                if ([trackLangPopUp indexOfSelectedItem] == 0)
-                {
-                    [trackLangPopUp selectItemAtIndex: 1];
-                }
-                [self audioTrackPopUpChanged: trackLangPopUp];
-                [audiocodecPopUp selectItemWithTitle:[tempObject objectForKey:@"AudioEncoder"]];
-                /* check our pref for core audio and use it in place of faac if applicable */
-                if ([[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] == YES && 
-                    [[tempObject objectForKey:@"AudioEncoder"] isEqualToString: @"AAC (faac)"])
-                {
-                    [audiocodecPopUp selectItemWithTitle:@"AAC (CoreAudio)"];
-                }                    
-                
-                [self audioTrackPopUpChanged: audiocodecPopUp];
-                [mixdownPopUp selectItemWithTitle:[tempObject objectForKey:@"AudioMixdown"]];
-                [self audioTrackMixdownChanged: mixdownPopUp];
-                /* check to see if the selection was available, if not, rerun audioTrackPopUpChanged using the codec to just set the default
-                 * mixdown*/
-                if  ([mixdownPopUp selectedItem] == nil)
-                {
-                    [self audioTrackPopUpChanged: audiocodecPopUp];
-                    [self writeToActivityLog: "presetSelected mixdown not selected, rerun audioTrackPopUpChanged"];
-                }
-                [sampleratePopUp selectItemWithTitle:[tempObject objectForKey:@"AudioSamplerate"]];
-                /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */
-                if (![[tempObject objectForKey:@"AudioEncoder"] isEqualToString:@"AC3 Passthru"])
-                {
-                    [bitratePopUp selectItemWithTitle:[tempObject objectForKey:@"AudioBitrate"]];
-                    /* check to see if the bitrate selection was available, if not, rerun audioTrackMixdownChanged using the mixdown to just set the
-                     *default mixdown bitrate*/
-                    if ([bitratePopUp selectedItem] == nil)
-                    {
-                        [self audioTrackMixdownChanged: mixdownPopUp];
-                    }
-                }
-                [drcSlider setFloatValue:[[tempObject objectForKey:@"AudioTrackDRCSlider"] floatValue]];
-                [self audioDRCSliderChanged: drcSlider];
-                
-                
-                /* If we are any track greater than 1 check to make sure we have a matching source codec is using ac3 passthru or dts passthru,
-                 * if not we will set the track to "None". Track 1 is allowed to mixdown to a suitable DPL2 mix if we cannot passthru */
-                
-                if( i > 1 )
-                {
-                    /* Check to see if the preset asks for a passhthru track (AC3 or DTS) and verify there is a matching source track if not, set the track to "None". */
-                    if (([[tempObject objectForKey:@"AudioEncoder"] isEqualToString:@"AC3 Passthru"] || [[tempObject objectForKey:@"AudioEncoder"] isEqualToString:@"DTS Passthru"])  && [trackLangPopUp indexOfSelectedItem] != 0)
-                    {
-                        hb_audio_config_t * audio;
-                        /* get the audio source audio codec */
-                        audio = (hb_audio_config_t *) hb_list_audio_config_item( fTitle->list_audio, [trackLangPopUp indexOfSelectedItem] - 1 );
-                        if (audio != NULL && [[tempObject objectForKey:@"AudioEncoder"] isEqualToString:@"AC3 Passthru"] && audio->in.codec != HB_ACODEC_AC3 ||
-                            [[tempObject objectForKey:@"AudioEncoder"] isEqualToString:@"DTS Passthru"] && audio->in.codec != HB_ACODEC_DCA )
-                        {
-                            /* We have a preset using ac3 passthru but no ac3 source audio, so set the track to "None" and bail */
-                            if ([[tempObject objectForKey:@"AudioEncoder"] isEqualToString:@"AC3 Passthru"])
-                            {
-                                [self writeToActivityLog: "Preset calls for AC3 Pass thru ..."];
-                            }
-                            if ([[tempObject objectForKey:@"AudioEncoder"] isEqualToString:@"DTS Passthru"])
-                            {
-                                [self writeToActivityLog: "Preset calls for DTS Pass thru ..."];
-                            }
-                            [self writeToActivityLog: "No matching source codec, setting track  %d to None", i];
-                            [trackLangPopUp selectItemAtIndex: 0];
-                            [self audioTrackPopUpChanged: trackLangPopUp]; 
-                        }   
-                    }
-                }
-            }
-            
-            /* We now cleanup any extra audio tracks that may have been previously set if we need to */
-            
-            if (i < 4)
-            {
-                [fAudLang4PopUp selectItemAtIndex: 0];
-                [self audioTrackPopUpChanged: fAudLang4PopUp];
-                
-                if (i < 3)
-                {
-                    [fAudLang3PopUp selectItemAtIndex: 0];
-                    [self audioTrackPopUpChanged: fAudLang3PopUp];
-                    
-                    if (i < 2)
-                    {
-                        [fAudLang2PopUp selectItemAtIndex: 0];
-                        [self audioTrackPopUpChanged: fAudLang2PopUp];
-                    }
-                }
-            }
-            
-        }
-        else
-        {
-            if ([chosenPreset objectForKey:@"Audio1Track"] > 0)
-            {
-                if ([fAudLang1PopUp indexOfSelectedItem] == 0)
-                {
-                    [fAudLang1PopUp selectItemAtIndex: 1];
-                }
-                [self audioTrackPopUpChanged: fAudLang1PopUp];
-                [fAudTrack1CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio1Encoder"]];
-                /* check our pref for core audio and use it in place of faac if applicable */
-                if ([[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] == YES && 
-                    [[chosenPreset objectForKey:@"Audio1Encoder"] isEqualToString: @"AAC (faac)"])
-                {
-                    [fAudTrack1CodecPopUp selectItemWithTitle:@"AAC (CoreAudio)"];
-                }
-                [self audioTrackPopUpChanged: fAudTrack1CodecPopUp];
-                [fAudTrack1MixPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio1Mixdown"]];
-                /* check to see if the selections was available, if not, rerun audioTrackPopUpChanged using the codec to just set the default
-                 * mixdown*/
-                if  ([fAudTrack1MixPopUp selectedItem] == nil)
-                {
-                    [self audioTrackPopUpChanged: fAudTrack1CodecPopUp];
-                }
-                [fAudTrack1RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio1Samplerate"]];
-                /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */
-                if (![[chosenPreset objectForKey:@"Audio1Encoder"] isEqualToString:@"AC3 Passthru"])
-                {
-                    [fAudTrack1BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio1Bitrate"]];
-                }
-                [fAudTrack1DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio1TrackDRCSlider"] floatValue]];
-                [self audioDRCSliderChanged: fAudTrack1DrcSlider];
-            }
-            
-            if ([chosenPreset objectForKey:@"Audio2Track"] > 0)
-            {
-                if ([fAudLang2PopUp indexOfSelectedItem] == 0)
-                {
-                    [fAudLang2PopUp selectItemAtIndex: 1];
-                }
-                [self audioTrackPopUpChanged: fAudLang2PopUp];
-                [fAudTrack2CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio2Encoder"]];
-                /* check our pref for core audio and use it in place of faac if applicable */
-                if ([[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] == YES && 
-                    [[chosenPreset objectForKey:@"Audio2Encoder"] isEqualToString: @"AAC (faac)"])
-                {
-                    [fAudTrack2CodecPopUp selectItemWithTitle:@"AAC (CoreAudio)"];
-                }
-                [self audioTrackPopUpChanged: fAudTrack2CodecPopUp];
-                [fAudTrack2MixPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio2Mixdown"]];
-                /* check to see if the selections was available, if not, rerun audioTrackPopUpChanged using the codec to just set the default
-                 * mixdown*/
-                if  ([fAudTrack2MixPopUp selectedItem] == nil)
-                {
-                    [self audioTrackPopUpChanged: fAudTrack2CodecPopUp];
-                }
-                [fAudTrack2RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio2Samplerate"]];
-                /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */
-                if (![[chosenPreset objectForKey:@"Audio2Encoder"] isEqualToString:@"AC3 Passthru"])
-                {
-                    [fAudTrack2BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio2Bitrate"]];
-                }
-                [fAudTrack2DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio2TrackDRCSlider"] floatValue]];
-                [self audioDRCSliderChanged: fAudTrack2DrcSlider];
-            }
-            if ([chosenPreset objectForKey:@"Audio3Track"] > 0)
-            {
-                if ([fAudLang3PopUp indexOfSelectedItem] == 0)
-                {
-                    [fAudLang3PopUp selectItemAtIndex: 1];
-                }
-                [self audioTrackPopUpChanged: fAudLang3PopUp];
-                [fAudTrack3CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio3Encoder"]];
-                /* check our pref for core audio and use it in place of faac if applicable */
-                if ([[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] == YES && 
-                    [[chosenPreset objectForKey:@"Audio3Encoder"] isEqualToString: @"AAC (faac)"])
-                {
-                    [fAudTrack3CodecPopUp selectItemWithTitle:@"AAC (CoreAudio)"];
-                }
-                [self audioTrackPopUpChanged: fAudTrack3CodecPopUp];
-                [fAudTrack3MixPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio3Mixdown"]];
-                /* check to see if the selections was available, if not, rerun audioTrackPopUpChanged using the codec to just set the default
-                 * mixdown*/
-                if  ([fAudTrack3MixPopUp selectedItem] == nil)
-                {
-                    [self audioTrackPopUpChanged: fAudTrack3CodecPopUp];
-                }
-                [fAudTrack3RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio3Samplerate"]];
-                /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */
-                if (![[chosenPreset objectForKey:@"Audio3Encoder"] isEqualToString: @"AC3 Passthru"])
-                {
-                    [fAudTrack3BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio3Bitrate"]];
-                }
-                [fAudTrack3DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio3TrackDRCSlider"] floatValue]];
-                [self audioDRCSliderChanged: fAudTrack3DrcSlider];
-            }
-            if ([chosenPreset objectForKey:@"Audio4Track"] > 0)
-            {
-                if ([fAudLang4PopUp indexOfSelectedItem] == 0)
-                {
-                    [fAudLang4PopUp selectItemAtIndex: 1];
-                }
-                [self audioTrackPopUpChanged: fAudLang4PopUp];
-                [fAudTrack4CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio4Encoder"]];
-                /* check our pref for core audio and use it in place of faac if applicable */
-                if ([[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] == YES && 
-                    [[chosenPreset objectForKey:@"Audio4Encoder"] isEqualToString: @"AAC (faac)"])
-                {
-                    [fAudTrack4CodecPopUp selectItemWithTitle:@"AAC (CoreAudio)"];
-                }
-                [self audioTrackPopUpChanged: fAudTrack4CodecPopUp];
-                [fAudTrack4MixPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio4Mixdown"]];
-                /* check to see if the selections was available, if not, rerun audioTrackPopUpChanged using the codec to just set the default
-                 * mixdown*/
-                if  ([fAudTrack4MixPopUp selectedItem] == nil)
-                {
-                    [self audioTrackPopUpChanged: fAudTrack4CodecPopUp];
-                }
-                [fAudTrack4RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio4Samplerate"]];
-                /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */
-                if (![[chosenPreset objectForKey:@"Audio4Encoder"] isEqualToString:@"AC3 Passthru"])
-                {
-                    [fAudTrack4BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio4Bitrate"]];
-                }
-                [fAudTrack4DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio4TrackDRCSlider"] floatValue]];
-                [self audioDRCSliderChanged: fAudTrack4DrcSlider];
-            }
-            
-            /* We now cleanup any extra audio tracks that may have been previously set if we need to */
-            
-            if (![chosenPreset objectForKey:@"Audio2Track"] || [chosenPreset objectForKey:@"Audio2Track"] == 0)
-            {
-                [fAudLang2PopUp selectItemAtIndex: 0];
-                [self audioTrackPopUpChanged: fAudLang2PopUp];
-            }
-            if (![chosenPreset objectForKey:@"Audio3Track"] || [chosenPreset objectForKey:@"Audio3Track"] > 0)
-            {
-                [fAudLang3PopUp selectItemAtIndex: 0];
-                [self audioTrackPopUpChanged: fAudLang3PopUp];
-            }
-            if (![chosenPreset objectForKey:@"Audio4Track"] || [chosenPreset objectForKey:@"Audio4Track"] > 0)
-            {
-                [fAudLang4PopUp selectItemAtIndex: 0];
-                [self audioTrackPopUpChanged: fAudLang4PopUp];
-            }
-        }
+               [fAudioDelegate addTracksFromPreset: chosenPreset];
         
         /*Subtitles*/
         [fSubPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Subtitles"]];
@@ -7153,14 +5616,36 @@ return YES;
                 job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"]  intValue];
                 if (job->keep_ratio == 1)
                 {
+                    int height = fTitle->height;
+
+                    if ( job->height && job->height < fTitle->height )
+                        height = job->height;
+
                     hb_fix_aspect( job, HB_KEEP_WIDTH );
-                    if( job->height > fTitle->height )
+                    // Make sure the resulting height is less than
+                    // the title height and less than the height
+                    // requested in the preset.
+                    if( job->height > height )
                     {
-                        job->height = fTitle->height;
+                        job->height = height;
                         hb_fix_aspect( job, HB_KEEP_HEIGHT );
                     }
                 }
                 job->anamorphic.mode = [[chosenPreset objectForKey:@"PicturePAR"]  intValue];
+                if ( job->anamorphic.mode > 0 )
+                {
+                    int w, h, par_w, par_h;
+
+                    job->anamorphic.par_width = fTitle->pixel_aspect_width;
+                    job->anamorphic.par_height = fTitle->pixel_aspect_height;
+                    job->maxWidth = job->width;
+                    job->maxHeight = job->height;
+                    hb_set_anamorphic_size( job, &w, &h, &par_w, &par_h );
+                    job->maxWidth = 0;
+                    job->maxHeight = 0;
+                    job->width = w;
+                    job->height = h;
+                }
                 
             }
             
@@ -7267,6 +5752,9 @@ return YES;
         [fPictureController SetTitle:fTitle];
         [self calculatePictureSizing:nil];
     }
+       else {
+               [self setHasValidPresetSelected: NO];
+       }
 }
 
 
@@ -7335,6 +5823,18 @@ return YES;
 }
 
 
+- (IBAction) addPresetPicDropdownChanged: (id) sender
+{
+    if ([fPresetNewPicSettingsPopUp indexOfSelectedItem] == 1)
+    {
+        [fPresetNewPicWidthHeightBox setHidden:NO];  
+    }
+    else
+    {
+        [fPresetNewPicWidthHeightBox setHidden:YES];
+    }
+}
+
 - (IBAction) showAddPresetPanel: (id) sender
 {
     /* Deselect the currently selected Preset if there is one*/
@@ -7343,7 +5843,7 @@ return YES;
     /* Populate the preset picture settings popup here */
     [fPresetNewPicSettingsPopUp removeAllItems];
     [fPresetNewPicSettingsPopUp addItemWithTitle:@"None"];
-    [fPresetNewPicSettingsPopUp addItemWithTitle:@"Current"];
+    [fPresetNewPicSettingsPopUp addItemWithTitle:@"Custom"];
     [fPresetNewPicSettingsPopUp addItemWithTitle:@"Source Maximum (post source scan)"];
     [fPresetNewPicSettingsPopUp selectItemAtIndex: 0]; 
     /* Uncheck the preset use filters checkbox */
@@ -7353,6 +5853,12 @@ return YES;
     /* Erase info from the input fields*/
        [fPresetNewName setStringValue: @""];
        [fPresetNewDesc setStringValue: @""];
+    
+    /* Initialize custom height and width settings to current values */
+    
+       [fPresetNewPicWidth setStringValue: [NSString stringWithFormat:@"%d",fTitle->job->width]];
+       [fPresetNewPicHeight setStringValue: [NSString stringWithFormat:@"%d",fTitle->job->height]];
+    [self addPresetPicDropdownChanged:nil];
        /* Show the panel */
        [NSApp beginSheet:fAddPresetPanel modalForWindow:fWindow modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
 }
@@ -7477,6 +5983,7 @@ return YES;
         {
             [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
         }
+        [preset setObject:[NSNumber numberWithInt:[fFrameratePfrCheck state]] forKey:@"VideoFrameratePFR"];
         
         /* 2 Pass Encoding */
         [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
@@ -7484,11 +5991,11 @@ return YES;
         [preset setObject:[NSNumber numberWithInt:[fVidTurboPassCheck state]] forKey:@"VideoTurboTwoPass"];
         /*Picture Settings*/
         hb_job_t * job = fTitle->job;
+        
         /* Picture Sizing */
-        /* Use Max Picture settings for whatever the dvd is.*/
         [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
-        [preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
-        [preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
+        [preset setObject:[NSNumber numberWithInt:[fPresetNewPicWidth intValue]] forKey:@"PictureWidth"];
+        [preset setObject:[NSNumber numberWithInt:[fPresetNewPicHeight intValue]] forKey:@"PictureHeight"];
         [preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
         [preset setObject:[NSNumber numberWithInt:fTitle->job->anamorphic.mode] forKey:@"PicturePAR"];
         [preset setObject:[NSNumber numberWithInt:fTitle->job->modulus] forKey:@"PictureModulus"];
@@ -7515,62 +6022,7 @@ return YES;
         
         /*Audio*/
         NSMutableArray *audioListArray = [[NSMutableArray alloc] init];
-        /* we actually call the methods for the nests here */
-        if ([fAudLang1PopUp indexOfSelectedItem] > 0)
-        {
-            NSMutableDictionary *audioTrack1Array = [[NSMutableDictionary alloc] init];
-            [audioTrack1Array setObject:[NSNumber numberWithInt:[fAudLang1PopUp indexOfSelectedItem]] forKey:@"AudioTrack"];
-            [audioTrack1Array setObject:[fAudLang1PopUp titleOfSelectedItem] forKey:@"AudioTrackDescription"];
-            [audioTrack1Array setObject:[fAudTrack1CodecPopUp titleOfSelectedItem] forKey:@"AudioEncoder"];
-            [audioTrack1Array setObject:[fAudTrack1MixPopUp titleOfSelectedItem] forKey:@"AudioMixdown"];
-            [audioTrack1Array setObject:[fAudTrack1RatePopUp titleOfSelectedItem] forKey:@"AudioSamplerate"];
-            [audioTrack1Array setObject:[fAudTrack1BitratePopUp titleOfSelectedItem] forKey:@"AudioBitrate"];
-            [audioTrack1Array setObject:[NSNumber numberWithFloat:[fAudTrack1DrcSlider floatValue]] forKey:@"AudioTrackDRCSlider"];
-            [audioTrack1Array autorelease];
-            [audioListArray addObject:audioTrack1Array];
-        }
-        
-        if ([fAudLang2PopUp indexOfSelectedItem] > 0)
-        {
-            NSMutableDictionary *audioTrack2Array = [[NSMutableDictionary alloc] init];
-            [audioTrack2Array setObject:[NSNumber numberWithInt:[fAudLang2PopUp indexOfSelectedItem]] forKey:@"AudioTrack"];
-            [audioTrack2Array setObject:[fAudLang2PopUp titleOfSelectedItem] forKey:@"AudioTrackDescription"];
-            [audioTrack2Array setObject:[fAudTrack2CodecPopUp titleOfSelectedItem] forKey:@"AudioEncoder"];
-            [audioTrack2Array setObject:[fAudTrack2MixPopUp titleOfSelectedItem] forKey:@"AudioMixdown"];
-            [audioTrack2Array setObject:[fAudTrack2RatePopUp titleOfSelectedItem] forKey:@"AudioSamplerate"];
-            [audioTrack2Array setObject:[fAudTrack2BitratePopUp titleOfSelectedItem] forKey:@"AudioBitrate"];
-            [audioTrack2Array setObject:[NSNumber numberWithFloat:[fAudTrack2DrcSlider floatValue]] forKey:@"AudioTrackDRCSlider"];
-            [audioTrack2Array autorelease];
-            [audioListArray addObject:audioTrack2Array];
-        }
-        
-        if ([fAudLang3PopUp indexOfSelectedItem] > 0)
-        {
-            NSMutableDictionary *audioTrack3Array = [[NSMutableDictionary alloc] init];
-            [audioTrack3Array setObject:[NSNumber numberWithInt:[fAudLang3PopUp indexOfSelectedItem]] forKey:@"AudioTrack"];
-            [audioTrack3Array setObject:[fAudLang3PopUp titleOfSelectedItem] forKey:@"AudioTrackDescription"];
-            [audioTrack3Array setObject:[fAudTrack3CodecPopUp titleOfSelectedItem] forKey:@"AudioEncoder"];
-            [audioTrack3Array setObject:[fAudTrack3MixPopUp titleOfSelectedItem] forKey:@"AudioMixdown"];
-            [audioTrack3Array setObject:[fAudTrack3RatePopUp titleOfSelectedItem] forKey:@"AudioSamplerate"];
-            [audioTrack3Array setObject:[fAudTrack3BitratePopUp titleOfSelectedItem] forKey:@"AudioBitrate"];
-            [audioTrack3Array setObject:[NSNumber numberWithFloat:[fAudTrack3DrcSlider floatValue]] forKey:@"AudioTrackDRCSlider"];
-            [audioTrack3Array autorelease];
-            [audioListArray addObject:audioTrack3Array];
-        }
-        
-        if ([fAudLang4PopUp indexOfSelectedItem] > 0)
-        {
-            NSMutableDictionary *audioTrack4Array = [[NSMutableDictionary alloc] init];
-            [audioTrack4Array setObject:[NSNumber numberWithInt:[fAudLang4PopUp indexOfSelectedItem]] forKey:@"AudioTrack"];
-            [audioTrack4Array setObject:[fAudLang4PopUp titleOfSelectedItem] forKey:@"AudioTrackDescription"];
-            [audioTrack4Array setObject:[fAudTrack4CodecPopUp titleOfSelectedItem] forKey:@"AudioEncoder"];
-            [audioTrack4Array setObject:[fAudTrack4MixPopUp titleOfSelectedItem] forKey:@"AudioMixdown"];
-            [audioTrack4Array setObject:[fAudTrack4RatePopUp titleOfSelectedItem] forKey:@"AudioSamplerate"];
-            [audioTrack4Array setObject:[fAudTrack4BitratePopUp titleOfSelectedItem] forKey:@"AudioBitrate"];
-            [audioTrack4Array setObject:[NSNumber numberWithFloat:[fAudTrack4DrcSlider floatValue]] forKey:@"AudioTrackDRCSlider"];
-            [audioTrack4Array autorelease];
-            [audioListArray addObject:audioTrack4Array];
-        }
+               [fAudioDelegate prepareAudioForPreset: audioListArray];
         
         
         [preset setObject:[NSMutableArray arrayWithArray: audioListArray] forKey:@"AudioList"];
@@ -8049,6 +6501,154 @@ return YES;
     
 }
 
+#pragma mark -
+#pragma mark Chapter Files Import / Export
+
+- (IBAction) browseForChapterFile: (id) sender
+{
+       /* Open a panel to let the user choose the file */
+       NSOpenPanel * panel = [NSOpenPanel openPanel];
+       /* We get the current file name and path from the destination field here */
+       [panel beginSheetForDirectory: [NSString stringWithFormat:@"%@/",
+                                    [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"]]
+                             file: NULL
+                            types: [NSArray arrayWithObjects:@"csv",nil]
+                   modalForWindow: fWindow modalDelegate: self
+                   didEndSelector: @selector( browseForChapterFileDone:returnCode:contextInfo: )
+                      contextInfo: NULL];
+}
+
+- (void) browseForChapterFileDone: (NSOpenPanel *) sheet
+    returnCode: (int) returnCode contextInfo: (void *) contextInfo
+{
+    NSArray *chaptersArray; /* temp array for chapters */
+       NSMutableArray *chaptersMutableArray; /* temp array for chapters */
+    NSString *chapterName;     /* temp string from file */
+    int chapters, i;
+    
+    if( returnCode == NSOKButton )  /* if they click OK */
+    {  
+        chapterName = [[NSString alloc] initWithContentsOfFile:[sheet filename] encoding:NSUTF8StringEncoding error:NULL];
+        chaptersArray = [chapterName componentsSeparatedByString:@"\n"];
+        chaptersMutableArray= [chaptersArray mutableCopy];
+               chapters = [fChapterTitlesDelegate numberOfRowsInTableView:fChapterTable];
+        if ([chaptersMutableArray count] > 0)
+        { 
+        /* if last item is empty remove it */
+            if ([[chaptersMutableArray objectAtIndex:[chaptersArray count]-1] length] == 0)
+            {
+                [chaptersMutableArray removeLastObject];
+            }
+        }
+        /* if chapters in table is not equal to array count */
+        if ((unsigned int) chapters != [chaptersMutableArray count])
+        {
+            [sheet close];
+            [[NSAlert alertWithMessageText:NSLocalizedString(@"Unable to load chapter file", @"Unable to load chapter file")
+                             defaultButton:NSLocalizedString(@"OK", @"OK")
+                           alternateButton:NULL 
+                               otherButton:NULL
+                 informativeTextWithFormat:NSLocalizedString(@"%d chapters expected, %d chapters found in %@", @"%d chapters expected, %d chapters found in %@"), 
+              chapters, [chaptersMutableArray count], [[sheet filename] lastPathComponent]] runModal];
+            return;
+        }
+               /* otherwise, go ahead and populate table with array */
+               for (i=0; i<chapters; i++)
+        {
+         
+            if([[chaptersMutableArray objectAtIndex:i] length] > 5)
+            { 
+                /* avoid a segfault */
+                /* Get the Range.location of the first comma in the line and then put everything after that into chapterTitle */
+                NSRange firstCommaRange = [[chaptersMutableArray objectAtIndex:i] rangeOfString:@","];
+                NSString *chapterTitle = [[chaptersMutableArray objectAtIndex:i] substringFromIndex:firstCommaRange.location + 1];
+                /* Since we store our chapterTitle commas as "\," for the cli, we now need to remove the escaping "\" from the title */
+                chapterTitle = [chapterTitle stringByReplacingOccurrencesOfString:@"\\," withString:@","];
+                [fChapterTitlesDelegate tableView:fChapterTable 
+                                   setObjectValue:chapterTitle
+                                   forTableColumn:fChapterTableNameColumn
+                                              row:i];
+            }
+            else 
+            {
+                [sheet close];
+                [[NSAlert alertWithMessageText:NSLocalizedString(@"Unable to load chapter file", @"Unable to load chapter file")
+                                 defaultButton:NSLocalizedString(@"OK", @"OK")
+                               alternateButton:NULL 
+                                   otherButton:NULL
+                     informativeTextWithFormat:NSLocalizedString(@"%@ was not formatted as expected.", @"%@ was not formatted as expected."), [[sheet filename] lastPathComponent]] runModal];   
+                [fChapterTable reloadData];
+                return;
+            }
+        }
+        [fChapterTable reloadData];
+    }
+}
+
+- (IBAction) browseForChapterFileSave: (id) sender
+{
+    NSSavePanel *panel = [NSSavePanel savePanel];
+    /* Open a panel to let the user save to a file */
+    [panel setAllowedFileTypes:[NSArray arrayWithObjects:@"csv",nil]];
+    [panel beginSheetForDirectory: [[fDstFile2Field stringValue] stringByDeletingLastPathComponent] 
+                             file: [[[[fDstFile2Field stringValue] lastPathComponent] stringByDeletingPathExtension] 
+                                     stringByAppendingString:@"-chapters.csv"]
+                   modalForWindow: fWindow 
+                    modalDelegate: self
+                   didEndSelector: @selector( browseForChapterFileSaveDone:returnCode:contextInfo: )
+                      contextInfo: NULL];
+}
+
+- (void) browseForChapterFileSaveDone: (NSSavePanel *) sheet
+    returnCode: (int) returnCode contextInfo: (void *) contextInfo
+{
+    NSString *chapterName;      /* pointer for string for later file-writing */
+    NSString *chapterTitle;
+    NSError *saveError = [[NSError alloc] init];
+    int chapters, i;    /* ints for the number of chapters in the table and the loop */
+    
+    if( returnCode == NSOKButton )   /* if they clicked OK */
+    {  
+        chapters = [fChapterTitlesDelegate numberOfRowsInTableView:fChapterTable];
+        chapterName = [NSString string];
+        for (i=0; i<chapters; i++)
+        {
+            /* put each chapter title from the table into the array */
+            if (i<9)
+            { /* if i is from 0 to 8 (chapters 1 to 9) add two leading zeros */
+                chapterName = [chapterName stringByAppendingFormat:@"00%d,",i+1];
+            }
+            else if (i<99)
+            { /* if i is from 9 to 98 (chapters 10 to 99) add one leading zero */
+                chapterName = [chapterName stringByAppendingFormat:@"0%d,",i+1];
+            }
+            else if (i<999)
+            { /* in case i is from 99 to 998 (chapters 100 to 999) no leading zeros */
+                chapterName = [chapterName stringByAppendingFormat:@"%d,",i+1];
+            }
+            
+            chapterTitle = [fChapterTitlesDelegate tableView:fChapterTable objectValueForTableColumn:fChapterTableNameColumn row:i];
+            /* escape any commas in the chapter name with "\," */
+            chapterTitle = [chapterTitle stringByReplacingOccurrencesOfString:@"," withString:@"\\,"];
+            chapterName = [chapterName stringByAppendingString:chapterTitle];
+            if (i+1 != chapters)
+            { /* if not the last chapter */
+                chapterName = [chapterName stringByAppendingString:@ "\n"];
+            }
+
+            
+        }
+        /* try to write it to where the user wanted */
+        if (![chapterName writeToFile:[sheet filename] 
+                           atomically:NO 
+                             encoding:NSUTF8StringEncoding 
+                                error:&saveError])
+        {
+            [sheet close];
+            [[NSAlert alertWithError:saveError] runModal];
+        }
+    }
+}
 
 @end