diff options
-rw-r--r-- | macosx/Controller.h | 31 | ||||
-rw-r--r-- | macosx/Controller.mm | 1826 | ||||
-rw-r--r-- | macosx/English.lproj/MainMenu.xib | 12 | ||||
-rw-r--r-- | macosx/English.lproj/Queue.xib | 908 | ||||
-rw-r--r-- | macosx/HBQueueController.h | 223 | ||||
-rw-r--r-- | macosx/HBQueueController.mm | 2503 |
6 files changed, 2302 insertions, 3201 deletions
diff --git a/macosx/Controller.h b/macosx/Controller.h index 4df14f944..897d833a1 100644 --- a/macosx/Controller.h +++ b/macosx/Controller.h @@ -203,6 +203,11 @@ BOOL fIsDragging; IBOutlet NSProgressIndicator * fRipIndicator; BOOL fRipIndicatorShown; + /* Queue File variables */ + NSString * QueueFile; + NSMutableArray * QueueFileArray; + int currentQueueEncodeIndex; // Used to track the currently encoding queueu item + /* User Preset variables here */ HBPresets * fPresetsBuiltin; IBOutlet NSDrawer * fPresetDrawer; @@ -231,13 +236,24 @@ BOOL fIsDragging; IBOutlet NSPopUpButton * fPresetsActionButton; hb_handle_t * fHandle; + + hb_handle_t * fQueueEncodeLibhb; // libhb for HB Encoding hb_title_t * fTitle; + hb_title_t * fQueueEncodeTitle; + int fEncodingQueueItem; // corresponds to the index of fJobGroups encoding item + int fPendingCount; // Number of various kinds of job groups in fJobGroups. + int fCompletedCount; + int fCanceledCount; + int fWorkingCount; + + /* integer to set to determine the previous state of encode 0==idle, 1==encoding, 2==cancelled*/ int fEncodeState; int currentScanCount; int currentSuccessfulScanCount; BOOL SuccessfulScan; + BOOL applyQueueToScan; NSString * currentSource; NSString * browsedSourceDisplayName; } @@ -271,7 +287,7 @@ BOOL fIsDragging; - (IBAction) audioTrackPopUpChanged: (id) sender mixdownToUse: (int) mixdownToUse; - (IBAction) audioTrackMixdownChanged: (id) sender; - (IBAction) subtitleSelectionChanged: (id) sender; - +- (void) prepareJob; - (IBAction) browseFile: (id) sender; - (void) browseFileDone: (NSSavePanel *) sheet returnCode: (int) returnCode contextInfo: (void *) contextInfo; @@ -284,6 +300,19 @@ BOOL fIsDragging; - (IBAction) calculatePictureSizing: (id) sender; - (IBAction) openMainWindow: (id) sender; +/* Queue File Stuff */ +- (void) loadQueueFile; +- (NSDictionary *)createQueueFileItem; +- (void)saveQueueFileItem; +- (void) incrementQueueItemDone:(int) queueItemDoneIndexNum; +- (void) performNewQueueScan:(NSString *) scanPath scanTitleNum: (int) scanTitleNum; +- (void) processNewQueueEncode; +- (void) clearQueueEncodedItems; +- (IBAction)applyQueueSettings:(id)sender; +- (void) removeQueueFileItem:(int) queueItemToRemove; +- (void) clearQueueAllItems; +- (void)moveObjectsInQueueArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(unsigned)insertIndex; +- (void)getQueueStats; - (IBAction) addToQueue: (id) sender; - (void) overwriteAddToQueueAlertDone: (NSWindow *) sheet returnCode: (int) returnCode contextInfo: (void *) contextInfo; diff --git a/macosx/Controller.mm b/macosx/Controller.mm index 8943fbbee..8a05d6737 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -37,7 +37,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [HBPreferencesController registerUserDefaults]; fHandle = NULL; - + fQueueEncodeLibhb = NULL; /* Check for check for the app support directory here as * outputPanel needs it right away, as may other future methods */ @@ -74,12 +74,14 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It { /* 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); - + /* Init a separate instance of libhb for user scanning and setting up jobs */ + fQueueEncodeLibhb = hb_init(HB_DEBUG_ALL, 0); + // Set the Growl Delegate [GrowlApplicationBridge setGrowlDelegate: self]; /* Init others controllers */ [fPictureController SetHandle: fHandle]; - [fQueueController setHandle: fHandle]; + [fQueueController setHandle: fQueueEncodeLibhb]; [fQueueController setHBController: self]; fChapterTitlesDelegate = [[ChapterTitles alloc] init]; @@ -101,10 +103,48 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [self showQueueWindow:nil]; [self openMainWindow:nil]; - + + /* We have to set the bool to tell hb what to do after a scan + * Initially we set it to NO until we start processing the queue + */ + applyQueueToScan = NO; + + /* Now we re-check the queue array to see if there are + * any remaining encodes to be done in it and ask the + * user if they want to reload the queue */ + if ([QueueFileArray count] > 0) + { + /*On Screen Notification*/ + NSString * alertTitle = [NSString stringWithFormat:NSLocalizedString(@"HandBrake Has Detected Item(s) From Your Previous Queue.", nil)]; + 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)); + // 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]; + } +} + +- (void) didDimissReloadQueue: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo +{ + if (returnCode == NSAlertOtherReturn) + { + [self clearQueueAllItems]; + } + + [self performSelectorOnMainThread:@selector(browseSources:) + withObject:nil waitUntilDone:NO]; } - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) app @@ -112,14 +152,13 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It // Warn if encoding a movie hb_state_t s; hb_get_state( fHandle, &s ); - HBJobGroup * jobGroup = [fQueueController currentJobGroup]; - if ( jobGroup && ( s.state != HB_STATE_IDLE ) ) + + if ( s.state != HB_STATE_IDLE ) { int result = NSRunCriticalAlertPanel( NSLocalizedString(@"Are you sure you want to quit HandBrake?", nil), - NSLocalizedString(@"%@ is currently encoding. 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, - jobGroup ? [jobGroup name] : @"A movie" ); + 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" ); if (result == NSAlertDefaultReturn) { @@ -153,6 +192,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [outputPanel release]; [fQueueController release]; hb_close(&fHandle); + hb_close(&fQueueEncodeLibhb); } @@ -171,10 +211,14 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It evaluate successive scans */ currentScanCount = 0; + /* Init UserPresets .plist */ [self loadPresets]; - - fRipIndicatorShown = NO; // initially out of view in the nib + + /* Init QueueFile .plist */ + [self loadQueueFile]; + + fRipIndicatorShown = NO; // initially out of view in the nib /* Show/Dont Show Presets drawer upon launch based on user preference DefaultPresetsDrawerShow*/ @@ -296,6 +340,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [self getDefaultPresets:nil]; /* lets initialize the current successful scancount here to 0 */ currentSuccessfulScanCount = 0; + + } - (void) enableUI: (bool) b @@ -448,11 +494,14 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It - (void) updateUI: (NSTimer *) timer { + + /* Update UI for fHandle (user scanning instance of libhb ) */ + hb_list_t * list; list = hb_get_titles( fHandle ); /* check to see if there has been a new scan done - this bypasses the constraints of HB_STATE_WORKING - not allowing setting a newly scanned source */ + this bypasses the constraints of HB_STATE_WORKING + not allowing setting a newly scanned source */ int checkScanCount = hb_get_scancount( fHandle ); if( checkScanCount > currentScanCount ) { @@ -462,14 +511,14 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [fScanIndicator setHidden: YES]; [self showNewScan:nil]; } - + hb_state_t s; hb_get_state( fHandle, &s ); - + switch( s.state ) { case HB_STATE_IDLE: - break; + break; #define p s.param.scanning case HB_STATE_SCANNING: { @@ -481,44 +530,116 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It break; } #undef p - + #define p s.param.scandone case HB_STATE_SCANDONE: { [fScanIndicator setIndeterminate: NO]; [fScanIndicator setDoubleValue: 0.0]; [fScanIndicator setHidden: YES]; - [self showNewScan:nil]; + [self writeToActivityLog:"ScanDone state received from fHandle"]; + [self showNewScan:nil]; [[fWindow toolbar] validateVisibleItems]; + break; } #undef p - + +#define p s.param.working + case HB_STATE_WORKING: + { + + break; + } +#undef p + +#define p s.param.muxing + case HB_STATE_MUXING: + { + + break; + } +#undef p + + case HB_STATE_PAUSED: + break; + + case HB_STATE_WORKDONE: + { + break; + } + } + + + /* Update UI for fQueueEncodeLibhb */ + // hb_list_t * list; + // list = hb_get_titles( fQueueEncodeLibhb ); //fQueueEncodeLibhb + /* check to see if there has been a new scan done + this bypasses the constraints of HB_STATE_WORKING + not allowing setting a newly scanned source */ + + checkScanCount = hb_get_scancount( fQueueEncodeLibhb ); + if( checkScanCount > currentScanCount ) + { + currentScanCount = checkScanCount; + [self writeToActivityLog:"currentScanCount received from fQueueEncodeLibhb"]; + } + + //hb_state_t s; + hb_get_state( fQueueEncodeLibhb, &s ); + + switch( s.state ) + { + case HB_STATE_IDLE: + break; +#define p s.param.scanning + case HB_STATE_SCANNING: + { + [fStatusField setStringValue: [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; + } +#undef p + +#define p s.param.scandone + case HB_STATE_SCANDONE: + { + [fRipIndicator setIndeterminate: NO]; + [fRipIndicator setDoubleValue: 0.0]; + + [self writeToActivityLog:"ScanDone state received from fQueueEncodeLibhb"]; + [self processNewQueueEncode]; + [[fWindow toolbar] validateVisibleItems]; + + break; + } +#undef p + #define p s.param.working case HB_STATE_WORKING: { float progress_total; NSMutableString * string; - /* Currently, p.job_cur and p.job_count get screwed up when adding - jobs during encoding, if they cannot be fixed in libhb, will implement a - nasty but working cocoa solution */ /* Update text field */ - string = [NSMutableString stringWithFormat: NSLocalizedString( @"Encoding: task %d of %d, %.2f %%", @"" ), p.job_cur, p.job_count, 100.0 * p.progress]; - + string = [NSMutableString stringWithFormat: NSLocalizedString( @"Encoding: pass %d of %d, %.2f %%", @"" ), p.job_cur, p.job_count, 100.0 * p.progress]; + if( p.seconds > -1 ) { [string appendFormat: - NSLocalizedString( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)", @"" ), - p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds]; + 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]; - + /* Update slider */ progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count; [fRipIndicator setIndeterminate: NO]; [fRipIndicator setDoubleValue: 100.0 * progress_total]; - + // If progress bar hasn't been revealed at the bottom of the window, do // that now. This code used to be in doRip. I moved it to here to handle // the case where hb_start is called by HBQueueController and not from @@ -533,68 +654,54 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [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 */ + or shut down when encoding is finished */ [self remindUserOfSleepOrShutdown]; } - + /* Update dock icon */ [self UpdateDockIcon: progress_total]; - - // Has current job changed? That means the queue has probably changed as - // well so update it - [fQueueController libhbStateChanged: s]; - + break; } #undef p - + #define p s.param.muxing case HB_STATE_MUXING: { /* Update text field */ [fStatusField setStringValue: NSLocalizedString( @"Muxing...", @"" )]; - + /* Update slider */ [fRipIndicator setIndeterminate: YES]; [fRipIndicator startAnimation: nil]; - + /* Update dock icon */ [self UpdateDockIcon: 1.0]; - - // Pass along the info to HBQueueController - [fQueueController libhbStateChanged: s]; - - break; + + break; } #undef p - + case HB_STATE_PAUSED: [fStatusField setStringValue: NSLocalizedString( @"Paused", @"" )]; - - // Pass along the info to HBQueueController - [fQueueController libhbStateChanged: s]; - - break; - + + break; + case HB_STATE_WORKDONE: { // HB_STATE_WORKDONE happpens as a result of libhb finishing all its jobs // or someone calling hb_stop. In the latter case, hb_stop does not clear // out the remaining passes/jobs in the queue. We'll do that here. - + // Delete all remaining jobs of this encode. - hb_job_t * job; - while( ( job = hb_job( fHandle, 0 ) ) && ( !IsFirstPass(job->sequence_id) ) ) - hb_rem( fHandle, job ); - [fStatusField setStringValue: NSLocalizedString( @"Done.", @"" )]; [fRipIndicator setIndeterminate: NO]; [fRipIndicator setDoubleValue: 0.0]; [[fWindow toolbar] validateVisibleItems]; - + /* Restore dock icon */ [self UpdateDockIcon: -1.0]; - + if( fRipIndicatorShown ) { NSRect frame = [fWindow frame]; @@ -605,17 +712,16 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [fWindow setFrame:frame display:YES animate:YES]; fRipIndicatorShown = NO; } - - // Pass along the info to HBQueueController - [fQueueController libhbStateChanged: s]; - - /* Check to see if the encode state has not been cancelled - to determine if we should check for encode done notifications */ + + /* Check to see if the encode state has not been cancelled + to determine if we should check for encode done notifications */ if( fEncodeState != 2 ) { + /* 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"] ) + [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Alert Window And Growl"] ) { /*On Screen Notification*/ int status; @@ -630,7 +736,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It NSDictionary* errorDict; NSAppleEventDescriptor* returnDescriptor = nil; NSAppleScript* scriptObject = [[NSAppleScript alloc] initWithSource: - @"tell application \"Finder\" to sleep"]; + @"tell application \"Finder\" to sleep"]; returnDescriptor = [scriptObject executeAndReturnError: &errorDict]; [scriptObject release]; } @@ -641,23 +747,18 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It NSDictionary* errorDict; NSAppleEventDescriptor* returnDescriptor = nil; NSAppleScript* scriptObject = [[NSAppleScript alloc] initWithSource: - @"tell application \"Finder\" to shut down"]; + @"tell application \"Finder\" to shut down"]; returnDescriptor = [scriptObject executeAndReturnError: &errorDict]; [scriptObject release]; } + + } + break; } } - - /* Lets show the queue status here in the main window */ - int queue_count = [fQueueController pendingCount]; - if( queue_count == 1 ) - [fQueueStatus setStringValue: NSLocalizedString( @"1 encode queued", @"" ) ]; - else if( queue_count > 1 ) - [fQueueStatus setStringValue: [NSString stringWithFormat: NSLocalizedString( @"%d encodes queued", @"" ), queue_count]]; - else - [fQueueStatus setStringValue: @""]; + } /* We use this to write messages to stderr from the macgui which show up in the activity window and log*/ @@ -794,7 +895,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It if (fHandle) { hb_state_t s; - hb_get_state2( fHandle, &s ); + hb_get_state2( fQueueEncodeLibhb, &s ); if (s.state == HB_STATE_WORKING || s.state == HB_STATE_MUXING) { @@ -853,7 +954,9 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } } - + /* If there are any pending queue items, make sure the start/stop button is active */ + if ([ident isEqualToString: StartEncodingIdentifier] && fPendingCount > 0) + return YES; if ([ident isEqualToString: ShowQueueIdentifier]) return YES; if ([ident isEqualToString: ToggleDrawerIdentifier]) @@ -1167,6 +1270,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /* Here we actually tell hb_scan to perform the source scan, using the path to source and title number*/ - (void) performScan:(NSString *) scanPath scanTitleNum: (int) scanTitleNum { + /* set the bool applyQueueToScan so that we dont apply a queue setting to the final scan */ + applyQueueToScan = NO; /* use a bool to determine whether or not we can decrypt using vlc */ BOOL cancelScanDecrypt = 0; NSString *path = scanPath; @@ -1248,91 +1353,90 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It 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) + - list = hb_get_titles( fHandle ); - - if( !hb_list_count( list ) ) - { - /* We display a message if a valid dvd source was not chosen */ - [fSrcDVD2Field setStringValue: @"No Valid Source Found"]; - SuccessfulScan = NO; - - // Notify ChapterTitles that there's no title - [fChapterTitlesDelegate resetWithTitle:nil]; - [fChapterTable reloadData]; - } - else - { - /* We increment the successful scancount here by one, - which we use at the end of this function to tell the gui - if this is the first successful scan since launch and whether - or not we should set all settings to the defaults */ - - currentSuccessfulScanCount++; - - [[fWindow toolbar] validateVisibleItems]; - - [fSrcTitlePopUp removeAllItems]; - for( int i = 0; i < hb_list_count( list ); i++ ) - { - title = (hb_title_t *) hb_list_item( list, i ); - - currentSource = [NSString stringWithUTF8String: title->name]; - - /*Set DVD Name at top of window with the browsedSourceDisplayName grokked right before -performScan */ - [fSrcDVD2Field setStringValue:browsedSourceDisplayName]; - - /* Use the dvd name in the default output field here - May want to add code to remove blank spaces for some dvd names*/ - /* Check to see if the last destination has been set,use if so, if not, use Desktop */ - if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"]) - { - [fDstFile2Field setStringValue: [NSString stringWithFormat: - @"%@/%@.mp4", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[browsedSourceDisplayName stringByDeletingPathExtension]]]; - } - else - { - [fDstFile2Field setStringValue: [NSString stringWithFormat: - @"%@/Desktop/%@.mp4", NSHomeDirectory(),[browsedSourceDisplayName stringByDeletingPathExtension]]]; - } - - if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds) - { - longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds; - indxpri=i; - } - /* Leave this here for now for reference. Keep it commented out or the macgui will crash in a - * fiery wreck if you change sources. - */ - //[self formatPopUpChanged:NULL]; - - [fSrcTitlePopUp addItemWithTitle: [NSString - stringWithFormat: @"%d - %02dh%02dm%02ds", - title->index, title->hours, title->minutes, - title->seconds]]; - } - - // Select the longuest title - [fSrcTitlePopUp selectItemAtIndex: indxpri]; - [self titlePopUpChanged:nil]; - - SuccessfulScan = YES; - [self enableUI: YES]; - - /* if its the initial successful scan after awakeFromNib */ - if (currentSuccessfulScanCount == 1) + list = hb_get_titles( fHandle ); + + if( !hb_list_count( list ) ) { - [self selectDefaultPreset:nil]; - /* initially set deinterlace to 0, will be overridden reset by the default preset anyway */ - //[fPictureController setDeinterlace:0]; + /* We display a message if a valid dvd source was not chosen */ + [fSrcDVD2Field setStringValue: @"No Valid Source Found"]; + SuccessfulScan = NO; + + // Notify ChapterTitles that there's no title + [fChapterTitlesDelegate resetWithTitle:nil]; + [fChapterTable reloadData]; + } + else + { + /* We increment the successful scancount here by one, + which we use at the end of this function to tell the gui + if this is the first successful scan since launch and whether + or not we should set all settings to the defaults */ + + currentSuccessfulScanCount++; + + [[fWindow toolbar] validateVisibleItems]; + + [fSrcTitlePopUp removeAllItems]; + for( int i = 0; i < hb_list_count( list ); i++ ) + { + title = (hb_title_t *) hb_list_item( list, i ); + + currentSource = [NSString stringWithUTF8String: title->name]; + /*Set DVD Name at top of window with the browsedSourceDisplayName grokked right before -performScan */ + [fSrcDVD2Field setStringValue:browsedSourceDisplayName]; + + /* Use the dvd name in the default output field here + May want to add code to remove blank spaces for some dvd names*/ + /* Check to see if the last destination has been set,use if so, if not, use Desktop */ + if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"]) + { + [fDstFile2Field setStringValue: [NSString stringWithFormat: + @"%@/%@.mp4", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[browsedSourceDisplayName stringByDeletingPathExtension]]]; + } + else + { + [fDstFile2Field setStringValue: [NSString stringWithFormat: + @"%@/Desktop/%@.mp4", NSHomeDirectory(),[browsedSourceDisplayName stringByDeletingPathExtension]]]; + } + + + if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds) + { + longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds; + indxpri=i; + } + + [fSrcTitlePopUp addItemWithTitle: [NSString + stringWithFormat: @"%d - %02dh%02dm%02ds", + title->index, title->hours, title->minutes, + title->seconds]]; + } + + // Select the longuest title + [fSrcTitlePopUp selectItemAtIndex: indxpri]; + [self titlePopUpChanged:nil]; + + SuccessfulScan = YES; + [self enableUI: YES]; + + /* if its the initial successful scan after awakeFromNib */ + if (currentSuccessfulScanCount == 1) + { + [self selectDefaultPreset:nil]; + /* initially set deinterlace to 0, will be overridden reset by the default preset anyway */ + //[fPictureController setDeinterlace:0]; + + /* lets set Denoise to index 0 or "None" since this is the first scan */ + //[fPictureController setDenoise:0]; + + [fPictureController setInitialPictureFilters]; + } - /* lets set Denoise to index 0 or "None" since this is the first scan */ - //[fPictureController setDenoise:0]; - [fPictureController setInitialPictureFilters]; } - - } + } @@ -1384,109 +1488,1065 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It return NO; } + #pragma mark - -#pragma mark Job Handling +#pragma mark Queue File +- (void) loadQueueFile { + /* We declare the default NSFileManager into fileManager */ + NSFileManager * fileManager = [NSFileManager defaultManager]; + /*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 */ + if ([fileManager fileExistsAtPath:QueueFile] == 0) + { + [fileManager createFileAtPath:QueueFile contents:nil attributes:nil]; + } -- (void) prepareJob + 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]; + } + currentQueueEncodeIndex = 0; +} + +- (void)addQueueFileItem { - hb_list_t * list = hb_get_titles( fHandle ); - hb_title_t * title = (hb_title_t *) hb_list_item( list, - [fSrcTitlePopUp indexOfSelectedItem] ); - hb_job_t * job = title->job; - hb_audio_config_t * audio; + [QueueFileArray addObject:[self createQueueFileItem]]; + [self saveQueueFileItem]; - /* Chapter selection */ - job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1; - job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1; - - /* Format (Muxer) and Video Encoder */ - job->mux = [[fDstFormatPopUp selectedItem] tag]; - job->vcodec = [[fVidEncoderPopUp selectedItem] tag]; +} +- (void) removeQueueFileItem:(int) queueItemToRemove +{ + + // FIX ME: WE NEED TO IDENTIFY AN ENCODING ITEM AND CALL + + [QueueFileArray removeObjectAtIndex:queueItemToRemove]; + [self saveQueueFileItem]; - /* If mpeg-4, then set mpeg-4 specific options like chapters and > 4gb file sizes */ - if( [fDstFormatPopUp indexOfSelectedItem] == 0 ) +} + +- (void)saveQueueFileItem +{ + [QueueFileArray writeToFile:QueueFile atomically:YES]; + [fQueueController setQueueArray: QueueFileArray]; + [self getQueueStats]; +} + +- (void)getQueueStats +{ +/* lets get the stats on the status of the queue array */ + +fEncodingQueueItem = 0; +fPendingCount = 0; +fCompletedCount = 0; +fCanceledCount = 0; +fWorkingCount = 0; + + /* We use a number system to set the encode status of the queue item + * in controller.mm + * 0 == already encoded + * 1 == is being encoded + * 2 == is yet to be encoded + * 3 == cancelled + */ + + int i = 0; + NSEnumerator *enumerator = [QueueFileArray objectEnumerator]; + id tempObject; + while (tempObject = [enumerator nextObject]) { - /* We set the largeFileSize (64 bit formatting) variable here to allow for > 4gb files based on the format being - mpeg4 and the checkbox being checked - *Note: this will break compatibility with some target devices like iPod, etc.!!!!*/ - if( [fDstMp4LargeFileCheck state] == NSOnState ) + NSDictionary *thisQueueDict = tempObject; + if ([[thisQueueDict objectForKey:@"Status"] intValue] == 0) // Completed { - job->largeFileSize = 1; + fCompletedCount++; } - else + if ([[thisQueueDict objectForKey:@"Status"] intValue] == 1) // being encoded { - job->largeFileSize = 0; + fWorkingCount++; + fEncodingQueueItem = i; } - /* We set http optimized mp4 here */ - if( [fDstMp4HttpOptFileCheck state] == NSOnState && [fDstMp4HttpOptFileCheck isEnabled] ) - { - job->mp4_optimize = 1; + if ([[thisQueueDict objectForKey:@"Status"] intValue] == 2) // pending + { + fPendingCount++; + } + if ([[thisQueueDict objectForKey:@"Status"] intValue] == 3) // cancelled + { + fCanceledCount++; + } + i++; + } + + /* Set the queue status field in the main window */ + NSMutableString * string; + if (fPendingCount == 1) + { + string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode pending in the queue", @"" ), fPendingCount]; + } + else + { + string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode(s) pending in the queue", @"" ), fPendingCount]; + } + [fQueueStatus setStringValue:string]; +} + + +/* 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 */ +- (void) clearQueueEncodedItems +{ + 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 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) + { + [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 */ +- (void) clearQueueAllItems +{ + 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] ) + { + [tempArray addObject:tempObject]; + } + + [QueueFileArray removeObjectsInArray:tempArray]; + [self saveQueueFileItem]; + +} + +/* This method will duplicate prepareJob however into the + * queue .plist instead of into the job structure so it can + * be recalled later */ +- (NSDictionary *)createQueueFileItem +{ + NSMutableDictionary *queueFileJob = [[NSMutableDictionary alloc] init]; + + hb_list_t * list = hb_get_titles( fHandle ); + hb_title_t * title = (hb_title_t *) hb_list_item( list, + [fSrcTitlePopUp indexOfSelectedItem] ); + hb_job_t * job = title->job; + //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 + * 1 == is being encoded + * 2 == is yet to be encoded + * 3 == cancelled + */ + [queueFileJob setObject:[NSNumber numberWithInt:2] forKey:@"Status"]; + /* Source and Destination Information */ + + [queueFileJob setObject:[NSString stringWithUTF8String: title->dvd] forKey:@"SourcePath"]; + [queueFileJob setObject:[fSrcDVD2Field stringValue] forKey:@"SourceName"]; + [queueFileJob setObject:[NSNumber numberWithInt:title->index] forKey:@"TitleNumber"]; + [queueFileJob setObject:[NSNumber numberWithInt:[fSrcChapterStartPopUp indexOfSelectedItem] + 1] forKey:@"ChapterStart"]; + + [queueFileJob setObject:[NSNumber numberWithInt:[fSrcChapterEndPopUp indexOfSelectedItem] + 1] forKey:@"ChapterEnd"]; + + [queueFileJob setObject:[fDstFile2Field stringValue] forKey:@"DestinationPath"]; + + /* Lets get the preset info if there is any */ + [queueFileJob setObject:[fPresetSelectedDisplay stringValue] forKey:@"PresetName"]; + [queueFileJob setObject:[NSNumber numberWithInt:[fPresetsOutlineView selectedRow]] forKey:@"PresetIndexNum"]; + + [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 */ + [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:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"]; + /* 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:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"]; + + /* GrayScale */ + [queueFileJob setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"]; + /* 2 Pass Encoding */ + [queueFileJob setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"]; + /* Turbo 2 pass Encoding fVidTurboPassCheck*/ + [queueFileJob setObject:[NSNumber numberWithInt:[fVidTurboPassCheck state]] forKey:@"VideoTurboTwoPass"]; + + /* 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"]; + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"]; + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"]; + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"]; + NSString * pictureSummary; + pictureSummary = [NSString stringWithFormat:@"Source: %@ Output: %@ Anamorphic: %@", + [fPicSettingsSrc stringValue], + [fPicSettingsOutp stringValue], + [fPicSettingsAnamorphic stringValue]]; + [queueFileJob setObject:pictureSummary forKey:@"PictureSizingSummary"]; + /* Set crop settings here */ + [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController autoCrop]] forKey:@"PictureAutoCrop"]; + [queueFileJob setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"]; + [queueFileJob setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"]; + [queueFileJob setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"]; + [queueFileJob setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"]; + + /* 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 decomb]] forKey:@"PictureDecomb"]; + + /*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"]; + } + + /* Subtitles*/ + [queueFileJob setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"]; + /* Forced Subtitles */ + [queueFileJob setObject:[NSNumber numberWithInt:[fSubForcedCheck state]] forKey:@"SubtitlesForced"]; + + + + /* Now we go ahead and set the "job->values in the plist for passing right to fQueueEncodeLibhb */ + + [queueFileJob setObject:[NSNumber numberWithInt:[fSrcChapterStartPopUp indexOfSelectedItem] + 1] forKey:@"JobChapterStart"]; + + [queueFileJob setObject:[NSNumber numberWithInt:[fSrcChapterEndPopUp indexOfSelectedItem] + 1] forKey:@"JobChapterEnd"]; + + + [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 */ + /* 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"]; + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"]; + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"]; + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"]; + + /* Set crop settings here */ + [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController autoCrop]] forKey:@"PictureAutoCrop"]; + [queueFileJob setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"]; + [queueFileJob setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"]; + [queueFileJob setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"]; + [queueFileJob setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"]; + + /* Picture Filters */ + [queueFileJob setObject:[fPicSettingDecomb stringValue] forKey:@"JobPictureDecomb"]; + + /*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"]; + } + /* Subtitles*/ + [queueFileJob setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"]; + /* Forced Subtitles */ + [queueFileJob setObject:[NSNumber numberWithInt:[fSubForcedCheck state]] forKey:@"SubtitlesForced"]; + + /* we need to auto relase the queueFileJob and return it */ + [queueFileJob autorelease]; + return queueFileJob; + +} + +/* this is actually called from the queue controller to modify the queue array and return it back to the queue controller */ +- (void)moveObjectsInQueueArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(unsigned)insertIndex +{ + unsigned index = [indexSet lastIndex]; + unsigned aboveInsertIndexCount = 0; + + while (index != NSNotFound) + { + unsigned removeIndex; + + if (index >= insertIndex) + { + removeIndex = index + aboveInsertIndexCount; + aboveInsertIndexCount++; } else { - job->mp4_optimize = 0; + removeIndex = index; + insertIndex--; } + + id object = [[QueueFileArray objectAtIndex:removeIndex] retain]; + [QueueFileArray removeObjectAtIndex:removeIndex]; + [QueueFileArray insertObject:object atIndex:insertIndex]; + [object release]; + + index = [indexSet indexLessThanIndex:index]; + } + /* We save all of the Queue data here + * and it also gets sent back to the queue controller*/ + [self saveQueueFileItem]; + +} + + +#pragma mark - +#pragma mark Queue Job Processing + +- (void) incrementQueueItemDone:(int) queueItemDoneIndexNum +{ + int i = currentQueueEncodeIndex; + [[QueueFileArray objectAtIndex:i] 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]]; } - if( [fDstFormatPopUp indexOfSelectedItem] == 0 || [fDstFormatPopUp indexOfSelectedItem] == 1 ) + else + { + [self writeToActivityLog: "incrementQueueItemDone the %d item queue is complete", currentQueueEncodeIndex - 1]; + } +} + +/* 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); + + /* 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; + NSString *path = scanPath; + HBDVDDetector *detector = [HBDVDDetector detectorForPath:path]; + + /*On Screen Notification*/ + //int status; + //status = NSRunAlertPanel(@"HandBrake is now loading up a new queue item...",@"Would You Like to wait until you add another encode?", @"Cancel", @"Okay", nil); + //[NSApp requestUserAttention:NSCriticalRequest]; + + // Notify ChapterTitles that there's no title + [fChapterTitlesDelegate resetWithTitle:nil]; + [fChapterTable reloadData]; + + //[self enableUI: NO]; + + if( [detector isVideoDVD] ) + { + // 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"; + NSFileManager * fileManager = [NSFileManager defaultManager]; + if ([fileManager fileExistsAtPath:vlcPath] == 0) + { + /*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"]; + int status; + status = NSRunAlertPanel(@"HandBrake could not find VLC.",@"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"); + [NSApp requestUserAttention:NSCriticalRequest]; + + if (status == NSAlertDefaultReturn) + { + /* 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/"]]; + } + else if (status == NSAlertAlternateReturn) + { + /* User chose to cancel the scan */ + [self writeToActivityLog: "cannot open physical dvd , scan cancelled"]; + } + else + { + /* User chose to override our warning and scan the physical dvd anyway, at their own peril. on an encrypted dvd this produces massive log files and fails */ + cancelScanDecrypt = 0; + [self writeToActivityLog: "user overrode vlc warning -trying to open physical dvd without decryption"]; + } + + } + else + { + /* 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"]; + } + } + + if (cancelScanDecrypt == 0) + { + /* we actually pass the scan off to libhb here */ + /* If there is no title number passed to scan, we use "0" + * which causes the default behavior of a full source scan + */ + if (!scanTitleNum) + { + scanTitleNum = 0; + } + if (scanTitleNum > 0) + { + [self writeToActivityLog: "scanning specifically for title: %d", scanTitleNum]; + } + [self writeToActivityLog: "performNewQueueScan currentQueueEncodeIndex is: %d", currentQueueEncodeIndex]; + hb_scan( fQueueEncodeLibhb, [path UTF8String], scanTitleNum ); + } +} + +/* This method was originally used to load up a new queue item in the gui and + * then start processing it. However we now have modified -prepareJob and use a second + * instance of libhb to do our actual encoding, therefor right now it is not required. + * Nonetheless I want to leave this in here + * because basically its everything we need to be able to actually modify a pending queue + * item in the gui and resave it. At least for now - dynaflash + */ + +- (IBAction)applyQueueSettings:(id)sender +{ + NSMutableDictionary * queueToApply = [QueueFileArray objectAtIndex:currentQueueEncodeIndex]; + hb_job_t * job = fTitle->job; + + /* Set title number and chapters */ + /* since the queue only scans a single title, we really don't need to pick a title */ + //[fSrcTitlePopUp selectItemAtIndex: [[queueToApply objectForKey:@"TitleNumber"] intValue] - 1]; + + [fSrcChapterStartPopUp selectItemAtIndex: [[queueToApply objectForKey:@"ChapterStart"] intValue] - 1]; + [fSrcChapterEndPopUp selectItemAtIndex: [[queueToApply objectForKey:@"ChapterEnd"] intValue] - 1]; + + /* File Format */ + [fDstFormatPopUp selectItemWithTitle:[queueToApply objectForKey:@"FileFormat"]]; + [self formatPopUpChanged:nil]; + + /* Chapter Markers*/ + [fCreateChapterMarkers setState:[[queueToApply objectForKey:@"ChapterMarkers"] intValue]]; + /* Allow Mpeg4 64 bit formatting +4GB file sizes */ + [fDstMp4LargeFileCheck setState:[[queueToApply objectForKey:@"Mp4LargeFile"] intValue]]; + /* Mux mp4 with http optimization */ + [fDstMp4HttpOptFileCheck setState:[[queueToApply objectForKey:@"Mp4HttpOptimize"] intValue]]; + + /* Video encoder */ + /* We set the advanced opt string here if applicable*/ + [fVidEncoderPopUp selectItemWithTitle:[queueToApply objectForKey:@"VideoEncoder"]]; + [fAdvancedOptions setOptions:[queueToApply objectForKey:@"x264Option"]]; + + /* 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:[[queueToApply objectForKey:@"Mp4iPodCompatible"] intValue]]; + [self calculateBitrate:nil]; + + /* Video quality */ + [fVidQualityMatrix selectCellAtRow:[[queueToApply objectForKey:@"VideoQualityType"] intValue] column:0]; + + [fVidTargetSizeField setStringValue:[queueToApply objectForKey:@"VideoTargetSize"]]; + [fVidBitrateField setStringValue:[queueToApply objectForKey:@"VideoAvgBitrate"]]; + [fVidQualitySlider setFloatValue:[[queueToApply 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*/ + if ([[queueToApply objectForKey:@"VideoFramerate"] isEqualToString:@"Same as source"]) + { + [fVidRatePopUp selectItemAtIndex: 0]; + } + else + { + [fVidRatePopUp selectItemWithTitle:[queueToApply objectForKey:@"VideoFramerate"]]; + } + + /* GrayScale */ + [fVidGrayscaleCheck setState:[[queueToApply objectForKey:@"VideoGrayScale"] intValue]]; + + /* 2 Pass Encoding */ + [fVidTwoPassCheck setState:[[queueToApply objectForKey:@"VideoTwoPass"] intValue]]; + [self twoPassCheckboxChanged:nil]; + /* Turbo 1st pass for 2 Pass Encoding */ + [fVidTurboPassCheck setState:[[queueToApply objectForKey:@"VideoTurboTwoPass"] intValue]]; + + /*Audio*/ + if ([queueToApply objectForKey:@"Audio1Track"] > 0) + { + if ([fAudLang1PopUp indexOfSelectedItem] == 0) + { + [fAudLang1PopUp selectItemAtIndex: 1]; + } + [self audioTrackPopUpChanged: fAudLang1PopUp]; + [fAudTrack1CodecPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio1Encoder"]]; + [self audioTrackPopUpChanged: fAudTrack1CodecPopUp]; + [fAudTrack1MixPopUp selectItemWithTitle:[queueToApply 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 (![[queueToApply objectForKey:@"Audio1Encoder"] isEqualToString:@"AC3 Passthru"]) + { + [fAudTrack1BitratePopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio1Bitrate"]]; + } + [fAudTrack1DrcSlider setFloatValue:[[queueToApply objectForKey:@"Audio1TrackDRCSlider"] floatValue]]; + [self audioDRCSliderChanged: fAudTrack1DrcSlider]; + } + if ([queueToApply objectForKey:@"Audio2Track"] > 0) + { + if ([fAudLang2PopUp indexOfSelectedItem] == 0) + { + [fAudLang2PopUp selectItemAtIndex: 1]; + } + [self audioTrackPopUpChanged: fAudLang2PopUp]; + [fAudTrack2CodecPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio2Encoder"]]; + [self audioTrackPopUpChanged: fAudTrack2CodecPopUp]; + [fAudTrack2MixPopUp selectItemWithTitle:[queueToApply 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:[queueToApply objectForKey:@"Audio2Samplerate"]]; + /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ + if (![[queueToApply objectForKey:@"Audio2Encoder"] isEqualToString:@"AC3 Passthru"]) + { + [fAudTrack2BitratePopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio2Bitrate"]]; + } + [fAudTrack2DrcSlider setFloatValue:[[queueToApply objectForKey:@"Audio2TrackDRCSlider"] floatValue]]; + [self audioDRCSliderChanged: fAudTrack2DrcSlider]; + } + if ([queueToApply objectForKey:@"Audio3Track"] > 0) + { + if ([fAudLang3PopUp indexOfSelectedItem] == 0) + { + [fAudLang3PopUp selectItemAtIndex: 1]; + } + [self audioTrackPopUpChanged: fAudLang3PopUp]; + [fAudTrack3CodecPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio3Encoder"]]; + [self audioTrackPopUpChanged: fAudTrack3CodecPopUp]; + [fAudTrack3MixPopUp selectItemWithTitle:[queueToApply 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:[queueToApply objectForKey:@"Audio3Samplerate"]]; + /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ + if (![[queueToApply objectForKey:@"Audio3Encoder"] isEqualToString: @"AC3 Passthru"]) + { + [fAudTrack3BitratePopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio3Bitrate"]]; + } + [fAudTrack3DrcSlider setFloatValue:[[queueToApply objectForKey:@"Audio3TrackDRCSlider"] floatValue]]; + [self audioDRCSliderChanged: fAudTrack3DrcSlider]; + } + if ([queueToApply objectForKey:@"Audio4Track"] > 0) + { + if ([fAudLang4PopUp indexOfSelectedItem] == 0) + { + [fAudLang4PopUp selectItemAtIndex: 1]; + } + [self audioTrackPopUpChanged: fAudLang4PopUp]; + [fAudTrack4CodecPopUp selectItemWithTitle:[queueToApply objectForKey:@"Audio4Encoder"]]; + [self audioTrackPopUpChanged: fAudTrack4CodecPopUp]; + [fAudTrack4MixPopUp selectItemWithTitle:[queueToApply 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:[queueToApply 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:[queueToApply objectForKey:@"Audio4Bitrate"]]; + } + [fAudTrack4DrcSlider setFloatValue:[[queueToApply objectForKey:@"Audio4TrackDRCSlider"] floatValue]]; + [self audioDRCSliderChanged: fAudTrack4DrcSlider]; + } + + + /*Subtitles*/ + [fSubPopUp selectItemWithTitle:[queueToApply objectForKey:@"Subtitles"]]; + /* Forced Subtitles */ + [fSubForcedCheck setState:[[queueToApply objectForKey:@"SubtitlesForced"] intValue]]; + + /* Picture Settings */ + /* we check to make sure the presets width/height does not exceed the sources width/height */ + if (fTitle->width < [[queueToApply objectForKey:@"PictureWidth"] intValue] || fTitle->height < [[queueToApply objectForKey:@"PictureHeight"] intValue]) + { + /* if so, then we use the sources height and width to avoid scaling up */ + job->width = fTitle->width; + job->height = fTitle->height; + } + else // source width/height is >= the preset height/width + { + /* we can go ahead and use the presets values for height and width */ + job->width = [[queueToApply objectForKey:@"PictureWidth"] intValue]; + job->height = [[queueToApply objectForKey:@"PictureHeight"] intValue]; + } + job->keep_ratio = [[queueToApply objectForKey:@"PictureKeepRatio"] intValue]; + if (job->keep_ratio == 1) + { + hb_fix_aspect( job, HB_KEEP_WIDTH ); + if( job->height > fTitle->height ) + { + job->height = fTitle->height; + hb_fix_aspect( job, HB_KEEP_HEIGHT ); + } + } + job->pixel_ratio = [[queueToApply 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 ([[queueToApply 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] = [[queueToApply objectForKey:@"PictureTopCrop"] intValue]; + job->crop[1] = [[queueToApply objectForKey:@"PictureBottomCrop"] intValue]; + job->crop[2] = [[queueToApply objectForKey:@"PictureLeftCrop"] intValue]; + job->crop[3] = [[queueToApply 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; + + } + + /* Filters */ + /* Deinterlace */ + [fPictureController setDeinterlace:[[queueToApply objectForKey:@"PictureDeinterlace"] intValue]]; + /* VFR */ + [fPictureController setVFR:[[queueToApply objectForKey:@"VFR"] intValue]]; + /* Detelecine */ + [fPictureController setDetelecine:[[queueToApply objectForKey:@"PictureDetelecine"] intValue]]; + /* Denoise */ + [fPictureController setDenoise:[[queueToApply objectForKey:@"PictureDenoise"] intValue]]; + /* Deblock */ + [fPictureController setDeblock:[[queueToApply objectForKey:@"PictureDeblock"] intValue]]; + /* Decomb */ + [fPictureController setDecomb:[[queueToApply objectForKey:@"PictureDecomb"] intValue]]; + + [self calculatePictureSizing:nil]; + + + /* 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"]; + if ([queueToApply objectForKey:@"PresetIndexNum"]) // This item used a preset so insert that info { - /* We set the chapter marker extraction here based on the format being - mpeg4 or mkv and the checkbox being checked */ - if ([fCreateChapterMarkers state] == NSOnState) - { - job->chapter_markers = 1; - } - else - { - job->chapter_markers = 0; - } + /* Deselect the currently selected Preset if there is one*/ + //[fPresetsOutlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:[[queueToApply objectForKey:@"PresetIndexNum"] intValue]] byExtendingSelection:NO]; + //[self selectPreset:nil]; + + //[fPresetsOutlineView selectRow:[[queueToApply objectForKey:@"PresetIndexNum"] intValue]]; + /* Change UI to show "Custom" settings are being used */ + //[fPresetSelectedDisplay setStringValue: [[queueToApply objectForKey:@"PresetName"] stringValue]]; + + curUserPresetChosenNum = nil; } + else + { + /* Deselect the currently selected Preset if there is one*/ + [fPresetsOutlineView deselectRow:[fPresetsOutlineView selectedRow]]; + /* Change UI to show "Custom" settings are being used */ + [fPresetSelectedDisplay setStringValue: @"Custom"]; + + //curUserPresetChosenNum = nil; + } + + /* We need to set this bool back to NO, in case the user wants to do a scan */ + //applyQueueToScan = NO; + + /* so now we go ahead and process the new settings */ + [self processNewQueueEncode]; +} + + + +/* This assumes that we have re-scanned and loaded up a new queue item to send to libhb as fQueueEncodeLibhb */ +- (void) processNewQueueEncode +{ + hb_list_t * list = hb_get_titles( fQueueEncodeLibhb ); + 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; + + if( !hb_list_count( list ) ) + { + [self writeToActivityLog: "processNewQueueEncode WARNING nothing found in the title list"]; + } + else + { + [self writeToActivityLog: "processNewQueueEncode title list is: %d", hb_list_count( list )]; + } + + NSMutableDictionary * queueToApply = [QueueFileArray objectAtIndex:currentQueueEncodeIndex]; + [self writeToActivityLog: "processNewQueueEncode currentQueueEncodeIndex is: %d", currentQueueEncodeIndex]; + job->file = [[queueToApply objectForKey:@"DestinationPath"] UTF8String]; + [self prepareJob]; + // [self writeToActivityLog: "prepareJob is over, back to processNewQueueEncode"]; + + if( [[queueToApply objectForKey:@"SubtitlesForced"] intValue] == 1 ) + job->subtitle_force = 1; + else + job->subtitle_force = 0; + + /* + * subtitle of -1 is a scan + */ + if( job->subtitle == -1 ) + { + char *x264opts_tmp; + + /* + * When subtitle scan is enabled do a fast pre-scan job + * which will determine which subtitles to enable, if any. + */ + job->pass = -1; + x264opts_tmp = job->x264opts; + job->subtitle = -1; + + job->x264opts = NULL; + + job->indepth_scan = 1; + + job->select_subtitle = (hb_subtitle_t**)malloc(sizeof(hb_subtitle_t*)); + *(job->select_subtitle) = NULL; + + /* + * Add the pre-scan job + */ + hb_add( fQueueEncodeLibhb, job ); + job->x264opts = x264opts_tmp; + } + else + job->select_subtitle = NULL; + + /* No subtitle were selected, so reset the subtitle to -1 (which before + * this point meant we were scanning + */ + if( job->subtitle == -2 ) + job->subtitle = -1; + + if( [[queueToApply objectForKey:@"VideoTwoPass"] intValue] == 1 ) + { + hb_subtitle_t **subtitle_tmp = job->select_subtitle; + job->indepth_scan = 0; + + /* + * Do not autoselect subtitles on the first pass of a two pass + */ + job->select_subtitle = NULL; + + job->pass = 1; + + hb_add( fQueueEncodeLibhb, job ); + job->pass = 2; + + job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ + strcpy(job->x264opts, [[queueToApply objectForKey:@"x264Option"] UTF8String]); + + job->select_subtitle = subtitle_tmp; + + hb_add( fQueueEncodeLibhb, job ); + + } + else + { + job->indepth_scan = 0; + [self writeToActivityLog: "processNewQueueEncode is adding a single pass job"]; + job->pass = 0; + + hb_add( fQueueEncodeLibhb, job ); + } + + NSString *destinationDirectory = [[queueToApply objectForKey:@"DestinationPath"] stringByDeletingLastPathComponent]; + [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"]; + /* Lets mark our new encode as 1 or "Encoding" */ + [queueToApply setObject:[NSNumber numberWithInt:1] forKey:@"Status"]; + [self saveQueueFileItem]; + /* We should be all setup so let 'er rip */ + [self doRip]; +} + + +#pragma mark - +#pragma mark Job Handling + + +- (void) prepareJob +{ + + NSMutableDictionary * queueToApply = [QueueFileArray objectAtIndex:currentQueueEncodeIndex]; + hb_list_t * list = hb_get_titles( fQueueEncodeLibhb ); + 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; + + /* Chapter selection */ + job->chapter_start = [[queueToApply objectForKey:@"JobChapterStart"] intValue]; + job->chapter_end = [[queueToApply objectForKey:@"JobChapterEnd"] intValue]; + + /* Format (Muxer) and Video Encoder */ + job->mux = [[queueToApply objectForKey:@"JobFileFormatMux"] intValue]; + job->vcodec = [[queueToApply objectForKey:@"JobVideoEncoderVcodec"] intValue]; + + + /* If mpeg-4, then set mpeg-4 specific options like chapters and > 4gb file sizes */ + //if( [fDstFormatPopUp indexOfSelectedItem] == 0 ) + //{ + /* We set the largeFileSize (64 bit formatting) variable here to allow for > 4gb files based on the format being + mpeg4 and the checkbox being checked + *Note: this will break compatibility with some target devices like iPod, etc.!!!!*/ + if( [[queueToApply objectForKey:@"Mp4LargeFile"] intValue] == 1) + { + job->largeFileSize = 1; + } + else + { + job->largeFileSize = 0; + } + /* We set http optimized mp4 here */ + if( [[queueToApply objectForKey:@"Mp4HttpOptimize"] intValue] == 1 ) + { + job->mp4_optimize = 1; + } + else + { + job->mp4_optimize = 0; + } + //} + + /* We set the chapter marker extraction here based on the format being + mpeg4 or mkv and the checkbox being checked */ + if ([[queueToApply objectForKey:@"Mp4HttpOptimize"] intValue] == 1) + { + job->chapter_markers = 1; + } + else + { + job->chapter_markers = 0; + } + if( job->vcodec & HB_VCODEC_X264 ) { - if ([fDstMp4iPodFileCheck state] == NSOnState) + if ([[queueToApply objectForKey:@"Mp4iPodCompatible"] intValue] == 1) { job->ipod_atom = 1; } else { - job->ipod_atom = 0; + job->ipod_atom = 0; } /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake Currently only used with Constant Quality setting*/ - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2) + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [[queueToApply objectForKey:@"VideoQualityType"] intValue] == 2) { job->crf = 1; } - /* Below Sends x264 options to the core library if x264 is selected*/ /* Lets use this as per Nyx, Thanks Nyx!*/ job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ /* Turbo first pass if two pass and Turbo First pass is selected */ - if( [fVidTwoPassCheck state] == NSOnState && [fVidTurboPassCheck state] == NSOnState ) + if( [[queueToApply objectForKey:@"VideoTwoPass"] intValue] == 1 && [[queueToApply objectForKey:@"VideoTurboTwoPass"] intValue] == 1 ) { /* pass the "Turbo" string to be appended to the existing x264 opts string into a variable for the first pass */ NSString *firstPassOptStringTurbo = @":ref=1:subme=1:me=dia:analyse=none:trellis=0:no-fast-pskip=0:8x8dct=0:weightb=0"; /* append the "Turbo" string variable to the existing opts string. Note: the "Turbo" string must be appended, not prepended to work properly*/ - NSString *firstPassOptStringCombined = [[fAdvancedOptions optionsString] stringByAppendingString:firstPassOptStringTurbo]; + NSString *firstPassOptStringCombined = [[[queueToApply objectForKey:@"x264Option"] stringValue] stringByAppendingString:firstPassOptStringTurbo]; strcpy(job->x264opts, [firstPassOptStringCombined UTF8String]); } else { - strcpy(job->x264opts, [[fAdvancedOptions optionsString] UTF8String]); + strcpy(job->x264opts, [[queueToApply objectForKey:@"x264Option"] UTF8String]); } } - + + /* Picture Size Settings */ + job->width = [[queueToApply objectForKey:@"PictureWidth"] intValue]; + job->height = [[queueToApply objectForKey:@"PictureHeight"] intValue]; + + job->keep_ratio = [[queueToApply objectForKey:@"PictureKeepRatio"] intValue]; + job->pixel_ratio = [[queueToApply objectForKey:@"PicturePAR"] intValue]; + + + /* Here we use the crop values saved at the time the preset was saved */ + job->crop[0] = [[queueToApply objectForKey:@"PictureTopCrop"] intValue]; + job->crop[1] = [[queueToApply objectForKey:@"PictureBottomCrop"] intValue]; + job->crop[2] = [[queueToApply objectForKey:@"PictureLeftCrop"] intValue]; + job->crop[3] = [[queueToApply objectForKey:@"PictureRightCrop"] intValue]; + /* Video settings */ - if( [fVidRatePopUp indexOfSelectedItem] > 0 ) + if( [[queueToApply objectForKey:@"JobIndexVideoFramerate"] intValue] > 0 ) { job->vrate = 27000000; - job->vrate_base = hb_video_rates[[fVidRatePopUp - indexOfSelectedItem]-1].rate; + 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 * to enable constant frame rate since user has specified * a specific framerate*/ @@ -1494,34 +2554,35 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } else { - job->vrate = title->rate; - job->vrate_base = title->rate_base; + 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; } - - switch( [fVidQualityMatrix selectedRow] ) + + if ( [[queueToApply objectForKey:@"VideoQualityType"] intValue] == 0 ) { - case 0: - /* Target size. - Bitrate should already have been calculated and displayed - in fVidBitrateField, so let's just use it */ - case 1: - job->vquality = -1.0; - job->vbitrate = [fVidBitrateField intValue]; - break; - case 2: - job->vquality = [fVidQualitySlider floatValue]; - job->vbitrate = 0; - break; + /* Target size. + Bitrate should already have been calculated and displayed + in fVidBitrateField, so let's just use it */ } - - job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState ); - + if ( [[queueToApply objectForKey:@"VideoQualityType"] intValue] == 1 ) + { + job->vquality = -1.0; + job->vbitrate = [[queueToApply objectForKey:@"VideoAvgBitrate"] intValue]; + } + if ( [[queueToApply objectForKey:@"VideoQualityType"] intValue] == 2 ) + { + job->vquality = [[queueToApply objectForKey:@"VideoQualitySlider"] floatValue]; + job->vbitrate = 0; + + } + + job->grayscale = [[queueToApply objectForKey:@"VideoGrayScale"] intValue]; /* Subtitle settings */ - job->subtitle = [fSubPopUp indexOfSelectedItem] - 2; - + job->subtitle = [[queueToApply objectForKey:@"Subtitles"] intValue] - 2; + /* 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); @@ -1531,78 +2592,77 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It hb_list_rem(job->list_audio, temp_audio); } /* Now lets add our new tracks to the audio list here */ - if ([fAudLang1PopUp indexOfSelectedItem] > 0) + if ([[queueToApply objectForKey:@"Audio1Track"] intValue] > 0) { audio = (hb_audio_config_t *) calloc(1, sizeof(*audio)); hb_audio_config_init(audio); - audio->in.track = [fAudLang1PopUp indexOfSelectedItem] - 1; + audio->in.track = [[queueToApply objectForKey:@"Audio1Track"] intValue] - 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]; + 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 ([fAudLang2PopUp indexOfSelectedItem] > 0) + if ([[queueToApply objectForKey:@"Audio2Track"] intValue] > 0) { + audio = (hb_audio_config_t *) calloc(1, sizeof(*audio)); hb_audio_config_init(audio); - audio->in.track = [fAudLang2PopUp indexOfSelectedItem] - 1; + audio->in.track = [[queueToApply objectForKey:@"Audio2Track"] intValue] - 1; + [self writeToActivityLog: "prepareJob audiotrack 2 is: %d", audio->in.track]; /* We go ahead and assign values to our audio->out.<properties> */ - audio->out.track = [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]; + 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 ([fAudLang3PopUp indexOfSelectedItem] > 0) + if ([[queueToApply objectForKey:@"Audio3Track"] intValue] > 0) { audio = (hb_audio_config_t *) calloc(1, sizeof(*audio)); hb_audio_config_init(audio); - audio->in.track = [fAudLang3PopUp indexOfSelectedItem] - 1; + audio->in.track = [[queueToApply objectForKey:@"Audio3Track"] intValue] - 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]; + 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); - + free(audio); } - - if ([fAudLang4PopUp indexOfSelectedItem] > 0) + + if ([[queueToApply objectForKey:@"Audio4Track"] intValue] > 0) { audio = (hb_audio_config_t *) calloc(1, sizeof(*audio)); hb_audio_config_init(audio); - audio->in.track = [fAudLang4PopUp indexOfSelectedItem] - 1; + audio->in.track = [[queueToApply objectForKey:@"Audio4Track"] intValue] - 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]; + 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:@"Audio3TrackDRCSlider"] floatValue]; hb_audio_add( job, audio ); free(audio); - } - + /* set vfr according to the Picture Window */ - if ([fPictureController vfr]) + if ([[queueToApply objectForKey:@"VFR"] intValue] == 1) { job->vfr = 1; } @@ -1615,40 +2675,36 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It job->filters = hb_list_init(); /* Now lets call the filters if applicable. - * The order of the filters is critical - */ - - /* Detelecine */ - if ([fPictureController detelecine]) + * The order of the filters is critical + */ + /* Detelecine */ + if ([[queueToApply objectForKey:@"PictureDetelecine"] intValue] == 1) { hb_list_add( job->filters, &hb_filter_detelecine ); } /* Decomb */ - if ([fPictureController decomb] > 0) + if ([[queueToApply objectForKey:@"PictureDecomb"] intValue] == 1) { /* Run old deinterlacer fd by default */ - //fPicSettingDecomb - hb_filter_decomb.settings = (char *) [[fPicSettingDecomb stringValue] UTF8String]; - //hb_filter_decomb.settings = "4:10:15:9:10:35:9"; // <-- jbrjakes recommended parameters as of 5/23/08 + hb_filter_decomb.settings = (char *) [[queueToApply objectForKey:@"JobPictureDecomb"] UTF8String]; hb_list_add( job->filters, &hb_filter_decomb ); } - /* Deinterlace */ - if ([fPictureController deinterlace] == 1) + if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 1) { /* Run old deinterlacer fd by default */ hb_filter_deinterlace.settings = "-1"; hb_list_add( job->filters, &hb_filter_deinterlace ); } - else if ([fPictureController deinterlace] == 2) + else if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 2) { /* Yadif mode 0 (without spatial deinterlacing.) */ hb_filter_deinterlace.settings = "2"; hb_list_add( job->filters, &hb_filter_deinterlace ); } - else if ([fPictureController deinterlace] == 3) + else if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 3) { /* Yadif (with spatial deinterlacing) */ hb_filter_deinterlace.settings = "0"; @@ -1656,28 +2712,28 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } /* Denoise */ - if ([fPictureController denoise] == 1) // Weak in popup + if ([[queueToApply objectForKey:@"PictureDenoise"] intValue] == 1) // Weak in popup { hb_filter_denoise.settings = "2:1:2:3"; hb_list_add( job->filters, &hb_filter_denoise ); } - else if ([fPictureController denoise] == 2) // Medium in popup + else if ([[queueToApply objectForKey:@"PictureDenoise"] intValue] == 2) // Medium in popup { hb_filter_denoise.settings = "3:2:2:3"; hb_list_add( job->filters, &hb_filter_denoise ); } - else if ([fPictureController denoise] == 3) // Strong in popup + else if ([[queueToApply objectForKey:@"PictureDenoise"] intValue] == 3) // Strong in popup { hb_filter_denoise.settings = "7:7:5:5"; hb_list_add( job->filters, &hb_filter_denoise ); } /* Deblock (uses pp7 default) */ - if ([fPictureController deblock]) + if ([[queueToApply objectForKey:@"PictureDeblock"] intValue] == 1) { hb_list_add( job->filters, &hb_filter_deblock ); } - + } @@ -1707,20 +2763,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [fDstFile2Field stringValue]] ); // overwriteAddToQueueAlertDone: will be called when the alert is dismissed. } - - // Warn if another pending job in the queue has the same destination path - else if ( ([fQueueController pendingJobGroupWithDestinationPath:[fDstFile2Field stringValue]] != nil) - || ([[[fQueueController currentJobGroup] destinationPath] isEqualToString: [fDstFile2Field stringValue]]) ) - { - NSBeginCriticalAlertSheet( NSLocalizedString( @"Another queued encode has specified the same destination.", @"" ), - NSLocalizedString( @"Cancel", @"" ), NSLocalizedString( @"Overwrite", @"" ), nil, fWindow, self, - @selector( overwriteAddToQueueAlertDone:returnCode:contextInfo: ), - NULL, NULL, [NSString stringWithFormat: - NSLocalizedString( @"Do you want to overwrite %@?", @"" ), - [fDstFile2Field stringValue]] ); - // overwriteAddToQueueAlertDone: will be called when the alert is dismissed. - } - else { [self doAddToQueue]; @@ -1739,118 +2781,10 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It - (void) doAddToQueue { - hb_list_t * list = hb_get_titles( fHandle ); - hb_title_t * title = (hb_title_t *) hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] ); - hb_job_t * job = title->job; - - // Create a Queue Controller job group. Each job that we submit to libhb will also - // get added to the job group so that the queue can track the jobs. - HBJobGroup * jobGroup = [HBJobGroup jobGroup]; - // The job group can maintain meta data that libhb can not... - [jobGroup setPresetName: [fPresetSelectedDisplay stringValue]]; - - // Job groups require that each job within the group be assigned a unique id so - // that the queue can xref between itself and the private jobs that libhb - // maintains. The ID is composed a group id number and a "sequence" number. libhb - // does not use this id. - static int jobGroupID = 0; - jobGroupID++; - - // A sequence number, starting at zero, is used to identifiy to each pass. This is - // used by the queue UI to determine if a pass if the first pass of an encode. - int sequenceNum = -1; - - [self prepareJob]; - - /* Destination file */ - job->file = [[fDstFile2Field stringValue] UTF8String]; - - if( [fSubForcedCheck state] == NSOnState ) - job->subtitle_force = 1; - else - job->subtitle_force = 0; - - /* - * subtitle of -1 is a scan - */ - if( job->subtitle == -1 ) - { - char *x264opts_tmp; - - /* - * When subtitle scan is enabled do a fast pre-scan job - * which will determine which subtitles to enable, if any. - */ - job->pass = -1; - x264opts_tmp = job->x264opts; - job->subtitle = -1; - - job->x264opts = NULL; - - job->indepth_scan = 1; - - job->select_subtitle = (hb_subtitle_t**)malloc(sizeof(hb_subtitle_t*)); - *(job->select_subtitle) = NULL; - - /* - * Add the pre-scan job - */ - job->sequence_id = MakeJobID(jobGroupID, ++sequenceNum); - hb_add( fHandle, job ); - [jobGroup addJob:[HBJob jobWithLibhbJob:job]]; // add this pass to the job group - - job->x264opts = x264opts_tmp; - } - else - job->select_subtitle = NULL; - - /* No subtitle were selected, so reset the subtitle to -1 (which before - * this point meant we were scanning - */ - if( job->subtitle == -2 ) - job->subtitle = -1; - - if( [fVidTwoPassCheck state] == NSOnState ) - { - hb_subtitle_t **subtitle_tmp = job->select_subtitle; - job->indepth_scan = 0; - - /* - * Do not autoselect subtitles on the first pass of a two pass - */ - job->select_subtitle = NULL; - - job->pass = 1; - job->sequence_id = MakeJobID(jobGroupID, ++sequenceNum); - hb_add( fHandle, job ); - [jobGroup addJob:[HBJob jobWithLibhbJob:job]]; // add this pass to the job group - - job->pass = 2; - job->sequence_id = MakeJobID(jobGroupID, ++sequenceNum); - - job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ - strcpy(job->x264opts, [[fAdvancedOptions optionsString] UTF8String]); + [self addQueueFileItem ]; +} - job->select_subtitle = subtitle_tmp; - hb_add( fHandle, job ); - [jobGroup addJob:[HBJob jobWithLibhbJob:job]]; // add this pass to the job group - } - else - { - job->indepth_scan = 0; - job->pass = 0; - job->sequence_id = MakeJobID(jobGroupID, ++sequenceNum); - hb_add( fHandle, job ); - [jobGroup addJob:[HBJob jobWithLibhbJob:job]]; // add this pass to the job group - } - - NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent]; - [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"]; - - // Let the queue controller know about the job group - [fQueueController addJobGroup:jobGroup]; -} /* Rip: puts up an alert before ultimately calling doRip */ @@ -1858,7 +2792,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It { /* Rip or Cancel ? */ hb_state_t s; - hb_get_state2( fHandle, &s ); + hb_get_state2( fQueueEncodeLibhb, &s ); if(s.state == HB_STATE_WORKING || s.state == HB_STATE_PAUSED) { @@ -1868,9 +2802,11 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It // If there are jobs in the queue, then this is a rip the queue - if (hb_count( fHandle ) > 0) + if ([QueueFileArray count] > 0) { - [self doRip]; + /* here lets start the queue with the first item */ + [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; + return; } @@ -1899,14 +2835,16 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It { /* if there are no jobs in the queue, then add this one to the queue and rip otherwise, just rip the queue */ - if( hb_count( fHandle ) == 0) + if([QueueFileArray count] == 0) { [self doAddToQueue]; } NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent]; [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"]; - [self doRip]; + /* go right to processing the new queue encode */ + [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; + } } @@ -1920,14 +2858,15 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It { /* if there are no jobs in the queue, then add this one to the queue and rip otherwise, just rip the queue */ - if( hb_count( fHandle ) == 0 ) + if( [QueueFileArray count] == 0 ) { [self doAddToQueue]; } NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent]; [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"]; - [self doRip]; + [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; + } } @@ -1964,24 +2903,12 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It - (void) doRip { /* Let libhb do the job */ - hb_start( fHandle ); - /*set the fEncodeState State */ + hb_start( fQueueEncodeLibhb ); + /*set the fEncodeState State */ fEncodeState = 1; } - - -//------------------------------------------------------------------------------------ -// Removes all jobs from the queue. Does not cancel the current processing job. -//------------------------------------------------------------------------------------ -- (void) doDeleteQueuedJobs -{ - hb_job_t * job; - while( ( job = hb_job( fHandle, 0 ) ) ) - hb_rem( fHandle, job ); -} - //------------------------------------------------------------------------------------ // Cancels and deletes the current job and stops libhb from processing the remaining // encodes. @@ -1994,10 +2921,32 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It // remaining passes of the job and then start the queue back up if there are any // remaining jobs. - [fQueueController libhbWillStop]; - hb_stop( fHandle ); + + 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++ ; + // ... 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]]; + } + else + { + [self writeToActivityLog: "doCancelCurrentJob the item queue is complete"]; + } + } //------------------------------------------------------------------------------------ @@ -2007,14 +2956,11 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It //------------------------------------------------------------------------------------ - (IBAction)Cancel: (id)sender { - if (!fHandle) return; - - HBJobGroup * jobGroup = [fQueueController currentJobGroup]; - if (!jobGroup) return; - - NSString * alertTitle = [NSString stringWithFormat:NSLocalizedString(@"Stop encoding %@?", nil), - [jobGroup name]]; + if (!fQueueController) return; + + NSString * alertTitle = [NSString stringWithFormat:NSLocalizedString(@"Stop encoding ?", nil)]; + // Which window to attach the sheet to? NSWindow * docWindow; if ([sender respondsToSelector: @selector(window)]) diff --git a/macosx/English.lproj/MainMenu.xib b/macosx/English.lproj/MainMenu.xib index a06210053..724a048e3 100644 --- a/macosx/English.lproj/MainMenu.xib +++ b/macosx/English.lproj/MainMenu.xib @@ -2,14 +2,14 @@ <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.02"> <data> <int key="IBDocument.SystemTarget">1050</int> - <string key="IBDocument.SystemVersion">9E17</string> + <string key="IBDocument.SystemVersion">9F33</string> <string key="IBDocument.InterfaceBuilderVersion">670</string> - <string key="IBDocument.AppKitVersion">949.33</string> + <string key="IBDocument.AppKitVersion">949.34</string> <string key="IBDocument.HIToolboxVersion">352.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> + <integer value="2"/> <integer value="1843"/> - <integer value="1476"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -3115,7 +3115,7 @@ <object class="NSTextField" id="1007421233"> <reference key="NSNextResponder" ref="168918359"/> <int key="NSvFlags">264</int> - <string key="NSFrame">{{610, 8}, {127, 14}}</string> + <string key="NSFrame">{{536, 8}, {201, 14}}</string> <reference key="NSSuperview" ref="168918359"/> <bool key="NSEnabled">YES</bool> <object class="NSTextFieldCell" key="NSCell" id="224806210"> @@ -11407,6 +11407,7 @@ <string>addFactoryPresets:</string> <string>addToQueue:</string> <string>addUserPreset:</string> + <string>applyQueueSettings:</string> <string>audioAddAudioTrackCodecs:</string> <string>audioCodecsPopUpChanged:</string> <string>audioDRCSliderChanged:</string> @@ -11436,6 +11437,7 @@ <string>selectPreset:</string> <string>setDefaultPreset:</string> <string>setEnabledStateOfAudioMixdownControls:</string> + <string>shouldEnableHttpMp4CheckBox:</string> <string>showAddPresetPanel:</string> <string>showDebugOutputPanel:</string> <string>showNewScan:</string> @@ -11501,6 +11503,8 @@ <string>id</string> <string>id</string> <string>id</string> + <string>id</string> + <string>id</string> </object> </object> <object class="NSMutableDictionary" key="outlets"> diff --git a/macosx/English.lproj/Queue.xib b/macosx/English.lproj/Queue.xib index bf4e0f262..3e0b27238 100644 --- a/macosx/English.lproj/Queue.xib +++ b/macosx/English.lproj/Queue.xib @@ -1,17 +1,18 @@ <?xml version="1.0" encoding="UTF-8"?> -<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.01"> +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.02"> <data> <int key="IBDocument.SystemTarget">1050</int> - <string key="IBDocument.SystemVersion">9C7010</string> - <string key="IBDocument.InterfaceBuilderVersion">629</string> - <string key="IBDocument.AppKitVersion">949.26</string> + <string key="IBDocument.SystemVersion">9F33</string> + <string key="IBDocument.InterfaceBuilderVersion">670</string> + <string key="IBDocument.AppKitVersion">949.34</string> <string key="IBDocument.HIToolboxVersion">352.00</string> <object class="NSMutableArray" key="IBDocument.EditedObjectIDs"> <bool key="EncodedWithXMLCoder">YES</bool> + <integer value="2577"/> </object> <object class="NSArray" key="IBDocument.PluginDependencies"> <bool key="EncodedWithXMLCoder">YES</bool> - <string id="862017636">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> </object> <object class="NSMutableArray" key="IBDocument.RootObjects" id="543585533"> <bool key="EncodedWithXMLCoder">YES</bool> @@ -37,173 +38,15 @@ <string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string> <string key="NSWindowContentMinSize">{525, 340}</string> <object class="NSView" key="NSWindowView" id="431299686"> - <nil key="NSNextResponder"/> + <reference key="NSNextResponder"/> <int key="NSvFlags">256</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSCustomView" id="813050146"> - <reference key="NSNextResponder" ref="431299686"/> - <int key="NSvFlags">266</int> - <object class="NSMutableArray" key="NSSubviews"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSProgressIndicator" id="916797324"> - <reference key="NSNextResponder" ref="813050146"/> - <int key="NSvFlags">1290</int> - <object class="NSPSMatrix" key="NSDrawMatrix"/> - <string key="NSFrame">{{18, -2}, {514, 20}}</string> - <reference key="NSSuperview" ref="813050146"/> - <int key="NSpiFlags">16394</int> - <double key="NSMaxValue">1.000000e+02</double> - </object> - <object class="NSTextField" id="917427971"> - <reference key="NSNextResponder" ref="813050146"/> - <int key="NSvFlags">268</int> - <string key="NSFrame">{{20, 22}, {534, 13}}</string> - <reference key="NSSuperview" ref="813050146"/> - <bool key="NSEnabled">YES</bool> - <object class="NSTextFieldCell" key="NSCell" id="722274491"> - <int key="NSCellFlags">67239424</int> - <int key="NSCellFlags2">272760832</int> - <string key="NSContents" id="129568696"/> - <object class="NSFont" key="NSSupport"> - <string key="NSName" id="686937577">LucidaGrande</string> - <double key="NSSize">1.000000e+01</double> - <int key="NSfFlags">2843</int> - </object> - <reference key="NSControlView" ref="917427971"/> - <object class="NSColor" key="NSBackgroundColor" id="987568653"> - <int key="NSColorSpace">6</int> - <string key="NSCatalogName" id="57794503">System</string> - <string key="NSColorName">controlColor</string> - <object class="NSColor" key="NSColor" id="724853981"> - <int key="NSColorSpace">3</int> - <bytes key="NSWhite">MC42NjY2NjY2OQA</bytes> - </object> - </object> - <object class="NSColor" key="NSTextColor" id="434514744"> - <int key="NSColorSpace">6</int> - <reference key="NSCatalogName" ref="57794503"/> - <string key="NSColorName">controlTextColor</string> - <object class="NSColor" key="NSColor" id="1016246953"> - <int key="NSColorSpace">3</int> - <bytes key="NSWhite">MAA</bytes> - </object> - </object> - </object> - </object> - <object class="NSImageView" id="39103954"> - <reference key="NSNextResponder" ref="813050146"/> - <int key="NSvFlags">268</int> - <object class="NSMutableSet" key="NSDragTypes"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSMutableArray" key="set.sortedObjects"> - <bool key="EncodedWithXMLCoder">YES</bool> - <string>Apple PDF pasteboard type</string> - <string>Apple PICT pasteboard type</string> - <string>Apple PNG pasteboard type</string> - <string>NSFilenamesPboardType</string> - <string>NeXT Encapsulated PostScript v1.2 pasteboard type</string> - <string>NeXT TIFF v4.0 pasteboard type</string> - </object> - </object> - <string key="NSFrame">{{20, 118}, {32, 32}}</string> - <reference key="NSSuperview" ref="813050146"/> - <bool key="NSEnabled">YES</bool> - <object class="NSImageCell" key="NSCell" id="604214377"> - <int key="NSCellFlags">130560</int> - <int key="NSCellFlags2">33554432</int> - <object class="NSCustomResource" key="NSContents"> - <string key="NSClassName" id="149668743">NSImage</string> - <string key="NSResourceName">JobLarge</string> - </object> - <int key="NSAlign">0</int> - <int key="NSScale">0</int> - <int key="NSStyle">0</int> - <bool key="NSAnimates">NO</bool> - </object> - <bool key="NSEditable">YES</bool> - </object> - <object class="NSTextField" id="756692114"> - <reference key="NSNextResponder" ref="813050146"/> - <int key="NSvFlags">266</int> - <string key="NSFrame">{{59, 46}, {498, 104}}</string> - <reference key="NSSuperview" ref="813050146"/> - <bool key="NSEnabled">YES</bool> - <object class="NSTextFieldCell" key="NSCell" id="772566242"> - <int key="NSCellFlags">67239424</int> - <int key="NSCellFlags2">272629760</int> - <string key="NSContents">No job processing</string> - <object class="NSFont" key="NSSupport" id="305042972"> - <reference key="NSName" ref="686937577"/> - <double key="NSSize">1.300000e+01</double> - <int key="NSfFlags">1044</int> - </object> - <reference key="NSControlView" ref="756692114"/> - <reference key="NSBackgroundColor" ref="987568653"/> - <reference key="NSTextColor" ref="434514744"/> - </object> - </object> - <object class="NSButton" id="219327174"> - <reference key="NSNextResponder" ref="813050146"/> - <int key="NSvFlags">265</int> - <string key="NSFrame">{{538, 2}, {16, 18}}</string> - <reference key="NSSuperview" ref="813050146"/> - <bool key="NSEnabled">YES</bool> - <object class="NSButtonCell" key="NSCell" id="781725379"> - <int key="NSCellFlags">67239424</int> - <int key="NSCellFlags2">134217728</int> - <reference key="NSContents" ref="129568696"/> - <reference key="NSSupport" ref="305042972"/> - <reference key="NSControlView" ref="219327174"/> - <int key="NSButtonFlags">138690815</int> - <int key="NSButtonFlags2">34</int> - <object class="NSCustomResource" key="NSNormalImage" id="698366776"> - <reference key="NSClassName" ref="149668743"/> - <string key="NSResourceName">Delete</string> - </object> - <object class="NSCustomResource" key="NSAlternateImage"> - <reference key="NSClassName" ref="149668743"/> - <string key="NSResourceName">DeletePressed</string> - </object> - <reference key="NSAlternateContents" ref="129568696"/> - <object class="NSMutableString" key="NSKeyEquivalent"> - <characters key="NS.bytes"/> - </object> - <int key="NSPeriodicDelay">200</int> - <int key="NSPeriodicInterval">25</int> - </object> - </object> - </object> - <string key="NSFrame">{{0, 253}, {574, 170}}</string> - <reference key="NSSuperview" ref="431299686"/> - <string key="NSClassName" id="160106209">NSView</string> - <string key="NSExtension" id="324718730">NSResponder</string> - </object> <object class="NSCustomView" id="60629844"> <reference key="NSNextResponder" ref="431299686"/> <int key="NSvFlags">274</int> <object class="NSMutableArray" key="NSSubviews"> <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSTextField" id="463845363"> - <reference key="NSNextResponder" ref="60629844"/> - <int key="NSvFlags">264</int> - <string key="NSFrame">{{17, 227}, {176, 14}}</string> - <reference key="NSSuperview" ref="60629844"/> - <bool key="NSEnabled">YES</bool> - <object class="NSTextFieldCell" key="NSCell" id="617812287"> - <int key="NSCellFlags">67239424</int> - <int key="NSCellFlags2">272760832</int> - <string key="NSContents">Pending Jobs</string> - <object class="NSFont" key="NSSupport" id="26"> - <reference key="NSName" ref="686937577"/> - <double key="NSSize">1.100000e+01</double> - <int key="NSfFlags">3100</int> - </object> - <reference key="NSControlView" ref="463845363"/> - <reference key="NSBackgroundColor" ref="987568653"/> - <reference key="NSTextColor" ref="434514744"/> - </object> - </object> <object class="NSScrollView" id="9160137"> <reference key="NSNextResponder" ref="60629844"/> <int key="NSvFlags">274</int> @@ -217,7 +60,7 @@ <object class="NSOutlineView" id="790027174"> <reference key="NSNextResponder" ref="13598910"/> <int key="NSvFlags">4352</int> - <string key="NSFrameSize">{517, 190}</string> + <string key="NSFrameSize">{517, 342}</string> <reference key="NSSuperview" ref="13598910"/> <bool key="NSEnabled">YES</bool> <object class="_NSCornerView" key="NSCornerView"> @@ -235,11 +78,15 @@ <object class="NSTableHeaderCell" key="NSHeaderCell"> <int key="NSCellFlags">67239424</int> <int key="NSCellFlags2">0</int> - <reference key="NSContents" ref="129568696"/> - <reference key="NSSupport" ref="26"/> + <string key="NSContents"/> + <object class="NSFont" key="NSSupport" id="26"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">1.100000e+01</double> + <int key="NSfFlags">3100</int> + </object> <object class="NSColor" key="NSBackgroundColor" id="122009290"> <int key="NSColorSpace">6</int> - <reference key="NSCatalogName" ref="57794503"/> + <string key="NSCatalogName">System</string> <string key="NSColorName">headerColor</string> <object class="NSColor" key="NSColor" id="983556133"> <int key="NSColorSpace">3</int> @@ -248,9 +95,12 @@ </object> <object class="NSColor" key="NSTextColor" id="204129071"> <int key="NSColorSpace">6</int> - <reference key="NSCatalogName" ref="57794503"/> + <string key="NSCatalogName">System</string> <string key="NSColorName">headerTextColor</string> - <reference key="NSColor" ref="1016246953"/> + <object class="NSColor" key="NSColor" id="1016246953"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MAA</bytes> + </object> </object> </object> <object class="NSImageCell" key="NSDataCell" id="592677893"> @@ -274,7 +124,7 @@ <object class="NSTableHeaderCell" key="NSHeaderCell"> <int key="NSCellFlags">75628032</int> <int key="NSCellFlags2">0</int> - <reference key="NSContents" ref="129568696"/> + <string key="NSContents"/> <reference key="NSSupport" ref="26"/> <object class="NSColor" key="NSBackgroundColor"> <int key="NSColorSpace">3</int> @@ -286,18 +136,23 @@ <int key="NSCellFlags">337772032</int> <int key="NSCellFlags2">0</int> <object class="NSFont" key="NSSupport" id="844481358"> - <reference key="NSName" ref="686937577"/> + <string key="NSName">LucidaGrande</string> <double key="NSSize">1.200000e+01</double> <int key="NSfFlags">16</int> </object> <reference key="NSControlView" ref="790027174"/> <object class="NSColor" key="NSBackgroundColor"> <int key="NSColorSpace">6</int> - <reference key="NSCatalogName" ref="57794503"/> + <string key="NSCatalogName">System</string> <string key="NSColorName">textBackgroundColor</string> <reference key="NSColor" ref="983556133"/> </object> - <reference key="NSTextColor" ref="434514744"/> + <object class="NSColor" key="NSTextColor" id="434514744"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlTextColor</string> + <reference key="NSColor" ref="1016246953"/> + </object> </object> <int key="NSResizingMask">1</int> <bool key="NSIsResizeable">YES</bool> @@ -311,7 +166,7 @@ <object class="NSTableHeaderCell" key="NSHeaderCell"> <int key="NSCellFlags">67239424</int> <int key="NSCellFlags2">134217728</int> - <reference key="NSContents" ref="129568696"/> + <string key="NSContents"/> <reference key="NSSupport" ref="26"/> <reference key="NSBackgroundColor" ref="122009290"/> <reference key="NSTextColor" ref="204129071"/> @@ -319,14 +174,17 @@ <object class="NSButtonCell" key="NSDataCell" id="620017021"> <int key="NSCellFlags">67239424</int> <int key="NSCellFlags2">134217728</int> - <reference key="NSContents" ref="129568696"/> + <string key="NSContents"/> <reference key="NSSupport" ref="844481358"/> <reference key="NSControlView" ref="790027174"/> <int key="NSButtonFlags">135020799</int> <int key="NSButtonFlags2">6</int> - <reference key="NSNormalImage" ref="698366776"/> - <reference key="NSAlternateContents" ref="129568696"/> - <reference key="NSKeyEquivalent" ref="129568696"/> + <object class="NSCustomResource" key="NSNormalImage"> + <string key="NSClassName">NSImage</string> + <string key="NSResourceName">Delete</string> + </object> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> <int key="NSPeriodicDelay">400</int> <int key="NSPeriodicInterval">75</int> </object> @@ -338,7 +196,7 @@ <reference key="NSBackgroundColor" ref="983556133"/> <object class="NSColor" key="NSGridColor"> <int key="NSColorSpace">6</int> - <reference key="NSCatalogName" ref="57794503"/> + <string key="NSCatalogName">System</string> <string key="NSColorName">gridColor</string> <object class="NSColor" key="NSColor"> <int key="NSColorSpace">3</int> @@ -353,25 +211,28 @@ <bool key="NSAllowsTypeSelect">YES</bool> </object> </object> - <string key="NSFrame">{{1, 1}, {517, 190}}</string> + <string key="NSFrame">{{1, 1}, {517, 342}}</string> <reference key="NSSuperview" ref="9160137"/> <reference key="NSNextKeyView" ref="790027174"/> <reference key="NSDocView" ref="790027174"/> <object class="NSColor" key="NSBGColor"> <int key="NSColorSpace">6</int> - <reference key="NSCatalogName" ref="57794503"/> + <string key="NSCatalogName">System</string> <string key="NSColorName">controlBackgroundColor</string> - <reference key="NSColor" ref="724853981"/> + <object class="NSColor" key="NSColor" id="724853981"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC42NjY2NjY2OQA</bytes> + </object> </object> <int key="NScvFlags">4</int> </object> <object class="NSScroller" id="459639248"> <reference key="NSNextResponder" ref="9160137"/> <int key="NSvFlags">256</int> - <string key="NSFrame">{{518, 1}, {15, 190}}</string> + <string key="NSFrame">{{518, 1}, {15, 342}}</string> <reference key="NSSuperview" ref="9160137"/> <reference key="NSTarget" ref="9160137"/> - <string key="NSAction" id="62811989">_doScroller:</string> + <string key="NSAction">_doScroller:</string> <double key="NSPercent">7.142857e-01</double> </object> <object class="NSScroller" id="636348341"> @@ -381,11 +242,11 @@ <reference key="NSSuperview" ref="9160137"/> <int key="NSsFlags">1</int> <reference key="NSTarget" ref="9160137"/> - <reference key="NSAction" ref="62811989"/> + <string key="NSAction">_doScroller:</string> <double key="NSPercent">9.656652e-01</double> </object> </object> - <string key="NSFrame">{{20, 20}, {534, 192}}</string> + <string key="NSFrame">{{20, 20}, {534, 344}}</string> <reference key="NSSuperview" ref="60629844"/> <reference key="NSNextKeyView" ref="13598910"/> <int key="NSsFlags">18</int> @@ -458,7 +319,12 @@ <string key="NSContents">Indent</string> <reference key="NSSupport" ref="26"/> <reference key="NSControlView" ref="316422061"/> - <reference key="NSBackgroundColor" ref="987568653"/> + <object class="NSColor" key="NSBackgroundColor" id="987568653"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlColor</string> + <reference key="NSColor" ref="724853981"/> + </object> <reference key="NSTextColor" ref="434514744"/> </object> </object> @@ -489,7 +355,7 @@ <int key="NSCellFlags2">134479872</int> <string key="NSContents">quick way to intercept delete key</string> <object class="NSFont" key="NSSupport"> - <reference key="NSName" ref="686937577"/> + <string key="NSName">LucidaGrande</string> <double key="NSSize">9.000000e+00</double> <int key="NSfFlags">3614</int> </object> @@ -497,24 +363,41 @@ <int key="NSButtonFlags">-2038021889</int> <int key="NSButtonFlags2">34</int> <object class="NSFont" key="NSAlternateImage"> - <reference key="NSName" ref="686937577"/> + <string key="NSName">LucidaGrande</string> <double key="NSSize">9.000000e+00</double> <int key="NSfFlags">16</int> </object> - <reference key="NSAlternateContents" ref="129568696"/> + <string key="NSAlternateContents"/> <string type="base64-UTF8" key="NSKeyEquivalent">fw</string> <int key="NSPeriodicDelay">200</int> <int key="NSPeriodicInterval">25</int> </object> </object> </object> - <string key="NSFrameSize">{574, 257}</string> + <string key="NSFrameSize">{574, 371}</string> + <reference key="NSSuperview" ref="431299686"/> + <string key="NSClassName">NSView</string> + <string key="NSExtension">NSResponder</string> + </object> + <object class="NSTextField" id="463845363"> + <reference key="NSNextResponder" ref="431299686"/> + <int key="NSvFlags">264</int> + <string key="NSFrame">{{17, 373}, {176, 14}}</string> <reference key="NSSuperview" ref="431299686"/> - <reference key="NSClassName" ref="160106209"/> - <reference key="NSExtension" ref="324718730"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="617812287"> + <int key="NSCellFlags">67239424</int> + <int key="NSCellFlags2">272760832</int> + <string key="NSContents">Pending Jobs</string> + <reference key="NSSupport" ref="26"/> + <reference key="NSControlView" ref="463845363"/> + <reference key="NSBackgroundColor" ref="987568653"/> + <reference key="NSTextColor" ref="434514744"/> + </object> </object> </object> - <string key="NSFrame">{{1, 9}, {574, 423}}</string> + <string key="NSFrameSize">{574, 423}</string> + <reference key="NSSuperview"/> </object> <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string> <string key="NSMinSize">{525, 362}</string> @@ -527,14 +410,6 @@ <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> - <string key="label">fCurrentJobPane</string> - <reference key="source" ref="678333032"/> - <reference key="destination" ref="813050146"/> - </object> - <int key="connectionID">2560</int> - </object> - <object class="IBConnectionRecord"> - <object class="IBOutletConnection" key="connection"> <string key="label">fQueuePane</string> <reference key="source" ref="678333032"/> <reference key="destination" ref="60629844"/> @@ -543,14 +418,6 @@ </object> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> - <string key="label">fProgressBar</string> - <reference key="source" ref="678333032"/> - <reference key="destination" ref="916797324"/> - </object> - <int key="connectionID">2562</int> - </object> - <object class="IBConnectionRecord"> - <object class="IBOutletConnection" key="connection"> <string key="label">fQueueCountField</string> <reference key="source" ref="678333032"/> <reference key="destination" ref="463845363"/> @@ -559,45 +426,13 @@ </object> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> - <string key="label">fProgressTextField</string> - <reference key="source" ref="678333032"/> - <reference key="destination" ref="917427971"/> - </object> - <int key="connectionID">2567</int> - </object> - <object class="IBConnectionRecord"> - <object class="IBOutletConnection" key="connection"> - <string key="label">fJobDescTextField</string> - <reference key="source" ref="678333032"/> - <reference key="destination" ref="756692114"/> - </object> - <int key="connectionID">2568</int> - </object> - <object class="IBConnectionRecord"> - <object class="IBOutletConnection" key="connection"> - <string key="label" id="1046363022">delegate</string> + <string key="label">delegate</string> <reference key="source" ref="238545558"/> <reference key="destination" ref="678333032"/> </object> <int key="connectionID">2579</int> </object> <object class="IBConnectionRecord"> - <object class="IBActionConnection" key="connection"> - <string key="label">cancelCurrentJob:</string> - <reference key="source" ref="678333032"/> - <reference key="destination" ref="219327174"/> - </object> - <int key="connectionID">2586</int> - </object> - <object class="IBConnectionRecord"> - <object class="IBOutletConnection" key="connection"> - <string key="label">fJobIconView</string> - <reference key="source" ref="678333032"/> - <reference key="destination" ref="39103954"/> - </object> - <int key="connectionID">2595</int> - </object> - <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> <string key="label">fOutlineView</string> <reference key="source" ref="678333032"/> @@ -615,7 +450,7 @@ </object> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> - <reference key="label" ref="1046363022"/> + <string key="label">delegate</string> <reference key="source" ref="790027174"/> <reference key="destination" ref="678333032"/> </object> @@ -676,71 +511,16 @@ <reference key="object" ref="431299686"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="813050146"/> <reference ref="60629844"/> + <reference ref="463845363"/> </object> <reference key="parent" ref="238545558"/> </object> <object class="IBObjectRecord"> - <int key="objectID">2543</int> - <reference key="object" ref="813050146"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="756692114"/> - <reference ref="39103954"/> - <reference ref="916797324"/> - <reference ref="917427971"/> - <reference ref="219327174"/> - </object> - <reference key="parent" ref="431299686"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">2515</int> - <reference key="object" ref="756692114"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="772566242"/> - </object> - <reference key="parent" ref="813050146"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">2538</int> - <reference key="object" ref="39103954"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="604214377"/> - </object> - <reference key="parent" ref="813050146"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">2539</int> - <reference key="object" ref="916797324"/> - <reference key="parent" ref="813050146"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">2541</int> - <reference key="object" ref="917427971"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="722274491"/> - </object> - <reference key="parent" ref="813050146"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">2584</int> - <reference key="object" ref="219327174"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="781725379"/> - </object> - <reference key="parent" ref="813050146"/> - </object> - <object class="IBObjectRecord"> <int key="objectID">2547</int> <reference key="object" ref="60629844"/> <object class="NSMutableArray" key="children"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="463845363"/> <reference ref="9160137"/> <reference ref="948250828"/> <reference ref="252090132"/> @@ -751,15 +531,6 @@ <reference key="parent" ref="431299686"/> </object> <object class="IBObjectRecord"> - <int key="objectID">2511</int> - <reference key="object" ref="463845363"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="617812287"/> - </object> - <reference key="parent" ref="60629844"/> - </object> - <object class="IBObjectRecord"> <int key="objectID">2596</int> <reference key="object" ref="9160137"/> <object class="NSMutableArray" key="children"> @@ -869,31 +640,6 @@ <reference key="parent" ref="60629844"/> </object> <object class="IBObjectRecord"> - <int key="objectID">2633</int> - <reference key="object" ref="772566242"/> - <reference key="parent" ref="756692114"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">2634</int> - <reference key="object" ref="604214377"/> - <reference key="parent" ref="39103954"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">2635</int> - <reference key="object" ref="722274491"/> - <reference key="parent" ref="917427971"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">2636</int> - <reference key="object" ref="781725379"/> - <reference key="parent" ref="219327174"/> - </object> - <object class="IBObjectRecord"> - <int key="objectID">2637</int> - <reference key="object" ref="617812287"/> - <reference key="parent" ref="463845363"/> - </object> - <object class="IBObjectRecord"> <int key="objectID">2638</int> <reference key="object" ref="1016294819"/> <reference key="parent" ref="948250828"/> @@ -934,6 +680,20 @@ <reference key="parent" ref="1017359617"/> <string key="objectName">Application</string> </object> + <object class="IBObjectRecord"> + <int key="objectID">2511</int> + <reference key="object" ref="463845363"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="617812287"/> + </object> + <reference key="parent" ref="431299686"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">2637</int> + <reference key="object" ref="617812287"/> + <reference key="parent" ref="463845363"/> + </object> </object> </object> <object class="NSMutableDictionary" key="flattenedProperties"> @@ -944,19 +704,11 @@ <string>-2.IBPluginDependency</string> <string>2511.IBPluginDependency</string> <string>2511.ImportedFromIB2</string> - <string>2515.IBPluginDependency</string> - <string>2515.ImportedFromIB2</string> - <string>2538.IBPluginDependency</string> - <string>2538.ImportedFromIB2</string> - <string>2539.IBPluginDependency</string> - <string>2539.ImportedFromIB2</string> - <string>2541.IBPluginDependency</string> - <string>2541.ImportedFromIB2</string> - <string>2543.IBPluginDependency</string> - <string>2543.ImportedFromIB2</string> <string>2547.IBPluginDependency</string> <string>2547.ImportedFromIB2</string> + <string>2576.IBEditorWindowLastContentRect</string> <string>2576.IBPluginDependency</string> + <string>2576.IBWindowTemplateEditedContentRect</string> <string>2576.ImportedFromIB2</string> <string>2576.windowTemplate.hasMaxSize</string> <string>2576.windowTemplate.hasMinSize</string> @@ -964,8 +716,6 @@ <string>2576.windowTemplate.minSize</string> <string>2577.IBPluginDependency</string> <string>2577.ImportedFromIB2</string> - <string>2584.IBPluginDependency</string> - <string>2584.ImportedFromIB2</string> <string>2596.IBPluginDependency</string> <string>2596.ImportedFromIB2</string> <string>2597.CustomClassName</string> @@ -999,59 +749,49 @@ </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="862017636"/> - <reference ref="862017636"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <integer value="1" id="9"/> - <reference ref="862017636"/> - <reference ref="9"/> - <reference ref="862017636"/> - <reference ref="9"/> - <reference ref="862017636"/> - <reference ref="9"/> - <reference ref="862017636"/> - <reference ref="9"/> - <reference ref="862017636"/> - <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> + <string>{{87, 422}, {574, 423}}</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>{{87, 422}, {574, 423}}</string> <reference ref="9"/> <reference ref="9"/> <reference ref="9"/> <string>{3.40282e+38, 3.40282e+38}</string> <string>{525, 340}</string> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> - <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> <string>HBQueueOutlineView</string> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <string id="602026114">HBImageAndTextCell</string> - <reference ref="862017636"/> + <string>HBImageAndTextCell</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> - <reference ref="862017636"/> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> <reference ref="9"/> <reference ref="9"/> <reference ref="9"/> @@ -1084,80 +824,18 @@ <bool key="EncodedWithXMLCoder">YES</bool> <object class="IBPartialClassDescription"> <string key="className">HBImageAndTextCell</string> - <string key="superclassName" id="679398894">NSTextFieldCell</string> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - </object> - <object class="NSMutableDictionary" key="outlets"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - </object> + <string key="superclassName">NSTextFieldCell</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey" id="929985091">IBProjectSource</string> + <string key="majorKey">IBProjectSource</string> <string key="minorKey">HBImageAndTextCell.h</string> </object> </object> <object class="IBPartialClassDescription"> - <reference key="className" ref="602026114"/> - <reference key="superclassName" ref="679398894"/> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - </object> - <object class="NSMutableDictionary" key="outlets"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - </object> + <string key="className">HBImageAndTextCell</string> + <string key="superclassName">NSTextFieldCell</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> <string key="majorKey">IBUserSource</string> - <reference key="minorKey" ref="129568696"/> - </object> - </object> - <object class="IBPartialClassDescription"> - <string key="className">NSObject</string> - <nil key="superclassName"/> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - </object> - <object class="NSMutableDictionary" key="outlets"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - </object> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <reference key="majorKey" ref="929985091"/> - <string key="minorKey">PictureController.h</string> + <string key="minorKey"/> </object> </object> <object class="IBPartialClassDescription"> @@ -1167,25 +845,19 @@ <bool key="EncodedWithXMLCoder">YES</bool> <object class="NSMutableArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> - <string>cancelCurrentJob:</string> <string>imageSpacingChanged:</string> <string>indentChanged:</string> - <string>removeSelectedJobGroups:</string> - <string>revealSelectedJobGroups:</string> + <string>removeSelectedQueueItem:</string> + <string>revealSelectedQueueItem:</string> <string>showQueueWindow:</string> - <string>togglePauseResume:</string> - <string>toggleStartCancel:</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> - <string id="1018042781">id</string> - <reference ref="1018042781"/> - <reference ref="1018042781"/> - <reference ref="1018042781"/> - <reference ref="1018042781"/> - <reference ref="1018042781"/> - <reference ref="1018042781"/> - <reference ref="1018042781"/> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> </object> </object> <object class="NSMutableDictionary" key="outlets"> @@ -1205,21 +877,21 @@ </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="160106209"/> + <string>NSView</string> <string>NSSlider</string> - <string id="755548317">NSTextField</string> + <string>NSTextField</string> <string>NSImageView</string> <string>HBQueueOutlineView</string> <string>NSProgressIndicator</string> - <reference ref="755548317"/> - <reference ref="755548317"/> - <reference ref="160106209"/> + <string>NSTextField</string> + <string>NSTextField</string> + <string>NSView</string> <string>NSSlider</string> </object> </object> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey" id="900838398">IBUserSource</string> - <string key="minorKey" id="766135184"/> + <object class="IBClassDescriptionSource" key="sourceIdentifier" id="333889241"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">HBQueueController.h</string> </object> </object> <object class="IBPartialClassDescription"> @@ -1227,308 +899,52 @@ <string key="superclassName">NSWindowController</string> <object class="NSMutableDictionary" key="actions"> <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - </object> - <object class="NSMutableDictionary" key="outlets"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> + <object class="NSMutableArray" key="dict.sortedKeys"> <bool key="EncodedWithXMLCoder">YES</bool> + <string>cancelCurrentJob:</string> + <string>removeSelectedJobGroups:</string> + <string>revealSelectedJobGroups:</string> + <string>togglePauseResume:</string> + <string>toggleStartCancel:</string> </object> <object class="NSMutableArray" key="dict.values"> <bool key="EncodedWithXMLCoder">YES</bool> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> + <string>id</string> </object> </object> <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <reference key="majorKey" ref="929985091"/> - <string key="minorKey">HBQueueController.h</string> + <string key="majorKey">IBUserSource</string> + <string key="minorKey"/> </object> </object> <object class="IBPartialClassDescription"> <string key="className">HBQueueOutlineView</string> <string key="superclassName">NSOutlineView</string> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - </object> - <object class="NSMutableDictionary" key="outlets"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - </object> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <reference key="majorKey" ref="929985091"/> - <string key="minorKey">HBQueueController.h</string> - </object> + <reference key="sourceIdentifier" ref="333889241"/> </object> <object class="IBPartialClassDescription"> <string key="className">HBQueueOutlineView</string> <string key="superclassName">NSOutlineView</string> - <object class="NSMutableDictionary" key="actions"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - </object> - <object class="NSMutableDictionary" key="outlets"> - <bool key="EncodedWithXMLCoder">YES</bool> - <object class="NSArray" key="dict.sortedKeys"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> - <object class="NSMutableArray" key="dict.values"> - <bool key="EncodedWithXMLCoder">YES</bool> - </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBUserSource</string> + <string key="minorKey"/> </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSObject</string> <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <reference key="majorKey" ref="900838398"/> - <reference key="minorKey" ref="766135184"/> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">PictureController.h</string> </object> </object> </object> </object> <int key="IBDocument.localizationMode">0</int> - <string key="IBDocument.LastKnownRelativeProjectPath">../../HandBrake.xcodeproj</string> + <string key="IBDocument.LastKnownRelativeProjectPath">../HandBrake.xcodeproj</string> <int key="IBDocument.defaultPropertyAccessControl">3</int> - <object class="NSMutableData" key="IBDocument.RunnableNib"> - <bytes key="NS.bytes">YnBsaXN0MDDUAAEAAgADAAQABQAGAAkAClgkdmVyc2lvblQkdG9wWSRhcmNoaXZlclgkb2JqZWN0cxIA -AYag0QAHAAhdSUIub2JqZWN0ZGF0YYABXxAPTlNLZXllZEFyY2hpdmVyrxEBMgALAAwAMQA1ADYAPAA9 -AEEARQBWAF4AbQB0AH4AiACJAJkAmgCiAKMApgCwALEAsgC3ALkAvgC/AMIAxgDMAN4A5ADyAPYBFwEY -ARkBGgEeAR8BIgEoATsBPAFCAUMBSAFJAUwBUQFSAVUBXgFhAWQBbgFvAXYBeQGCAMQBgwGIAY0BjgGR -AZkBmgGhAbMBuAG5AboBvQHAAcQByQHKAc0BzgHTAdQB1wHiAeMB5AHnAe8B8AHxAfQB/AH9AhECFAIY -AhsCHAIfAiICKQIqAjMCNQI8Aj0CRQJGAk0CTgJVAlYCXgJfAm0CbgJzAnYCdwJ6AMoAywJ7An4CfwKD -AogClAKdAqYCpwKoAqkCqgKrAqwCrQKxArUCtgK5AroCvwLHAtIC1ALXAtgC2wLiAuMC6gLuAvUC9gL9 -Av4DAwMLAwwDFgMaAxsDHQMeAx8DJAMlAyoDKwMwA04DTwNQA1EDVANVA1YDWwNcA14DXwNUA2ADYQNk -A2UDagNrA3ADcQN0A3kDegN/A4ADhQOGA4sDkAORA5YDlwO+A8EDwgPEA+sEEwQ7BDwEPQQ+BD8EQARB -BEIEQwREBEUERgRHBEgESQRKBEsETARNBE4ETwRQBFEEUgRTBFQEVQRWBFcEWARZBFoEWwRcBF0EXgRf -BGAEZQRqBKAE1gTXBNgE2QTaBNsE3ATdBN4E3wTgBOEE4gTjBOQE5QTmBOcE6ATpBOoE6wTsBO0E7gTv -BPAE8QTyBPME9AT1BPYE9wT4BPkE+gT7BPwE/QT+BP8FAAUBBQIFAwUEBQUFBgUHBQgFCQUMBQ8FElUk -bnVsbN8QEgANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYA -JwAoACkAKgArACwALQAuAC8AMFZOU1Jvb3RWJGNsYXNzXU5TT2JqZWN0c0tleXNfEA9OU0NsYXNzZXNW -YWx1ZXNfEBlOU0FjY2Vzc2liaWxpdHlPaWRzVmFsdWVzXU5TQ29ubmVjdGlvbnNbTlNOYW1lc0tleXNb -TlNGcmFtZXdvcmtdTlNDbGFzc2VzS2V5c1pOU09pZHNLZXlzXU5TTmFtZXNWYWx1ZXNfEBlOU0FjY2Vz -c2liaWxpdHlDb25uZWN0b3JzXU5TRm9udE1hbmFnZXJfEBBOU1Zpc2libGVXaW5kb3dzXxAPTlNPYmpl -Y3RzVmFsdWVzXxAXTlNBY2Nlc3NpYmlsaXR5T2lkc0tleXNZTlNOZXh0T2lkXE5TT2lkc1ZhbHVlc4AC -gQExgMuA+IEBMIAIgNCABYD3gPmA0YEBLoAAgAaAz4EBLxEKV4D60gAOADIAMwA0W05TQ2xhc3NOYW1l -gASAA18QEUhCUXVldWVDb250cm9sbGVy0gA3ADgAOQA6WCRjbGFzc2VzWiRjbGFzc25hbWWiADoAO15O -U0N1c3RvbU9iamVjdFhOU09iamVjdF8QEElCQ29jb2FGcmFtZXdvcmvSAA4APgA/AEBaTlMub2JqZWN0 -c4AHoNIANwA4AEIAQ6MAQwBEADtcTlNNdXRhYmxlU2V0VU5TU2V00gAOAD4ARgBHgEuuAEgASQBKAEsA -TABNAE4ATwBQAFEAUgBTAFQAVYAJgH6AjoCmgKiAqoC7gL2AwIDCgMSAxoDHgMnUAA4AVwBYAFkAWgBb -AB8AXV1OU0Rlc3RpbmF0aW9uWE5TU291cmNlV05TTGFiZWyAfYAKgAKAfNgAXwAOAGAAYQBiADIAYwBk -AGUAZgBnAGgAaQBqAGsAZV8QD05TTmV4dFJlc3BvbmRlclpOU1N1YnZpZXdzWE5TdkZsYWdzW05TRnJh -bWVTaXplW05TRXh0ZW5zaW9uW05TU3VwZXJ2aWV3gAuAe4AMEQESgHiAeYB6gAvVAF8ADgBuAGAAYQAr -AHAAcQByAHNXTlNGcmFtZYAAgLSAs4CyEQEA0gAOAD4ARgB2gEunAHcAeAB5AHoAewB8AH2ADYAegFuA -ZIBogGyAcNcAXwAOAG4AfwBhAIAAZABbAIIAgwCEAIUAhgBbVk5TQ2VsbFlOU0VuYWJsZWSACoAdgA6A -DxEBCAmACl8QFnt7MTcsIDIyN30sIHsxNzYsIDE0fX3YAIoADgCLAIwAjQCOAI8AkACRAJIAkwCUAJUA -dwCXAJhbTlNDZWxsRmxhZ3NfEBFOU0JhY2tncm91bmRDb2xvclpOU0NvbnRlbnRzWU5TU3VwcG9ydF1O -U0NvbnRyb2xWaWV3XE5TQ2VsbEZsYWdzMltOU1RleHRDb2xvchIEAf4AgByAFIAQgBGADRIQQgAAgBlc -UGVuZGluZyBKb2Jz1AAOAJsAnACdAJ4AnwCgAKFWTlNTaXplVk5TTmFtZVhOU2ZGbGFnc4ATI0AmAAAA -AAAAgBIRDBxcTHVjaWRhR3JhbmRl0gA3ADgApAClogClADtWTlNGb2501QAOAKcAqACpAKoAqwCsAK0A -rgCvV05TQ29sb3JcTlNDb2xvclNwYWNlW05TQ29sb3JOYW1lXU5TQ2F0YWxvZ05hbWWAGIAXEAaAFoAV -VlN5c3RlbVxjb250cm9sQ29sb3LTAA4AqACzAKsAtQC2V05TV2hpdGWAGBADSzAuNjY2NjY2NjkA0gA3 -ADgAuACnogCnADvVAA4ApwCoAKkAqgCrALsArQC8AK+AGIAbgBqAFV8QEGNvbnRyb2xUZXh0Q29sb3LT -AA4AqACzAKsAtQDBgBhCMADSADcAOADDAMSkAMQAxQB/ADtfEA9OU1RleHRGaWVsZENlbGxcTlNBY3Rp -b25DZWxs0gA3ADgAxwDIpQDIAMkAygDLADtbTlNUZXh0RmllbGRZTlNDb250cm9sVk5TVmlld1tOU1Jl -c3BvbmRlctwAXwDNAA4AbgDOAGAAzwBhAGQA0ADRANIAWwDUANUA1gDXANgA2QBoAFsA2wDcANxbTlNI -U2Nyb2xsZXJYTlNzRmxhZ3NcTlNTY3JvbGxBbXRzW05TVlNjcm9sbGVyXU5TTmV4dEtleVZpZXddTlND -b250ZW50Vmlld4AKgFeAWoBZEBKAH08QEAAAAAAAAAAAQZgAAEGYAACACoBTgCCAINIADgA+AEYA4IBL -owDcANsA1IAggFOAV9oAXwAOAG4A5QBgAGEA5gDnAGQA0QB4AOkA6gDrAOwA7QDuAO8AeADuWU5TY3ZG -bGFnc1lOU0RvY1ZpZXdZTlNCR0NvbG9ygB6AUoBPEASAIREJAIAigFCAHoAi0gAOAD4ARgD0gEuhAO6A -It8QFABfAPcADgD4APkAiwD6APsA/AD9AP4AYQBiAIAAMgD/AQAAZAEBAQIA3AEEAQUBBgEHAQgAhgEK -AQsBDAENAQ4BDwCGAREBEgETANwBFQEWXxAfTlNEcmFnZ2luZ1NvdXJjZU1hc2tGb3JOb25Mb2NhbFlO -U1R2RmxhZ3NfEBNOU09yaWdpbmFsQ2xhc3NOYW1lXxASTlNBbGxvd3NUeXBlU2VsZWN0XE5TQ29ybmVy -Vmlld18QF05TSW50ZXJjZWxsU3BhY2luZ1dpZHRoXxAZTlNDb2x1bW5BdXRvcmVzaXppbmdTdHlsZV8Q -GE5TSW50ZXJjZWxsU3BhY2luZ0hlaWdodFtOU0dyaWRDb2xvcl8QHE5TRHJhZ2dpbmdTb3VyY2VNYXNr -Rm9yTG9jYWxeTlNUYWJsZUNvbHVtbnNbTlNSb3dIZWlnaHSAIBAAgEESGsCAAIAkgDAJgCYjQAgAAAAA -AAAQASNAAAAAAAAAABERAIAlCYAjgEwQD4AggCkjQDEAAAAAAABfEBJIQlF1ZXVlT3V0bGluZVZpZXdd -TlNPdXRsaW5lVmlld1p7NTE3LCAxOTB91ABfAA4AbgBhACsBHAEdAHOAAIAogCdfEBR7ezUxOCwgMH0s -IHsxNiwgMTd9fdIANwA4ASABIaQBIQDKAMsAO11fTlNDb3JuZXJWaWV30gAOAD4ARgEkgEujASUBJgEn -gCqAN4BC2wEpAA4BKgErASwBLQEuAS8BMAExATIAhgE0ATUBNgE3ATgAtQE3ATcAhgDuXk5TSXNSZXNp -emVhYmxlXE5TSGVhZGVyQ2VsbFxOU0lkZW50aWZpZXJXTlNXaWR0aFpOU0RhdGFDZWxsXk5TUmVzaXpp -bmdNYXNrWk5TTWluV2lkdGhaTlNNYXhXaWR0aFxOU0lzRWRpdGFibGVbTlNUYWJsZVZpZXcJgDaALIAr -I0BDAAAAAAAAgDQJgCJUaWNvbtcAigAOAIsAjACNAI8AkACRAT0BPgE/AJUBBAFBgDOALoAtgBGAMVDV -AA4ApwCoAKkAqgCrAQgArQFGAK+AGIAwgC+AFVtoZWFkZXJDb2xvctMADgCoALMAqwC1AUuAGEIxANUA -DgCnAKgAqQCqAKsAuwCtAU8Ar4AYgBuAMoAVXxAPaGVhZGVyVGV4dENvbG9y0gA3ADgBUwFUpQFUAMQA -xQB/ADtfEBFOU1RhYmxlSGVhZGVyQ2VsbNcAigAOAVYBVwFYAI8BWQFaAVsBBAC1AQQBXACGV05TU3R5 -bGVXTlNBbGlnbldOU1NjYWxlWk5TQW5pbWF0ZXMSAAH+AIA1EgIAAAAJ0gA3ADgBXwFgowFgAH8AO1tO -U0ltYWdlQ2VsbNIANwA4AWIBY6IBYwA7XU5TVGFibGVDb2x1bW7aASkADgEqASsBLAEtAS4BLwEwATIA -hgE0AWcBaAFpAWoBDAFrAWwA7gmANoA5gDgjQHwgAAAAAACAOyNARAAAAAAAACNAs4gAAAAAAIAiVGRl -c2PXAIoADgCLAIwAjQCPAJABcAE9AXIBPwCVAQQBQRIEgf4AgDOAOoAtgBGAMdMADgCoALMAqwC1AXiA -GEswLjMzMzMzMjk5ANkAigAOAPkAiwCNAI4AjwAyAJABegEFAXwBfQF+AO4BBAGAAJgSFCH+AIBBgD2A -P4A+gCKAPIAZXxASSEJJbWFnZUFuZFRleHRDZWxs1AAOAJsAnACdAJ4BhQCgAYeAEyNAKAAAAAAAAIAS -EBDVAA4ApwCoAKkAqgCrAQgArQGLAK+AGIAwgECAFV8QE3RleHRCYWNrZ3JvdW5kQ29sb3LSADcAOAGP -AZCiAZAAO15OU0NsYXNzU3dhcHBlctgADgEqASsBLAEtAS8BMAEyATQBkwGUAZUBlgGXAZUA7oA2gESA -QyNANAAAAAAAAIBFI0AgAAAAAAAAgCJWYWN0aW9u1wCKAA4AiwCMAI0AjwCQAJEBPQE+AT8AlQGfAUGA -M4AugC2AERIIAAAAgDHdAIoADgGiAaMBpAGlAaYAjACNAI4BpwCPAagAkQGpAT8BqwGsAK0BPwE/AX4A -7gGxAZ8Bsl8QE05TQWx0ZXJuYXRlQ29udGVudHNdTlNOb3JtYWxJbWFnZV8QEk5TUGVyaW9kaWNJbnRl -cnZhbF5OU0J1dHRvbkZsYWdzMl8QD05TS2V5RXF1aXZhbGVudF8QD05TUGVyaW9kaWNEZWxheV1OU0J1 -dHRvbkZsYWdzgEqALYBGEEuALYAtgD6AIhEBkBIIDED/0wAOADIBtAG1AbYBt15OU1Jlc291cmNlTmFt -ZYBJgEeASFdOU0ltYWdlVkRlbGV0ZdIANwA4AbsBvKIBvAA7XxAQTlNDdXN0b21SZXNvdXJjZdIANwA4 -Ab4Bv6QBvwDFAH8AO1xOU0J1dHRvbkNlbGzSADcAOAHBAcKjAcIBwwA7Xk5TTXV0YWJsZUFycmF5V05T -QXJyYXnVAA4ApwCoAKkAqgCrAcYArQHHAK+AGIBOgE2AFVlncmlkQ29sb3LTAA4AqACzAKsAtQHMgBhE -MC41AF8QFHt7MSwgMX0sIHs1MTcsIDE5MH191QAOAKcAqACpAKoAqwCsAK0B0QCvgBiAF4BRgBVfEBZj -b250cm9sQmFja2dyb3VuZENvbG9y0gA3ADgB1QHWpAHWAMoAywA7Wk5TQ2xpcFZpZXfYAF8B2AAOAG4A -YQHZAGQB2gB4AHgB3QHeAHMB3wB4AeFYTlNUYXJnZXRYTlNBY3Rpb25ZTlNQZXJjZW50gB6AHoBWgFSA -VYAeIz/m222gAAAAXxAVe3s1MTgsIDF9LCB7MTUsIDE5MH19XF9kb1Njcm9sbGVyOtIANwA4AeUB5qUB -5gDJAMoAywA7Wk5TU2Nyb2xsZXLZAF8B2AAOAG4AzgBhAdkAZAHaAHgAeAHdAesBDABzAd8AeAHugB6A -HoBWgFiAVYAeIz/u5rrAAAAAXxAZe3stMTAwLCAtMTAwfSwgezI4MiwgMTV9fV8QFnt7MjAsIDIwfSwg -ezUzNCwgMTkyfX3SADcAOAHyAfOkAfMAygDLADtcTlNTY3JvbGxWaWV31wBfAA4AbgB/AGEAgABkAFsB -9gH3AfgB+QCGAFuACoBjgFyAXRP/////gAABJAmACl8QFHt7NjAsIDF9LCB7MTgwLCAxNn193gH+AIoA -DgH/AgAAjACNAI4CAQICAI8CAwIEAgUBDQIGAgcCCAEMAgkCCgB5AgwCDQIOAg8CDQCGV05TVmFsdWVf -EBNOU051bWJlck9mVGlja01hcmtzXxASTlNUaWNrTWFya1Bvc2l0aW9uWk5TTWF4VmFsdWVaTlNNaW5W -YWx1ZVpOU1ZlcnRpY2FsXU5TQWx0SW5jVmFsdWVfEBpOU0FsbG93c1RpY2tNYXJrVmFsdWVzT25seRIE -Bf8AgGIQH4BegGCAWyNAPgAAAAAAACMAAAAAAAAAABIABAAACAnSAA4CEgITAUJZTlMuc3RyaW5ngF/S -ADcAOAIVAhajAhYCFwA7XxAPTlNNdXRhYmxlU3RyaW5nWE5TU3RyaW5n1AAOAJsAnACdAJ4BhQIaAYeA -E4BhWUhlbHZldGljYdIANwA4Ah0CHqQCHgDFAH8AO1xOU1NsaWRlckNlbGzSADcAOAIgAiGlAiEAyQDK -AMsAO1hOU1NsaWRlctcAXwAOAG4AfwBhAIAAZABbAfYCJQImAfkAhgBbgAqAY4BlgGYJgApfEBR7ezI5 -NiwgMn0sIHs4MCwgMTZ9fd4B/gCKAA4B/wIAAIwAjQCOAgECAgCPAgMCBAIFAQsCBgIHAiwBDAItAgoA -egIwAg0CDgIPAg0AhoBiEAuAZ4BggGQjQCQAAAAAAAAICdIADgISAhMBQoBf1wBfAA4AbgB/AGEAgABk -AFsAggI4AjkB+QCGAFuACoAdgGmAagmACl8QE3t7MTcsIDB9LCB7MzgsIDE0fX3YAIoADgCLAIwAjQCO -AI8AkACRAJIAkwJAAJUAewJDAJiAHIAUgGuAEYBoEhBAAACAGVZJbmRlbnTXAF8ADgBuAH8AYQCAAGQA -WwCCAkkCSgH5AIYAW4AKgB2AbYBuCYAKXxAUe3syNDUsIDF9LCB7NDYsIDE0fX3YAIoADgCLAIwAjQCO -AI8AkACRAJIAkwJRAJUAfAJDAJiAHIAUgG+AEYBsgBlXU3BhY2luZ9cAXwAOAG4AfwBhAIAAZABbAlgC -WQJaAlsAhgBbgAqAd4BxgHIRASQJgApfEBV7ezYsIC0yNX0sIHsxNTksIDE2fX3dAIoADgGiAaQBpQJg -AaYAjACNAI4BpwCPAagAkQGpAT8CYwJkAmUCZgJnAmgAfQJqAmsCbF8QEE5TQWx0ZXJuYXRlSW1hZ2WA -SoAtEBkQIoB1gHaAc4B0gHAQyBIIBAAAE/////+GhkD/XxAhcXVpY2sgd2F5IHRvIGludGVyY2VwdCBk -ZWxldGUga2V51AAOAJsAnACdAJ4CcACgAnKAEyNAIgAAAAAAAIASEQ4e1AAOAJsAnACdAJ4CcACgAYeA -E4ASUX/SADcAOAJ4AnmlAnkAyQDKAMsAO1hOU0J1dHRvblp7NTc0LCAyNTd90gA3ADgCfAJ9pAJ9AMoA -ywA7XE5TQ3VzdG9tVmlld1pmUXVldWVQYW5l0gA3ADgCgAKBowKBAoIAO18QFE5TTmliT3V0bGV0Q29u -bmVjdG9yXk5TTmliQ29ubmVjdG9y1AAOAFcAWABZAFoChQAfAoeAfYB/gAKAjdkAXwAOAG4CiQB/AooA -YQCAAGQCiwKMAo0AhgKPApACkQCGAotaTlNFZGl0YWJsZVtOU0RyYWdUeXBlc4CAgIyAiAmAiYCBEQEM -CYCA2ABfAA4AbgBgAGEAMgBjAGQAZQBmApcCmAKZAGoAawBlgAuAe4CkgI8RAQqAeYB6gAvSAA4APgA/ -Ap+AB6YCoAKhAqICowKkAqWAgoCDgISAhYCGgIdfEBlBcHBsZSBQREYgcGFzdGVib2FyZCB0eXBlXxAZ -QXBwbGUgUE5HIHBhc3RlYm9hcmQgdHlwZV8QFU5TRmlsZW5hbWVzUGJvYXJkVHlwZV8QMU5lWFQgRW5j -YXBzdWxhdGVkIFBvc3RTY3JpcHQgdjEuMiBwYXN0ZWJvYXJkIHR5cGVfEB5OZVhUIFRJRkYgdjQuMCBw -YXN0ZWJvYXJkIHR5cGVfEBpBcHBsZSBQSUNUIHBhc3RlYm9hcmQgdHlwZV8QFXt7MjAsIDExOH0sIHsz -MiwgMzJ9fdgAigAOAVYAjAFXAVgAjwFZAVoBWwEEAq8BBAEEAVwCD4A1gIoI0wAOADIBtAG1AbYCtIBJ -gEeAi1hKb2JMYXJnZdIANwA4ArcCuKUCuADJAMoAywA7W05TSW1hZ2VWaWV3XGZKb2JJY29uVmlld9QA -DgBXAFgAWQBaAosAHwK+gH2AgIACgKXSAA4APgBGAsGAS6UCwgLDAoUCxQLGgJCAlYB/gJmAntgAXwAO -AG4CAQBhAsgAZALJAosCywLMAs0CzgLPAosC0VlOU3BpRmxhZ3NcTlNEcmF3TWF0cml4gICAlICTI0BZ -AAAAAAAAEQUKEUAKgICAkdEADgLTgJLSADcAOALVAtaiAtYAO1pOU1BTTWF0cml4XxAVe3sxOCwgLTJ9 -LCB7NTE0LCAyMH190gA3ADgC2QLapALaAMoAywA7XxATTlNQcm9ncmVzc0luZGljYXRvctcAXwAOAG4A -fwBhAIAAZAKLAIIC3gLfApEAhgKLgICAHYCWgJcJgIBfEBV7ezIwLCAyMn0sIHs1MzQsIDEzfX3YAIoA -DgCLAIwAjQCOAI8AkACRAJIAkwE/AucCwwCXAJiAHIAUgC2AmICVgBnUAA4AmwCcAJ0AngIwAKAC7YAT -gBIRCxvXAF8ADgBuAH8AYQCAAGQCiwCCAvEC8gKZAIYCi4CAgB2AmoCbCYCAXxAWe3s1OSwgNDZ9LCB7 -NDk4LCAxMDR9fdgAigAOAIsAjACNAI4AjwCQAJEAkgCTAvkC+gLFAkMAmIAcgBSAnICdgJmAGV8QEU5v -IGpvYiBwcm9jZXNzaW5n1AAOAJsAnACdAJ4DAACgAwKAEyNAKgAAAAAAAIASEQQU1wBfAA4AbgB/AGEA -gABkAosCWAMGAwcDCACGAouAgIB3gJ+AoBEBCQmAgF8QFHt7NTM4LCAyfSwgezE2LCAxOH193gCKAA4B -ogGjAaQBpQJgAaYAjACNAI4BpwCPAagAkQGpAT8BqwJjAmQDEAMRAT8C+gLGAmoBnwMVgEqALYBGgKGA -o4AtgJ2AnhIIRED/0wAOADIBtAG1AbYDGYBJgEeAol1EZWxldGVQcmVzc2Vk0gAOAhICEwFCgF9fEBZ7 -ezAsIDI1M30sIHs1NzQsIDE3MH19XxAPZkN1cnJlbnRKb2JQYW5l1AAOAFcAWABZAFoCwgAfAyOAfYCQ -gAKAp1xmUHJvZ3Jlc3NCYXLUAA4AVwBYAFkAWgLDAB8DKYB9gJWAAoCpXxASZlByb2dyZXNzVGV4dEZp -ZWxk1AAOAFcAWABZAFoDLQAfAy+AfYCrgAKAut8QDwMxAA4DMgMzAzQDNQM2AzcDOAM5AzoDOwM8Az0D -PgBlA0ADQQNCA0MDRANFA0YDRwNIA0kDSgNLA0wDTVxOU1dpbmRvd1ZpZXdfEBZOU1dpbmRvd0NvbnRl -bnRNYXhTaXplXE5TU2NyZWVuUmVjdF8QE05TRnJhbWVBdXRvc2F2ZU5hbWVdTlNXaW5kb3dUaXRsZVlO -U1dURmxhZ3NdTlNXaW5kb3dDbGFzc18QFk5TV2luZG93Q29udGVudE1pblNpemVcTlNXaW5kb3dSZWN0 -WU5TTWF4U2l6ZV8QD05TV2luZG93QmFja2luZ18QEU5TV2luZG93U3R5bGVNYXNrWU5TTWluU2l6ZVtO -U1ZpZXdDbGFzc4ALgLmAsIC1gLiArRJweAAAgK6AsYCsgLcQAhEQD4C2gK9fEBh7ezg5MywgMTM3fSwg -ezU3NCwgNDIzfX1fEBFRdWV1ZSAtIEhhbmRCcmFrZVhOU1dpbmRvd9IADgISAhMDU4BfVFZpZXdfEBp7 -My40MDI4MmUrMzgsIDMuNDAyODJlKzM4fVp7NTI1LCAzNDB90gAOAD4ARgNYgEuiAosAW4CAgApfEBR7 -ezEsIDl9LCB7NTc0LCA0MjN9fdIANwA4A10AyqMAygDLADtfEBZ7ezAsIDB9LCB7MTkyMCwgMTE3OH19 -Wns1MjUsIDM2Mn1bUXVldWVXaW5kb3fSADcAOANiA2OiA2MAO18QEE5TV2luZG93VGVtcGxhdGVWd2lu -ZG931AAOAFcAWABZAFoAdwAfA2mAfYANgAKAvF8QEGZRdWV1ZUNvdW50RmllbGTUAA4AVwBYAFkDbAAf -AsYDb4C/gAKAnoC+XxARY2FuY2VsQ3VycmVudEpvYjrSADcAOANyA3OjA3MCggA7XxAVTlNOaWJDb250 -cm9sQ29ubmVjdG9y1AAOAFcAWABZAFoAHwDuA3iAfYACgCKAwVhkZWxlZ2F0ZdQADgBXAFgAWQBaAsUA -HwN+gH2AmYACgMNfEBFmSm9iRGVzY1RleHRGaWVsZNQADgBXAFgAWQBaAO4AHwOEgH2AIoACgMVcZk91 -dGxpbmVWaWV31AAOAFcAWABZAFoAHwMtA3iAfYACgKuAwdQADgBXAFgAWQNsAB8AfQOPgL+AAoBwgMhf -EBhyZW1vdmVTZWxlY3RlZEpvYkdyb3VwczrUAA4AVwBYAFkAWgAfAO4DlYB9gAKAIoDKWmRhdGFTb3Vy -Y2XSAA4APgOYA5mAzq8QJAJaAHoCiwDuAfgAeQLCASYAdwLFAScAfAMtASUCxgCEAGUBOALDA60A1ADb -AvICjwKFAwcAWwFqAjkC3wJKAiYAfQB4AHsBloBygGSAgIAigF2AW4CQgDeADYCZgEKAbICrgCqAnoAP -gAuANICVgMyAV4BTgJuAiYB/gKCACoA7gGqAl4BugGaAcIAegGiARdIADgAyADMDwIAEgM1dTlNBcHBs -aWNhdGlvbtIANwA4A8MBw6IBwwA70gAOAD4DmAPGgM6vECQAfQBbAGUAeAB5AFsCiwDuAFsCiwDuAFsA -HwDuAosAdwMtASUCiwAfAHgAeALFAoUCiwLGAGUBJgB7AsMAfAB6AFsAWwBbASeAcIAKgAuAHoBbgAqA -gIAigAqAgIAigAqAAoAigICADYCrgCqAgIACgB6AHoCZgH+AgICegAuAN4BogJWAbIBkgAqACoAKgELS -AA4APgOYA+2Azq8QJQJaAHoCiwDuAB8B+AB5AsIBJgB3AsUAfAEnAy0BJQLGAIQAZQE4AsMDrQDUANsC -8gMHAoUCjwBbAkoCOQB9At8CJgFqAHgAewGWgHKAZICAgCKAAoBdgFuAkIA3gA2AmYBsgEKAq4AqgJ6A -D4ALgDSAlYDMgFeAU4CbgKCAf4CJgAqAboBqgHCAl4BmgDuAHoBogEXSAA4APgOYBBWAzq8QJQQWBBcE -GAQZBBoEGwQcBB0EHgQfBCAEIQQiBCMEJAQlBCYEJwQoBCkEKgQrBCwELQQuBC8EMAQxBDIEMwQ0BDUE -NgQ3BDgEOQQ6gNKA04DUgNWA1oDXgNiA2YDagNuA3IDdgN6A34DggOGA4oDjgOSA5YDmgOeA6IDpgOqA -64DsgO2A7oDvgPCA8YDygPOA9ID1gPZfEC9CdXR0b24gQ2VsbCAocXVpY2sgd2F5IHRvIGludGVyY2Vw -dCBkZWxldGUga2V5KV8QGkhvcml6b250YWwgVGljayBUb3AgU2xpZGVyW0N1c3RvbSBWaWV3XxASUXVl -dWUgT3V0bGluZSBWaWV3XEZpbGUncyBPd25lcl1TbGlkZXIgQ2VsbC0xXxAcSG9yaXpvbnRhbCBUaWNr -IFRvcCBTbGlkZXItMV8QHUhvcml6b250YWwgUHJvZ3Jlc3MgSW5kaWNhdG9yXxATVGFibGUgQ29sdW1u -IChkZXNjKV8QGlN0YXRpYyBUZXh0IChQZW5kaW5nIEpvYnMpXxAfU3RhdGljIFRleHQgKE5vIGpvYiBw -cm9jZXNzaW5nKV8QFVN0YXRpYyBUZXh0IChTcGFjaW5nKV8QFVRhYmxlIENvbHVtbiAoYWN0aW9uKVZX -aW5kb3dfEBNUYWJsZSBDb2x1bW4gKGljb24pXxAPU3F1YXJlIChEZWxldGUpXxAeVGV4dCBGaWVsZCBD -ZWxsIChQZW5kaW5nIEpvYnMpXENvbnRlbnQgVmlld1pJbWFnZSBDZWxsW1N0YXRpYyBUZXh0W0FwcGxp -Y2F0aW9uXxATSG9yaXpvbnRhbCBTY3JvbGxlcl8QEVZlcnRpY2FsIFNjcm9sbGVyXxAjVGV4dCBGaWVs -ZCBDZWxsIChObyBqb2IgcHJvY2Vzc2luZylfEBRCdXR0b24gQ2VsbCAoRGVsZXRlKV8QFUltYWdlIFZp -ZXcgKEpvYkxhcmdlKV8QFUltYWdlIENlbGwgKEpvYkxhcmdlKV1DdXN0b20gVmlldy0xXxAZVGV4dCBG -aWVsZCBDZWxsIChTcGFjaW5nKV8QGFRleHQgRmllbGQgQ2VsbCAoSW5kZW50KV8QKlNxdWFyZSAocXVp -Y2sgd2F5IHRvIGludGVyY2VwdCBkZWxldGUga2V5KV8QD1RleHQgRmllbGQgQ2VsbFtTbGlkZXIgQ2Vs -bF8QE0ltYWdlIEFuZCBUZXh0IENlbGxbU2Nyb2xsIFZpZXdfEBRTdGF0aWMgVGV4dCAoSW5kZW50KV8Q -FkJ1dHRvbiBDZWxsIChEZWxldGUpLTHSAA4APgOYBGKAzqIA7gFqgCKAO9IADgA+A5gEZ4DOogERAYCA -I4A80gAOAD4DmARsgM6vEDMCWgB6AosA7gH4AFUASQBRAFAAeQBUAScCxgBOAGUDrQBPANsC8gFqAkoA -SAI5At8AeABLAEoATQAfAEwCwgEmAFIAdwBTAsUAfAMtASUBOACEAsMA1AKPAwcChQBbAH0CJgB7AZaA -coBkgICAIoBdgMmAfoDCgMCAW4DHgEKAnoC7gAuAzIC9gFOAm4A7gG6ACYBqgJeAHoCmgI6AqoACgKiA -kIA3gMSADYDGgJmAbICrgCqANIAPgJWAV4CJgKCAf4AKgHCAZoBogEXSAA4APgOYBKKAzq8QMwSjBKQE -pQSmBKcEqASpBKoEqwSsBK0ErgSvBLAEsQSyBLMEtAS1BLYEtwS4BLkEugS7BLwEvQS+BL8EwATBBMIE -wwTEBMUExgTHBMgEyQTKBMsEzATNBM4EzwTQBNEE0gTTBNQE1YD7gPyA/YD+gP+BAQCBAQGBAQKBAQOB -AQSBAQWBAQaBAQeBAQiBAQmBAQqBAQuBAQyBAQ2BAQ6BAQ+BARCBARGBARKBAROBARSBARWBARaBAReB -ARiBARmBARqBARuBARyBAR2BAR6BAR+BASCBASGBASKBASOBASSBASWBASaBASeBASiBASmBASqBASuB -ASyBAS0RClIRCjMRCe8RCiURCk4RCioRCiMRCggRCisRCjIRCj8RCiwRChgRCgQRChET//////////0R -ChoRClMRCkkRCjERClERCgERClARCksRCiQRCgIRCgARClURClYRCgcRCesRCicRCikRCc8RChMRCdMR -CjcRChARCkARCkERCk0RCe0RClQRCkoRCkwRCeoRCfMRCj4RCk8RCjYRCi3SAA4APgBGBQuAS6DSAA4A -PgOYBQ6AzqDSAA4APgOYBRGAzqDSADcAOAUTBRSiBRQAO15OU0lCT2JqZWN0RGF0YQAIABkAIgAnADEA -OgA/AEQAUgBUAGYCzgLUAx8DJgMtAzsDTQNpA3cDgwOPA50DqAO2A9ID4APzBAUEHwQpBDYEOAQ7BD0E -PwRCBEQERgRIBEoETAROBFEEUwRVBFcEWgRdBF8EaAR0BHYEeASMBJUEngSpBK4EvQTGBNkE4gTtBO8E -8AT5BQAFDQUTBRwFHgU7BT0FPwVBBUMFRQVHBUkFSwVNBU8FUQVTBVUFVwVoBXYFfwWHBYkFiwWNBY8F -sAXCBc0F1gXiBe4F+gX8Bf4GAAYDBgUGBwYJBgsGIAYoBioGLAYuBjAGMwY8Bj4GTQZPBlEGUwZVBlcG -WQZbBngGfwaJBosGjQaPBpEGlAaVBpcGsAbRBt0G8Qb8BwYHFAchBy0HMgc0BzYHOAc6BzwHQQdDB1AH -YQdoB28HeAd6B4MHhQeIB5UHngejB6oHvwfHB9QH4AfuB/AH8gf0B/YH+Af/CAwIGQghCCMIJQgxCDoI -PwhUCFYIWAhaCFwIbwh8CH4IgQiKCJMIpQiyCLsIxgjSCNwI4wjvCSAJLAk1CUIJTglcCWoJbAluCXAJ -cgl0CXYJiQmLCY0JjwmRCZoJnAmjCaUJpwmpCdIJ3AnmCfAJ8gn0CfYJ+An6Cf0J/woBCgMKBQoOChAK -EwoVCmgKigqUCqoKvwrMCuYLAgsdCykLSAtXC2MLZQtnC2kLbgtwC3ILcwt1C34LgAuJC4wLjguPC5EL -kwuVC5cLmQuiC7cLxQvQC+EL4wvlC+cL/gwHDBAMHgwnDCkMMAwyDDQMNgxjDHIMfwyMDJQMnwyuDLkM -xAzRDN0M3gzgDOIM5AztDO8M8AzyDPcNFA0WDRgNGg0cDR4NHw00DTYNOA06DTwNSA1VDVcNWg1vDXEN -cw11DXcNiQ2SDZ0NsQ3ODdYN3g3mDfEN9g34Df0N/g4HDg4OGg4jDigONg5fDmAOYg5kDmYObw5xDnoO -gw6FDooOpw6sDq4OsA6yDrQOtg7DDsUO0Q72DvsO/Q7/DwEPAw8FDwcPCQ8eDy8PMQ86DzwPPg9TD1UP -Vw9ZD1sPcQ96D38Pjg+vD7EPsw+1D74PwA/JD8sP0g/vD/EP8w/1D/cP/A/+EDMQSRBXEGwQexCNEJ8Q -rRCvELEQsxC1ELcQuRC7EL0QwBDFENIQ4RDjEOUQ5xDvEPYQ/xEEERcRIBEpETYRPxFGEVURXRFyEXQR -dhF4EXoRhBGREZMRmBGvEcQRxhHIEcoRzBHlEe4R9xICEiMSLBI1Ej8SQRJDEkUSRxJJEksSVBJsEnkS -ghKNEpgSvRK/EsESwxLFEscSyRLSEu4TBxMQExkTJhNDE0UTRxNJE0sTVBNVE1cTbhOnE68TxRPaE+UT -8BP7FAkUJhQrFC0ULxQxFDMUNRQ+FEcUTBRNFE4UVxRhFGMUbBRzFIUUjhSfFKEUoxStFLYUvxTMFNUU -4BTpFQYVCBUKFQwVDhUPFREVKBVhFWMVZRVnFWkVaxV0FXUVdhV/FYEVnhWgFaIVpBWmFacVqRW/FeAV -4hXkFeYV6BXqFe8V8RX4FhUWFxYZFhsWHRYeFiAWNxZYFloWXBZeFmAWYhZkFmwWiRaLFo0WjxaRFpQW -lRaXFq8W5Bb3FvkW+xb9Fv8XARcDFwUXBxcJFwsXEBcZFz0XThdQF1kXWxdeF28XcRdzF3UXfheJF5IX -nRemF68XvBfHF9AX1xfuF/0YDhgQGBIYFBgWGDsYRhhSGFQYVhhYGFkYWxhdGGAYYRhjGIQYhhiIGIoY -jBiPGJEYkxiVGJ4YoBitGK8YsRizGLUYtxi5GNUY8RkJGT0ZXhl7GZMZtBm2GbgZuRnGGcgZyhnMGdUZ -3hnpGfUaAhoTGhUaFxoZGhsaJBomGjEaMxo1GjcaORo7GlwaZhpzGnUadxp5GoIahRqIGooajBqRGpMa -nBqhGqwaxBrNGtYa7BsJGwsbDRsPGxEbEhsUGywbTRtPG1EbUxtVG1cbWRtqG2wbbhtxG44bkBuSG5Qb -lhuXG5kbshvTG9Ub1xvZG9sb3RvfG/McBBwGHA8cERwUHDEcMxw1HDccORw8HD0cPxxWHI8ckRyTHJUc -lxyZHJscnRyfHKQcsRyzHLUctxzFHM4c0BzpHPsdDB0OHRAdEh0UHSEdMh00HTYdOB06HU8dYB1iHWQd -Zh1oHacdtB3NHdod8B3+HggeFh4vHjweRh5YHmwedh6CHoQehh6IHooejB6OHpMelR6XHpkemx6dHqAe -oh6kHr8e0x7cHuUe5x7sHwkfFB8dHx8fJB8mHygfPx9IH08faB9zH38fiB+NH6Afpx+4H7ofvB++H8Af -0x/kH+Yf6B/qH+wgACAJIBAgKCA5IDsgPSA/IEEgSiBbIF0gXyBhIGMgdyCIIIogjCCOIJAgnSCuILAg -siC0ILYgxyDJIMsgzSDPIOog+yD9IP8hASEDIQ4hFyEZIWQhZiFoIWohbCFuIXAhciF0IXYheCF6IXwh -fiGAIYIhhCGGIYghiiGMIY4hkCGSIZQhliGYIZohnCGeIaAhoiGkIaYhqCGqIawhtSG3IbkhxyHQIdUh -3iHgIisiLSIvIjEiMyI1IjciOSI7Ij0iPyJBIkMiRSJHIkkiSyJNIk8iUSJTIlUiVyJZIlsiXSJfImEi -YyJlImciaSJrIm0ibyJxInMifCJ+IssizSLPItEi0yLVItci2SLbIt0i3yLhIuMi5SLnIuki6yLtIu8i -8SLzIvUi9yL5Ivsi/SL/IwEjAyMFIwcjCSMLIw0jDyMRIxMjFSMeIyAjbSNvI3EjcyN1I3cjeSN7I30j -fyOBI4MjhSOHI4kjiyONI48jkSOTI5UjlyOZI5sjnSOfI6EjoyOlI6cjqSOrI60jryOxI7MjtSO3I+kk -BiQSJCckNCRCJGEkgSSXJLQk1iTuJQYlDSUjJTUlViVjJW4leiWGJZwlsCXWJe0mBSYdJismRyZiJo8m -oSatJsMmzybmJv8nCCcKJw8nEScTJxwnHicjJyUnJycwJzInmyedJ58noSejJ6UnpyepJ6snrSevJ7En -sye1J7cnuSe7J70nvyfBJ8MnxSfHJ8knyyfNJ88n0SfTJ9Un1yfZJ9sn3SffJ+En4yflJ+cn6SfrJ+0n -7yfxJ/Mn9Sf3J/kn+yf9J/8oASgKKAwodSh3KHkoeyh9KH8ogiiFKIgoiyiOKJEolCiXKJoonSigKKMo -piipKKworyiyKLUouCi7KL4owSjEKMcoyijNKNAo0yjWKNko3CjfKOIo5SjoKOso7ijxKPQo9yj6KP0p -ACkDKQYpCSkMKQ8pEikVKRgpGykeKSEpJCknKSopLSkwKTMpNik/KUIpRSlIKUspTilRKVQpVylaKV0p -YCljKWYpaSlsKW8pcil1KXgpeyl+KYEphCmHKYopjSmQKZMplimZKZwpnymiKaUpqCmxKbMptCm9Kb8p -wCnJKcspzCnVKdoAAAAAAAACAgAAAAAAAAUVAAAAAAAAAAAAAAAAAAAp6Q</bytes> - </object> </data> </archive> diff --git a/macosx/HBQueueController.h b/macosx/HBQueueController.h index 262557881..92379793f 100644 --- a/macosx/HBQueueController.h +++ b/macosx/HBQueueController.h @@ -9,32 +9,12 @@ #include "hb.h" @class HBController; -@class HBJob; -@class HBJobGroup; + #define HB_QUEUE_DRAGGING 0 // <--- NOT COMPLETELY FUNCTIONAL YET #define HB_OUTLINE_METRIC_CONTROLS 0 // for tweaking the outline cell spacings -// hb_job_t contains a sequence_id field. The high word is a unique job group id. -// The low word contains the "sequence id" which is a value starting at 0 and -// incremented for each pass in the job group. Use the function below to create and -// interpret a sequence_id field. -int MakeJobID(int jobGroupID, int sequenceNum); -bool IsFirstPass(int jobID); -typedef enum _HBQueueJobGroupStatus -{ - HBStatusNone = 0, - HBStatusPending = 1, - HBStatusWorking = 2, - HBStatusCompleted = 3, - HBStatusCanceled = 4 -} HBQueueJobGroupStatus; - -// Notification sent whenever the status of a HBJobGroup changes (via setStatus). The -// user info contains one object, @"HBOldJobGroupStatus", which is an NSNumber -// containing the previous status of the job group. -extern NSString * HBJobGroupStatusNotification; //------------------------------------------------------------------------------------ // As usual, we need to subclass NSOutlineView to handle a few special cases: @@ -56,161 +36,29 @@ extern NSString * HBJobGroupStatusNotification; @interface HBQueueOutlineView : NSOutlineView { -#if HB_QUEUE_DRAGGING -BOOL fIsDragging; -#endif -} -#if HB_QUEUE_DRAGGING -- (BOOL) isDragging; -#endif -@end -//------------------------------------------------------------------------------------ -// HBJob is the UI's equivalent to libhb's hb_job_t struct. It is used mainly for -// drawing the job's description. HBJob are referred to in the UI as 'passes'. -//------------------------------------------------------------------------------------ +BOOL fIsDragging; -@interface HBJob : NSObject -{ - HBJobGroup *jobGroup; // The group this job belongs to - - // The following fields match up with similar fields found in hb_job_t and it's - // various substructures. -@public - // from hb_job_s - int sequence_id; // This is how we xref to the jobs inside libhb - - int chapter_start; - int chapter_end; - int chapter_markers; - int crop[4]; - int deinterlace; - int width; // source dimensions - int height; - int output_width; // output dimensions - int output_height; - int anamorphic_width; // anamorphic dimensions - int anamorphic_height; - int keep_ratio; - int grayscale; - int pixel_ratio; - int pixel_aspect_width; - int pixel_aspect_height; - int vcodec; - float vquality; - int vbitrate; - int vrate; - int vrate_base; - int pass; - int h264_level; - int crf; - NSString *x264opts; - /* Used to concatenate audio list values into a string for display */ - NSString *audioinfo_codecs; - NSString *audioinfo_summary; - - int audio_mixdowns[8]; - int acodec; - int abitrate; - int arate; - int subtitle; - - int mux; - NSString *file; - - // from hb_title_s - NSString *titleName; - int titleIndex; - int titleWidth; - int titleHeight; - - // from hb_subtitle_s - NSString *subtitleLang; } -+ (HBJob*) jobWithLibhbJob: (hb_job_t *) job; -- (id) initWithLibhbJob: (hb_job_t *) job; -- (HBJobGroup *) jobGroup; -- (void) setJobGroup: (HBJobGroup *)aJobGroup; -- (NSMutableAttributedString *) attributedDescriptionWithIcon: (BOOL)withIcon - withTitle: (BOOL)withTitle - withPassName: (BOOL)withPassName - withFormatInfo: (BOOL)withFormatInfo - withDestination: (BOOL)withDestination - withPictureInfo: (BOOL)withPictureInfo - withVideoInfo: (BOOL)withVideoInfo - withx264Info: (BOOL)withx264Info - withAudioInfo: (BOOL)withAudioInfo - withSubtitleInfo: (BOOL)withSubtitleInfo; - -// Attributes used by attributedDescriptionWithIcon::::::::: -+ (NSMutableParagraphStyle *) descriptionParagraphStyle; -+ (NSDictionary *) descriptionDetailAttribute; -+ (NSDictionary *) descriptionDetailBoldAttribute; -+ (NSDictionary *) descriptionTitleAttribute; -+ (NSDictionary *) descriptionShortHeightAttribute; +- (BOOL) isDragging; @end -//------------------------------------------------------------------------------------ -// HBJobGroup is what's referred to in the UI as an 'encode'. A job group contains -// multiple HBJobs, one for each 'pass' of the encode. Whereas libhb keeps a simple -// list of jobs in it's queue, the queue controller presents them to the user as a -// series of encodes and passes (HBJObGroups and HBJobs). -//------------------------------------------------------------------------------------ - -@interface HBJobGroup : NSObject -{ - NSMutableArray *fJobs; // array of HBJob - NSMutableAttributedString *fDescription; - BOOL fNeedsDescription; - CGFloat fLastDescriptionHeight; - CGFloat fLastDescriptionWidth; - HBQueueJobGroupStatus fStatus; - NSString *fPresetName; -} - -// Creating a job group -+ (HBJobGroup *) jobGroup; - -// Adding jobs -- (void) addJob: (HBJob *)aJob; - -// Querying a job group -- (unsigned int) count; -- (HBJob *) jobAtIndex: (unsigned)index; -- (unsigned int) indexOfJob: (HBJob *)aJob; -- (NSMutableArray *) fJobs; -- (void) setStatus: (HBQueueJobGroupStatus)status; -- (HBQueueJobGroupStatus) status; -- (void) setPresetName: (NSString *)name; -- (NSString *) presetName; -- (NSString *) destinationPath; -- (NSString *) name; - -// Creating a description -- (void) setNeedsDescription: (BOOL)flag; -- (NSMutableAttributedString *) attributedDescription; -- (CGFloat) heightOfDescriptionForWidth:(CGFloat)width; -- (CGFloat) lastDescriptionHeight; -@end -//------------------------------------------------------------------------------------ @interface HBQueueController : NSWindowController { - hb_handle_t *fHandle; // reference to libhb + hb_handle_t *fQueueEncodeLibhb; // reference to libhb HBController *fHBController; // reference to HBController - NSMutableArray *fJobGroups; // libhb's job list organized in a hierarchy of HBJobGroup and HBJob - HBJobGroup *fCurrentJobGroup; // the HJobGroup currently being processed by libhb - HBJob *fCurrentJob; // the HJob (pass) currently being processed by libhb - int fCurrentJobID; // this is how we track when hbib has started processing a different job. This is the job's sequence_id. - - unsigned int fPendingCount; // Number of various kinds of job groups in fJobGroups. - unsigned int fCompletedCount; // Don't access these directly as they may not always be up-to-date. - unsigned int fCanceledCount; // Use the accessor functions instead. - unsigned int fWorkingCount; + NSMutableArray *fJobGroups; // mirror image of the queue array from controller.mm + + int fEncodingQueueItem; // corresponds to the index of fJobGroups encoding item + int fPendingCount; // Number of various kinds of job groups in fJobGroups. + int fCompletedCount; + int fCanceledCount; + int fWorkingCount; BOOL fJobGroupCountsNeedUpdating; BOOL fCurrentJobPaneShown; // NO when fCurrentJobPane has been shifted out of view (see showCurrentJobPane) @@ -250,6 +98,7 @@ BOOL fIsDragging; IBOutlet NSView *fQueuePane; IBOutlet HBQueueOutlineView *fOutlineView; IBOutlet NSTextField *fQueueCountField; + NSArray *fDraggedNodes; #if HB_OUTLINE_METRIC_CONTROLS IBOutlet NSSlider *fIndentation; // debug IBOutlet NSSlider *fSpacing; // debug @@ -259,36 +108,44 @@ BOOL fIsDragging; - (void)setHandle: (hb_handle_t *)handle; - (void)setHBController: (HBController *)controller; -- (void)libhbStateChanged: (hb_state_t)state; -- (void)libhbWillStop; -// Adding items to the queue -- (void) addJobGroup: (HBJobGroup *) aJobGroup; +- (void)setupToolbar; + +- (void)setQueueArray: (NSMutableArray *)QueueFileArray; +- (id)outlineView:(NSOutlineView *)fOutlineView child:(NSInteger)index ofItem:(id)item; + +- (BOOL)outlineView:(NSOutlineView *)fOutlineView isItemExpandable:(id)item; + +- (BOOL)outlineView:(NSOutlineView *)fOutlineView shouldExpandItem:(id)item; + +- (NSInteger)outlineView:(NSOutlineView *)fOutlineView numberOfChildrenOfItem:(id)item; -// Getting the currently processing job group -- (HBJobGroup *) currentJobGroup; -- (HBJob *) currentJob; +- (id)outlineView:(NSOutlineView *)fOutlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item; -// Getting job groups -- (HBJobGroup *) pendingJobGroupWithDestinationPath: (NSString *)path; +- (void)outlineView:(NSOutlineView *)fOutlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item; + +- (void)moveObjectsInQueueArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(unsigned)insertIndex; + +/* Animate the icon for the current encode */ +- (void) animateWorkingEncodeIconInQueue; +- (void) startAnimatingCurrentWorkingEncodeInQueue; +- (void) stopAnimatingCurrentJobGroupInQueue; -// Getting queue statistics -- (unsigned int) pendingCount; -- (unsigned int) completedCount; -- (unsigned int) canceledCount; -- (unsigned int) workingCount; - (IBAction)showQueueWindow: (id)sender; -- (IBAction)removeSelectedJobGroups: (id)sender; -- (IBAction)revealSelectedJobGroups: (id)sender; -- (IBAction)cancelCurrentJob: (id)sender; -- (IBAction)toggleStartCancel: (id)sender; -- (IBAction)togglePauseResume: (id)sender; + + +/* control encodes in the window */ +- (IBAction)removeSelectedQueueItem: (id)sender; +- (IBAction)revealSelectedQueueItem: (id)sender; #if HB_OUTLINE_METRIC_CONTROLS - (IBAction)imageSpacingChanged: (id)sender; - (IBAction)indentChanged: (id)sender; #endif -@end + + + +@end diff --git a/macosx/HBQueueController.mm b/macosx/HBQueueController.mm index f410e4edf..42674b550 100644 --- a/macosx/HBQueueController.mm +++ b/macosx/HBQueueController.mm @@ -9,24 +9,14 @@ #import "HBImageAndTextCell.h" #define HB_ROW_HEIGHT_TITLE_ONLY 17.0 - +#define HB_ROW_HEIGHT_FULL_DESCRIPTION 200.0 // Pasteboard type for or drag operations -#define HBQueuePboardType @"HBQueuePboardType" +#define DragDropSimplePboardType @"MyCustomOutlineViewPboardType" //------------------------------------------------------------------------------------ -// Job ID Utilities +#pragma mark - //------------------------------------------------------------------------------------ -int MakeJobID(int jobGroupID, int sequenceNum) -{ - return jobGroupID<<16 | sequenceNum; -} - -bool IsFirstPass(int jobID) -{ - return LoWord(jobID) == 0; -} - //------------------------------------------------------------------------------------ // NSMutableAttributedString (HBAdditions) //------------------------------------------------------------------------------------ @@ -45,9 +35,6 @@ bool IsFirstPass(int jobID) } @end -//------------------------------------------------------------------------------------ -#pragma mark - -//------------------------------------------------------------------------------------ @implementation HBQueueOutlineView @@ -60,796 +47,39 @@ bool IsFirstPass(int jobID) [super viewDidEndLiveResize]; } -#if HB_QUEUE_DRAGGING + + +/* This should be for dragging, we take this info from the presets right now */ - (NSImage *)dragImageForRowsWithIndexes:(NSIndexSet *)dragRows tableColumns:(NSArray *)tableColumns event:(NSEvent*)dragEvent offset:(NSPointPointer)dragImageOffset { - // Set the fIsDragging flag so that other's know that a drag operation is being - // performed. fIsDragging = YES; // By default, NSTableView only drags an image of the first column. Change this to - // drag an image of the queue's icon and desc columns. - NSArray * cols = [NSArray arrayWithObjects: [self tableColumnWithIdentifier:@"icon"], [self tableColumnWithIdentifier:@"desc"], nil]; + // drag an image of the queue's icon and desc and action columns. + NSArray * cols = [NSArray arrayWithObjects: [self tableColumnWithIdentifier:@"desc"], [self tableColumnWithIdentifier:@"icon"],[self tableColumnWithIdentifier:@"action"], nil]; return [super dragImageForRowsWithIndexes:dragRows tableColumns:cols event:dragEvent offset:dragImageOffset]; } -#endif - -#if HB_QUEUE_DRAGGING -- (void) mouseDown:(NSEvent *)theEvent -{ - // After a drag operation, reset fIsDragging back to NO. This is really the only way - // for us to detect when a drag has finished. You can't do it in acceptDrop because - // that won't be called if the dragged item is released outside the view. - [super mouseDown:theEvent]; - fIsDragging = NO; -} -#endif - -#if HB_QUEUE_DRAGGING -- (BOOL) isDragging; -{ - return fIsDragging; -} -#endif - -@end - -#pragma mark - - -//------------------------------------------------------------------------------------ -// HBJob -//------------------------------------------------------------------------------------ - -static NSMutableParagraphStyle * _descriptionParagraphStyle = nil; -static NSDictionary* _detailAttribute = nil; -static NSDictionary* _detailBoldAttribute = nil; -static NSDictionary* _titleAttribute = nil; -static NSDictionary* _shortHeightAttribute = nil; - -@implementation HBJob - -+ (HBJob*) jobWithLibhbJob: (hb_job_t *) job -{ - return [[[HBJob alloc] initWithLibhbJob:job] autorelease]; -} - -- (id) initWithLibhbJob: (hb_job_t *) job -{ - if (self = [super init]) - { - sequence_id = job->sequence_id; - - chapter_start = job->chapter_start; - chapter_end = job->chapter_end; - chapter_markers = job->chapter_markers; - memcpy(crop, job->crop, sizeof(crop)); - deinterlace = job->deinterlace; - width = job->width; - height = job->height; - keep_ratio = job->keep_ratio; - grayscale = job->grayscale; - pixel_ratio = job->pixel_ratio; - pixel_aspect_width = job->pixel_aspect_width; - pixel_aspect_height = job->pixel_aspect_height; - vcodec = job->vcodec; - vquality = job->vquality; - vbitrate = job->vbitrate; - vrate = job->vrate; - vrate_base = job->vrate_base; - pass = job->pass; - h264_level = job->h264_level; - crf = job->crf; - if (job->x264opts) - x264opts = [[NSString stringWithUTF8String:job->x264opts] retain]; - /* So, with the advent of job->list_audio's I decided why not just use an NSString and concatanate - all of the info we need for all of the audio values to display right into an NSString here ? So I - did. I have no idea why we are reading libhb stuff just to display it in the queue gui. So here we - are with a huge string. But its easy to change and saves alot of messing about. Maybe we move a bunch - of other display stuff into strings for display for each job. It's not like they have to actually do - anything.*/ - hb_audio_config_t * audio; - NSString * thisJobAudioCodecs = [NSString stringWithFormat:@""]; - NSString * thisJobAudioInfo = [NSString stringWithFormat:@""]; - int i; - for( i = 0; i < hb_list_count(job->list_audio); i++ ) - { - audio = (hb_audio_config_t *) hb_list_audio_config_item( job->list_audio, i ); - /* Output Codec */ - NSString *outputCodec; - if (audio->out.codec == HB_ACODEC_AC3) - outputCodec = @"AC3"; - else if (audio->out.codec == HB_ACODEC_FAAC) - outputCodec = @"AAC"; - else if (audio->out.codec == HB_ACODEC_LAME) - outputCodec = @"MP3"; - else if (audio->out.codec == HB_ACODEC_VORBIS) - outputCodec = @"Vorbis"; - else - outputCodec = @"Unknown Codec"; - /* Add the codec to the audio codecs list ( We should check against dupes)*/ - thisJobAudioCodecs = [thisJobAudioCodecs stringByAppendingString:[NSString stringWithFormat:@" %@,",outputCodec]]; - if (i > 0) - { - /* Insert a line break so that we get each track on a separate line */ - /* Wicked HACK alert!!, use 18 whitespaces to align offset in display for list > 2 to offset "Audio" in the queue display - Please Fix Me because this is embarrassing (but it works) */ - thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:@"\n "]; - } - /* Detailed Job audio track info*/ - /* Track Number and Mixdown Info */ - if (audio->out.mixdown == HB_ACODEC_AC3)// Remember for ac3 passthru the mixdown uses the source codec - thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@"Track %d: Source: %@ Output: %@, Pass-Thru", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]]; - else if (audio->out.mixdown == HB_AMIXDOWN_MONO) - thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@"Track %d: Source: %@ Output: %@, Mono", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]]; - else if (audio->out.mixdown == HB_AMIXDOWN_STEREO) - thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@"Track %d: Source: %@ Output: %@, Stereo", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]]; - else if (audio->out.mixdown == HB_AMIXDOWN_DOLBY) - thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@"Track %d: Source: %@ Output: %@, Dolby Surround", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]]; - else if (audio->out.mixdown == HB_AMIXDOWN_DOLBYPLII) - thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@"Track %d: Source: %@ Output: %@, Dolby Pro Logic II", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]]; - else if (audio->out.mixdown == HB_AMIXDOWN_6CH) - thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@"Track %d: Source: %@ Output: %@, 6 Channel Discreet", i + 1, [NSString stringWithUTF8String:audio->lang.description], outputCodec]]; - else - thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@"Track %d: Source: %@ Output: Unknown Codec Info", i + 1, [NSString stringWithUTF8String:audio->lang.description]]]; - - thisJobAudioInfo = [thisJobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", %d kbps, %d Hz", audio->out.bitrate, audio->out.samplerate]]; - - } - audioinfo_summary = [[NSString stringWithFormat:@"%@",thisJobAudioInfo]retain]; - audioinfo_codecs = [[NSString stringWithFormat:@"%@",thisJobAudioCodecs]retain]; - - subtitle = job->subtitle; - mux = job->mux; - if (job->file) - file = [[NSString stringWithUTF8String:job->file] retain]; - if (job->title->name) - titleName = [[NSString stringWithUTF8String:job->title->name] retain]; - titleIndex = job->title->index; - titleWidth = job->title->width; - titleHeight = job->title->height; - if (job->subtitle >= 0) - { - hb_subtitle_t * aSubtitle = (hb_subtitle_t *) hb_list_item(job->title->list_subtitle, job->subtitle); - if (aSubtitle) - subtitleLang = [[NSString stringWithUTF8String:aSubtitle->lang] retain]; - } - - // Calculate and store output dimensions and anamorphic dimensions - if (pixel_ratio == 1) // Original PAR Implementation, now called Strict Anamorphic - { - output_width = titleWidth - crop[2] - crop[3]; - output_height = titleHeight - crop[0] - crop[1]; - anamorphic_width = output_width * pixel_aspect_width / pixel_aspect_height; - anamorphic_height = output_height; - } - else if (pixel_ratio == 2) // Loose Anamorphic - { - // call hb_set_anamorphic_size to do a "dry run" to get the values to be - // used by libhb for loose anamorphic. - int par_width, par_height; - hb_set_anamorphic_size(job, &output_width, &output_height, &par_width, &par_height); - anamorphic_width = output_width * par_width / par_height; - anamorphic_height = output_height; - } - else // No Anamorphic - { - output_width = width; - output_height = height; - anamorphic_width = 0; // not needed for this case - anamorphic_height = 0; // not needed for this case - } - - } - return self; -} - -- (void) dealloc -{ - // jobGroup is a weak reference and does not need to be deleted - [x264opts release]; - [file release]; - [titleName release]; - [subtitleLang release]; - [audioinfo_summary release]; - [audioinfo_codecs release]; - [super dealloc]; -} - -- (HBJobGroup *) jobGroup -{ - return jobGroup; -} - -- (void) setJobGroup: (HBJobGroup *)aJobGroup -{ - // This is a weak reference. We don't retain or release it. - jobGroup = aJobGroup; -} - -//------------------------------------------------------------------------------------ -// Generate string to display in UI. -//------------------------------------------------------------------------------------ - -- (NSMutableAttributedString *) attributedDescriptionWithIcon: (BOOL)withIcon - withTitle: (BOOL)withTitle - withPassName: (BOOL)withPassName - withFormatInfo: (BOOL)withFormatInfo - withDestination: (BOOL)withDestination - withPictureInfo: (BOOL)withPictureInfo - withVideoInfo: (BOOL)withVideoInfo - withx264Info: (BOOL)withx264Info - withAudioInfo: (BOOL)withAudioInfo - withSubtitleInfo: (BOOL)withSubtitleInfo - -{ - NSMutableAttributedString * finalString = [[[NSMutableAttributedString alloc] initWithString: @""] autorelease]; - - // Attributes - NSMutableParagraphStyle * ps = [HBJob descriptionParagraphStyle]; - NSDictionary* detailAttr = [HBJob descriptionDetailAttribute]; - NSDictionary* detailBoldAttr = [HBJob descriptionDetailBoldAttribute]; - NSDictionary* titleAttr = [HBJob descriptionTitleAttribute]; - NSDictionary* shortHeightAttr = [HBJob descriptionShortHeightAttribute]; - - // Title with summary - if (withTitle) - { - if (withIcon) - { - NSFileWrapper * wrapper = [[[NSFileWrapper alloc] initWithPath:[[NSBundle mainBundle] pathForImageResource: @"JobSmall"]] autorelease]; - NSTextAttachment * imageAttachment = [[[NSTextAttachment alloc] initWithFileWrapper:wrapper] autorelease]; - - NSDictionary* imageAttributes = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithFloat: -2.0], NSBaselineOffsetAttributeName, - imageAttachment, NSAttachmentAttributeName, - ps, NSParagraphStyleAttributeName, - nil]; - - NSAttributedString * imageAsString = [[[NSAttributedString alloc] - initWithString: [NSString stringWithFormat:@"%C%C", NSAttachmentCharacter, NSTabCharacter] - attributes: imageAttributes] autorelease]; - - [finalString appendAttributedString:imageAsString]; - } - - // Note: use title->name instead of title->dvd since name is just the chosen - // folder, instead of dvd which is the full path - [finalString appendString:titleName withAttributes:titleAttr]; - - NSString * summaryInfo; - - NSString * chapterString = (chapter_start == chapter_end) ? - [NSString stringWithFormat:@"Chapter %d", chapter_start] : - [NSString stringWithFormat:@"Chapters %d through %d", chapter_start, chapter_end]; - - BOOL hasIndepthScan = (pass == -1); - int numVideoPasses = 0; - - // To determine number of video passes, we need to skip past the subtitle scan. - if (hasIndepthScan) - { - // When job is the one currently being processed, then the next in its group - // is the the first job in the queue. - HBJob * nextjob = nil; - NSUInteger index = [jobGroup indexOfJob:self]; - if (index != NSNotFound) - nextjob = [jobGroup jobAtIndex:index+1]; - if (nextjob) // Overly cautious in case there is no next job! - numVideoPasses = MIN( 2, nextjob->pass + 1 ); - } - else - numVideoPasses = MIN( 2, pass + 1 ); - - if (hasIndepthScan && numVideoPasses == 1) - summaryInfo = [NSString stringWithFormat: @" (Title %d, %@, Deep Scan, Single Video Pass)", titleIndex, chapterString]; - else if (hasIndepthScan && numVideoPasses > 1) - summaryInfo = [NSString stringWithFormat: @" (Title %d, %@, Deep Scan, %d Video Passes)", titleIndex, chapterString, numVideoPasses]; - else if (numVideoPasses == 1) - summaryInfo = [NSString stringWithFormat: @" (Title %d, %@, Single Video Pass)", titleIndex, chapterString]; - else - summaryInfo = [NSString stringWithFormat: @" (Title %d, %@, %d Video Passes)", titleIndex, chapterString, numVideoPasses]; - - [finalString appendString:[NSString stringWithFormat:@"%@\n", summaryInfo] withAttributes:detailAttr]; - - // Insert a short-in-height line to put some white space after the title - [finalString appendString:@"\n" withAttributes:shortHeightAttr]; - } - - // End of title stuff - - - // Pass Name - if (withPassName) - { - if (withIcon) - { - NSString * imageName; - switch (pass) - { - case -1: imageName = @"JobPassSubtitleSmall"; break; - case 0: imageName = @"JobPassFirstSmall"; break; - case 1: imageName = @"JobPassFirstSmall"; break; - case 2: imageName = @"JobPassSecondSmall"; break; - default: imageName = @"JobPassUnknownSmall"; break; - } - - NSFileWrapper * wrapper = [[[NSFileWrapper alloc] initWithPath:[[NSBundle mainBundle] pathForImageResource: imageName]] autorelease]; - NSTextAttachment * imageAttachment = [[[NSTextAttachment alloc] initWithFileWrapper:wrapper] autorelease]; - - NSDictionary* imageAttributes = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithFloat: -2.0], NSBaselineOffsetAttributeName, - imageAttachment, NSAttachmentAttributeName, - ps, NSParagraphStyleAttributeName, - nil]; - - NSAttributedString * imageAsString = [[[NSAttributedString alloc] - initWithString: [NSString stringWithFormat:@"%C%C", NSAttachmentCharacter, NSTabCharacter] - attributes: imageAttributes] autorelease]; - - [finalString appendAttributedString:imageAsString]; - } - - NSString * jobPassName; - if (pass == -1) - jobPassName = NSLocalizedString (@"Deep Scan", nil); - else - { - int passNum = MAX( 1, pass ); - if (passNum == 0) - jobPassName = NSLocalizedString (@"1st Pass", nil); - else if (passNum == 1) - jobPassName = NSLocalizedString (@"1st Pass", nil); - else if (passNum == 2) - jobPassName = NSLocalizedString (@"2nd Pass", nil); - else - jobPassName = [NSString stringWithFormat: NSLocalizedString(@"Pass %d", nil), passNum]; - } - [finalString appendString:[NSString stringWithFormat:@"%@\n", jobPassName] withAttributes:detailBoldAttr]; - } - - // Video Codec needed by FormatInfo and withVideoInfo - NSString * jobVideoCodec = nil; - if (withFormatInfo || withVideoInfo) - { - // 2097152 - // Video Codec settings (Encoder in the gui) - if (vcodec == HB_VCODEC_FFMPEG) - jobVideoCodec = @"FFmpeg"; // HB_VCODEC_FFMPEG - else if (vcodec == HB_VCODEC_XVID) - jobVideoCodec = @"XviD"; // HB_VCODEC_XVID - else if (vcodec == HB_VCODEC_X264) - { - // Deterimine for sure how we are now setting iPod uuid atom - if (h264_level) // We are encoding for iPod - jobVideoCodec = @"x264 (H.264 iPod)"; // HB_VCODEC_X264 - else - jobVideoCodec = @"x264 (H.264 Main)"; // HB_VCODEC_X264 - } - } - if (jobVideoCodec == nil) - jobVideoCodec = @"unknown"; - - if (withFormatInfo) - { - NSString * jobFormatInfo; - // Muxer settings (File Format in the gui) - if (mux == 65536 || mux == 131072 || mux == 1048576) - jobFormatInfo = @"MP4"; // HB_MUX_MP4,HB_MUX_PSP,HB_MUX_IPOD - else if (mux == 262144) - jobFormatInfo = @"AVI"; // HB_MUX_AVI - else if (mux == 524288) - jobFormatInfo = @"OGM"; // HB_MUX_OGM - else if (mux == 2097152) - jobFormatInfo = @"MKV"; // HB_MUX_MKV - else - jobFormatInfo = @"unknown"; - - if (chapter_markers == 1) - jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video + %@ Audio, Chapter Markers\n", jobFormatInfo, jobVideoCodec, audioinfo_codecs]; - else - jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video + %@ Audio\n", jobFormatInfo, jobVideoCodec, audioinfo_codecs]; - - [finalString appendString: @"Format: " withAttributes:detailBoldAttr]; - [finalString appendString: jobFormatInfo withAttributes:detailAttr]; - } - - if (withDestination) - { - [finalString appendString: @"Destination: " withAttributes:detailBoldAttr]; - [finalString appendString:[NSString stringWithFormat:@"%@\n", file] withAttributes:detailAttr]; - } - - - if (withPictureInfo) - { - NSString * jobPictureInfo; - if (pixel_ratio == 1) // Original PAR Implementation, now called Strict Anamorphic - jobPictureInfo = [NSString stringWithFormat:@"%d x %d (%d x %d Strict Anamorphic)", output_width, output_height, anamorphic_width, anamorphic_height]; - else if (pixel_ratio == 2) // Loose Anamorphic - jobPictureInfo = [NSString stringWithFormat:@"%d x %d (%d x %d Loose Anamorphic)", output_width, output_height, anamorphic_width, anamorphic_height]; - else - jobPictureInfo = [NSString stringWithFormat:@"%d x %d", output_width, output_height]; - if (keep_ratio == 1) - jobPictureInfo = [jobPictureInfo stringByAppendingString:@" Keep Aspect Ratio"]; - - if (grayscale == 1) - jobPictureInfo = [jobPictureInfo stringByAppendingString:@", Grayscale"]; - - if (deinterlace == 1) - jobPictureInfo = [jobPictureInfo stringByAppendingString:@", Deinterlace"]; - if (withIcon) // implies indent the info - [finalString appendString: @"\t" withAttributes:detailBoldAttr]; - [finalString appendString: @"Picture: " withAttributes:detailBoldAttr]; - [finalString appendString:[NSString stringWithFormat:@"%@\n", jobPictureInfo] withAttributes:detailAttr]; - } - - if (withVideoInfo) - { - NSString * jobVideoQuality; - NSString * jobVideoDetail; - - if (vquality <= 0 || vquality >= 1) - jobVideoQuality = [NSString stringWithFormat:@"%d kbps", vbitrate]; - else - { - NSNumber * vidQuality; - vidQuality = [NSNumber numberWithInt:vquality * 100]; - // this is screwed up kind of. Needs to be formatted properly. - if (crf == 1) - jobVideoQuality = [NSString stringWithFormat:@"%@%% CRF", vidQuality]; - else - jobVideoQuality = [NSString stringWithFormat:@"%@%% CQP", vidQuality]; - } - - if (vrate_base == 1126125) - { - // NTSC FILM 23.976 - jobVideoDetail = [NSString stringWithFormat:@"%@, %@, 23.976 fps", jobVideoCodec, jobVideoQuality]; - } - else if (vrate_base == 900900) - { - // NTSC 29.97 - jobVideoDetail = [NSString stringWithFormat:@"%@, %@, 29.97 fps", jobVideoCodec, jobVideoQuality]; - } - else - { - // Everything else - jobVideoDetail = [NSString stringWithFormat:@"%@, %@, %d fps", jobVideoCodec, jobVideoQuality, vrate / vrate_base]; - } - if (withIcon) // implies indent the info - [finalString appendString: @"\t" withAttributes:detailBoldAttr]; - [finalString appendString: @"Video: " withAttributes:detailBoldAttr]; - [finalString appendString:[NSString stringWithFormat:@"%@\n", jobVideoDetail] withAttributes:detailAttr]; - } - - if (withx264Info) - { - if (vcodec == HB_VCODEC_X264 && x264opts) - { - if (withIcon) // implies indent the info - [finalString appendString: @"\t" withAttributes:detailBoldAttr]; - [finalString appendString: @"x264 Options: " withAttributes:detailBoldAttr]; - [finalString appendString:[NSString stringWithFormat:@"%@\n", x264opts] withAttributes:detailAttr]; - } - } - - if (withAudioInfo) - { - if (withIcon) // implies indent the info - [finalString appendString: @"\t" withAttributes:detailBoldAttr]; - [finalString appendString: @"Audio: " withAttributes:detailBoldAttr]; - [finalString appendString:[NSString stringWithFormat:@"%@\n", audioinfo_summary] withAttributes:detailAttr]; - } - - if (withSubtitleInfo) - { - // subtitle scan == -1 in two cases: - // autoselect: when pass == -1 - // none: when pass != -1 - if ((subtitle == -1) && (pass == -1)) - { - if (withIcon) // implies indent the info - [finalString appendString: @"\t" withAttributes:detailBoldAttr]; - [finalString appendString: @"Subtitles: " withAttributes:detailBoldAttr]; - [finalString appendString: @"Autoselect " withAttributes:detailAttr]; - } - else if (subtitle >= 0) - { - if (subtitleLang) - { - if (withIcon) // implies indent the info - [finalString appendString: @"\t" withAttributes:detailBoldAttr]; - [finalString appendString: @"Subtitles: " withAttributes:detailBoldAttr]; - [finalString appendString: subtitleLang withAttributes:detailAttr]; - } - } - } - - - if ([[finalString string] hasSuffix: @"\n"]) - [finalString deleteCharactersInRange: NSMakeRange([[finalString string] length]-1, 1)]; - - return finalString; -} - -+ (NSMutableParagraphStyle *) descriptionParagraphStyle -{ - if (!_descriptionParagraphStyle) - { - _descriptionParagraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] retain]; - [_descriptionParagraphStyle setHeadIndent: 40.0]; - [_descriptionParagraphStyle setParagraphSpacing: 1.0]; - [_descriptionParagraphStyle setTabStops:[NSArray array]]; // clear all tabs - [_descriptionParagraphStyle addTabStop: [[[NSTextTab alloc] initWithType: NSLeftTabStopType location: 20.0] autorelease]]; - } - return _descriptionParagraphStyle; -} - -+ (NSDictionary *) descriptionDetailAttribute -{ - if (!_detailAttribute) - _detailAttribute = [[NSDictionary dictionaryWithObjectsAndKeys: - [NSFont systemFontOfSize:10.0], NSFontAttributeName, - _descriptionParagraphStyle, NSParagraphStyleAttributeName, - nil] retain]; - return _detailAttribute; -} - -+ (NSDictionary *) descriptionDetailBoldAttribute -{ - if (!_detailBoldAttribute) - _detailBoldAttribute = [[NSDictionary dictionaryWithObjectsAndKeys: - [NSFont boldSystemFontOfSize:10.0], NSFontAttributeName, - _descriptionParagraphStyle, NSParagraphStyleAttributeName, - nil] retain]; - return _detailBoldAttribute; -} - -+ (NSDictionary *) descriptionTitleAttribute -{ - if (!_titleAttribute) - _titleAttribute = [[NSDictionary dictionaryWithObjectsAndKeys: - [NSFont systemFontOfSize:[NSFont systemFontSize]], NSFontAttributeName, - _descriptionParagraphStyle, NSParagraphStyleAttributeName, - nil] retain]; - return _titleAttribute; -} - -+ (NSDictionary *) descriptionShortHeightAttribute -{ - if (!_shortHeightAttribute) - _shortHeightAttribute = [[NSDictionary dictionaryWithObjectsAndKeys: - [NSFont systemFontOfSize:2.0], NSFontAttributeName, - nil] retain]; - return _shortHeightAttribute; -} - - -@end - -#pragma mark - - -//------------------------------------------------------------------------------------ -// HBJobGroup -//------------------------------------------------------------------------------------ - -// Notification sent from HBJobGroup setStatus whenever the status changes. -NSString *HBJobGroupStatusNotification = @"HBJobGroupStatusNotification"; - -@implementation HBJobGroup - -+ (HBJobGroup *) jobGroup; -{ - return [[[HBJobGroup alloc] init] autorelease]; -} - -- (id) init -{ - if (self = [super init]) - { - fJobs = [[NSMutableArray arrayWithCapacity:0] retain]; - fDescription = [[NSMutableAttributedString alloc] initWithString: @""]; - [self setNeedsDescription: NO]; - fStatus = HBStatusNone; - } - return self; -} - -- (void) dealloc -{ - [fPresetName release]; - [fJobs release]; - [super dealloc]; -} - -- (unsigned int) count -{ - return [fJobs count]; -} - -- (void) addJob: (HBJob *)aJob -{ - [aJob setJobGroup:self]; - [fJobs addObject: aJob]; - [self setNeedsDescription: YES]; - fLastDescriptionHeight = 0; - fLastDescriptionWidth = 0; -} - -- (HBJob *) jobAtIndex: (unsigned)index -{ - return [fJobs objectAtIndex: index]; -} - -- (unsigned) indexOfJob: (HBJob *)aJob; -{ - return [fJobs indexOfObject: aJob]; -} - -- (NSMutableArray *) fJobs -{ - return fJobs; -} - -- (void) setNeedsDescription: (BOOL)flag -{ - fNeedsDescription = flag; -} - -- (void) updateDescription -{ - fNeedsDescription = NO; - - [fDescription deleteCharactersInRange: NSMakeRange(0, [fDescription length])]; - - if ([self count] == 0) - { - NSAssert(NO, @" jobgroup with no jobs"); - return; - } - - HBJob * job = [self jobAtIndex:0]; - - // append the title - [fDescription appendAttributedString: [job attributedDescriptionWithIcon: NO - withTitle: YES - withPassName: NO - withFormatInfo: NO - withDestination: NO - withPictureInfo: NO - withVideoInfo: NO - withx264Info: NO - withAudioInfo: NO - withSubtitleInfo: NO]]; - - // append the preset name - if ([fPresetName length]) - { - [fDescription appendString:@"Preset: " withAttributes:[HBJob descriptionDetailBoldAttribute]]; - [fDescription appendString:fPresetName withAttributes:[HBJob descriptionDetailAttribute]]; - [fDescription appendString:@"\n" withAttributes:[HBJob descriptionDetailAttribute]]; - } - - // append the format and destinaton - [fDescription appendAttributedString: [job attributedDescriptionWithIcon: NO - withTitle: NO - withPassName: NO - withFormatInfo: YES - withDestination: YES - withPictureInfo: NO - withVideoInfo: NO - withx264Info: NO - withAudioInfo: NO - withSubtitleInfo: NO]]; - - - NSAttributedString * carriageReturn = [[NSAttributedString alloc] initWithString:@"\n"]; - - for( job in fJobs ) - { - int pass = job->pass; - [fDescription appendAttributedString:carriageReturn]; - [fDescription appendAttributedString: - [job attributedDescriptionWithIcon: YES - withTitle: NO - withPassName: YES - withFormatInfo: NO - withDestination: NO - withPictureInfo: pass != -1 - withVideoInfo: pass != -1 - withx264Info: pass != -1 - withAudioInfo: pass == 0 || pass == 2 - withSubtitleInfo: YES]]; - } - -} -- (NSMutableAttributedString *) attributedDescription -{ - if (fNeedsDescription) - [self updateDescription]; - return fDescription; -} -- (CGFloat) heightOfDescriptionForWidth:(CGFloat)width -{ - // Try to return the cached value if no changes have happened since the last time - if ((width == fLastDescriptionWidth) && (fLastDescriptionHeight != 0) && !fNeedsDescription) - return fLastDescriptionHeight; - - if (fNeedsDescription) - [self updateDescription]; - - // Calculate the height - NSRect bounds = [fDescription boundingRectWithSize:NSMakeSize(width, 10000) options:NSStringDrawingUsesLineFragmentOrigin]; - fLastDescriptionHeight = bounds.size.height + 6.0; // add some border to bottom - fLastDescriptionWidth = width; - return fLastDescriptionHeight; -/* supposedly another way to do this, in case boundingRectWithSize isn't working - NSTextView* tmpView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, width, 1)]; - [[tmpView textStorage] setAttributedString:aString]; - [tmpView setHorizontallyResizable:NO]; - [tmpView setVerticallyResizable:YES]; -// [[tmpView textContainer] setHeightTracksTextView: YES]; -// [[tmpView textContainer] setContainerSize: NSMakeSize(width, 10000)]; - [tmpView sizeToFit]; - float height = [tmpView frame].size.height; - [tmpView release]; - return height; -*/ -} - -- (CGFloat) lastDescriptionHeight +- (void) mouseDown:(NSEvent *)theEvent { - return fLastDescriptionHeight; + [super mouseDown:theEvent]; + fIsDragging = NO; } -- (void) setStatus: (HBQueueJobGroupStatus)status -{ - // Create a dictionary with the old status - NSDictionary * userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:self->fStatus] forKey:@"HBOldJobGroupStatus"]; - - self->fStatus = status; - - // Send notification with old status - [[NSNotificationCenter defaultCenter] postNotificationName:HBJobGroupStatusNotification object:self userInfo:userInfo]; -} -- (HBQueueJobGroupStatus) status -{ - return self->fStatus; -} -- (void) setPresetName: (NSString *)name -{ - [name retain]; - [fPresetName release]; - fPresetName = name; -} - -- (NSString *) presetName +- (BOOL) isDragging; { - return fPresetName; + return fIsDragging; } -- (NSString *) name -{ - HBJob * firstJob = [self jobAtIndex:0]; - return firstJob ? firstJob->titleName : nil; -} -- (NSString *) destinationPath -{ - HBJob * firstJob = [self jobAtIndex:0]; - return firstJob ? firstJob->file : nil; -} @end - -#pragma mark - - +#pragma mark Toolbar Identifiers // Toolbar identifiers static NSString* HBQueueToolbar = @"HBQueueToolbar1"; static NSString* HBQueueStartCancelToolbarIdentifier = @"HBQueueStartCancelToolbarIdentifier"; @@ -881,1018 +111,177 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe nil]]; fJobGroups = [[NSMutableArray arrayWithCapacity:0] retain]; - - // Register for HBJobGroup status changes - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jobGroupStatusNotification:) name:HBJobGroupStatusNotification object:nil]; - } - return self; -} - -//------------------------------------------------------------------------------------ -// dealloc -//------------------------------------------------------------------------------------ -- (void)dealloc -{ - // clear the delegate so that windowWillClose is not attempted - if( [[self window] delegate] == self ) - [[self window] setDelegate:nil]; - - [fJobGroups release]; - [fCurrentJobGroup release]; - [fSavedExpandedItems release]; - [fSavedSelectedItems release]; - - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - [super dealloc]; -} - -//------------------------------------------------------------------------------------ -// Receive HB handle -//------------------------------------------------------------------------------------ -- (void)setHandle: (hb_handle_t *)handle -{ - fHandle = handle; -} - -//------------------------------------------------------------------------------------ -// Receive HBController -//------------------------------------------------------------------------------------ -- (void)setHBController: (HBController *)controller -{ - fHBController = controller; -} - -#pragma mark - -#pragma mark - Getting the currently processing job group - -//------------------------------------------------------------------------------------ -// Returns the HBJobGroup that is currently being encoded; nil if no encoding is -// occurring. -//------------------------------------------------------------------------------------ -- (HBJobGroup *) currentJobGroup; -{ - return fCurrentJobGroup; -} - -//------------------------------------------------------------------------------------ -// Returns the HBJob (pass) that is currently being encoded; nil if no encoding is -// occurring. -//------------------------------------------------------------------------------------ -- (HBJob *) currentJob -{ - return fCurrentJob; -} - -#pragma mark - - -//------------------------------------------------------------------------------------ -// Displays and brings the queue window to the front -//------------------------------------------------------------------------------------ -- (IBAction) showQueueWindow: (id)sender -{ - [self showWindow:sender]; - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"QueueWindowIsOpen"]; -} - -//------------------------------------------------------------------------------------ -// Show or hide the current job pane (fCurrentJobPane). -//------------------------------------------------------------------------------------ -- (void) showCurrentJobPane: (BOOL)showPane -{ - if (showPane == fCurrentJobPaneShown) - return; - - // Things to keep in mind: - // - When the current job pane is shown, it occupies the upper portion of the - // window with the queue occupying the bottom portion of the window. - // - When the current job pane is hidden, it slides up and out of view. - // NSView setHidden is NOT used. The queue pane is resized to occupy the full - // window. - - NSRect windowFrame = [[fCurrentJobPane superview] frame]; - NSRect queueFrame, jobFrame; - if (showPane) - NSDivideRect(windowFrame, &jobFrame, &queueFrame, NSHeight([fCurrentJobPane frame]), NSMaxYEdge); - else - { - queueFrame = windowFrame; - jobFrame = [fCurrentJobPane frame]; - jobFrame.origin.y = NSHeight(windowFrame); - } - - // Move fCurrentJobPane - NSDictionary * dict1 = [NSDictionary dictionaryWithObjectsAndKeys: - fCurrentJobPane, NSViewAnimationTargetKey, - [NSValue valueWithRect:jobFrame], NSViewAnimationEndFrameKey, - nil]; - - // Resize fQueuePane - NSDictionary * dict2 = [NSDictionary dictionaryWithObjectsAndKeys: - fQueuePane, NSViewAnimationTargetKey, - [NSValue valueWithRect:queueFrame], NSViewAnimationEndFrameKey, - nil]; - - NSViewAnimation * anAnimation = [[[NSViewAnimation alloc] initWithViewAnimations:nil] autorelease]; - [anAnimation setViewAnimations:[NSArray arrayWithObjects:dict1, dict2, nil]]; - [anAnimation setDuration:0.25]; - [anAnimation setAnimationBlockingMode:NSAnimationBlocking]; // prevent user from resizing the window during an animation - [anAnimation startAnimation]; - - fCurrentJobPaneShown = showPane; -} - -//------------------------------------------------------------------------------------ -// Sets fCurrentJobGroup to a new job group. -//------------------------------------------------------------------------------------ -- (void) setCurrentJobGroup: (HBJobGroup *)aJobGroup -{ - if (aJobGroup) - [aJobGroup setStatus: HBStatusWorking]; - - [aJobGroup retain]; - [fCurrentJobGroup release]; - fCurrentJobGroup = aJobGroup; -} - -#pragma mark - Finding job groups - -//------------------------------------------------------------------------------------ -// Returns the first pending job with a specified destination path or nil if no such -// job exists. -//------------------------------------------------------------------------------------ -- (HBJobGroup *) pendingJobGroupWithDestinationPath: (NSString *)path -{ - for( HBJobGroup * aJobGroup in fJobGroups ) - { - if ([[aJobGroup destinationPath] isEqualToString: path]) - return aJobGroup; - } - return nil; + } + return self; } -//------------------------------------------------------------------------------------ -// Locates and returns a HBJob whose sequence_id matches a specified value. -//------------------------------------------------------------------------------------ -- (HBJob *) findJobWithID: (int)aJobID +- (void)setQueueArray: (NSMutableArray *)QueueFileArray { - for( HBJobGroup * aJobGroup in fJobGroups ) - { - for( HBJob * job in [aJobGroup fJobs] ) - { - if (job->sequence_id == aJobID) - return job; - } - } - return nil; -} + [fJobGroups setArray:QueueFileArray]; + + /* First stop any timer working now */ +[self stopAnimatingCurrentJobGroupInQueue]; + [fOutlineView reloadData]; -//------------------------------------------------------------------------------------ -// Locates and returns a libhb job whose sequence_id matches a specified value. -//------------------------------------------------------------------------------------ -- (hb_job_t *) findLibhbJobWithID: (int)aJobID -{ - hb_job_t * job; - int index = 0; - while( ( job = hb_job( fHandle, index++ ) ) ) - { - if (job->sequence_id == aJobID) - return job; - } - return nil; -} -#pragma mark - -#pragma mark Queue Counts - -//------------------------------------------------------------------------------------ -// Sets a flag indicating that the values for fPendingCount, fCompletedCount, -// fCanceledCount, and fWorkingCount need to be recalculated. -//------------------------------------------------------------------------------------ -- (void) setJobGroupCountsNeedUpdating: (BOOL)flag -{ - fJobGroupCountsNeedUpdating = flag; -} - -//------------------------------------------------------------------------------------ -// Recalculates and stores new values in fPendingCount, fCompletedCount, -// fCanceledCount, and fWorkingCount. -//------------------------------------------------------------------------------------ -- (void) recalculateJobGroupCounts -{ - fPendingCount = 0; - fCompletedCount = 0; - fCanceledCount = 0; - fWorkingCount = 0; - for( HBJobGroup * aJobGroup in fJobGroups ) - { - switch ([aJobGroup status]) - { - case HBStatusNone: - // We don't track these. - break; - case HBStatusPending: - fPendingCount++; - break; - case HBStatusCompleted: - fCompletedCount++; - break; - case HBStatusCanceled: - fCanceledCount++; - break; - case HBStatusWorking: - fWorkingCount++; - break; - } - } - fJobGroupCountsNeedUpdating = NO; -} +/* lets get the stats on the status of the queue array */ -//------------------------------------------------------------------------------------ -// Returns the number of job groups whose status is HBStatusPending. -//------------------------------------------------------------------------------------ -- (unsigned int) pendingCount -{ - if (fJobGroupCountsNeedUpdating) - [self recalculateJobGroupCounts]; - return fPendingCount; -} - -//------------------------------------------------------------------------------------ -// Returns the number of job groups whose status is HBStatusCompleted. -//------------------------------------------------------------------------------------ -- (unsigned int) completedCount -{ - if (fJobGroupCountsNeedUpdating) - [self recalculateJobGroupCounts]; - return fCompletedCount; -} - -//------------------------------------------------------------------------------------ -// Returns the number of job groups whose status is HBStatusCanceled. -//------------------------------------------------------------------------------------ -- (unsigned int) canceledCount -{ - if (fJobGroupCountsNeedUpdating) - [self recalculateJobGroupCounts]; - return fCanceledCount; -} - -//------------------------------------------------------------------------------------ -// Returns the number of job groups whose status is HBStatusWorking. -//------------------------------------------------------------------------------------ -- (unsigned int) workingCount -{ - if (fJobGroupCountsNeedUpdating) - [self recalculateJobGroupCounts]; - return fWorkingCount; -} - -#pragma mark - -#pragma mark UI Updating - -//------------------------------------------------------------------------------------ -// Saves the state of the items that are currently expanded and selected. Calling -// restoreOutlineViewState will restore the state of all items to match what was saved -// by saveOutlineViewState. Nested calls to saveOutlineViewState are not supported. -//------------------------------------------------------------------------------------ -- (void) saveOutlineViewState -{ - if (!fSavedExpandedItems) - fSavedExpandedItems = [[NSMutableIndexSet alloc] init]; - else - [fSavedExpandedItems removeAllIndexes]; - - // This code stores the sequence_id of the first job of each job group into an - // index set. This is sufficient to identify each group uniquely. - - HBJobGroup * aJobGroup; - for( aJobGroup in fJobGroups ) - { - if ([fOutlineView isItemExpanded: aJobGroup]) - [fSavedExpandedItems addIndex: [aJobGroup jobAtIndex:0]->sequence_id]; - } - - // Save the selection also. - - if (!fSavedSelectedItems) - fSavedSelectedItems = [[NSMutableIndexSet alloc] init]; - else - [fSavedSelectedItems removeAllIndexes]; - - NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes]; - NSInteger row = [selectedRows firstIndex]; - while (row != NSNotFound) - { - aJobGroup = [fOutlineView itemAtRow: row]; - [fSavedSelectedItems addIndex: [aJobGroup jobAtIndex:0]->sequence_id]; - row = [selectedRows indexGreaterThanIndex: row]; - } - -} - -//------------------------------------------------------------------------------------ -// Restores the expanded state of items in the outline view to match those saved by a -// previous call to saveOutlineViewState. -//------------------------------------------------------------------------------------ -- (void) restoreOutlineViewState -{ - if (fSavedExpandedItems) - { - for( HBJobGroup * aJobGroup in fJobGroups ) - { - HBJob * job = [aJobGroup jobAtIndex:0]; - if (job && [fSavedExpandedItems containsIndex: job->sequence_id]) - [fOutlineView expandItem: aJobGroup]; - } - } - - if (fSavedSelectedItems) - { - NSMutableIndexSet * rowsToSelect = [[[NSMutableIndexSet alloc] init] autorelease]; - NSInteger i = 0; - for( HBJobGroup * aJobGroup in fJobGroups ) - { - HBJob * job = [aJobGroup jobAtIndex:0]; - if (job && [fSavedSelectedItems containsIndex: job->sequence_id]) - [rowsToSelect addIndex: i]; - i++; - } - if ([rowsToSelect count] == 0) - [fOutlineView deselectAll: nil]; - else - [fOutlineView selectRowIndexes:rowsToSelect byExtendingSelection:NO]; - } -} - -//------------------------------------------------------------------------------------ -// Marks the icon region of a job group in the queue view as needing display. -//------------------------------------------------------------------------------------ -- (void) updateJobGroupIconInQueue:(HBJobGroup*)aJobGroup -{ - NSInteger row = [fOutlineView rowForItem: aJobGroup]; - NSInteger col = [fOutlineView columnWithIdentifier: @"icon"]; - if (row != -1 && col != -1) - { - NSRect frame = [fOutlineView frameOfCellAtColumn:col row:row]; - [fOutlineView setNeedsDisplayInRect: frame]; - } -} - -//------------------------------------------------------------------------------------ -// Marks the entire region of a job group in the queue view as needing display. -//------------------------------------------------------------------------------------ -- (void) updateJobGroupInQueue:(HBJobGroup*)aJobGroup -{ - NSInteger row = [fOutlineView rowForItem: aJobGroup]; - if (row != -1) - { - NSRect frame = [fOutlineView rectOfRow:row]; - [fOutlineView setNeedsDisplayInRect: frame]; - } -} - -//------------------------------------------------------------------------------------ -// If a job is currently processing, its job icon in the queue outline view is -// animated to its next state. -//------------------------------------------------------------------------------------ -- (void) animateCurrentJobGroupInQueue:(NSTimer*)theTimer -{ - if (fCurrentJobGroup) - { - fAnimationIndex++; - fAnimationIndex %= 6; // there are 6 animation images; see outlineView:objectValueForTableColumn:byItem: below. - [self updateJobGroupIconInQueue: fCurrentJobGroup]; - } -} - -//------------------------------------------------------------------------------------ -// Starts animating the job icon of the currently processing job in the queue outline -// view. -//------------------------------------------------------------------------------------ -- (void) startAnimatingCurrentJobGroupInQueue -{ - if (!fAnimationTimer) - fAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0/12.0 // 1/12 because there are 6 images in the animation cycle - target:self - selector:@selector(animateCurrentJobGroupInQueue:) - userInfo:nil - repeats:YES] retain]; -} +fEncodingQueueItem = 0; +fPendingCount = 0; +fCompletedCount = 0; +fCanceledCount = 0; +fWorkingCount = 0; -//------------------------------------------------------------------------------------ -// Stops animating the job icon of the currently processing job in the queue outline -// view. -//------------------------------------------------------------------------------------ -- (void) stopAnimatingCurrentJobGroupInQueue -{ - if (fAnimationTimer && [fAnimationTimer isValid]) - { - [fAnimationTimer invalidate]; - [fAnimationTimer release]; - fAnimationTimer = nil; - } -} - -//------------------------------------------------------------------------------------ -// Generate string to display in UI. -//------------------------------------------------------------------------------------ -- (NSString *) progressStatusStringForJob: (HBJob *)job state: (hb_state_t *)s -{ - if (s->state == HB_STATE_WORKING) - { - NSString * msg; - if (job->pass == -1) - msg = NSLocalizedString( @"Deep Scan", nil ); - else if (job->pass == 1) - msg = NSLocalizedString( @"Analyzing video", nil ); - else if ((job->pass == 0) || (job->pass == 2)) - msg = NSLocalizedString( @"Encoding movie", nil ); - else - return @""; // unknown condition! - - if( s->param.working.seconds > -1 ) - { - return [NSString stringWithFormat: - NSLocalizedString( @"%@ (%.2f fps, avg %.2f fps)", nil ), - msg, s->param.working.rate_cur, s->param.working.rate_avg]; - } - else - return msg; - - } - - else if (s->state == HB_STATE_MUXING) - return NSLocalizedString( @"Muxing", nil ); - - else if (s->state == HB_STATE_PAUSED) - return NSLocalizedString( @"Paused", nil ); - - else if (s->state == HB_STATE_WORKDONE) - return NSLocalizedString( @"Done", nil ); - - return @""; -} - -//------------------------------------------------------------------------------------ -// Generate string to display in UI. -//------------------------------------------------------------------------------------ -- (NSString *) progressTimeRemainingStringForJob: (HBJob *)job state: (hb_state_t *)s -{ - if (s->state == HB_STATE_WORKING) - { - #define p s->param.working - if (p.seconds < 0) - return @""; - - // Minutes always needed - NSString * minutes; - if (p.minutes > 1) - minutes = [NSString stringWithFormat:NSLocalizedString( @"%d minutes ", nil ), p.minutes]; - else if (p.minutes == 1) - minutes = NSLocalizedString( @"1 minute ", nil ); - else - minutes = @""; - - if (p.hours >= 1) - { - NSString * hours; - if (p.hours > 1) - hours = [NSString stringWithFormat:NSLocalizedString( @"%d hours ", nil ), p.hours]; - else - hours = NSLocalizedString( @"1 hour ", nil ); - - return [NSString stringWithFormat:NSLocalizedString( @"%@%@remaining", nil ), hours, minutes]; - } + /* We use a number system to set the encode status of the queue item + * in controller.mm + * 0 == already encoded + * 1 == is being encoded + * 2 == is yet to be encoded + * 3 == cancelled + */ - else + int i = 0; + NSEnumerator *enumerator = [fJobGroups objectEnumerator]; + id tempObject; + while (tempObject = [enumerator nextObject]) + { + NSDictionary *thisQueueDict = tempObject; + if ([[thisQueueDict objectForKey:@"Status"] intValue] == 0) // Completed + { + fCompletedCount++; + } + if ([[thisQueueDict objectForKey:@"Status"] intValue] == 1) // being encoded + { + fWorkingCount++; + fEncodingQueueItem = i; + } + if ([[thisQueueDict objectForKey:@"Status"] intValue] == 2) // pending { - NSString * seconds; - if (p.seconds > 1) - seconds = [NSString stringWithFormat:NSLocalizedString( @"%d seconds ", nil ), p.seconds]; - else - seconds = NSLocalizedString( @"1 second ", nil ); - - return [NSString stringWithFormat:NSLocalizedString( @"%@%@remaining", nil ), minutes, seconds]; - } - -/* here is code that does it more like the Finder - if( p.seconds > -1 ) + fPendingCount++; + } + if ([[thisQueueDict objectForKey:@"Status"] intValue] == 3) // cancelled { - float estHours = (p.hours + (p.minutes / 60.0)); - float estMinutes = (p.minutes + (p.seconds / 60.0)); - - if (estHours > 1.5) - return [NSString stringWithFormat:NSLocalizedString( @"Time remaining: About %d hours", nil ), lrintf(estHours)]; - else if (estHours > 0.983) // 59 minutes - return NSLocalizedString( @"Time remaining: About 1 hour", nil ); - else if (estMinutes > 1.5) - return [NSString stringWithFormat:NSLocalizedString( @"Time remaining: About %d minutes", nil ), lrintf(estMinutes)]; - else if (estMinutes > 0.983) // 59 seconds - return NSLocalizedString( @"Time remaining: About 1 minute", nil ); - else if (p.seconds <= 5) - return NSLocalizedString( @"Time remaining: Less than 5 seconds", nil ); - else if (p.seconds <= 10) - return NSLocalizedString( @"Time remaining: Less than 10 seconds", nil ); - else - return NSLocalizedString( @"Time remaining: Less than 1 minute", nil ); - } - else - return NSLocalizedString( @"Time remaining: Calculating...", nil ); -*/ - #undef p - } + fCanceledCount++; + } + i++; + } - return @""; -} +/* We should fire up the encoding timer here based on fWorkingCount */ -//------------------------------------------------------------------------------------ -// Refresh progress bar (fProgressTextField) from current state. -//------------------------------------------------------------------------------------ -- (void) updateProgressTextForJob: (HBJob *)job state: (hb_state_t *)s +if (fWorkingCount > 0) { - NSString * statusMsg = [self progressStatusStringForJob:job state:s]; - NSString * timeMsg = [self progressTimeRemainingStringForJob:job state:s]; - if ([timeMsg length] > 0) - statusMsg = [NSString stringWithFormat:@"%@ - %@", statusMsg, timeMsg]; - [fProgressTextField setStringValue:statusMsg]; + /* we have an encoding job so, lets start the animation timer */ + [self startAnimatingCurrentWorkingEncodeInQueue]; } -//------------------------------------------------------------------------------------ -// Refresh progress bar (fProgressBar) from current state. -//------------------------------------------------------------------------------------ -- (void) updateProgressBarWithState: (hb_state_t *)s -{ - if (s->state == HB_STATE_WORKING) - { - #define p s->param.working - [fProgressBar setIndeterminate:NO]; - float progress_total = 100.0 * ( p.progress + p.job_cur - 1 ) / p.job_count; - [fProgressBar setDoubleValue:progress_total]; - #undef p - } - - else if (s->state == HB_STATE_MUXING) +/* Set the queue status field in the queue window */ + NSMutableString * string; + if (fPendingCount == 1) { - #define p s->param.muxing - [fProgressBar setIndeterminate:YES]; - [fProgressBar startAnimation:nil]; - #undef p - } - - else if (s->state == HB_STATE_WORKDONE) - { - [fProgressBar setIndeterminate:NO]; - [fProgressBar stopAnimation:nil]; - [fProgressBar setDoubleValue:0.0]; - } - - else - [fProgressBar stopAnimation:nil]; // just in case in was animating -} - -//------------------------------------------------------------------------------------ -// Refresh queue count text field (fQueueCountField). -//------------------------------------------------------------------------------------ -- (void)updateQueueCountField -{ - NSString * msg; - int jobCount = [fJobGroups count]; - int pendingCount = [self pendingCount]; - if (jobCount == 0) - msg = NSLocalizedString(@"No encodes", nil); - else if ((jobCount == 1) && (pendingCount == 0)) - msg = NSLocalizedString(@"1 encode", nil); - else if (jobCount == pendingCount) // ie, all jobs listed are pending - { - if (jobCount == 1) - msg = NSLocalizedString(@"1 pending encode", nil); - else - msg = [NSString stringWithFormat:NSLocalizedString(@"%d pending encodes", nil), pendingCount]; - } - else // some completed, some pending - msg = [NSString stringWithFormat:NSLocalizedString(@"%d encodes (%d pending)", nil), jobCount, pendingCount]; - - [fQueueCountField setStringValue:msg]; -} - -//------------------------------------------------------------------------------------ -// Refresh the UI in the current job pane. Should be called whenever the current job -// being processed has changed. -//------------------------------------------------------------------------------------ -- (void)updateCurrentJobDescription -{ - if (fCurrentJob) - { - switch (fCurrentJob->pass) - { - case -1: // Subtitle scan - [fJobDescTextField setAttributedStringValue: - [fCurrentJob attributedDescriptionWithIcon: NO - withTitle: YES - withPassName: YES - withFormatInfo: NO - withDestination: NO - withPictureInfo: NO - withVideoInfo: NO - withx264Info: NO - withAudioInfo: NO - withSubtitleInfo: YES]]; - break; - - case 1: // video 1st pass - [fJobDescTextField setAttributedStringValue: - [fCurrentJob attributedDescriptionWithIcon: NO - withTitle: YES - withPassName: YES - withFormatInfo: NO - withDestination: NO - withPictureInfo: YES - withVideoInfo: YES - withx264Info: YES - withAudioInfo: NO - withSubtitleInfo: NO]]; - break; - - case 0: // single pass - case 2: // video 2nd pass + audio - [fJobDescTextField setAttributedStringValue: - [fCurrentJob attributedDescriptionWithIcon: NO - withTitle: YES - withPassName: YES - withFormatInfo: NO - withDestination: NO - withPictureInfo: YES - withVideoInfo: YES - withx264Info: YES - withAudioInfo: YES - withSubtitleInfo: YES]]; - break; - - default: // unknown - [fJobDescTextField setAttributedStringValue: - [fCurrentJob attributedDescriptionWithIcon: NO - withTitle: YES - withPassName: YES - withFormatInfo: NO - withDestination: NO - withPictureInfo: YES - withVideoInfo: YES - withx264Info: YES - withAudioInfo: YES - withSubtitleInfo: YES]]; - } + string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode pending", @"" ), fPendingCount]; } else { - [fJobDescTextField setStringValue: @"No encodes pending"]; - + string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode(s) pending", @"" ), fPendingCount]; } + [fQueueCountField setStringValue:string]; } //------------------------------------------------------------------------------------ -// Refresh the UI in the current job pane. Should be called whenever the current job -// being processed has changed or when progress has changed. -//------------------------------------------------------------------------------------ -- (void)updateCurrentJobProgress -{ - hb_state_t s; - hb_get_state2( fHandle, &s ); - [self updateProgressTextForJob: fCurrentJob state: &s]; - [self updateProgressBarWithState:&s]; -} - -//------------------------------------------------------------------------------------ -// Notifies HBQueuecontroller that the contents of fJobGroups is about to be modified. -// HBQueuecontroller remembers the state of the UI (selection and expanded items). -//------------------------------------------------------------------------------------ -- (void) beginEditingJobGroupsArray -{ - [self saveOutlineViewState]; -} - -//------------------------------------------------------------------------------------ -// Notifies HBQueuecontroller that modifications to fJobGroups as indicated by a prior -// call to beginEditingJobGroupsArray have been completed. HBQueuecontroller reloads -// the queue view and restores the state of the UI (selection and expanded items). -//------------------------------------------------------------------------------------ -- (void) endEditingJobGroupsArray -{ - [self setJobGroupCountsNeedUpdating:YES]; - [fOutlineView noteNumberOfRowsChanged]; - [fOutlineView reloadData]; - [self restoreOutlineViewState]; - [self updateQueueCountField]; -} - -#pragma mark - -#pragma mark Actions - -//------------------------------------------------------------------------------------ -// Deletes the selected jobs from HB and the queue UI +// dealloc //------------------------------------------------------------------------------------ -- (IBAction)removeSelectedJobGroups: (id)sender +- (void)dealloc { - if (!fHandle) return; - - NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes]; - NSInteger row = [selectedRows firstIndex]; - if (row != NSNotFound) - { - [self beginEditingJobGroupsArray]; - while (row != NSNotFound) - { - HBJobGroup * jobGroup = [fOutlineView itemAtRow: row]; - switch ([jobGroup status]) - { - case HBStatusCompleted: - case HBStatusCanceled: - [fJobGroups removeObject: jobGroup]; - break; - case HBStatusWorking: - [self cancelCurrentJob: sender]; - break; - case HBStatusPending: - // Remove from libhb - for( HBJob * job in [jobGroup fJobs] ) - { - hb_job_t * libhbJob = [self findLibhbJobWithID:job->sequence_id]; - if (libhbJob) - hb_rem( fHandle, libhbJob ); - } - // Remove from our list - [fJobGroups removeObject: jobGroup]; - break; - case HBStatusNone: - break; - } - - row = [selectedRows indexGreaterThanIndex: row]; - } - [self endEditingJobGroupsArray]; - } -} + // clear the delegate so that windowWillClose is not attempted + if( [[self window] delegate] == self ) + [[self window] setDelegate:nil]; -//------------------------------------------------------------------------------------ -// Reveals the file icons in the Finder of the selected job groups. -//------------------------------------------------------------------------------------ -- (IBAction)revealSelectedJobGroups: (id)sender -{ - if (!fHandle) return; + [fJobGroups release]; - NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes]; - NSInteger row = [selectedRows firstIndex]; - if (row != NSNotFound) - { - while (row != NSNotFound) - { - HBJobGroup * jobGroup = [fOutlineView itemAtRow: row]; - if ([[jobGroup destinationPath] length]) - [[NSWorkspace sharedWorkspace] selectFile:[jobGroup destinationPath] inFileViewerRootedAtPath:nil]; + [fSavedExpandedItems release]; + [fSavedSelectedItems release]; - row = [selectedRows indexGreaterThanIndex: row]; - } - } -} + [[NSNotificationCenter defaultCenter] removeObserver:self]; -//------------------------------------------------------------------------------------ -// Calls HBController Cancel: which displays an alert asking user if they want to -// cancel encoding of current job. cancelCurrentJob: returns immediately after posting -// the alert. Later, when the user acknowledges the alert, HBController will call -// libhb to cancel the job. -//------------------------------------------------------------------------------------ -- (IBAction)cancelCurrentJob: (id)sender -{ - [fHBController Cancel:sender]; + [super dealloc]; } //------------------------------------------------------------------------------------ -// Starts or cancels the processing of jobs depending on the current state +// Receive HB handle //------------------------------------------------------------------------------------ -- (IBAction)toggleStartCancel: (id)sender +- (void)setHandle: (hb_handle_t *)handle { - if (!fHandle) return; - - hb_state_t s; - hb_get_state2 (fHandle, &s); - - if ((s.state == HB_STATE_PAUSED) || (s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING)) - [fHBController Cancel: fQueuePane]; // sender == fQueuePane so that warning alert shows up on queue window - - else if ([self pendingCount] > 0) - [fHBController doRip]; + fQueueEncodeLibhb = handle; } //------------------------------------------------------------------------------------ -// Toggles the pause/resume state of libhb +// Receive HBController //------------------------------------------------------------------------------------ -- (IBAction)togglePauseResume: (id)sender +- (void)setHBController: (HBController *)controller { - if (!fHandle) return; - - hb_state_t s; - hb_get_state2 (fHandle, &s); - - if (s.state == HB_STATE_PAUSED) - hb_resume (fHandle); - else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING)) - hb_pause (fHandle); + fHBController = controller; } #pragma mark - -#pragma mark Synchronizing with libhb //------------------------------------------------------------------------------------ -// Queues a job group. The job group's status is set to HBStatusPending. +// Displays and brings the queue window to the front //------------------------------------------------------------------------------------ -- (void) addJobGroup: (HBJobGroup *) aJobGroup +- (IBAction) showQueueWindow: (id)sender { - NSAssert(![fJobGroups containsObject:aJobGroup], @"Duplicate job group"); - [aJobGroup setStatus:HBStatusPending]; - - [self beginEditingJobGroupsArray]; - [fJobGroups addObject:aJobGroup]; - [self endEditingJobGroupsArray]; + [self showWindow:sender]; + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"QueueWindowIsOpen"]; } -//------------------------------------------------------------------------------------ -// Notifies HBQueueController that libhb's current job has changed -//------------------------------------------------------------------------------------ -- (void)currentJobChanged: (HBJob *) currentJob -{ - /* if the job has a destination path, lets perform finished job notifications in fHBController - * We call this here so that we pickup the last job in the queue and single encodes before fCurrentJob - * is released. So for the first job and the beginning of single encodes we check for the existence - * of a valid fCurrentJob jobGroup - */ - [currentJob retain]; - /* We need to compare the job group to determine if this is the end of a job group - * or just the end of a job within a group to keep from sending encode done notification - * after the first pass in a two pass encode - */ - HBJobGroup * theJobGroupCheck = [currentJob jobGroup]; - if ((theJobGroupCheck == nil) || (theJobGroupCheck != fCurrentJobGroup)) - { - /* we need to make sure that we are not at the beginning of a queue and also that the job hasn't - * been cancelled - */ - if ([[fCurrentJob jobGroup] destinationPath] && [fCurrentJobGroup status] != HBStatusCanceled) - { - /* send encode messages to fHBController. User prefs are grokked there. */ - [fHBController showGrowlDoneNotification: [[fCurrentJob jobGroup] destinationPath]]; - [fHBController sendToMetaX: [[fCurrentJob jobGroup] destinationPath]]; - } - } - [fCurrentJob release]; - fCurrentJob = currentJob; - - // Log info about the preset name. We do this for each job, since libhb logs each - // job separately. The preset name is found in the job's job group object. - if (fCurrentJob && [fCurrentJob jobGroup] && ([[[fCurrentJob jobGroup] presetName] length] > 0)) - [fHBController writeToActivityLog: "Using preset: %s", [[[fCurrentJob jobGroup] presetName] UTF8String]]; - // Check to see if this is also a change in Job Group - - HBJobGroup * theJobGroup = [currentJob jobGroup]; - if ((theJobGroup == nil) || (theJobGroup != fCurrentJobGroup)) // no more job groups or start of a new group - { - // Previous job has completed - if (fCurrentJobGroup) - { - // Update the status of the job that just finished. If the user canceled, - // the status will have already been set to canceled by libhbWillStop. So - // all other cases are assumed to be a successful encode. BTW, libhb - // doesn't currently report errors back to the GUI. - if ([fCurrentJobGroup status] != HBStatusCanceled) - { - [fCurrentJobGroup setStatus:HBStatusCompleted]; - } - - } - - // Set the new group - [self setCurrentJobGroup: theJobGroup]; - - // Update the UI - [self updateCurrentJobDescription]; - [self updateCurrentJobProgress]; - [self showCurrentJobPane: fCurrentJobGroup != nil]; - if (fCurrentJobGroup) - [self startAnimatingCurrentJobGroupInQueue]; - else - [self stopAnimatingCurrentJobGroupInQueue]; - } - - else // start a new job/pass in the same group - { - // Update the UI - [self updateCurrentJobDescription]; - [self updateCurrentJobProgress]; - } - -} //------------------------------------------------------------------------------------ -// Notifies HBQueueController that hb_stop is about to be called. This signals us that -// the current job is going to be canceled and deleted. This is somewhat of a hack to -// let HBQueueController know when a job group has been cancelled. Otherwise, we'd -// have no way of knowing if a job was canceled or completed sucessfully. -//------------------------------------------------------------------------------------ -- (void)libhbWillStop -{ - if (fCurrentJobGroup) - [fCurrentJobGroup setStatus: HBStatusCanceled]; -} - -//------------------------------------------------------------------------------------ -// Notifies HBQueueController that libhb's state has changed +// awakeFromNib //------------------------------------------------------------------------------------ -- (void)libhbStateChanged: (hb_state_t)state +- (void)awakeFromNib { - switch( state.state ) - { - case HB_STATE_WORKING: - { - //NSLog(@"job = %x; job_cur = %d; job_count = %d", state.param.working.sequence_id, state.param.working.job_cur, state.param.working.job_count); - // First check to see if libhb has moved on to another job. We get no direct - // message when this happens, so we have to detect it ourself. The new job could - // be either just the next job in the current group, or the start of a new group. - if (fCurrentJobID != state.param.working.sequence_id) - { - fCurrentJobID = state.param.working.sequence_id; - HBJob * currentJob = [self findJobWithID:fCurrentJobID]; - [self currentJobChanged: currentJob]; - } - - if (fCurrentJob) - { - [self updateCurrentJobProgress]; - [self startAnimatingCurrentJobGroupInQueue]; - } - break; - } + [self setupToolbar]; - case HB_STATE_MUXING: - { - [self updateCurrentJobProgress]; - break; - } + if( ![[self window] setFrameUsingName:@"Queue"] ) + [[self window] center]; + [self setWindowFrameAutosaveName:@"Queue"]; + [[self window] setExcludedFromWindowsMenu:YES]; - case HB_STATE_PAUSED: - { - [self updateCurrentJobProgress]; - [self stopAnimatingCurrentJobGroupInQueue]; - break; - } + /* lets setup our queue list outline view for drag and drop here */ + [fOutlineView registerForDraggedTypes: [NSArray arrayWithObject:DragDropSimplePboardType] ]; + [fOutlineView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES]; + [fOutlineView setVerticalMotionCanBeginDrag: YES]; - case HB_STATE_WORKDONE: - { - // HB_STATE_WORKDONE means that libhb has finished processing all the jobs - // in *its* queue. This message is NOT sent as each individual job is - // completed. - [self currentJobChanged: nil]; - fCurrentJobID = 0; - break; - } + // Don't allow autoresizing of main column, else the "delete" column will get + // pushed out of view. + [fOutlineView setAutoresizesOutlineColumn: NO]; - } +#if HB_OUTLINE_METRIC_CONTROLS + [fIndentation setHidden: NO]; + [fSpacing setHidden: NO]; + [fIndentation setIntegerValue:[fOutlineView indentationPerLevel]]; // debug + [fSpacing setIntegerValue:3]; // debug +#endif -} + // Show/hide UI elements + fCurrentJobPaneShown = NO; // it's shown in the nib + //[self showCurrentJobPane:NO]; -#if HB_OUTLINE_METRIC_CONTROLS -static CGFloat spacingWidth = 3.0; -- (IBAction)imageSpacingChanged: (id)sender; -{ - spacingWidth = [sender floatValue]; - [fOutlineView setNeedsDisplay: YES]; -} -- (IBAction)indentChanged: (id)sender -{ - [fOutlineView setIndentationPerLevel: [sender floatValue]]; - [fOutlineView setNeedsDisplay: YES]; + //[self updateQueueCountField]; } -#endif -#pragma mark - //------------------------------------------------------------------------------------ -// Receives notification whenever an HBJobGroup's status is changed. +// windowWillClose //------------------------------------------------------------------------------------ -- (void) jobGroupStatusNotification:(NSNotification *)notification +- (void)windowWillClose:(NSNotification *)aNotification { - [self setJobGroupCountsNeedUpdating: YES]; -// HBQueueJobGroupStatus oldStatus = (HBQueueJobGroupStatus) [[[notification userInfo] objectForKey:@"HBOldJobGroupStatus"] integerValue]; - HBJobGroup * jobGroup = [notification object]; - if (jobGroup) - [self updateJobGroupInQueue:jobGroup]; - [self updateQueueCountField]; + [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"QueueWindowIsOpen"]; } - -#pragma mark - #pragma mark Toolbar //------------------------------------------------------------------------------------ @@ -2006,12 +395,12 @@ static CGFloat spacingWidth = 3.0; // Optional method: This message is sent to us since we are the target of some // toolbar item actions. - if (!fHandle) return NO; + if (!fQueueEncodeLibhb) return NO; BOOL enable = NO; hb_state_t s; - hb_get_state2 (fHandle, &s); + hb_get_state2 (fQueueEncodeLibhb, &s); if ([[toolbarItem itemIdentifier] isEqual: HBQueueStartCancelToolbarIdentifier]) { @@ -2023,7 +412,7 @@ static CGFloat spacingWidth = 3.0; [toolbarItem setToolTip: @"Stop Encoding"]; } - else if ([self pendingCount] > 0) + else if (fPendingCount > 0) { enable = YES; [toolbarItem setImage:[NSImage imageNamed: @"Play"]]; @@ -2071,51 +460,134 @@ static CGFloat spacingWidth = 3.0; #pragma mark - + +#pragma mark Queue Item Controls //------------------------------------------------------------------------------------ -// awakeFromNib +// Delete pending or cancelled item from the queue window and accompanying array //------------------------------------------------------------------------------------ -- (void)awakeFromNib +- (IBAction)removeSelectedQueueItem: (id)sender { - [self setupToolbar]; + NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes]; + int row = [selectedRows firstIndex]; + [fHBController removeQueueFileItem:row]; +} - if( ![[self window] setFrameUsingName:@"Queue"] ) - [[self window] center]; - [self setWindowFrameAutosaveName:@"Queue"]; - [[self window] setExcludedFromWindowsMenu:YES]; +//------------------------------------------------------------------------------------ +// Show the finished encode in the finder +//------------------------------------------------------------------------------------ +- (IBAction)revealSelectedQueueItem: (id)sender +{ + NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes]; + NSInteger row = [selectedRows firstIndex]; + if (row != NSNotFound) + { + while (row != NSNotFound) + { + NSMutableDictionary *queueItemToOpen = [fOutlineView itemAtRow: row]; + [[NSWorkspace sharedWorkspace] selectFile:[queueItemToOpen objectForKey:@"DestinationPath"] inFileViewerRootedAtPath:nil]; -#if HB_QUEUE_DRAGGING - [fOutlineView registerForDraggedTypes: [NSArray arrayWithObject:HBQueuePboardType] ]; - [fOutlineView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES]; - [fOutlineView setVerticalMotionCanBeginDrag: YES]; -#endif + row = [selectedRows indexGreaterThanIndex: row]; + } + } +} - // Don't allow autoresizing of main column, else the "delete" column will get - // pushed out of view. - [fOutlineView setAutoresizesOutlineColumn: NO]; -#if HB_OUTLINE_METRIC_CONTROLS - [fIndentation setHidden: NO]; - [fSpacing setHidden: NO]; - [fIndentation setIntegerValue:[fOutlineView indentationPerLevel]]; // debug - [fSpacing setIntegerValue:3]; // debug -#endif +//------------------------------------------------------------------------------------ +// Starts or cancels the processing of jobs depending on the current state +//------------------------------------------------------------------------------------ +- (IBAction)toggleStartCancel: (id)sender +{ + if (!fQueueEncodeLibhb) return; - // Show/hide UI elements - fCurrentJobPaneShown = YES; // it's shown in the nib - [self showCurrentJobPane:NO]; + hb_state_t s; + hb_get_state2 (fQueueEncodeLibhb, &s); + + if ((s.state == HB_STATE_PAUSED) || (s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING)) + [fHBController Cancel: fQueuePane]; // sender == fQueuePane so that warning alert shows up on queue window - [self updateQueueCountField]; + else if (fPendingCount > 0) + [fHBController Rip: NULL]; } +//------------------------------------------------------------------------------------ +// Toggles the pause/resume state of libhb +//------------------------------------------------------------------------------------ +- (IBAction)togglePauseResume: (id)sender +{ + if (!fQueueEncodeLibhb) return; + + hb_state_t s; + hb_get_state2 (fQueueEncodeLibhb, &s); + + if (s.state == HB_STATE_PAUSED) + hb_resume (fQueueEncodeLibhb); + else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING)) + hb_pause (fQueueEncodeLibhb); +} + +#pragma mark - + + +#pragma mark Animate Endcoding Item + + + //------------------------------------------------------------------------------------ -// windowWillClose +// Starts animating the job icon of the currently processing job in the queue outline +// view. //------------------------------------------------------------------------------------ -- (void)windowWillClose:(NSNotification *)aNotification +- (void) startAnimatingCurrentWorkingEncodeInQueue { - [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"QueueWindowIsOpen"]; + if (!fAnimationTimer) + fAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0/12.0 // 1/12 because there are 6 images in the animation cycle + target:self + selector:@selector(animateWorkingEncodeInQueue:) + userInfo:nil + repeats:YES] retain]; } +//------------------------------------------------------------------------------------ +// If a job is currently processing, its job icon in the queue outline view is +// animated to its next state. +//------------------------------------------------------------------------------------ +- (void) animateWorkingEncodeInQueue:(NSTimer*)theTimer +{ + if (fWorkingCount > 0) + { + fAnimationIndex++; + fAnimationIndex %= 6; // there are 6 animation images; see outlineView:objectValueForTableColumn:byItem: below. + [self animateWorkingEncodeIconInQueue]; + } +} + + +- (void) animateWorkingEncodeIconInQueue +{ + NSInteger row = fEncodingQueueItem; /// need to set to fEncodingQueueItem + NSInteger col = [fOutlineView columnWithIdentifier: @"icon"]; + if (row != -1 && col != -1) + { + NSRect frame = [fOutlineView frameOfCellAtColumn:col row:row]; + [fOutlineView setNeedsDisplayInRect: frame]; + } +} + +//------------------------------------------------------------------------------------ +// Stops animating the job icon of the currently processing job in the queue outline +// view. +//------------------------------------------------------------------------------------ +- (void) stopAnimatingCurrentJobGroupInQueue +{ + if (fAnimationTimer && [fAnimationTimer isValid]) + { + [fAnimationTimer invalidate]; + [fAnimationTimer release]; + fAnimationTimer = nil; + } +} + + #pragma mark - - (void)moveObjectsInArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex @@ -2147,10 +619,12 @@ static CGFloat spacingWidth = 3.0; } } + #pragma mark - #pragma mark NSOutlineView delegate -- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item + +- (id)outlineView:(NSOutlineView *)fOutlineView child:(NSInteger)index ofItem:(id)item { if (item == nil) return [fJobGroups objectAtIndex:index]; @@ -2160,26 +634,26 @@ static CGFloat spacingWidth = 3.0; return nil; } -- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item +- (BOOL)outlineView:(NSOutlineView *)fOutlineView isItemExpandable:(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 YES; } -- (BOOL)outlineView:(NSOutlineView *)outlineView shouldExpandItem:(id)item +- (BOOL)outlineView:(NSOutlineView *)fOutlineView 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. -#if HB_QUEUE_DRAGGING + // Don't autoexpand while dragging, since we can't drop into the items - return ![(HBQueueOutlineView*)outlineView isDragging]; -#else - return YES; -#endif + // return ![(HBQueueOutlineView*)fOutlineView isDragging]; + + return YES; //<-- Needs to be YES to allow expanding + } -- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item +- (NSInteger)outlineView:(NSOutlineView *)fOutlineView numberOfChildrenOfItem:(id)item { // Our outline view has no levels, so number of children will be zero for all // top-level items. @@ -2213,62 +687,405 @@ static CGFloat spacingWidth = 3.0; // resize. So if in a live resize, simply return the previously calculated // height. The row heights will get fixed up after the resize because we have // implemented viewDidEndLiveResize to force all of them to be recalculated. - if ([outlineView inLiveResize] && [item lastDescriptionHeight] > 0) - return [item lastDescriptionHeight]; + // if ([outlineView inLiveResize] && [item lastDescriptionHeight] > 0) + // return [item lastDescriptionHeight]; - CGFloat width = [[outlineView tableColumnWithIdentifier: @"desc"] width]; + // CGFloat width = [[outlineView tableColumnWithIdentifier: @"desc"] width]; // Column width is NOT what is ultimately used. I can't quite figure out what // width to use for calculating text metrics. No matter how I tweak this value, // there are a few conditions in which the drawn text extends below the bounds // of the row cell. In previous versions, which ran under Tiger, I was // reducing width by 47 pixles. - width -= 2; // (?) for intercell spacing + // width -= 2; // (?) for intercell spacing - CGFloat height = [item heightOfDescriptionForWidth: width]; - return height; + // CGFloat height = [item heightOfDescriptionForWidth: width]; + // return height; + + return HB_ROW_HEIGHT_FULL_DESCRIPTION; } else return HB_ROW_HEIGHT_TITLE_ONLY; } -- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item +- (CGFloat) heightOfDescriptionForWidth:(CGFloat)width +{ + // Try to return the cached value if no changes have happened since the last time + //if ((width == fLastDescriptionWidth) && (fLastDescriptionHeight != 0) && !fNeedsDescription) + // return fLastDescriptionHeight; + + //if (fNeedsDescription) + // [self updateDescription]; + + // Calculate the height + //NSRect bounds = [fDescription boundingRectWithSize:NSMakeSize(width, 10000) options:NSStringDrawingUsesLineFragmentOrigin]; + //fLastDescriptionHeight = bounds.size.height + 6.0; // add some border to bottom + //fLastDescriptionWidth = width; + return HB_ROW_HEIGHT_FULL_DESCRIPTION; + +/* supposedly another way to do this, in case boundingRectWithSize isn't working + NSTextView* tmpView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, width, 1)]; + [[tmpView textStorage] setAttributedString:aString]; + [tmpView setHorizontallyResizable:NO]; + [tmpView setVerticallyResizable:YES]; +// [[tmpView textContainer] setHeightTracksTextView: YES]; +// [[tmpView textContainer] setContainerSize: NSMakeSize(width, 10000)]; + [tmpView sizeToFit]; + float height = [tmpView frame].size.height; + [tmpView release]; + return height; +*/ +} + +- (CGFloat) lastDescriptionHeight +{ + return HB_ROW_HEIGHT_FULL_DESCRIPTION; +} + +- (id)outlineView:(NSOutlineView *)fOutlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { // nb: The "desc" column is currently an HBImageAndTextCell. However, we are longer // using the image portion of the cell so we could switch back to a regular NSTextFieldCell. - + if ([[tableColumn identifier] isEqualToString:@"desc"]) - return [item attributedDescription]; + { + /* This should have caused the description we wanted to show*/ + //return [item objectForKey:@"SourceName"]; + + /* code to build the description as per old queue */ + //return [self formatEncodeItemDescription:item]; + + /* Below should be put into a separate method but I am way too f'ing lazy right now */ + NSMutableAttributedString * finalString = [[[NSMutableAttributedString alloc] initWithString: @""] autorelease]; + // Attributes + NSMutableParagraphStyle * ps = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] retain]; + [ps setHeadIndent: 40.0]; + [ps setParagraphSpacing: 1.0]; + [ps setTabStops:[NSArray array]]; // clear all tabs + [ps addTabStop: [[[NSTextTab alloc] initWithType: NSLeftTabStopType location: 20.0] autorelease]]; + + + NSDictionary* detailAttr = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:10.0], NSFontAttributeName, + ps, NSParagraphStyleAttributeName, + nil]; + + NSDictionary* detailBoldAttr = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont boldSystemFontOfSize:10.0], NSFontAttributeName, + ps, NSParagraphStyleAttributeName, + nil]; + + NSDictionary* titleAttr = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:[NSFont systemFontSize]], NSFontAttributeName, + ps, NSParagraphStyleAttributeName, + nil]; + + NSDictionary* shortHeightAttr = [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont systemFontOfSize:2.0], NSFontAttributeName, + nil]; + + /* First line, we should strip the destination path and just show the file name and add the title num and chapters (if any) */ + //finalDescription = [finalDescription stringByAppendingString:[NSString stringWithFormat:@"Source: %@ Output: %@\n", [item objectForKey:@"SourceName"],[item objectForKey:@"DestinationPath"]]]; + NSString * summaryInfo; + + NSString * titleString = [NSString stringWithFormat:@"Title %d", [[item objectForKey:@"TitleNumber"] intValue]]; + + NSString * chapterString = ([[item objectForKey:@"ChapterStart"] intValue] == [[item objectForKey:@"ChapterEnd"] intValue]) ? + [NSString stringWithFormat:@"Chapter %d", [[item objectForKey:@"ChapterStart"] intValue]] : + [NSString stringWithFormat:@"Chapters %d through %d", [[item objectForKey:@"ChapterStart"] intValue], [[item objectForKey:@"ChapterEnd"] intValue]]; + + NSString * passesString; + if ([[item objectForKey:@"VideoTwoPass"] intValue] == 0) + { + passesString = [NSString stringWithFormat:@"1 Video Pass"]; + } + else + { + if ([[item objectForKey:@"VideoTurboTwoPass"] intValue] == 1) + { + passesString = [NSString stringWithFormat:@"2 Video Passes Turbo"]; + } + else + { + passesString = [NSString stringWithFormat:@"2 Video Passes"]; + } + } + + [finalString appendString:[NSString stringWithFormat:@"%@", [item objectForKey:@"SourceName"]] withAttributes:titleAttr]; + + summaryInfo = [NSString stringWithFormat: @" (%@, %@, %@)", titleString, chapterString, passesString]; + + [finalString appendString:[NSString stringWithFormat:@"%@\n", summaryInfo] withAttributes:detailAttr]; + + // Insert a short-in-height line to put some white space after the title + [finalString appendString:@"\n" withAttributes:shortHeightAttr]; + // End of Title Stuff + + /* Second Line (Preset Name)*/ + [finalString appendString: @"Preset: " withAttributes:detailBoldAttr]; + [finalString appendString:[NSString stringWithFormat:@"%@\n", [item objectForKey:@"PresetName"]] withAttributes:detailAttr]; + + /* Third Line (Format Summary) */ + NSString * audioCodecSummary = @""; + /* Lets also get our audio track detail since we are going through the logic for use later */ + NSString * audioDetail1 = @"None"; + NSString * audioDetail2 = @"None"; + NSString * audioDetail3 = @"None"; + NSString * audioDetail4 = @"None"; + if ([[item objectForKey:@"Audio1Track"] intValue] > 0) + { + audioCodecSummary = [NSString stringWithFormat:@"%@", [item objectForKey:@"Audio1Encoder"]]; + audioDetail1 = [NSString stringWithFormat:@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)", + [item objectForKey:@"Audio1TrackDescription"] , + [item objectForKey:@"Audio1Encoder"], + [item objectForKey:@"Audio1Mixdown"] , + [item objectForKey:@"Audio1Samplerate"], + [item objectForKey:@"Audio1Bitrate"]]; + } + + if ([[item objectForKey:@"Audio2Track"] intValue] > 0) + { + audioCodecSummary = [NSString stringWithFormat:@"%@, %@",audioCodecSummary ,[item objectForKey:@"Audio2Encoder"]]; + audioDetail2 = [NSString stringWithFormat:@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)", + [item objectForKey:@"Audio2TrackDescription"] , + [item objectForKey:@"Audio2Encoder"], + [item objectForKey:@"Audio2Mixdown"] , + [item objectForKey:@"Audio2Samplerate"], + [item objectForKey:@"Audio2Bitrate"]]; + } + + if ([[item objectForKey:@"Audio3Track"] intValue] > 0) + { + audioCodecSummary = [NSString stringWithFormat:@"%@, %@",audioCodecSummary ,[item objectForKey:@"Audio3Encoder"]]; + audioDetail3 = [NSString stringWithFormat:@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)", + [item objectForKey:@"Audio3TrackDescription"] , + [item objectForKey:@"Audio3Encoder"], + [item objectForKey:@"Audio3Mixdown"] , + [item objectForKey:@"Audio3Samplerate"], + [item objectForKey:@"Audio3Bitrate"]]; + } + if ([[item objectForKey:@"Audio4Track"] intValue] > 0) + { + audioCodecSummary = [NSString stringWithFormat:@"%@, %@",audioCodecSummary ,[item objectForKey:@"Audio3Encoder"]]; + audioDetail4 = [NSString stringWithFormat:@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)", + [item objectForKey:@"Audio4TrackDescription"] , + [item objectForKey:@"Audio4Encoder"], + [item objectForKey:@"Audio4Mixdown"] , + [item objectForKey:@"Audio4Samplerate"], + [item objectForKey:@"Audio4Bitrate"]]; + } + + NSString * jobFormatInfo; + if ([[item objectForKey:@"ChapterMarkers"] intValue] == 1) + jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video %@ Audio, Chapter Markers\n", [item objectForKey:@"FileFormat"], [item objectForKey:@"VideoEncoder"], audioCodecSummary]; + else + jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video %@ Audio\n", [item objectForKey:@"FileFormat"], [item objectForKey:@"VideoEncoder"], audioCodecSummary]; + + + [finalString appendString: @"Format: " withAttributes:detailBoldAttr]; + [finalString appendString: jobFormatInfo withAttributes:detailAttr]; + + /* Optional String for mp4 options */ + if ([[item objectForKey:@"FileFormat"] isEqualToString: @"MP4 file"]) + { + NSString * MP4Opts = @""; + BOOL mp4OptsPresent = NO; + if( [[item objectForKey:@"Mp4LargeFile"] intValue] == 1) + { + mp4OptsPresent = YES; + MP4Opts = [MP4Opts stringByAppendingString:@" - 64 Bit"]; + } + if( [[item objectForKey:@"Mp4HttpOptimize"] intValue] == 1) + { + mp4OptsPresent = YES; + MP4Opts = [MP4Opts stringByAppendingString:@" - Http Optimized"]; + } + + if( [[item objectForKey:@"Mp4iPodCompatible"] intValue] == 1) + { + mp4OptsPresent = YES; + MP4Opts = [MP4Opts stringByAppendingString:@" - iPod Atom "]; + } + if (mp4OptsPresent == YES) + { + [finalString appendString: @"MP4 Options: " withAttributes:detailBoldAttr]; + [finalString appendString: MP4Opts withAttributes:detailAttr]; + [finalString appendString:@"\n" withAttributes:detailAttr]; + } + } + + /* Fourth Line (Destination Path)*/ + [finalString appendString: @"Destination: " withAttributes:detailBoldAttr]; + [finalString appendString: [item objectForKey:@"DestinationPath"] withAttributes:detailAttr]; + [finalString appendString:@"\n" withAttributes:detailAttr]; + /* Fifth Line Picture Details*/ + NSString * pictureInfo; + pictureInfo = [NSString stringWithFormat:@"%@", [item objectForKey:@"PictureSizingSummary"]]; + if ([[item objectForKey:@"PictureKeepRatio"] intValue] == 1) + { + pictureInfo = [pictureInfo stringByAppendingString:@" Keep Aspect Ratio"]; + } + if ([[item objectForKey:@"VideoGrayScale"] intValue] == 1) + { + pictureInfo = [pictureInfo stringByAppendingString:@", Grayscale"]; + } + + [finalString appendString: @"Picture: " withAttributes:detailBoldAttr]; + [finalString appendString: pictureInfo withAttributes:detailAttr]; + [finalString appendString:@"\n" withAttributes:detailAttr]; + + /* Optional String for mp4 options */ + + NSString * pictureFilters = @""; + BOOL pictureFiltersPresent = NO; + if( [[item objectForKey:@"VFR"] intValue] == 1) + { + pictureFiltersPresent = YES; + pictureFilters = [pictureFilters stringByAppendingString:@" - VFR"]; + } + if( [[item objectForKey:@"PictureDetelecine"] intValue] == 1 ) + { + pictureFiltersPresent = YES; + pictureFilters = [pictureFilters stringByAppendingString:@" - Detelecine"]; + } + + if( [[item objectForKey:@"PictureDecomb"] intValue] == 1) + { + pictureFiltersPresent = YES; + pictureFilters = [pictureFilters stringByAppendingString:@" - Decomb "]; + } + + if ([[item objectForKey:@"PictureDeinterlace"] intValue] != 0) + { + pictureFiltersPresent = YES; + if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 1) + { + pictureFilters = [pictureFilters stringByAppendingString:@" - Decomb: Fast "]; + } + else if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 2) + { + pictureFilters = [pictureFilters stringByAppendingString:@" - Decomb: Slow "]; + } + else if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 3) + { + pictureFilters = [pictureFilters stringByAppendingString:@" - Decomb: Slower "]; + } + + } + if ([[item objectForKey:@"PictureDenoise"] intValue] != 0) + { + pictureFiltersPresent = YES; + if ([[item objectForKey:@"PictureDenoise"] intValue] == 1) + { + pictureFilters = [pictureFilters stringByAppendingString:@" - Denoise: Weak "]; + } + else if ([[item objectForKey:@"PictureDenoise"] intValue] == 2) + { + pictureFilters = [pictureFilters stringByAppendingString:@" - Denoise: Medium "]; + } + else if ([[item objectForKey:@"PictureDenoise"] intValue] == 3) + { + pictureFilters = [pictureFilters stringByAppendingString:@" - Denoise: Strong "]; + } + + } + if ([[item objectForKey:@"PictureDeblock"] intValue] == 1) + { + pictureFilters = [pictureFilters stringByAppendingString:@" - Deblock "]; + } + if (pictureFiltersPresent == YES) + { + [finalString appendString: @"Filters: " withAttributes:detailBoldAttr]; + [finalString appendString: pictureFilters withAttributes:detailAttr]; + [finalString appendString:@"\n" withAttributes:detailAttr]; + } + + + /* Sixth Line Video Details*/ + + NSString * videoInfo; + videoInfo = [NSString stringWithFormat:@"Encoder: %@", [item objectForKey:@"VideoEncoder"]]; + videoInfo = [NSString stringWithFormat:@"%@ Framerate: %@", videoInfo ,[item objectForKey:@"VideoFramerate"]]; + + if ([[item objectForKey:@"VideoQualityType"] intValue] == 0)// Target Size MB + { + videoInfo = [NSString stringWithFormat:@"%@ Target Size: %@(MB)", videoInfo ,[item objectForKey:@"VideoTargetSize"]]; + } + else if ([[item objectForKey:@"VideoQualityType"] intValue] == 1) // ABR + { + videoInfo = [NSString stringWithFormat:@"%@ Bitrate: %d(kbps)", videoInfo ,[[item objectForKey:@"VideoAvgBitrate"] intValue]]; + } + else // CRF + { + videoInfo = [NSString stringWithFormat:@"%@ Constant Quality: %.0f %%", videoInfo ,[[item objectForKey:@"VideoQualitySlider"] floatValue] * 100]; + } + + [finalString appendString: @"Video: " withAttributes:detailBoldAttr]; + [finalString appendString: videoInfo withAttributes:detailAttr]; + [finalString appendString:@"\n" withAttributes:detailAttr]; + + if ([[item objectForKey:@"VideoEncoder"] isEqualToString: @"H.264 (x264)"]) + { + [finalString appendString: @"x264 Options: " withAttributes:detailBoldAttr]; + [finalString appendString: [item objectForKey:@"x264Option"] withAttributes:detailAttr]; + [finalString appendString:@"\n" withAttributes:detailAttr]; + } + + + /* Seventh Line Audio Details*/ + [finalString appendString: @"Audio Track 1: " withAttributes:detailBoldAttr]; + [finalString appendString: audioDetail1 withAttributes:detailAttr]; + [finalString appendString:@"\n" withAttributes:detailAttr]; + + [finalString appendString: @"Audio Track 2: " withAttributes:detailBoldAttr]; + [finalString appendString: audioDetail2 withAttributes:detailAttr]; + [finalString appendString:@"\n" withAttributes:detailAttr]; + + [finalString appendString: @"Audio Track 3: " withAttributes:detailBoldAttr]; + [finalString appendString: audioDetail3 withAttributes:detailAttr]; + [finalString appendString:@"\n" withAttributes:detailAttr]; + + [finalString appendString: @"Audio Track 4: " withAttributes:detailBoldAttr]; + [finalString appendString: audioDetail4 withAttributes:detailAttr]; + //[finalString appendString:@"\n" withAttributes:detailAttr]; + + + return finalString; + + + + + } else if ([[tableColumn identifier] isEqualToString:@"icon"]) { - switch ([(HBJobGroup*)item status]) + if ([[item objectForKey:@"Status"] intValue] == 0) + { + return [NSImage imageNamed:@"EncodeComplete"]; + } + else if ([[item objectForKey:@"Status"] intValue] == 1) { - case HBStatusCanceled: - return [NSImage imageNamed:@"EncodeCanceled"]; - break; - case HBStatusCompleted: - return [NSImage imageNamed:@"EncodeComplete"]; - break; - case HBStatusWorking: - return [NSImage imageNamed: [NSString stringWithFormat: @"EncodeWorking%d", fAnimationIndex]]; - break; - default: - return [NSImage imageNamed:@"JobSmall"]; - break; + return [NSImage imageNamed: [NSString stringWithFormat: @"EncodeWorking%d", fAnimationIndex]]; } + else if ([[item objectForKey:@"Status"] intValue] == 3) + { + return [NSImage imageNamed:@"EncodeCanceled"]; + } + else + { + return [NSImage imageNamed:@"JobSmall"]; + } + } else + { return @""; + } } - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item { if ([[tableColumn identifier] isEqualToString:@"desc"]) { -#if HB_OUTLINE_METRIC_CONTROLS - NSSize theSize = [cell imageSpacing]; - theSize.width = spacingWidth; - [cell setImageSpacing: theSize]; -#endif + // nb: The "desc" column is currently an HBImageAndTextCell. However, we are longer // using the image portion of the cell so we could switch back to a regular NSTextFieldCell. @@ -2276,14 +1093,13 @@ static CGFloat spacingWidth = 3.0; // Set the image here since the value returned from outlineView:objectValueForTableColumn: didn't specify the image part [cell setImage:nil]; } - else if ([[tableColumn identifier] isEqualToString:@"action"]) { [cell setEnabled: YES]; BOOL highlighted = [outlineView isRowSelected:[outlineView rowForItem: item]] && [[outlineView window] isKeyWindow] && ([[outlineView window] firstResponder] == outlineView); - if ([(HBJobGroup*)item status] == HBStatusCompleted) + if ([[item objectForKey:@"Status"] intValue] == 0) { - [cell setAction: @selector(revealSelectedJobGroups:)]; + [cell setAction: @selector(revealSelectedQueueItem:)]; if (highlighted) { [cell setImage:[NSImage imageNamed:@"RevealHighlight"]]; @@ -2294,7 +1110,7 @@ static CGFloat spacingWidth = 3.0; } else { - [cell setAction: @selector(removeSelectedJobGroups:)]; + [cell setAction: @selector(removeSelectedQueueItem:)]; if (highlighted) { [cell setImage:[NSImage imageNamed:@"DeleteHighlight"]]; @@ -2323,31 +1139,30 @@ static CGFloat spacingWidth = 3.0; // NSTableView delegate //------------------------------------------------------------------------------------ -#if HB_QUEUE_DRAGGING + - (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard { // Dragging is only allowed of the pending items. - for( HBJobGroup * group in items ) + if ([[[fJobGroups objectAtIndex:[outlineView selectedRow]] objectForKey:@"Status"] intValue] != 2) // 2 is pending { - if ([group status] != HBStatusPending) - return NO; + return NO; } - + // Don't retain since this is just holding temporaral drag information, and it is //only used during a drag! We could put this in the pboard actually. fDraggedNodes = items; - + // Provide data for our custom type, and simple NSStrings. - [pboard declareTypes:[NSArray arrayWithObjects: HBQueuePboardType, nil] owner:self]; - + [pboard declareTypes:[NSArray arrayWithObjects: DragDropSimplePboardType, nil] owner:self]; + // the actual data doesn't matter since DragDropSimplePboardType drags aren't recognized by anyone but us!. - [pboard setData:[NSData data] forType:HBQueuePboardType]; - + [pboard setData:[NSData data] forType:DragDropSimplePboardType]; + return YES; } -#endif -#if HB_QUEUE_DRAGGING + +/* This method is used to validate the drops. */ - (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index { // Don't allow dropping ONTO an item since they can't really contain any children. @@ -2362,36 +1177,70 @@ static CGFloat spacingWidth = 3.0; item = nil; } - // Prevent dragging into the completed or current job. - int firstPendingIndex = [self completedCount]; - if (fCurrentJobGroup) - firstPendingIndex++; - index = MAX (index, firstPendingIndex); - + // NOTE: Should we allow dropping a pending job *above* the + // finished or already encoded jobs ? + // We do not let the user drop a pending job before or *above* + // already finished or currently encoding jobs. + if (index <= fEncodingQueueItem) + { + return NSDragOperationNone; + index = MAX (index, fEncodingQueueItem); + } + + [outlineView setDropItem:item dropChildIndex:index]; return NSDragOperationGeneric; } -#endif -#if HB_QUEUE_DRAGGING + + - (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(NSInteger)index { - NSMutableIndexSet *moveItems = [NSMutableIndexSet indexSet]; - - for( id obj in fDraggedNodes) + NSMutableIndexSet *moveItems = [NSMutableIndexSet indexSet]; + + id obj; + NSEnumerator *enumerator = [fDraggedNodes objectEnumerator]; + while (obj = [enumerator nextObject]) { [moveItems addIndex:[fJobGroups indexOfObject:obj]]; } - // Rearrange the data and view - [self saveOutlineViewState]; - [self moveObjectsInArray:fJobGroups fromIndexes:moveItems toIndex: index]; - [fOutlineView reloadData]; - [self restoreOutlineViewState]; - + // Successful drop, we use moveObjectsInQueueArray:... in fHBController + // to properly rearrange the queue array, save it to plist and then send it back here. + // since Controller.mm is handling all queue array manipulation. + // We *could do this here, but I think we are better served keeping that code together. + [fHBController moveObjectsInQueueArray:fJobGroups fromIndexes:moveItems toIndex: index]; return YES; } -#endif +- (void)moveObjectsInQueueArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(unsigned)insertIndex +{ + unsigned index = [indexSet lastIndex]; + unsigned aboveInsertIndexCount = 0; + + while (index != NSNotFound) + { + unsigned removeIndex; + + if (index >= insertIndex) + { + removeIndex = index + aboveInsertIndexCount; + aboveInsertIndexCount++; + } + else + { + removeIndex = index; + insertIndex--; + } + + id object = [[array objectAtIndex:removeIndex] retain]; + [array removeObjectAtIndex:removeIndex]; + [array insertObject:object atIndex:insertIndex]; + [object release]; + + index = [indexSet indexLessThanIndex:index]; + } +} + @end |