- (void) applicationDidFinishLaunching: (NSNotification *) notification
{
/* Init libhb with check for updates libhb style set to "0" so its ignored and lets sparkle take care of it */
- fHandle = hb_init(HB_DEBUG_ALL, 0);
+ int loggingLevel = [[[NSUserDefaults standardUserDefaults] objectForKey:@"LoggingLevel"] intValue];
+ fHandle = hb_init(loggingLevel, 0);
/* Init a separate instance of libhb for user scanning and setting up jobs */
- fQueueEncodeLibhb = hb_init(HB_DEBUG_ALL, 0);
+ fQueueEncodeLibhb = hb_init(loggingLevel, 0);
// Set the Growl Delegate
[GrowlApplicationBridge setGrowlDelegate: self];
* user if they want to reload the queue */
if ([QueueFileArray count] > 0)
{
+ /* run getQueueStats to see whats in the queue file */
+ [self getQueueStats];
+ /* this results in these values
+ * fEncodingQueueItem = 0;
+ * fPendingCount = 0;
+ * fCompletedCount = 0;
+ * fCanceledCount = 0;
+ * fWorkingCount = 0;
+ */
+
/*On Screen Notification*/
- NSString * alertTitle = [NSString stringWithFormat:NSLocalizedString(@"HandBrake Has Detected Item(s) From Your Previous Queue.", nil)];
+ NSString * alertTitle;
+ if (fWorkingCount > 0)
+ {
+ alertTitle = [NSString stringWithFormat:
+ NSLocalizedString(@"HandBrake Has Detected %d Previously Encoding Item 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));
+ 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));
// call didDimissReloadQueue: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo
// right below to either clear the old queue or keep it loaded up.
}
else
{
-
- /* Show Browse Sources Window ASAP */
- [self performSelectorOnMainThread:@selector(browseSources:)
- withObject:nil waitUntilDone:NO];
- }
+
+ /* Show Browse Sources Window ASAP */
+ [self performSelectorOnMainThread:@selector(browseSources:)
+ withObject:nil waitUntilDone:NO];
+ }
}
- (void) didDimissReloadQueue: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo
if (returnCode == NSAlertOtherReturn)
{
[self clearQueueAllItems];
- }
-
- [self performSelectorOnMainThread:@selector(browseSources:)
+ [self performSelectorOnMainThread:@selector(browseSources:)
withObject:nil waitUntilDone:NO];
+ }
+ else
+ {
+ [self setQueueEncodingItemsAsPending];
+ [self showQueueWindow:NULL];
+ }
}
- (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) app
{
+
// Warn if encoding a movie
hb_state_t s;
- hb_get_state( fHandle, &s );
+ hb_get_state( fQueueEncodeLibhb, &s );
if ( s.state != HB_STATE_IDLE )
{
int result = NSRunCriticalAlertPanel(
- NSLocalizedString(@"Are you sure you want to quit HandBrake?", nil),
- NSLocalizedString(@"If you quit HandBrake, your movie will be lost. Do you want to quit anyway?", nil),
- NSLocalizedString(@"Quit", nil), NSLocalizedString(@"Don't Quit", nil), nil, @"A movie" );
+ NSLocalizedString(@"Are you sure you want to quit HandBrake?", nil),
+ NSLocalizedString(@"If you quit HandBrake your current encode will be reloaded into your queue at next launch. Do you want to quit anyway?", nil),
+ NSLocalizedString(@"Quit", nil), NSLocalizedString(@"Don't Quit", nil), nil, @"A movie" );
if (result == NSAlertDefaultReturn)
{
- [self doCancelCurrentJob];
return NSTerminateNow;
}
else
}
// Warn if items still in the queue
- else if ( hb_count( fHandle ) > 0 )
+ else if ( fPendingCount > 0 )
{
int result = NSRunCriticalAlertPanel(
- NSLocalizedString(@"Are you sure you want to quit HandBrake?", nil),
- NSLocalizedString(@"One or more encodes are queued for encoding. Do you want to quit anyway?", nil),
- NSLocalizedString(@"Quit", nil), NSLocalizedString(@"Don't Quit", nil), nil);
+ NSLocalizedString(@"Are you sure you want to quit HandBrake?", nil),
+ NSLocalizedString(@"There are pending encodes in your queue. Do you want to quit anyway?",nil),
+ NSLocalizedString(@"Quit", nil), NSLocalizedString(@"Don't Quit", nil), nil);
if ( result == NSAlertDefaultReturn )
return NSTerminateNow;
[fStatusField setStringValue: [NSString stringWithFormat:
NSLocalizedString( @"Queue Scanning title %d of %d...", @"" ),
p.title_cur, p.title_count]];
+
+ /* Set the status string in fQueueController as well */
+ [fQueueController setQueueStatusString: [NSString stringWithFormat:
+ NSLocalizedString( @"Queue Scanning title %d of %d...", @"" ),
+ p.title_cur, p.title_count]];
+
[fRipIndicator setHidden: NO];
[fRipIndicator setDoubleValue: 100.0 * ( p.title_cur - 1 ) / p.title_count];
break;
}
[fStatusField setStringValue: string];
-
+ /* Set the status string in fQueueController as well */
+ [fQueueController setQueueStatusString: string];
/* Update slider */
progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
[fRipIndicator setIndeterminate: NO];
frame.origin.y -= 36;
[fWindow setFrame:frame display:YES animate:YES];
fRipIndicatorShown = YES;
- /* We check to see if we need to warn the user that the computer will go to sleep
- or shut down when encoding is finished */
- [self remindUserOfSleepOrShutdown];
+
}
/* Update dock icon */
{
/* Update text field */
[fStatusField setStringValue: NSLocalizedString( @"Muxing...", @"" )];
-
+ /* Set the status string in fQueueController as well */
+ [fQueueController setQueueStatusString: NSLocalizedString( @"Muxing...", @"" )];
/* Update slider */
[fRipIndicator setIndeterminate: YES];
[fRipIndicator startAnimation: nil];
case HB_STATE_PAUSED:
[fStatusField setStringValue: NSLocalizedString( @"Paused", @"" )];
+ [fQueueController setQueueStatusString: NSLocalizedString( @"Paused", @"" )];
break;
// out the remaining passes/jobs in the queue. We'll do that here.
// Delete all remaining jobs of this encode.
- [fStatusField setStringValue: NSLocalizedString( @"Done.", @"" )];
+ [fStatusField setStringValue: NSLocalizedString( @"Encode Finished.", @"" )];
+ /* Set the status string in fQueueController as well */
+ [fQueueController setQueueStatusString: NSLocalizedString( @"Encode Finished.", @"" )];
[fRipIndicator setIndeterminate: NO];
[fRipIndicator setDoubleValue: 0.0];
[[fWindow toolbar] validateVisibleItems];
[fWindow setFrame:frame display:YES animate:YES];
fRipIndicatorShown = NO;
}
-
- /* Check to see if the encode state has not been cancelled
+ /* Since we are done with this encode, tell output to stop writing to the
+ * individual encode log
+ */
+ [outputPanel endEncodeLog];
+ /* Check to see if the encode state has not been cancelled
to determine if we should check for encode done notifications */
if( fEncodeState != 2 )
{
+ NSString *pathOfFinishedEncode;
+ /* Get the output file name for the finished encode */
+ 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];
- /* 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;
- NSBeep();
- status = NSRunAlertPanel(@"Put down that cocktail...",@"Your HandBrake encode 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"] )
+ [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)
{
- /* Shut Down */
- NSDictionary* errorDict;
- NSAppleEventDescriptor* returnDescriptor = nil;
- NSAppleScript* scriptObject = [[NSAppleScript alloc] initWithSource:
- @"tell application \"Finder\" to shut down"];
- returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
- [scriptObject release];
+ /* 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;
+ 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];
+ }
+
}
-(void)showGrowlDoneNotification:(NSString *) filePath
{
- /* This is called from HBQueueController as jobs roll off of the queue in currentJobChanged */
+ /* This end of encode action is called as each encode rolls off of the queue */
NSString * finishedEncode = filePath;
/* strip off the path to just show the file name */
finishedEncode = [finishedEncode lastPathComponent];
}
-(void)sendToMetaX:(NSString *) filePath
{
- /* This is called from HBQueueController as jobs roll off of the queue in currentJobChanged */
+ /* This end of encode action is called as each encode rolls off of the queue */
if([[NSUserDefaults standardUserDefaults] boolForKey: @"sendToMetaX"] == YES)
{
NSAppleScript *myScript = [[NSAppleScript alloc] initWithSource: [NSString stringWithFormat: @"%@%@%@", @"tell application \"MetaX\" to open (POSIX file \"", filePath, @"\")"]];
- (void) removeQueueFileItem:(int) queueItemToRemove
{
- // FIX ME: WE NEED TO IDENTIFY AN ENCODING ITEM AND CALL
-
+ /* 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];
[fQueueStatus setStringValue:string];
}
+/* This method will set any item marked as encoding back to pending
+ * currently used right after a queue reload
+ */
+- (void) setQueueEncodingItemsAsPending
+{
+ NSEnumerator *enumerator = [QueueFileArray objectEnumerator];
+ id tempObject;
+ NSMutableArray *tempArray;
+ tempArray = [NSMutableArray array];
+ /* we look here to see if the preset is we move on to the next one */
+ while ( tempObject = [enumerator nextObject] )
+ {
+ /* If the 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];
+ }
+
+ [QueueFileArray setArray:tempArray];
+ [self saveQueueFileItem];
+}
+
/* This method will clear the queue of any encodes that are not still pending
* this includes both successfully completed encodes as well as cancelled encodes */
/* 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 not still pending (finished successfully or it was cancelled
- * during the last session, then we put it in tempArray to be deleted from QueueFileArray*/
- if ([[tempObject objectForKey:@"Status"] intValue] != 2)
+ /* If the queue item is either completed (0) or cancelled (3) from the
+ * last session, then we put it in tempArray to be deleted from QueueFileArray.
+ * NOTE: this means we retain pending (2) and also an item that is marked as
+ * still encoding (1). If the queue has an item that is still marked as encoding
+ * from a previous session, we can conlude that HB was either shutdown, or crashed
+ * during the encodes so we keep it and tell the user in the "Load Queue Alert"
+ */
+ if ([[tempObject objectForKey:@"Status"] intValue] == 0 || [[tempObject objectForKey:@"Status"] intValue] == 3)
{
[tempArray addObject:tempObject];
}
[QueueFileArray removeObjectsInArray:tempArray];
[self saveQueueFileItem];
-
}
-/* This method will clear the queue of any encodes that are not still pending
- * this includes both successfully completed encodes as well as cancelled encodes */
+/* This method will clear the queue of all encodes. effectively creating an empty queue */
- (void) clearQueueAllItems
{
NSEnumerator *enumerator = [QueueFileArray objectEnumerator];
[QueueFileArray removeObjectsInArray:tempArray];
[self saveQueueFileItem];
-
}
/* This method will duplicate prepareJob however into the
hb_title_t * title = (hb_title_t *) hb_list_item( list,
[fSrcTitlePopUp indexOfSelectedItem] );
hb_job_t * job = title->job;
- //hb_audio_config_t * audio;
- // For picture filters
- //hb_job_t * job = fTitle->job;
+
/* We use a number system to set the encode status of the queue item
* 0 == already encoded
[queueFileJob setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
/* Chapter Markers fCreateChapterMarkers*/
[queueFileJob setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"];
- /* Allow Mpeg4 64 bit formatting +4GB file sizes */
+
+ /* We need to get the list of chapter names to put into an array and store
+ * in our queue, so they can be reapplied in prepareJob when this queue
+ * item comes up if Chapter Markers is set to on.
+ */
+ int i;
+ NSMutableArray *ChapterNamesArray = [[NSMutableArray alloc] init];
+ int chaptercount = hb_list_count( fTitle->list_chapter );
+ for( i = 0; i < chaptercount; i++ )
+ {
+ hb_chapter_t *chapter = (hb_chapter_t *) hb_list_item( fTitle->list_chapter, i );
+ if( chapter != NULL )
+ {
+ [ChapterNamesArray addObject:[NSString stringWithFormat:@"%s",chapter->title]];
+ }
+ }
+ [queueFileJob setObject:[NSMutableArray arrayWithArray: ChapterNamesArray] forKey:@"ChapterNames"];
+ [ChapterNamesArray autorelease];
+
+ /* Allow Mpeg4 64 bit formatting +4GB file sizes */
[queueFileJob setObject:[NSNumber numberWithInt:[fDstMp4LargeFileCheck state]] forKey:@"Mp4LargeFile"];
/* Mux mp4 with http optimization */
[queueFileJob setObject:[NSNumber numberWithInt:[fDstMp4HttpOptFileCheck state]] forKey:@"Mp4HttpOptimize"];
/* Picture Filters */
[queueFileJob setObject:[NSNumber numberWithInt:[fPictureController deinterlace]] forKey:@"PictureDeinterlace"];
[queueFileJob setObject:[NSNumber numberWithInt:[fPictureController detelecine]] forKey:@"PictureDetelecine"];
- [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController vfr]] forKey:@"VFR"];
- [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController denoise]] forKey:@"PictureDenoise"];
- [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController deblock]] forKey:@"PictureDeblock"];
+ [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController denoise]] forKey:@"PictureDenoise"];
+ [queueFileJob setObject:[NSString stringWithFormat:@"%d",[fPictureController deblock]] forKey:@"PictureDeblock"];
[queueFileJob setObject:[NSNumber numberWithInt:[fPictureController decomb]] forKey:@"PictureDecomb"];
/*Audio*/
[queueFileJob setObject:[NSNumber numberWithInt:[[fDstFormatPopUp selectedItem] tag]] forKey:@"JobFileFormatMux"];
- /* Chapter Markers fCreateChapterMarkers*/
- //[queueFileJob setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"];
- /* Allow Mpeg4 64 bit formatting +4GB file sizes */
- //[queueFileJob setObject:[NSNumber numberWithInt:[fDstMp4LargeFileCheck state]] forKey:@"Mp4LargeFile"];
- /* Mux mp4 with http optimization */
- //[queueFileJob setObject:[NSNumber numberWithInt:[fDstMp4HttpOptFileCheck state]] forKey:@"Mp4HttpOptimize"];
- /* Add iPod uuid atom */
- //[queueFileJob setObject:[NSNumber numberWithInt:[fDstMp4iPodFileCheck state]] forKey:@"Mp4iPodCompatible"];
/* Codecs */
/* Video encoder */
[queueFileJob setObject:[NSNumber numberWithInt:[[fVidEncoderPopUp selectedItem] tag]] forKey:@"JobVideoEncoderVcodec"];
- /* x264 Option String */
- //[queueFileJob setObject:[fAdvancedOptions optionsString] forKey:@"x264Option"];
-
- //[queueFileJob setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"];
- //[queueFileJob setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
- //[queueFileJob setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
- //[queueFileJob setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+
/* Framerate */
[queueFileJob setObject:[NSNumber numberWithInt:[fVidRatePopUp indexOfSelectedItem]] forKey:@"JobIndexVideoFramerate"];
[queueFileJob setObject:[NSNumber numberWithInt:title->rate] forKey:@"JobVrate"];
[queueFileJob setObject:[NSNumber numberWithInt:title->rate_base] forKey:@"JobVrateBase"];
- /* Picture Sizing */
+
+ /* Picture Sizing */
/* Use Max Picture settings for whatever the dvd is.*/
[queueFileJob setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
[queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
/* 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
{
- //NSRunAlertPanel(@"Hello!", @"We are now performing a new queue scan!", @"OK", nil, nil);
-
+ /* Tell HB to output a new activity log file for this encode */
+ [outputPanel startEncodeLog:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"DestinationPath"]];
+
+
/* 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
/* Filters */
/* Deinterlace */
[fPictureController setDeinterlace:[[queueToApply objectForKey:@"PictureDeinterlace"] intValue]];
- /* VFR */
- [fPictureController setVFR:[[queueToApply objectForKey:@"VFR"] intValue]];
+
/* Detelecine */
[fPictureController setDetelecine:[[queueToApply objectForKey:@"PictureDetelecine"] intValue]];
/* Denoise */
}
NSMutableDictionary * queueToApply = [QueueFileArray objectAtIndex:currentQueueEncodeIndex];
- [self writeToActivityLog: "processNewQueueEncode currentQueueEncodeIndex is: %d", currentQueueEncodeIndex];
+ //[self writeToActivityLog: "processNewQueueEncode currentQueueEncodeIndex is: %d", currentQueueEncodeIndex];
[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 writeToActivityLog: "processNewQueueEncode sending to prepareJob"];
[self prepareJob];
- [self writeToActivityLog: "processNewQueueEncode back from prepareJob"];
if( [[queueToApply objectForKey:@"SubtitlesForced"] intValue] == 1 )
job->subtitle_force = 1;
else
hb_title_t * title = (hb_title_t *) hb_list_item( list,0 ); // is always zero since now its a single title scan
hb_job_t * job = title->job;
hb_audio_config_t * audio;
- [self writeToActivityLog: "prepareJob reached"];
/* Chapter selection */
job->chapter_start = [[queueToApply objectForKey:@"JobChapterStart"] intValue];
job->chapter_end = [[queueToApply objectForKey:@"JobChapterEnd"] intValue];
{
job->mp4_optimize = 0;
}
+
//}
/* We set the chapter marker extraction here based on the format being
if ([[queueToApply objectForKey:@"ChapterMarkers"] intValue] == 1)
{
job->chapter_markers = 1;
+
+ /* now lets get our saved chapter names out the array in the queue file
+ * and insert them back into the title chapter list. We have it here,
+ * because unless we are inserting chapter markers there is no need to
+ * spend the overhead of iterating through the chapter names array imo
+ * Also, note that if for some reason we don't apply chapter names, the
+ * chapters just come out 001, 002, etc. etc.
+ */
+
+ NSMutableArray *ChapterNamesArray = [queueToApply objectForKey:@"ChapterNames"];
+ int i = 0;
+ NSEnumerator *enumerator = [ChapterNamesArray objectEnumerator];
+ id tempObject;
+ while (tempObject = [enumerator nextObject])
+ {
+ hb_chapter_t *chapter = (hb_chapter_t *) hb_list_item( title->list_chapter, i );
+ if( chapter != NULL )
+ {
+ strncpy( chapter->title, [tempObject UTF8String], 1023);
+ chapter->title[1023] = '\0';
+ }
+ i++;
+ }
}
else
{
job->chapter_markers = 0;
}
-
+
+
+
+
if( job->vcodec & HB_VCODEC_X264 )
{
if ([[queueToApply objectForKey:@"Mp4iPodCompatible"] intValue] == 1)
}
- [self writeToActivityLog: "prepareJob reached Picture Settings"];
/* Picture Size Settings */
job->width = [[queueToApply objectForKey:@"PictureWidth"] intValue];
job->height = [[queueToApply objectForKey:@"PictureHeight"] intValue];
job->crop[2] = [[queueToApply objectForKey:@"PictureLeftCrop"] intValue];
job->crop[3] = [[queueToApply objectForKey:@"PictureRightCrop"] intValue];
- [self writeToActivityLog: "prepareJob reached Frame Rate"];
-
/* Video settings */
+ /* Framerate */
+
+ /* Set vfr to 0 as it's only on if using same as source in the framerate popup
+ * and detelecine is on, so we handle that in the logic below
+ */
+ job->vfr = 0;
if( [[queueToApply objectForKey:@"JobIndexVideoFramerate"] intValue] > 0 )
{
+ /* a specific framerate has been chosen */
job->vrate = 27000000;
job->vrate_base = hb_video_rates[[[queueToApply objectForKey:@"JobIndexVideoFramerate"] intValue]-1].rate;
/* We are not same as source so we set job->cfr to 1
}
else
{
+ /* We are same as source (variable) */
job->vrate = [[queueToApply objectForKey:@"JobVrate"] intValue];
job->vrate_base = [[queueToApply objectForKey:@"JobVrateBase"] intValue];
/* We are same as source so we set job->cfr to 0
* to enable true same as source framerate */
job->cfr = 0;
+ /* If we are same as source and we have detelecine on, we need to turn on
+ * job->vfr
+ */
+ if ([[queueToApply objectForKey:@"PictureDetelecine"] intValue] == 1)
+ {
+ job->vfr = 1;
+ }
}
- [self writeToActivityLog: "prepareJob reached Bitrate Video Quality"];
- if ( [[queueToApply objectForKey:@"VideoQualityType"] intValue] == 0 )
+ if ( [[queueToApply objectForKey:@"VideoQualityType"] intValue] != 2 )
{
/* Target size.
Bitrate should already have been calculated and displayed
- in fVidBitrateField, so let's just use it */
- }
- if ( [[queueToApply objectForKey:@"VideoQualityType"] intValue] == 1 )
- {
+ in fVidBitrateField, so let's just use it same as abr*/
job->vquality = -1.0;
job->vbitrate = [[queueToApply objectForKey:@"VideoAvgBitrate"] intValue];
}
/* Subtitle settings */
job->subtitle = [[queueToApply objectForKey:@"JobSubtitlesIndex"] intValue] - 2;
- [self writeToActivityLog: "prepareJob reached Audio"];
/* 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);
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:@"Audio3TrackDRCSlider"] floatValue];
+ audio->out.dynamic_range_compression = [[queueToApply objectForKey:@"Audio4TrackDRCSlider"] floatValue];
hb_audio_add( job, audio );
free(audio);
}
- /* set vfr according to the Picture Window */
- if ([[queueToApply objectForKey:@"VFR"] intValue] == 1)
- {
- job->vfr = 1;
- }
- else
- {
- job->vfr = 0;
- }
-
- [self writeToActivityLog: "prepareJob reached Filters"];
- /* Filters */
+ /* Filters */
job->filters = hb_list_init();
/* Now lets call the filters if applicable.
}
/* Deblock (uses pp7 default) */
- if ([[queueToApply objectForKey:@"PictureDeblock"] intValue] == 1)
+ /* NOTE: even though there is a valid deblock setting of 0 for the filter, for
+ * the macgui's purposes a value of 0 actually means to not even use the filter
+ * current hb_filter_deblock.settings valid ranges are from 5 - 15
+ */
+ if ([[queueToApply objectForKey:@"PictureDeblock"] intValue] != 0)
{
+ hb_filter_deblock.settings = (char *) [[queueToApply objectForKey:@"PictureDeblock"] UTF8String];
hb_list_add( job->filters, &hb_filter_deblock );
}
[self writeToActivityLog: "prepareJob exiting"];
return;
}
- // If there are pending jobs in the queue, then this is a rip the queue
+ /* We check to see if we need to warn the user that the computer will go to sleep
+ or shut down when encoding is finished */
+ [self remindUserOfSleepOrShutdown];
+ // If there are pending jobs in the queue, then this is a rip the queue
if (fPendingCount > 0)
{
/* here lets start the queue with the first pending item */
{
if (!fQueueController) return;
-
- NSString * alertTitle = [NSString stringWithFormat:NSLocalizedString(@"Stop encoding ?", nil)];
+ hb_pause( fQueueEncodeLibhb );
+ NSString * alertTitle = [NSString stringWithFormat:NSLocalizedString(@"You are currently encoding. What would you like to do ?", nil)];
// Which window to attach the sheet to?
NSWindow * docWindow;
NSBeginCriticalAlertSheet(
alertTitle,
- NSLocalizedString(@"Keep Encoding", nil),
- nil,
- NSLocalizedString(@"Stop Encoding", nil),
+ NSLocalizedString(@"Continue Encoding", nil),
+ NSLocalizedString(@"Cancel Current and Stop", nil),
+ NSLocalizedString(@"Cancel Current and Continue", nil),
docWindow, self,
- nil, @selector(didDimissCancelCurrentJob:returnCode:contextInfo:), nil,
- NSLocalizedString(@"Your movie will be lost if you don't continue encoding.", nil));
+ nil, @selector(didDimissCancel:returnCode:contextInfo:), nil,
+ NSLocalizedString(@"Your encode will be cancelled if you don't continue encoding.", nil));
// didDimissCancelCurrentJob:returnCode:contextInfo: will be called when the dialog is dismissed
}
-- (void) didDimissCancelCurrentJob: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo
+- (void) didDimissCancel: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo
{
- if (returnCode == NSAlertOtherReturn)
+ hb_resume( fQueueEncodeLibhb );
+ if (returnCode == NSAlertOtherReturn)
+ {
[self doCancelCurrentJob]; // <- this also stops libhb
+ }
+ if (returnCode == NSAlertAlternateReturn)
+ {
+ [self doCancelCurrentJobAndStop];
+ }
}
+- (void) doCancelCurrentJobAndStop
+{
+ hb_stop( fQueueEncodeLibhb );
+ fEncodeState = 2; // don't alert at end of processing since this was a cancel
+
+ // now that we've stopped the currently encoding job, lets mark it as cancelled
+ [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:3] forKey:@"Status"];
+ // 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++ ;
+ [self writeToActivityLog: "cancelling current job and stopping the queue"];
+}
- (IBAction) Pause: (id) sender
{
hb_state_t s;
- hb_get_state2( fHandle, &s );
+ hb_get_state2( fQueueEncodeLibhb, &s );
if( s.state == HB_STATE_PAUSED )
{
- hb_resume( fHandle );
+ hb_resume( fQueueEncodeLibhb );
}
else
{
- hb_pause( fHandle );
+ hb_pause( fQueueEncodeLibhb );
}
}
curUserPresetChosenNum = nil;
}
+[self calculateBitrate:nil];
}
hb_title_t * title = (hb_title_t *) hb_list_item( list,
[fSrcTitlePopUp indexOfSelectedItem] );
hb_job_t * job = title->job;
-
- [fVidBitrateField setIntValue: hb_calc_bitrate( job,
- [fVidTargetSizeField intValue] )];
+ hb_audio_config_t * audio;
+ /* For hb_calc_bitrate in addition to the Target Size in MB out of the
+ * Target Size Field, we also need the job info for the Muxer, the Chapters
+ * as well as all of the audio track info.
+ * This used to be accomplished by simply calling prepareJob here, however
+ * since the resilient queue sets the queue array values instead of the job
+ * values directly, we duplicate the old prepareJob code here for the variables
+ * needed
+ */
+ job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;
+ job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1;
+ job->mux = [[fDstFormatPopUp selectedItem] tag];
+
+ /* Audio goes here */
+ int audiotrack_count = hb_list_count(job->list_audio);
+ for( int i = 0; i < audiotrack_count;i++)
+ {
+ hb_audio_t * temp_audio = (hb_audio_t*) hb_list_item( job->list_audio, 0 );
+ hb_list_rem(job->list_audio, temp_audio);
+ }
+ /* Now we need our audio info here for each track if applicable */
+ if ([fAudLang1PopUp indexOfSelectedItem] > 0)
+ {
+ audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
+ hb_audio_config_init(audio);
+ audio->in.track = [fAudLang1PopUp indexOfSelectedItem] - 1;
+ /* We go ahead and assign values to our audio->out.<properties> */
+ audio->out.track = [fAudLang1PopUp indexOfSelectedItem] - 1;
+ audio->out.codec = [[fAudTrack1CodecPopUp selectedItem] tag];
+ audio->out.mixdown = [[fAudTrack1MixPopUp selectedItem] tag];
+ audio->out.bitrate = [[fAudTrack1BitratePopUp selectedItem] tag];
+ audio->out.samplerate = [[fAudTrack1RatePopUp selectedItem] tag];
+ audio->out.dynamic_range_compression = [fAudTrack1DrcField floatValue];
+
+ hb_audio_add( job, audio );
+ free(audio);
+ }
+ if ([fAudLang2PopUp indexOfSelectedItem] > 0)
+ {
+ audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
+ hb_audio_config_init(audio);
+ audio->in.track = [fAudLang2PopUp indexOfSelectedItem] - 1;
+ /* We go ahead and assign values to our audio->out.<properties> */
+ audio->out.track = [fAudLang2PopUp indexOfSelectedItem] - 1;
+ audio->out.codec = [[fAudTrack2CodecPopUp selectedItem] tag];
+ audio->out.mixdown = [[fAudTrack2MixPopUp selectedItem] tag];
+ audio->out.bitrate = [[fAudTrack2BitratePopUp selectedItem] tag];
+ audio->out.samplerate = [[fAudTrack2RatePopUp selectedItem] tag];
+ audio->out.dynamic_range_compression = [fAudTrack2DrcField floatValue];
+
+ hb_audio_add( job, audio );
+ free(audio);
+
+ }
+
+ if ([fAudLang3PopUp indexOfSelectedItem] > 0)
+ {
+ audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
+ hb_audio_config_init(audio);
+ audio->in.track = [fAudLang3PopUp indexOfSelectedItem] - 1;
+ /* We go ahead and assign values to our audio->out.<properties> */
+ audio->out.track = [fAudLang3PopUp indexOfSelectedItem] - 1;
+ audio->out.codec = [[fAudTrack3CodecPopUp selectedItem] tag];
+ audio->out.mixdown = [[fAudTrack3MixPopUp selectedItem] tag];
+ audio->out.bitrate = [[fAudTrack3BitratePopUp selectedItem] tag];
+ audio->out.samplerate = [[fAudTrack3RatePopUp selectedItem] tag];
+ audio->out.dynamic_range_compression = [fAudTrack3DrcField floatValue];
+
+ hb_audio_add( job, audio );
+ free(audio);
+
+ }
+
+ if ([fAudLang4PopUp indexOfSelectedItem] > 0)
+ {
+ audio = (hb_audio_config_t *) calloc(1, sizeof(*audio));
+ hb_audio_config_init(audio);
+ audio->in.track = [fAudLang4PopUp indexOfSelectedItem] - 1;
+ /* We go ahead and assign values to our audio->out.<properties> */
+ audio->out.track = [fAudLang4PopUp indexOfSelectedItem] - 1;
+ audio->out.codec = [[fAudTrack4CodecPopUp selectedItem] tag];
+ audio->out.mixdown = [[fAudTrack4MixPopUp selectedItem] tag];
+ audio->out.bitrate = [[fAudTrack4BitratePopUp selectedItem] tag];
+ audio->out.samplerate = [[fAudTrack4RatePopUp selectedItem] tag];
+ audio->out.dynamic_range_compression = [fAudTrack4DrcField floatValue];
+
+ hb_audio_add( job, audio );
+ free(audio);
+
+ }
+
+[fVidBitrateField setIntValue: hb_calc_bitrate( job, [fVidTargetSizeField intValue] )];
}
#pragma mark -
- (IBAction) revertPictureSizeToMax: (id) sender
{
hb_job_t * job = fTitle->job;
- /* We use the output picture width and height
- as calculated from libhb right after title is set
- in TitlePopUpChanged */
- job->width = PicOrigOutputWidth;
- job->height = PicOrigOutputHeight;
- [fPictureController setAutoCrop:YES];
- /* Here we use the auto crop values determined right after scan */
- job->crop[0] = AutoCropTop;
- job->crop[1] = AutoCropBottom;
- job->crop[2] = AutoCropLeft;
- job->crop[3] = AutoCropRight;
-
+ /* Here we apply the max source storage width and height */
+ job->width = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3];
+ job->height = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1];
[self calculatePictureSizing: sender];
/* We call method to change UI to reflect whether a preset is used or not*/
}
/* VFR (Variable Frame Rate) */
- if ([fPictureController vfr]) {
- /* We change the string of the fps popup to warn that vfr is on Framerate (FPS): */
- [fVidRateField setStringValue: @"Framerate (VFR On):"];
- /* for VFR we select same as source (or title framerate) and disable the popup.
- * We know its index 0 as that is determined in titlePopUpChanged */
- [fVidRatePopUp selectItemAtIndex: 0];
- [fVidRatePopUp setEnabled: NO];
-
- }
- else {
- /* make sure the label for framerate is set to its default */
- [fVidRateField setStringValue: @"Framerate (FPS):"];
- [fVidRatePopUp setEnabled: YES];
- }
+
/* Deinterlace */
if ([fPictureController deinterlace] == 0)
}
/* Deblock */
- if ([fPictureController deblock]) {
- [fPicSettingDeblock setStringValue: @"Yes"];
+ if ([fPictureController deblock] == 0)
+ {
+ [fPicSettingDeblock setStringValue: @"Off"];
}
- else {
- [fPicSettingDeblock setStringValue: @"No"];
+ else
+ {
+ [fPicSettingDeblock setStringValue: [NSString stringWithFormat:@"%d",[fPictureController deblock]]];
}
if (fTitle->job->pixel_ratio > 0)
[drcSlider setEnabled: YES];
[drcField setEnabled: YES];
}
-
+[self calculateBitrate:nil];
}
- (IBAction) audioDRCSliderChanged: (id) sender
#pragma mark Preset Outline View Methods
#pragma mark - Required
/* These are required by the NSOutlineView Datasource Delegate */
-/* We use this to deterimine children of an item */
-- (id)outlineView:(NSOutlineView *)fPresetsOutlineView child:(NSInteger)index ofItem:(id)item
-{
-if (item == nil)
- return [UserPresets objectAtIndex:index];
-
- // We are only one level deep, so we can't be asked about children
- NSAssert (NO, @"Presets View outlineView:child:ofItem: currently can't handle nested items.");
- return nil;
-}
-/* We use this to determine if an item should be expandable */
-- (BOOL)outlineView:(NSOutlineView *)fPresetsOutlineView isItemExpandable:(id)item
-{
- /* For now, we maintain one level, so set to no
- * when nested, we set to yes for any preset "folders"
- */
- return NO;
-}
/* used to specify the number of levels to show for each item */
- (int)outlineView:(NSOutlineView *)fPresetsOutlineView numberOfChildrenOfItem:(id)item
{
/* currently use no levels to test outline view viability */
- if (item == nil)
+ if (item == nil) // for an outline view the root level of the hierarchy is always nil
+ {
return [UserPresets count];
+ }
else
- return 0;
+ {
+ /* we need to return the count of the array in ChildrenArray for this folder */
+ NSArray *children = nil;
+ children = [item objectForKey:@"ChildrenArray"];
+ if ([children count] > 0)
+ {
+ return [children count];
+ }
+ else
+ {
+ return 0;
+ }
+ }
}
-/* Used to tell the outline view which information is to be displayed per item */
-- (id)outlineView:(NSOutlineView *)fPresetsOutlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
+
+/* We use this to deterimine children of an item */
+- (id)outlineView:(NSOutlineView *)fPresetsOutlineView child:(int)index ofItem:(id)item
{
- /* We have two columns right now, icon and PresetName */
-
- if ([[tableColumn identifier] isEqualToString:@"PresetName"])
+
+ /* we need to return the count of the array in ChildrenArray for this folder */
+ NSArray *children = nil;
+ if (item == nil)
{
- return [item objectForKey:@"PresetName"];
+ children = UserPresets;
+ }
+ else
+ {
+ if ([item objectForKey:@"ChildrenArray"])
+ {
+ children = [item objectForKey:@"ChildrenArray"];
+ }
+ }
+ if ((children == nil) || ([children count] <= index))
+ {
+ return nil;
}
else
{
- return @"something";
+ return [children objectAtIndex:index];
}
+
+
+ // We are only one level deep, so we can't be asked about children
+ //NSAssert (NO, @"Presets View outlineView:child:ofItem: currently can't handle nested items.");
+ //return nil;
}
-#pragma mark - Added Functionality (optional)
-/* Use to customize the font and display characteristics of the title cell */
-- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
-{
+/* We use this to determine if an item should be expandable */
+- (BOOL)outlineView:(NSOutlineView *)fPresetsOutlineView isItemExpandable:(id)item
+{
+
+ /* we need to return the count of the array in ChildrenArray for this folder */
+ NSArray *children= nil;
+ if (item == nil)
+ {
+ children = UserPresets;
+ }
+ else
+ {
+ if ([item objectForKey:@"ChildrenArray"])
+ {
+ children = [item objectForKey:@"ChildrenArray"];
+ }
+ }
+
+ /* To deterimine if an item should show a disclosure triangle
+ * we could do it by the children count as so:
+ * if ([children count] < 1)
+ * However, lets leave the triangle show even if there are no
+ * children to help indicate a folder, just like folder in the
+ * finder can show a disclosure triangle even when empty
+ */
+
+ /* We need to determine if the item is a folder */
+ if ([[item objectForKey:@"Folder"] intValue] == 1)
+ {
+ return YES;
+ }
+ else
+ {
+ return NO;
+ }
+
+}
+
+- (BOOL)outlineView:(NSOutlineView *)outlineView shouldExpandItem:(id)item
+{
+ // Our outline view has no levels, but we can still expand every item. Doing so
+ // just makes the row taller. See heightOfRowByItem below.
+//return ![(HBQueueOutlineView*)outlineView isDragging];
+
+return YES;
+}
+
+
+/* Used to tell the outline view which information is to be displayed per item */
+- (id)outlineView:(NSOutlineView *)fPresetsOutlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
+{
+ /* We have two columns right now, icon and PresetName */
+
+ if ([[tableColumn identifier] isEqualToString:@"PresetName"])
+ {
+ return [item objectForKey:@"PresetName"];
+ }
+ else
+ {
+ //return @"";
+ return nil;
+ }
+}
+
+#pragma mark - Added Functionality (optional)
+/* Use to customize the font and display characteristics of the title cell */
+- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
+{
if ([[tableColumn identifier] isEqualToString:@"PresetName"])
{
- NSDictionary *userPresetDict = item;
NSFont *txtFont;
NSColor *fontColor;
NSColor *shadowColor;
}
else
{
- if ([[userPresetDict objectForKey:@"Type"] intValue] == 0)
+ if ([[item objectForKey:@"Type"] intValue] == 0)
{
fontColor = [NSColor blueColor];
}
{
fontColor = [NSColor blackColor];
}
- shadowColor = nil;
+ /* check to see if its a folder */
+ //if ([[item objectForKey:@"Folder"] intValue] == 1)
+ //{
+ //fontColor = [NSColor greenColor];
+ //}
+
+
}
/* We use Bold Text for the HB Default */
- if ([[userPresetDict objectForKey:@"Default"] intValue] == 1)// 1 is HB default
+ if ([[item objectForKey:@"Default"] intValue] == 1)// 1 is HB default
{
txtFont = [NSFont boldSystemFontOfSize: [NSFont smallSystemFontSize]];
}
/* We use Bold Text for the User Specified Default */
- if ([[userPresetDict objectForKey:@"Default"] intValue] == 2)// 2 is User default
+ if ([[item objectForKey:@"Default"] intValue] == 2)// 2 is User default
{
txtFont = [NSFont boldSystemFontOfSize: [NSFont smallSystemFontSize]];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
{
// Dragging is only allowed for custom presets.
- if ([[[UserPresets objectAtIndex:[fPresetsOutlineView selectedRow]] objectForKey:@"Type"] intValue] == 0) // 0 is built in preset
+ //[[[fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]] objectForKey:@"Default"] intValue] != 1
+ if ([[[fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]] objectForKey:@"Type"] intValue] == 0) // 0 is built in preset
{
return NO;
}
- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
{
+
// Don't allow dropping ONTO an item since they can't really contain any children.
BOOL isOnDropTypeProposal = index == NSOutlineViewDropOnItemIndex;
if (isOnDropTypeProposal)
return NSDragOperationNone;
-
- // Don't allow dropping INTO an item since they can't really contain any children as of yet.
-
- if (item != nil)
+ // Don't allow dropping INTO an item since they can't really contain any children as of yet.
+ if (item != nil)
{
index = [fPresetsOutlineView rowForItem: item] + 1;
item = nil;
{
return NSDragOperationNone;
index = MAX (index, presetCurrentBuiltInCount);
- }
+ }
[outlineView setDropItem:item dropChildIndex:index];
return NSDragOperationGeneric;
- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index
{
- NSMutableIndexSet *moveItems = [NSMutableIndexSet indexSet];
-
- id obj;
- NSEnumerator *enumerator = [fDraggedNodes objectEnumerator];
- while (obj = [enumerator nextObject])
- {
- [moveItems addIndex:[UserPresets indexOfObject:obj]];
+ /* first, lets see if we are dropping into a folder */
+ if ([[fPresetsOutlineView itemAtRow:index] objectForKey:@"Folder"] && [[[fPresetsOutlineView itemAtRow:index] objectForKey:@"Folder"] intValue] == 1) // if its a folder
+ {
+ NSMutableArray *childrenArray = [[NSMutableArray alloc] init];
+ childrenArray = [[fPresetsOutlineView itemAtRow:index] objectForKey:@"ChildrenArray"];
+ [childrenArray addObject:item];
+ [[fPresetsOutlineView itemAtRow:index] setObject:[NSMutableArray arrayWithArray: childrenArray] forKey:@"ChildrenArray"];
+ [childrenArray autorelease];
+ }
+ else // We are not, so we just move the preset into the existing array
+ {
+ NSMutableIndexSet *moveItems = [NSMutableIndexSet indexSet];
+ id obj;
+ NSEnumerator *enumerator = [fDraggedNodes objectEnumerator];
+ while (obj = [enumerator nextObject])
+ {
+ [moveItems addIndex:[UserPresets indexOfObject:obj]];
+ }
+ // Successful drop, lets rearrange the view and save it all
+ [self moveObjectsInPresetsArray:UserPresets fromIndexes:moveItems toIndex: index];
}
- // Successful drop, lets rearrange the view and save it all
- [self moveObjectsInPresetsArray:UserPresets fromIndexes:moveItems toIndex: index];
[fPresetsOutlineView reloadData];
[self savePreset];
return YES;
- (IBAction)selectPreset:(id)sender
{
-
- if ([fPresetsOutlineView selectedRow] >= 0)
+
+ if ([fPresetsOutlineView selectedRow] >= 0 && [[[fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]] objectForKey:@"Folder"] intValue] != 1)
{
chosenPreset = [fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]];
- /* we set the preset display field in main window here */
[fPresetSelectedDisplay setStringValue:[chosenPreset objectForKey:@"PresetName"]];
+
if ([[chosenPreset objectForKey:@"Default"] intValue] == 1)
{
[fPresetSelectedDisplay setStringValue:[NSString stringWithFormat:@"%@ (Default)", [chosenPreset objectForKey:@"PresetName"]]];
{
[fPresetSelectedDisplay setStringValue:[chosenPreset objectForKey:@"PresetName"]];
}
+
/* File Format */
[fDstFormatPopUp selectItemWithTitle:[chosenPreset objectForKey:@"FileFormat"]];
[self formatPopUpChanged:nil];
-
+
/* Chapter Markers*/
[fCreateChapterMarkers setState:[[chosenPreset objectForKey:@"ChapterMarkers"] intValue]];
/* Allow Mpeg4 64 bit formatting +4GB file sizes */
[fDstMp4LargeFileCheck setState:[[chosenPreset objectForKey:@"Mp4LargeFile"] intValue]];
/* Mux mp4 with http optimization */
[fDstMp4HttpOptFileCheck setState:[[chosenPreset objectForKey:@"Mp4HttpOptimize"] intValue]];
-
+
/* Video encoder */
/* We set the advanced opt string here if applicable*/
[fAdvancedOptions setOptions:[chosenPreset objectForKey:@"x264Option"]];
{
[fVidEncoderPopUp selectItemWithTitle:[chosenPreset objectForKey:@"VideoEncoder"]];
}
-
+
/* Lets run through the following functions to get variables set there */
[self videoEncoderPopUpChanged:nil];
/* Set the state of ipod compatible with Mp4iPodCompatible. Only for x264*/
[fDstMp4iPodFileCheck setState:[[chosenPreset objectForKey:@"Mp4iPodCompatible"] intValue]];
[self calculateBitrate:nil];
-
+
/* Video quality */
[fVidQualityMatrix selectCellAtRow:[[chosenPreset objectForKey:@"VideoQualityType"] intValue] column:0];
-
+
[fVidTargetSizeField setStringValue:[chosenPreset objectForKey:@"VideoTargetSize"]];
[fVidBitrateField setStringValue:[chosenPreset objectForKey:@"VideoAvgBitrate"]];
[fVidQualitySlider setFloatValue:[[chosenPreset objectForKey:@"VideoQualitySlider"] floatValue]];
-
+
[self videoMatrixChanged:nil];
-
+
/* 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*/
{
[fVidRatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"VideoFramerate"]];
}
-
+
/* GrayScale */
[fVidGrayscaleCheck setState:[[chosenPreset objectForKey:@"VideoGrayScale"] intValue]];
-
+
/* 2 Pass Encoding */
[fVidTwoPassCheck setState:[[chosenPreset objectForKey:@"VideoTwoPass"] intValue]];
[self twoPassCheckboxChanged:nil];
/* Turbo 1st pass for 2 Pass Encoding */
[fVidTurboPassCheck setState:[[chosenPreset objectForKey:@"VideoTurboTwoPass"] intValue]];
-
+
/*Audio*/
if ([chosenPreset objectForKey:@"FileCodecs"])
{
}
}
/* We detect here if we have the old audio sample rate and if so we apply samplerate and bitrate to the existing four tracks if chosen
- * UNLESS the CodecPopUp is AC3 in which case the preset values are ignored in favor of rates set in audioTrackMixdownChanged*/
+ * UNLESS the CodecPopUp is AC3 in which case the preset values are ignored in favor of rates set in audioTrackMixdownChanged*/
if ([chosenPreset objectForKey:@"AudioSampleRate"])
{
if ([fAudLang1PopUp indexOfSelectedItem] > 0 && [fAudTrack1CodecPopUp titleOfSelectedItem] != @"AC3 Passthru")
[fAudTrack4DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio4TrackDRCSlider"] floatValue]];
[self audioDRCSliderChanged: fAudTrack4DrcSlider];
}
-
-
+
+
}
-
+
/* We now cleanup any extra audio tracks that may be previously set if we need to, we do it here so we don't have to
* duplicate any code for legacy presets.*/
/* First we handle the legacy Codecs crazy AVC/H.264 Video / AAC + AC3 Audio atv hybrid */
[self audioTrackPopUpChanged: fAudLang4PopUp];
}
}
-
+
/*Subtitles*/
[fSubPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Subtitles"]];
/* Forced Subtitles */
[fSubForcedCheck setState:[[chosenPreset objectForKey:@"SubtitlesForced"] intValue]];
-
+
/* Picture Settings */
/* Note: objectForKey:@"UsesPictureSettings" now refers to picture size, this encompasses:
* height, width, keep ar, anamorphic and crop settings.
if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] > 0)
{
hb_job_t * job = fTitle->job;
+
+ /* If Cropping is set to custom, then recall all four crop values from
+ when the preset was created and apply them */
+ if ([[chosenPreset objectForKey:@"PictureAutoCrop"] intValue] == 0)
+ {
+ [fPictureController setAutoCrop:NO];
+
+ /* Here we use the custom crop values saved at the time the preset was saved */
+ job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"] intValue];
+ job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"] intValue];
+ job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"] intValue];
+ job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"] intValue];
+
+ }
+ else /* if auto crop has been saved in preset, set to auto and use post scan auto crop */
+ {
+ [fPictureController setAutoCrop:YES];
+ /* Here we use the auto crop values determined right after scan */
+ job->crop[0] = AutoCropTop;
+ job->crop[1] = AutoCropBottom;
+ job->crop[2] = AutoCropLeft;
+ job->crop[3] = AutoCropRight;
+
+ }
+
+
/* Check to see if the objectForKey:@"UsesPictureSettings is 2 which is "Use Max for the source */
if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] == 2 || [[chosenPreset objectForKey:@"UsesMaxPictureSettings"] intValue] == 1)
{
job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue];
- /* If Cropping is set to custom, then recall all four crop values from
- when the preset was created and apply them */
- if ([[chosenPreset objectForKey:@"PictureAutoCrop"] intValue] == 0)
- {
- [fPictureController setAutoCrop:NO];
-
- /* Here we use the custom crop values saved at the time the preset was saved */
- job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"] intValue];
- job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"] intValue];
- job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"] intValue];
- job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"] intValue];
-
- }
- else /* if auto crop has been saved in preset, set to auto and use post scan auto crop */
- {
- [fPictureController setAutoCrop:YES];
- /* Here we use the auto crop values determined right after scan */
- job->crop[0] = AutoCropTop;
- job->crop[1] = AutoCropBottom;
- job->crop[2] = AutoCropLeft;
- job->crop[3] = AutoCropRight;
-
- }
- /* If the preset has no objectForKey:@"UsesPictureFilters", then we know it is a legacy preset
+ /* If the preset has no objectForKey:@"UsesPictureFilters", then we know it is a legacy preset
* and handle the filters here as before.
* NOTE: This should be removed when the update presets code is done as we can be assured that legacy
* presets are updated to work properly with new keys.
/* VFR */
if ([[chosenPreset objectForKey:@"VFR"] intValue] == 1)
{
- [fPictureController setVFR:[[chosenPreset objectForKey:@"VFR"] intValue]];
- }
- else
- {
- [fPictureController setVFR:0];
+ // We make sure that framerate is set to Same as source variable
+ // detelecine will take care of itself right below
+ //[fPictureController setVFR:[[chosenPreset objectForKey:@"VFR"] intValue]];
}
+
/* Detelecine */
if ([[chosenPreset objectForKey:@"PictureDetelecine"] intValue] == 1)
{
/* Deblock */
if ([[chosenPreset objectForKey:@"PictureDeblock"] intValue] == 1)
{
- [fPictureController setDeblock:[[chosenPreset objectForKey:@"PictureDeblock"] intValue]];
+ /* since we used to use 1 to turn on deblock, we now use a 5 in our sliding scale */
+ [fPictureController setDeblock:5];
}
else
{
[fPictureController setDeblock:0];
+
}
-
- [self calculatePictureSizing:nil];
+
+ [self calculatePictureSizing:nil];
}
-
+
}
-
-
+
+
}
/* If the preset has an objectForKey:@"UsesPictureFilters", then we know it is a newer style filters preset
* and handle the filters here depending on whether or not the preset specifies applying the filter.
{
[fPictureController setDeinterlace:0];
}
- /* VFR */
- if ([[chosenPreset objectForKey:@"VFR"] intValue] == 1)
- {
- [fPictureController setVFR:[[chosenPreset objectForKey:@"VFR"] intValue]];
- }
- else
- {
- [fPictureController setVFR:0];
- }
+
/* Detelecine */
if ([[chosenPreset objectForKey:@"PictureDetelecine"] intValue] == 1)
{
/* Deblock */
if ([[chosenPreset objectForKey:@"PictureDeblock"] intValue] == 1)
{
- [fPictureController setDeblock:[[chosenPreset objectForKey:@"PictureDeblock"] intValue]];
+ /* if its a one, then its the old on/off deblock, set on to 5*/
+ [fPictureController setDeblock:5];
}
else
{
- [fPictureController setDeblock:0];
+ /* use the settings intValue */
+ [fPictureController setDeblock:[[chosenPreset objectForKey:@"PictureDeblock"] intValue]];
}
/* Decomb */
/* Even though we currently allow for a custom setting for decomb, ultimately it will only have Off and
[fPresetNewPicSettingsPopUp selectItemAtIndex: 0];
/* Uncheck the preset use filters checkbox */
[fPresetNewPicFiltersCheck setState:NSOffState];
+ // fPresetNewFolderCheck
+ [fPresetNewFolderCheck setState:NSOffState];
/* Erase info from the input fields*/
[fPresetNewName setStringValue: @""];
[fPresetNewDesc setStringValue: @""];
NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
/* Get the New Preset Name from the field in the AddPresetPanel */
[preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"];
+ /* Set whether or not this is to be a folder fPresetNewFolderCheck*/
+ [preset setObject:[NSNumber numberWithBool:[fPresetNewFolderCheck state]] forKey:@"Folder"];
/*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
[preset setObject:[NSNumber numberWithInt:1] forKey:@"Type"];
/*Set whether or not this is default, at creation set to 0*/
[preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
- /*Get the whether or not to apply pic Size and Cropping (includes Anamorphic)*/
- [preset setObject:[NSNumber numberWithInt:[fPresetNewPicSettingsPopUp indexOfSelectedItem]] forKey:@"UsesPictureSettings"];
- /* Get whether or not to use the current Picture Filter settings for the preset */
- [preset setObject:[NSNumber numberWithInt:[fPresetNewPicFiltersCheck state]] forKey:@"UsesPictureFilters"];
-
- /* Get New Preset Description from the field in the AddPresetPanel*/
- [preset setObject:[fPresetNewDesc stringValue] forKey:@"PresetDescription"];
- /* File Format */
- [preset setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
- /* Chapter Markers fCreateChapterMarkers*/
- [preset setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"];
- /* Allow Mpeg4 64 bit formatting +4GB file sizes */
- [preset setObject:[NSNumber numberWithInt:[fDstMp4LargeFileCheck state]] forKey:@"Mp4LargeFile"];
- /* Mux mp4 with http optimization */
- [preset setObject:[NSNumber numberWithInt:[fDstMp4HttpOptFileCheck state]] forKey:@"Mp4HttpOptimize"];
- /* Add iPod uuid atom */
- [preset setObject:[NSNumber numberWithInt:[fDstMp4iPodFileCheck state]] forKey:@"Mp4iPodCompatible"];
-
- /* Codecs */
- /* Video encoder */
- [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
- /* x264 Option String */
- [preset setObject:[fAdvancedOptions optionsString] forKey:@"x264Option"];
-
- [preset setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"];
- [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
- [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
- [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
-
- /* Video framerate */
- if ([fVidRatePopUp indexOfSelectedItem] == 0) // Same as source is selected
- {
- [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
- }
- else // we can record the actual titleOfSelectedItem
- {
- [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
- }
- /* GrayScale */
- [preset setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"];
- /* 2 Pass Encoding */
- [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
- /* Turbo 2 pass Encoding fVidTurboPassCheck*/
- [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:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
- [preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
-
- /* Set crop settings here */
- [preset setObject:[NSNumber numberWithInt:[fPictureController autoCrop]] forKey:@"PictureAutoCrop"];
- [preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
- [preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
- [preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
- [preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
-
- /* Picture Filters */
- [preset setObject:[NSNumber numberWithInt:[fPictureController deinterlace]] forKey:@"PictureDeinterlace"];
- [preset setObject:[NSNumber numberWithInt:[fPictureController detelecine]] forKey:@"PictureDetelecine"];
- [preset setObject:[NSNumber numberWithInt:[fPictureController vfr]] forKey:@"VFR"];
- [preset setObject:[NSNumber numberWithInt:[fPictureController denoise]] forKey:@"PictureDenoise"];
- [preset setObject:[NSNumber numberWithInt:[fPictureController deblock]] forKey:@"PictureDeblock"];
- [preset setObject:[NSNumber numberWithInt:[fPictureController decomb]] forKey:@"PictureDecomb"];
-
-
- /*Audio*/
- if ([fAudLang1PopUp indexOfSelectedItem] > 0)
- {
- [preset setObject:[NSNumber numberWithInt:[fAudLang1PopUp indexOfSelectedItem]] forKey:@"Audio1Track"];
- [preset setObject:[fAudLang1PopUp titleOfSelectedItem] forKey:@"Audio1TrackDescription"];
- [preset setObject:[fAudTrack1CodecPopUp titleOfSelectedItem] forKey:@"Audio1Encoder"];
- [preset setObject:[fAudTrack1MixPopUp titleOfSelectedItem] forKey:@"Audio1Mixdown"];
- [preset setObject:[fAudTrack1RatePopUp titleOfSelectedItem] forKey:@"Audio1Samplerate"];
- [preset setObject:[fAudTrack1BitratePopUp titleOfSelectedItem] forKey:@"Audio1Bitrate"];
- [preset setObject:[NSNumber numberWithFloat:[fAudTrack1DrcSlider floatValue]] forKey:@"Audio1TrackDRCSlider"];
- }
- if ([fAudLang2PopUp indexOfSelectedItem] > 0)
- {
- [preset setObject:[NSNumber numberWithInt:[fAudLang2PopUp indexOfSelectedItem]] forKey:@"Audio2Track"];
- [preset setObject:[fAudLang2PopUp titleOfSelectedItem] forKey:@"Audio2TrackDescription"];
- [preset setObject:[fAudTrack2CodecPopUp titleOfSelectedItem] forKey:@"Audio2Encoder"];
- [preset setObject:[fAudTrack2MixPopUp titleOfSelectedItem] forKey:@"Audio2Mixdown"];
- [preset setObject:[fAudTrack2RatePopUp titleOfSelectedItem] forKey:@"Audio2Samplerate"];
- [preset setObject:[fAudTrack2BitratePopUp titleOfSelectedItem] forKey:@"Audio2Bitrate"];
- [preset setObject:[NSNumber numberWithFloat:[fAudTrack2DrcSlider floatValue]] forKey:@"Audio2TrackDRCSlider"];
- }
- if ([fAudLang3PopUp indexOfSelectedItem] > 0)
+ if ([fPresetNewFolderCheck state] == YES)
{
- [preset setObject:[NSNumber numberWithInt:[fAudLang3PopUp indexOfSelectedItem]] forKey:@"Audio3Track"];
- [preset setObject:[fAudLang3PopUp titleOfSelectedItem] forKey:@"Audio3TrackDescription"];
- [preset setObject:[fAudTrack3CodecPopUp titleOfSelectedItem] forKey:@"Audio3Encoder"];
- [preset setObject:[fAudTrack3MixPopUp titleOfSelectedItem] forKey:@"Audio3Mixdown"];
- [preset setObject:[fAudTrack3RatePopUp titleOfSelectedItem] forKey:@"Audio3Samplerate"];
- [preset setObject:[fAudTrack3BitratePopUp titleOfSelectedItem] forKey:@"Audio3Bitrate"];
- [preset setObject:[NSNumber numberWithFloat:[fAudTrack3DrcSlider floatValue]] forKey:@"Audio3TrackDRCSlider"];
+ /* initialize and set an empty array for children here since we are a new folder */
+ NSMutableArray *childrenArray = [[NSMutableArray alloc] init];
+ [preset setObject:[NSMutableArray arrayWithArray: childrenArray] forKey:@"ChildrenArray"];
+ [childrenArray autorelease];
}
- if ([fAudLang4PopUp indexOfSelectedItem] > 0)
+ else // we are not creating a preset folder, so we go ahead with the rest of the preset info
{
- [preset setObject:[NSNumber numberWithInt:[fAudLang4PopUp indexOfSelectedItem]] forKey:@"Audio4Track"];
- [preset setObject:[fAudLang4PopUp titleOfSelectedItem] forKey:@"Audio4TrackDescription"];
- [preset setObject:[fAudTrack4CodecPopUp titleOfSelectedItem] forKey:@"Audio4Encoder"];
- [preset setObject:[fAudTrack4MixPopUp titleOfSelectedItem] forKey:@"Audio4Mixdown"];
- [preset setObject:[fAudTrack4RatePopUp titleOfSelectedItem] forKey:@"Audio4Samplerate"];
- [preset setObject:[fAudTrack4BitratePopUp titleOfSelectedItem] forKey:@"Audio4Bitrate"];
- [preset setObject:[NSNumber numberWithFloat:[fAudTrack4DrcSlider floatValue]] forKey:@"Audio4TrackDRCSlider"];
+ /*Get the whether or not to apply pic Size and Cropping (includes Anamorphic)*/
+ [preset setObject:[NSNumber numberWithInt:[fPresetNewPicSettingsPopUp indexOfSelectedItem]] forKey:@"UsesPictureSettings"];
+ /* Get whether or not to use the current Picture Filter settings for the preset */
+ [preset setObject:[NSNumber numberWithInt:[fPresetNewPicFiltersCheck state]] forKey:@"UsesPictureFilters"];
+
+ /* Get New Preset Description from the field in the AddPresetPanel*/
+ [preset setObject:[fPresetNewDesc stringValue] forKey:@"PresetDescription"];
+ /* File Format */
+ [preset setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
+ /* Chapter Markers fCreateChapterMarkers*/
+ [preset setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"];
+ /* Allow Mpeg4 64 bit formatting +4GB file sizes */
+ [preset setObject:[NSNumber numberWithInt:[fDstMp4LargeFileCheck state]] forKey:@"Mp4LargeFile"];
+ /* Mux mp4 with http optimization */
+ [preset setObject:[NSNumber numberWithInt:[fDstMp4HttpOptFileCheck state]] forKey:@"Mp4HttpOptimize"];
+ /* Add iPod uuid atom */
+ [preset setObject:[NSNumber numberWithInt:[fDstMp4iPodFileCheck state]] forKey:@"Mp4iPodCompatible"];
+
+ /* Codecs */
+ /* Video encoder */
+ [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
+ /* x264 Option String */
+ [preset setObject:[fAdvancedOptions optionsString] forKey:@"x264Option"];
+
+ [preset setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"];
+ [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
+ [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
+ [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+
+ /* Video framerate */
+ if ([fVidRatePopUp indexOfSelectedItem] == 0) // Same as source is selected
+ {
+ [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
+ }
+ else // we can record the actual titleOfSelectedItem
+ {
+ [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
+ }
+ /* GrayScale */
+ [preset setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"];
+ /* 2 Pass Encoding */
+ [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
+ /* Turbo 2 pass Encoding fVidTurboPassCheck*/
+ [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:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
+ [preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
+
+ /* Set crop settings here */
+ [preset setObject:[NSNumber numberWithInt:[fPictureController autoCrop]] forKey:@"PictureAutoCrop"];
+ [preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
+ [preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
+ [preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
+ [preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
+
+ /* Picture Filters */
+ [preset setObject:[NSNumber numberWithInt:[fPictureController deinterlace]] forKey:@"PictureDeinterlace"];
+ [preset setObject:[NSNumber numberWithInt:[fPictureController detelecine]] forKey:@"PictureDetelecine"];
+ //[preset setObject:[NSNumber numberWithInt:[fPictureController vfr]] forKey:@"VFR"];
+ [preset setObject:[NSNumber numberWithInt:[fPictureController denoise]] forKey:@"PictureDenoise"];
+ [preset setObject:[NSNumber numberWithInt:[fPictureController deblock]] forKey:@"PictureDeblock"];
+ [preset setObject:[NSNumber numberWithInt:[fPictureController decomb]] forKey:@"PictureDecomb"];
+
+
+ /*Audio*/
+ if ([fAudLang1PopUp indexOfSelectedItem] > 0)
+ {
+ [preset setObject:[NSNumber numberWithInt:[fAudLang1PopUp indexOfSelectedItem]] forKey:@"Audio1Track"];
+ [preset setObject:[fAudLang1PopUp titleOfSelectedItem] forKey:@"Audio1TrackDescription"];
+ [preset setObject:[fAudTrack1CodecPopUp titleOfSelectedItem] forKey:@"Audio1Encoder"];
+ [preset setObject:[fAudTrack1MixPopUp titleOfSelectedItem] forKey:@"Audio1Mixdown"];
+ [preset setObject:[fAudTrack1RatePopUp titleOfSelectedItem] forKey:@"Audio1Samplerate"];
+ [preset setObject:[fAudTrack1BitratePopUp titleOfSelectedItem] forKey:@"Audio1Bitrate"];
+ [preset setObject:[NSNumber numberWithFloat:[fAudTrack1DrcSlider floatValue]] forKey:@"Audio1TrackDRCSlider"];
+ }
+ if ([fAudLang2PopUp indexOfSelectedItem] > 0)
+ {
+ [preset setObject:[NSNumber numberWithInt:[fAudLang2PopUp indexOfSelectedItem]] forKey:@"Audio2Track"];
+ [preset setObject:[fAudLang2PopUp titleOfSelectedItem] forKey:@"Audio2TrackDescription"];
+ [preset setObject:[fAudTrack2CodecPopUp titleOfSelectedItem] forKey:@"Audio2Encoder"];
+ [preset setObject:[fAudTrack2MixPopUp titleOfSelectedItem] forKey:@"Audio2Mixdown"];
+ [preset setObject:[fAudTrack2RatePopUp titleOfSelectedItem] forKey:@"Audio2Samplerate"];
+ [preset setObject:[fAudTrack2BitratePopUp titleOfSelectedItem] forKey:@"Audio2Bitrate"];
+ [preset setObject:[NSNumber numberWithFloat:[fAudTrack2DrcSlider floatValue]] forKey:@"Audio2TrackDRCSlider"];
+ }
+ if ([fAudLang3PopUp indexOfSelectedItem] > 0)
+ {
+ [preset setObject:[NSNumber numberWithInt:[fAudLang3PopUp indexOfSelectedItem]] forKey:@"Audio3Track"];
+ [preset setObject:[fAudLang3PopUp titleOfSelectedItem] forKey:@"Audio3TrackDescription"];
+ [preset setObject:[fAudTrack3CodecPopUp titleOfSelectedItem] forKey:@"Audio3Encoder"];
+ [preset setObject:[fAudTrack3MixPopUp titleOfSelectedItem] forKey:@"Audio3Mixdown"];
+ [preset setObject:[fAudTrack3RatePopUp titleOfSelectedItem] forKey:@"Audio3Samplerate"];
+ [preset setObject:[fAudTrack3BitratePopUp titleOfSelectedItem] forKey:@"Audio3Bitrate"];
+ [preset setObject:[NSNumber numberWithFloat:[fAudTrack3DrcSlider floatValue]] forKey:@"Audio3TrackDRCSlider"];
+ }
+ if ([fAudLang4PopUp indexOfSelectedItem] > 0)
+ {
+ [preset setObject:[NSNumber numberWithInt:[fAudLang4PopUp indexOfSelectedItem]] forKey:@"Audio4Track"];
+ [preset setObject:[fAudLang4PopUp titleOfSelectedItem] forKey:@"Audio4TrackDescription"];
+ [preset setObject:[fAudTrack4CodecPopUp titleOfSelectedItem] forKey:@"Audio4Encoder"];
+ [preset setObject:[fAudTrack4MixPopUp titleOfSelectedItem] forKey:@"Audio4Mixdown"];
+ [preset setObject:[fAudTrack4RatePopUp titleOfSelectedItem] forKey:@"Audio4Samplerate"];
+ [preset setObject:[fAudTrack4BitratePopUp titleOfSelectedItem] forKey:@"Audio4Bitrate"];
+ [preset setObject:[NSNumber numberWithFloat:[fAudTrack4DrcSlider floatValue]] forKey:@"Audio4TrackDRCSlider"];
+ }
+
+ /* Subtitles*/
+ [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"];
+ /* Forced Subtitles */
+ [preset setObject:[NSNumber numberWithInt:[fSubForcedCheck state]] forKey:@"SubtitlesForced"];
}
-
- /* Subtitles*/
- [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"];
- /* Forced Subtitles */
- [preset setObject:[NSNumber numberWithInt:[fSubForcedCheck state]] forKey:@"SubtitlesForced"];
-
[preset autorelease];
return preset;
-
+
}
- (void)savePreset
- (IBAction)deletePreset:(id)sender
{
- int status;
- NSEnumerator *enumerator;
- NSNumber *index;
- NSMutableArray *tempArray;
- id tempObject;
+
if ( [fPresetsOutlineView numberOfSelectedRows] == 0 )
+ {
return;
+ }
/* Alert user before deleting preset */
- /* Comment out for now, tie to user pref eventually */
-
- //NSBeep();
+ int status;
status = NSRunAlertPanel(@"Warning!", @"Are you sure that you want to delete the selected preset?", @"OK", @"Cancel", nil);
- if ( status == NSAlertDefaultReturn ) {
- enumerator = [fPresetsOutlineView selectedRowEnumerator];
+ if ( status == NSAlertDefaultReturn )
+ {
+ int presetToModLevel = [fPresetsOutlineView levelForItem: [fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]]];
+ NSDictionary *presetToMod = [fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]];
+ NSDictionary *presetToModParent = [fPresetsOutlineView parentForItem: presetToMod];
+
+ NSEnumerator *enumerator;
+ NSMutableArray *presetsArrayToMod;
+ NSMutableArray *tempArray;
+ id tempObject;
+ /* If we are a root level preset, we are modding the UserPresets array */
+ if (presetToModLevel == 0)
+ {
+ presetsArrayToMod = UserPresets;
+ }
+ else // We have a parent preset, so we modify the chidren array object for key
+ {
+ presetsArrayToMod = [presetToModParent objectForKey:@"ChildrenArray"];
+ }
+
+ enumerator = [presetsArrayToMod objectEnumerator];
tempArray = [NSMutableArray array];
- while ( (index = [enumerator nextObject]) ) {
- tempObject = [UserPresets objectAtIndex:[index intValue]];
- [tempArray addObject:tempObject];
+ while (tempObject = [enumerator nextObject])
+ {
+ NSDictionary *thisPresetDict = tempObject;
+ if (thisPresetDict == presetToMod)
+ {
+ [tempArray addObject:tempObject];
+ }
}
- [UserPresets removeObjectsInArray:tempArray];
+ [presetsArrayToMod removeObjectsInArray:tempArray];
[fPresetsOutlineView reloadData];
[self savePreset];
}
- (IBAction)getDefaultPresets:(id)sender
{
- int i = 0;
+ presetHbDefault = nil;
+ presetUserDefault = nil;
+ presetUserDefaultParent = nil;
+ presetUserDefaultParentParent = nil;
+ NSMutableDictionary *presetHbDefaultParent = nil;
+ NSMutableDictionary *presetHbDefaultParentParent = nil;
+
+ int i = 0;
+ BOOL userDefaultFound = NO;
presetCurrentBuiltInCount = 0;
+ /* First we iterate through the root UserPresets array to check for defaults */
NSEnumerator *enumerator = [UserPresets objectEnumerator];
id tempObject;
while (tempObject = [enumerator nextObject])
{
- NSDictionary *thisPresetDict = tempObject;
+ NSMutableDictionary *thisPresetDict = tempObject;
if ([[thisPresetDict objectForKey:@"Default"] intValue] == 1) // 1 is HB default
{
- presetHbDefault = i;
+ presetHbDefault = thisPresetDict;
}
if ([[thisPresetDict objectForKey:@"Default"] intValue] == 2) // 2 is User specified default
{
- presetUserDefault = i;
- }
+ presetUserDefault = thisPresetDict;
+ userDefaultFound = YES;
+ }
if ([[thisPresetDict objectForKey:@"Type"] intValue] == 0) // Type 0 is a built in preset
{
presetCurrentBuiltInCount++; // <--increment the current number of built in presets
}
i++;
+
+ /* if we run into a folder, go to level 1 and iterate through the children arrays for the default */
+ if ([thisPresetDict objectForKey:@"ChildrenArray"])
+ {
+ NSMutableDictionary *thisPresetDictParent = thisPresetDict;
+ NSEnumerator *enumerator = [[thisPresetDict objectForKey:@"ChildrenArray"] objectEnumerator];
+ id tempObject;
+ while (tempObject = [enumerator nextObject])
+ {
+ NSMutableDictionary *thisPresetDict = tempObject;
+ if ([[thisPresetDict objectForKey:@"Default"] intValue] == 1) // 1 is HB default
+ {
+ presetHbDefault = thisPresetDict;
+ presetHbDefaultParent = thisPresetDictParent;
+ }
+ if ([[thisPresetDict objectForKey:@"Default"] intValue] == 2) // 2 is User specified default
+ {
+ presetUserDefault = thisPresetDict;
+ presetUserDefaultParent = thisPresetDictParent;
+ userDefaultFound = YES;
+ }
+
+ /* if we run into a folder, go to level 2 and iterate through the children arrays for the default */
+ if ([thisPresetDict objectForKey:@"ChildrenArray"])
+ {
+ NSMutableDictionary *thisPresetDictParentParent = thisPresetDict;
+ NSEnumerator *enumerator = [[thisPresetDict objectForKey:@"ChildrenArray"] objectEnumerator];
+ id tempObject;
+ while (tempObject = [enumerator nextObject])
+ {
+ NSMutableDictionary *thisPresetDict = tempObject;
+ if ([[thisPresetDict objectForKey:@"Default"] intValue] == 1) // 1 is HB default
+ {
+ presetHbDefault = thisPresetDict;
+ presetHbDefaultParent = thisPresetDictParent;
+ presetHbDefaultParentParent = thisPresetDictParentParent;
+ }
+ if ([[thisPresetDict objectForKey:@"Default"] intValue] == 2) // 2 is User specified default
+ {
+ presetUserDefault = thisPresetDict;
+ presetUserDefaultParent = thisPresetDictParent;
+ presetUserDefaultParentParent = thisPresetDictParentParent;
+ userDefaultFound = YES;
+ }
+
+ }
+ }
+ }
+ }
+
}
+ /* check to see if a user specified preset was found, if not then assign the parents for
+ * the presetHbDefault so that we can open the parents for the nested presets
+ */
+ if (userDefaultFound == NO)
+ {
+ presetUserDefaultParent = presetHbDefaultParent;
+ presetUserDefaultParentParent = presetHbDefaultParentParent;
+ }
}
- (IBAction)setDefaultPreset:(id)sender
{
+/* We need to determine if the item is a folder */
+ if ([[[fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]] objectForKey:@"Folder"] intValue] == 1)
+ {
+ return;
+ }
+
int i = 0;
NSEnumerator *enumerator = [UserPresets objectEnumerator];
id tempObject;
/* First make sure the old user specified default preset is removed */
- while (tempObject = [enumerator nextObject])
+ while (tempObject = [enumerator nextObject])
{
- /* make sure we are not removing the default HB preset */
- if ([[[UserPresets objectAtIndex:i] objectForKey:@"Default"] intValue] != 1) // 1 is HB default
+ NSMutableDictionary *thisPresetDict = tempObject;
+ if ([[tempObject objectForKey:@"Default"] intValue] != 1) // if not the default HB Preset, set to 0
{
- [[UserPresets objectAtIndex:i] setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+ [[UserPresets objectAtIndex:i] setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
}
- i++;
- }
- /* Second, go ahead and set the appropriate user specfied preset */
- /* we get the chosen preset from the UserPresets array */
- if ([[[UserPresets objectAtIndex:[fPresetsOutlineView selectedRow]] objectForKey:@"Default"] intValue] != 1) // 1 is HB default
- {
- [[UserPresets objectAtIndex:[fPresetsOutlineView selectedRow]] setObject:[NSNumber numberWithInt:2] forKey:@"Default"];
+
+ /* if we run into a folder, go to level 1 and iterate through the children arrays for the default */
+ if ([thisPresetDict objectForKey:@"ChildrenArray"])
+ {
+ NSEnumerator *enumerator = [[thisPresetDict objectForKey:@"ChildrenArray"] objectEnumerator];
+ id tempObject;
+ int ii = 0;
+ while (tempObject = [enumerator nextObject])
+ {
+ NSMutableDictionary *thisPresetDict1 = tempObject;
+ if ([[tempObject objectForKey:@"Default"] intValue] != 1) // if not the default HB Preset, set to 0
+ {
+ [[[thisPresetDict objectForKey:@"ChildrenArray"] objectAtIndex:ii] setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+ }
+ /* if we run into a folder, go to level 2 and iterate through the children arrays for the default */
+ if ([thisPresetDict1 objectForKey:@"ChildrenArray"])
+ {
+ NSEnumerator *enumerator = [[thisPresetDict1 objectForKey:@"ChildrenArray"] objectEnumerator];
+ id tempObject;
+ int iii = 0;
+ while (tempObject = [enumerator nextObject])
+ {
+ if ([[tempObject objectForKey:@"Default"] intValue] != 1) // if not the default HB Preset, set to 0
+ {
+ [[[thisPresetDict1 objectForKey:@"ChildrenArray"] objectAtIndex:iii] setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+ }
+ iii++;
+ }
+ }
+ ii++;
+ }
+
+ }
+ i++;
}
- /*FIX ME: I think we now need to use the items not rows in NSOutlineView */
- presetUserDefault = [fPresetsOutlineView selectedRow];
-
- /* We save all of the preset data here */
+
+
+ int presetToModLevel = [fPresetsOutlineView levelForItem: [fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]]];
+ NSDictionary *presetToMod = [fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]];
+ NSDictionary *presetToModParent = [fPresetsOutlineView parentForItem: presetToMod];
+
+
+ NSMutableArray *presetsArrayToMod;
+ NSMutableArray *tempArray;
+
+ /* If we are a root level preset, we are modding the UserPresets array */
+ if (presetToModLevel == 0)
+ {
+ presetsArrayToMod = UserPresets;
+ }
+ else // We have a parent preset, so we modify the chidren array object for key
+ {
+ presetsArrayToMod = [presetToModParent objectForKey:@"ChildrenArray"];
+ }
+
+ enumerator = [presetsArrayToMod objectEnumerator];
+ tempArray = [NSMutableArray array];
+ int iiii = 0;
+ while (tempObject = [enumerator nextObject])
+ {
+ NSDictionary *thisPresetDict = tempObject;
+ if (thisPresetDict == presetToMod)
+ {
+ if ([[tempObject objectForKey:@"Default"] intValue] != 1) // if not the default HB Preset, set to 2
+ {
+ [[presetsArrayToMod objectAtIndex:iiii] setObject:[NSNumber numberWithInt:2] forKey:@"Default"];
+ }
+ }
+ iiii++;
+ }
+
+
+ /* We save all of the preset data here */
[self savePreset];
- /* We Reload the New Table data for presets */
+ /* We Reload the New Table data for presets */
[fPresetsOutlineView reloadData];
}
- (IBAction)selectDefaultPreset:(id)sender
{
- /* if there is a user specified default, we use it */
+ NSMutableDictionary *presetToMod;
+ /* if there is a user specified default, we use it */
if (presetUserDefault)
{
- [fPresetsOutlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:presetUserDefault] byExtendingSelection:NO];
- [self selectPreset:nil];
- }
+ presetToMod = presetUserDefault;
+ }
else if (presetHbDefault) //else we use the built in default presetHbDefault
{
- [fPresetsOutlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:presetHbDefault] byExtendingSelection:NO];
- [self selectPreset:nil];
+ presetToMod = presetHbDefault;
}
+ else
+ {
+ return;
+ }
+
+ if (presetUserDefaultParent != nil)
+ {
+ [fPresetsOutlineView expandItem:presetUserDefaultParent];
+
+ }
+ if (presetUserDefaultParentParent != nil)
+ {
+ [fPresetsOutlineView expandItem:presetUserDefaultParentParent];
+
+ }
+
+ [fPresetsOutlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:[fPresetsOutlineView rowForItem: presetToMod]] byExtendingSelection:NO];
+ [self selectPreset:nil];
}
// By default, NSTableView only drags an image of the first column. Change this to
// drag an image of the queue's icon and PresetName columns.
- NSArray * cols = [NSArray arrayWithObjects: [self tableColumnWithIdentifier:@"icon"], [self tableColumnWithIdentifier:@"PresetName"], nil];
+ NSArray * cols = [NSArray arrayWithObjects: [self tableColumnWithIdentifier:@"PresetName"], nil];
return [super dragImageForRowsWithIndexes:dragRows tableColumns:cols event:dragEvent offset:dragImageOffset];
}