X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=macosx%2FController.m;h=a744ad21c824aaa117b5153805a125d933466491;hb=92a6427d5319576aa5717018afd09a639dab7e36;hp=ce3e70a4d066643750e98a38dd229d3ba1cbd813;hpb=96214cd6203085933c0dc1dabacecbdd847d7fba;p=handbrake-jp%2Fhandbrake-jp-git.git
diff --git a/macosx/Controller.m b/macosx/Controller.m
index ce3e70a4..a744ad21 100644
--- a/macosx/Controller.m
+++ b/macosx/Controller.m
@@ -4,6 +4,7 @@
Homepage: .
It may be used under the terms of the GNU General Public License. */
+#include
#import "Controller.h"
#import "HBOutputPanelController.h"
#import "HBPreferencesController.h"
@@ -11,6 +12,12 @@
#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];
@@ -301,7 +411,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
-
+ [currentQueueEncodeNameString release];
[browsedSourceDisplayName release];
[outputPanel release];
[fQueueController release];
@@ -309,8 +419,10 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
[fPictureController release];
[fApplicationIcon release];
- hb_close(&fHandle);
+ hb_close(&fHandle);
hb_close(&fQueueEncodeLibhb);
+ hb_global_close();
+
}
@@ -333,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
@@ -452,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: @""];
@@ -487,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
@@ -500,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++ )
@@ -531,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];
@@ -754,10 +835,10 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
break;
}
#undef p
-
+
#define p s.param.working
-
+
case HB_STATE_SEARCHING:
{
NSMutableString * string;
@@ -804,7 +885,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
break;
}
-
+
case HB_STATE_WORKING:
{
NSMutableString * string;
@@ -826,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 )
{
@@ -834,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];
@@ -858,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
@@ -936,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*/
@@ -1347,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
{
@@ -1381,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
@@ -1608,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)
@@ -1662,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)
@@ -1783,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 ..."];
}
}
@@ -1800,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 );
@@ -1820,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
{
@@ -1859,6 +1858,14 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
}
[fSrcDVD2Field setStringValue:browsedSourceDisplayName];
+ // use the correct extension based on the container
+ int format = [fDstFormatPopUp indexOfSelectedItem];
+ char *ext = "mp4";
+ if (format == 1)
+ {
+ ext = "mkv";
+ }
+
/* If its a queue rescan for edit, get the queue item output path */
/* if not, its a new source scan. */
/* Check to see if the last destination has been set,use if so, if not, use Desktop */
@@ -1869,24 +1876,29 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It
else if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"])
{
[fDstFile2Field setStringValue: [NSString stringWithFormat:
- @"%@/%@.mp4", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[browsedSourceDisplayName stringByDeletingPathExtension]]];
+ @"%@/%@.%s", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[browsedSourceDisplayName stringByDeletingPathExtension],ext]];
}
else
{
[fDstFile2Field setStringValue: [NSString stringWithFormat:
- @"%@/Desktop/%@.mp4", NSHomeDirectory(),[browsedSourceDisplayName stringByDeletingPathExtension]]];
+ @"%@/Desktop/%@.%s", NSHomeDirectory(),[browsedSourceDisplayName stringByDeletingPathExtension],ext]];
}
+ // set m4v extension if necessary - do not override user-specified .mp4 extension
+ if (format == 0 && applyQueueToScan != YES)
+ {
+ [self autoSetM4vExtension: sender];
+ }
- 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
- stringWithFormat: @"%s %d - %02dh%02dm%02ds",
- title->name,title->index, title->hours, title->minutes,
+ stringWithFormat: @"%@ %d - %02dh%02dm%02ds",
+ currentSource, title->index, title->hours, title->minutes,
title->seconds]];
}
@@ -1897,8 +1909,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];
@@ -1978,12 +1990,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 {
@@ -2000,53 +2009,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];
@@ -2090,7 +2084,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
{
@@ -2105,17 +2105,45 @@ fWorkingCount = 0;
/* Set the queue status field in the main window */
NSMutableString * string;
- if (fPendingCount == 1)
+ if (fPendingCount == 0)
+ {
+ string = [NSMutableString stringWithFormat: NSLocalizedString( @"No encode pending", @"" )];
+ }
+ else 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 encodes 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 encode 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
*/
@@ -2128,15 +2156,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];
@@ -2242,7 +2274,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"];
@@ -2300,6 +2332,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"];
@@ -2358,46 +2391,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];
@@ -2438,41 +2432,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;
@@ -2518,46 +2478,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];
@@ -2569,10 +2541,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"];
@@ -2601,6 +2572,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"];
}
}
@@ -2620,10 +2592,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 */
- int hb_num_previews = [[[NSUserDefaults standardUserDefaults] objectForKey:@"PreviewsNumber"] intValue];
- hb_scan( fQueueEncodeLibhb, [path UTF8String], scanTitleNum, hb_num_previews, 0 );
+ /* Only scan 10 previews before an encode - additional previews are only useful for autocrop and static previews,
+ * which are already taken care of at this point */
+ hb_scan( fQueueEncodeLibhb, [path UTF8String], scanTitleNum, 10, 0, 0 );
}
}
@@ -2643,7 +2614,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];
/*
@@ -2718,13 +2688,10 @@ fWorkingCount = 0;
free(subtitle);
}
-
/* We should be all setup so let 'er rip */
[self doRip];
}
-
-
#pragma mark -
#pragma mark Queue Item Editing
@@ -2734,8 +2701,10 @@ fWorkingCount = 0;
fqueueEditRescanItemNum = selectedQueueItem;
[self writeToActivityLog: "rescanQueueItemToMainWindow: Re-scanning queue item at index:%d",fqueueEditRescanItemNum];
applyQueueToScan = YES;
+ /* Make sure we release the display name before reassigning it */
+ [browsedSourceDisplayName release];
/* Set the browsedSourceDisplayName for showNewScan */
- browsedSourceDisplayName = [[QueueFileArray objectAtIndex:fqueueEditRescanItemNum] objectForKey:@"SourceName"];
+ browsedSourceDisplayName = [[[QueueFileArray objectAtIndex:fqueueEditRescanItemNum] objectForKey:@"SourceName"] retain];
[self performScan:scanPath scanTitleNum:scanTitleNum];
}
@@ -2815,7 +2784,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*/
@@ -2838,88 +2807,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"]];
@@ -2979,9 +2868,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.
@@ -3079,10 +2965,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*/
@@ -3165,7 +3050,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
{
@@ -3241,23 +3133,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
{
@@ -3291,8 +3178,10 @@ bool one_burned = FALSE;
sub_config.offset = [[tempObject objectForKey:@"subtitleTrackSrtOffset"] intValue];
/* we need to srncpy file path and char code */
- strncpy(sub_config.src_filename, [[tempObject objectForKey:@"subtitleSourceSrtFilePath"] UTF8String], 128);
- strncpy(sub_config.src_codeset, [[tempObject objectForKey:@"subtitleTrackSrtCharCode"] UTF8String], 40);
+ strncpy(sub_config.src_filename, [[tempObject objectForKey:@"subtitleSourceSrtFilePath"] UTF8String], 255);
+ sub_config.src_filename[255] = 0;
+ strncpy(sub_config.src_codeset, [[tempObject objectForKey:@"subtitleTrackSrtCharCode"] UTF8String], 39);
+ sub_config.src_codeset[39] = 0;
sub_config.force = 0;
sub_config.dest = PASSTHRUSUB;
@@ -3305,17 +3194,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
@@ -3323,6 +3205,13 @@ bool one_burned = FALSE;
continue;
one_burned = TRUE;
}
+
+ /* Besides VOBSUBS we can also burn in SSA text subs */
+ if (subt->source == SSASUB && burned)
+ {
+ sub_config.dest = RENDERSUB;
+ }
+
sub_config.force = force;
sub_config.default_track = def;
hb_subtitle_add( job, &sub_config, subtitle );
@@ -3339,83 +3228,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. */
- 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. */
- 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. */
- 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. */
- 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];
@@ -3442,6 +3255,7 @@ bool one_burned = FALSE;
*/
/* Detelecine */
+ hb_filter_detelecine.settings = NULL;
if ([fPictureController detelecine] == 1)
{
/* use a custom detelecine string */
@@ -3460,6 +3274,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 */
@@ -3570,51 +3385,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];
+
}
@@ -3755,7 +3547,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
{
@@ -3837,22 +3637,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
{
@@ -3901,24 +3697,24 @@ 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 )
+ else if ( burned )
{
// Only allow one subtitle to be burned into the video
if (one_burned)
continue;
one_burned = TRUE;
}
+
+ /* Besides VOBSUBS we can also burn in SSA text subs */
+ if (subt->source == SSASUB && burned)
+ {
+ sub_config.dest = RENDERSUB;
+ }
+
sub_config.force = force;
sub_config.default_track = def;
hb_subtitle_add( job, &sub_config, subtitle );
@@ -3941,75 +3737,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. */
- 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. */
- 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. */
- 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. */
- 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. */
+ 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();
@@ -4018,6 +3764,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 */
@@ -4034,6 +3781,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 */
@@ -4118,7 +3866,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 */
@@ -4168,7 +3916,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:
@@ -4220,6 +3968,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]];
@@ -4257,6 +4006,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]];
}
@@ -4279,8 +4029,9 @@ bool one_burned = FALSE;
NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
[[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
+ currentQueueEncodeIndex = [self getNextPendingQueueIndex];
[self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]];
-
+
}
}
@@ -4394,23 +4145,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
@@ -4557,7 +4314,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++)
{
@@ -4565,25 +4330,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*/
@@ -4737,15 +4484,7 @@ bool one_burned = FALSE;
switch( format )
{
case 0:
- /*Get Default MP4 File Extension*/
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
- {
- ext = "m4v";
- }
- else
- {
- ext = "mp4";
- }
+ [self autoSetM4vExtension: nil];
/* Add additional video encoders here */
menuItem = [[fVidEncoderPopUp menu] addItemWithTitle:@"H.264 (x264)" action: NULL keyEquivalent: @""];
[menuItem setTag: HB_VCODEC_X264];
@@ -4773,6 +4512,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)
{
@@ -4783,10 +4531,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];
@@ -4796,10 +4540,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 )
{
@@ -4822,23 +4562,23 @@ bool one_burned = FALSE;
{
if ( [fDstFormatPopUp indexOfSelectedItem] )
return;
-
+
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 ||
- [fCreateChapterMarkers state] == NSOnState ||
- [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0 )
+
+ BOOL anyCodecAC3 = [fAudioDelegate anyCodecMatches: HB_ACODEC_AC3] || [fAudioDelegate anyCodecMatches: HB_ACODEC_AC3_PASS];
+
+ if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultMpegExtension"] isEqualToString: @".m4v"] ||
+ ((YES == anyCodecAC3 || [fCreateChapterMarkers state] == NSOnState) &&
+ [[[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultMpegExtension"] isEqualToString: @"Auto"] ))
{
extension = @"m4v";
}
-
+
if( [extension isEqualTo: [[fDstFile2Field stringValue] pathExtension]] )
return;
else
[fDstFile2Field setStringValue: [NSString stringWithFormat:@"%@.%@",
- [[fDstFile2Field stringValue] stringByDeletingPathExtension], extension]];
+ [[fDstFile2Field stringValue] stringByDeletingPathExtension], extension]];
}
/* Method to determine if we should change the UI
@@ -4926,6 +4666,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];
@@ -5044,6 +4795,12 @@ the user is using "Custom" settings by determining the sender*/
{
[fVidQualityRFField setStringValue: [NSString stringWithFormat: @"%.2f", sliderRfInverse]];
}
+ /* Show a warning if x264 and rf 0 which is lossless */
+ if ([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_X264 && sliderRfInverse == 0.0)
+ {
+ [fVidQualityRFField setStringValue: [NSString stringWithFormat: @"%.2f (Warning: Lossless)", sliderRfInverse]];
+ }
+
[self customSettingUsed: sender];
}
@@ -5077,82 +4834,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. */
- 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. */
- 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. */
- 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. */
- 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] )];
}
@@ -5308,892 +4990,53 @@ the user is using "Custom" settings by determining the sender*/
#pragma mark -
#pragma mark - Audio and Subtitles
-- (IBAction) audioCodecsPopUpChanged: (id) sender
+
+
+#pragma mark -
+
+- (BOOL) hasValidPresetSelected
+
{
-
- 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;
- }
+ return ([fPresetsOutlineView selectedRow] >= 0 && [[[fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]] objectForKey:@"Folder"] intValue] != 1);
+}
+
+// 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) browseImportSrtFile: (id) sender
+{
+
+ NSOpenPanel * panel;
- /* 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];
-
+ panel = [NSOpenPanel openPanel];
+ [panel setAllowsMultipleSelection: NO];
+ [panel setCanChooseFiles: YES];
+ [panel setCanChooseDirectories: NO ];
+ NSString * sourceDirectory;
+ if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastSrtImportDirectory"])
+ {
+ sourceDirectory = [[NSUserDefaults standardUserDefaults] stringForKey:@"LastSrtImportDirectory"];
+ }
+ else
+ {
+ sourceDirectory = @"~/Desktop";
+ sourceDirectory = [sourceDirectory stringByExpandingTildeInPath];
+ }
+ /* we open up the browse srt sheet here and call for browseImportSrtFileDone after the sheet is closed */
+ NSArray *fileTypes = [NSArray arrayWithObjects:@"plist", @"srt", nil];
+ [panel beginSheetForDirectory: sourceDirectory file: nil types: fileTypes
+ modalForWindow: fWindow modalDelegate: self
+ didEndSelector: @selector( browseImportSrtFileDone:returnCode:contextInfo: )
+ contextInfo: sender];
}
-- (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] );
-
- hb_audio_config_t * audio;
-
- [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];
-
-}
-
-- (IBAction) selectAudioTrackInPopUp: (id) sender searchPrefixString: (NSString *) searchPrefixString selectIndexIfNotFound: (int) selectIndexIfNotFound
-{
-
- /* this method can be used to find a language, or a language-and-source-format combination, by passing in the appropriate string */
- /* e.g. to find the first French track, pass in an NSString * of "Francais" */
- /* e.g. to find the first English 5.1 AC3 track, pass in an NSString * of "English (AC3) (5.1 ch)" */
- /* if no matching track is found, then selectIndexIfNotFound is used to choose which track to select instead */
-
- if (searchPrefixString)
- {
-
- 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 */
- // CA_AAC
- menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (CoreAudio)" action: NULL keyEquivalent: @""];
- [menuItem setTag: HB_ACODEC_CA_AAC];
- // FAAC
- menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (faac)" action: NULL keyEquivalent: @""];
- [menuItem setTag: HB_ACODEC_FAAC];
- // AC3 Passthru
- menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AC3 Passthru" action: NULL keyEquivalent: @""];
- [menuItem setTag: HB_ACODEC_AC3];
- break;
-
- case 1:
- /* MKV */
- // CA_AAC
- menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (CoreAudio)" action: NULL keyEquivalent: @""];
- [menuItem setTag: HB_ACODEC_CA_AAC];
- // FAAC
- menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (faac)" action: NULL keyEquivalent: @""];
- [menuItem setTag: HB_ACODEC_FAAC];
- // 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;
- }
- [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 CoreAudio aac for all containers.
- */
- if (audio->in.codec != HB_ACODEC_AC3 && [[audiocodecPopUp selectedItem] tag] == HB_ACODEC_AC3)
- {
- [audiocodecPopUp selectItemWithTag: HB_ACODEC_CA_AAC];
- }
-
- /* 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 CoreAudio aac for all containers.
- */
- if (audio->in.codec != HB_ACODEC_DCA && [[audiocodecPopUp selectedItem] tag] == HB_ACODEC_DCA)
- {
- [audiocodecPopUp selectItemWithTag: HB_ACODEC_CA_AAC];
- }
-
- /* 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"])
- {
- sourceDirectory = [[NSUserDefaults standardUserDefaults] stringForKey:@"LastSrtImportDirectory"];
- }
- else
- {
- sourceDirectory = @"~/Desktop";
- sourceDirectory = [sourceDirectory stringByExpandingTildeInPath];
- }
- /* we open up the browse srt sheet here and call for browseImportSrtFileDone after the sheet is closed */
- NSArray *fileTypes = [NSArray arrayWithObjects:@"plist", @"srt", nil];
- [panel beginSheetForDirectory: sourceDirectory file: nil types: fileTypes
- modalForWindow: fWindow modalDelegate: self
- didEndSelector: @selector( browseImportSrtFileDone:returnCode:contextInfo: )
- contextInfo: sender];
-}
-
-- (void) browseImportSrtFileDone: (NSSavePanel *) sheet
- returnCode: (int) returnCode contextInfo: (void *) contextInfo
+- (void) browseImportSrtFileDone: (NSSavePanel *) sheet
+ returnCode: (int) returnCode contextInfo: (void *) contextInfo
{
if( returnCode == NSOKButton )
{
@@ -6221,12 +5064,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"]];
}
/**
@@ -6512,6 +5355,14 @@ return YES;
//}
}
+- (void) outlineViewSelectionDidChange: (NSNotification *) ignored
+
+{
+ [self willChangeValueForKey: @"hasValidPresetSelected"];
+ [self didChangeValueForKey: @"hasValidPresetSelected"];
+ return;
+}
+
#pragma mark -
#pragma mark Preset Outline View Methods (dragging related)
@@ -6626,7 +5477,7 @@ return YES;
- (IBAction)selectPreset:(id)sender
{
- if ([fPresetsOutlineView selectedRow] >= 0 && [[[fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]] objectForKey:@"Folder"] intValue] != 1)
+ if (YES == [self hasValidPresetSelected])
{
chosenPreset = [fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]];
[fPresetSelectedDisplay setStringValue:[chosenPreset objectForKey:@"PresetName"]];
@@ -6710,7 +5561,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]];
@@ -6720,307 +5573,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 preset is a built in */
- if ([[chosenPreset objectForKey:@"Type"] intValue] == 0 &&
- [[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 preset is built in */
- if ([[chosenPreset objectForKey:@"Type"] intValue] == 0 &&
- [[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 preset is built in */
- if ([[chosenPreset objectForKey:@"Type"] intValue] == 0 &&
- [[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 preset is built in */
- if ([[chosenPreset objectForKey:@"Type"] intValue] == 0 &&
- [[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 preset is built in */
- if ([[chosenPreset objectForKey:@"Type"] intValue] == 0 &&
- [[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"]];
@@ -7110,14 +5663,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;
+ }
}
@@ -7292,6 +5867,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*/
@@ -7300,7 +5887,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 */
@@ -7310,6 +5897,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];
}
@@ -7434,6 +6027,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"];
@@ -7441,11 +6035,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"];
@@ -7472,62 +6066,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"];
@@ -7641,7 +6180,7 @@ return YES;
/* now get and add selected presets to export */
}
- if ([fPresetsOutlineView selectedRow] >= 0 && [[[fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]] objectForKey:@"Folder"] intValue] != 1)
+ if (YES == [self hasValidPresetSelected])
{
[presetsToExport addObject:[fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]]];
[presetsToExport writeToFile:exportPresetsFile atomically:YES];
@@ -8006,6 +6545,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 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