From 740e2405e2bedecb743dcc581f5f0f1f7905ff98 Mon Sep 17 00:00:00 2001 From: dynaflash Date: Sat, 17 Jul 2010 19:15:38 +0000 Subject: [PATCH] MacGui: Initial implementation of new queue sync code which allows multi-instance encoding. This allows more than one instances of HandBrake.app to run off of the same queue file. In the case of multi-instance use these changes occur in the queue window: - The delete icon for a given queue item does not exist in the queue window if another instance is doing the encoding. - The encoding icon does not spin if another instance is doing the encoding. - As before if the queue window is for the instance doing the encoding on that item it will be animated and "spins". - The queue window status readout now also includes the output file name for the file being encoded for that instance. Known bugs: - Drag and Drop queue reordering is somwehat borked. Doesn't corrupt queue but can not allow a drop in some instances. - I have tested this over 20 multi instance encodes and not once had an issue, but anytime more than one instance is writing to the same external file anything can happen. Beware! - The session activity log will of course be full of activity log info from all instances in a multi instance scenario. Individual encode logs are unaffected. git-svn-id: svn://localhost/HandBrake/trunk@3443 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- macosx/Controller.h | 7 +- macosx/Controller.m | 214 +++++++++++++++++++++++++++-------------- macosx/English.lproj/Queue.xib | 184 ++++++++++++++++++++++++++++++++--- macosx/HBQueueController.h | 6 +- macosx/HBQueueController.mm | 92 +++++++++--------- 5 files changed, 365 insertions(+), 138 deletions(-) diff --git a/macosx/Controller.h b/macosx/Controller.h index 742aa3a5..662563e7 100644 --- a/macosx/Controller.h +++ b/macosx/Controller.h @@ -275,7 +275,8 @@ BOOL fIsDragging; int fWorkingCount; int fqueueEditRescanItemNum; // queue array item to be reloaded into the main window - + int pidNum; // The pid number for this instance + NSString * currentQueueEncodeNameString; /* integer to set to determine the previous state of encode 0==idle, 1==encoding, 2==cancelled*/ @@ -285,11 +286,12 @@ BOOL fIsDragging; BOOL SuccessfulScan; BOOL applyQueueToScan; NSString * currentSource; - NSString * browsedSourceDisplayName; + NSString * browsedSourceDisplayName; double dockIconProgress; } +- (int) getThisHBInstancePID; - (IBAction) showAboutPanel:(id)sender; - (void) writeToActivityLog:(const char *) format, ...; @@ -458,6 +460,7 @@ BOOL fIsDragging; - (void)moveObjectsInPresetsArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex; - (int) hbInstances; +- (int) getThisHBInstancePID; // Chapter files methods - (IBAction) browseForChapterFile: (id) sender; diff --git a/macosx/Controller.m b/macosx/Controller.m index 60e16940..66d7674a 100644 --- a/macosx/Controller.m +++ b/macosx/Controller.m @@ -83,7 +83,12 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It fPreferencesController = [[HBPreferencesController alloc] init]; /* Lets report the HandBrake version number here to the activity log and text log file */ NSString *versionStringFull = [[NSString stringWithFormat: @"Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]]; - [self writeToActivityLog: "%s", [versionStringFull UTF8String]]; + [self writeToActivityLog: "%s", [versionStringFull UTF8String]]; + + /* Get the PID number for this hb instance, used in multi instance encoding */ + pidNum = [self getThisHBInstancePID]; + /* Report this pid to the activity log */ + [self writeToActivityLog: "Pid for this instance:%d", pidNum]; return self; } @@ -122,12 +127,19 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [fPresetsOutlineView setAutosaveExpandedItems:YES]; dockIconProgress = 0; - + + /* Init QueueFile .plist */ + [self loadQueueFile]; + /* Call UpdateUI every 1/2 sec */ + [[NSRunLoop currentRunLoop] addTimer:[NSTimer - scheduledTimerWithTimeInterval:0.5 target:self - selector:@selector(updateUI:) userInfo:nil repeats:YES] - forMode:NSDefaultRunLoopMode]; + scheduledTimerWithTimeInterval:0.5 + target:self + selector:@selector(updateUI:) + userInfo:nil repeats:YES] + forMode:NSDefaultRunLoopMode]; + // Open debug output window now if it was visible when HB was closed if ([[NSUserDefaults standardUserDefaults] boolForKey:@"OutputPanelIsOpen"]) @@ -217,29 +229,42 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [self browseSources:(id)fOpenSourceTitleMMenu]; } } + currentQueueEncodeNameString = @""; } +#pragma mark - +#pragma mark Multiple Instances - (int) hbInstances { /* check to see if another instance of HandBrake.app is running */ NSArray *runningAppDictionaries = [[NSWorkspace sharedWorkspace] launchedApplications]; - NSDictionary *aDictionary; + NSDictionary *runningAppsDictionary; int hbInstances = 0; - for (aDictionary in runningAppDictionaries) + for (runningAppsDictionary in runningAppDictionaries) { - if ([[aDictionary valueForKey:@"NSApplicationName"] isEqualToString:@"HandBrake"]) + if ([[runningAppsDictionary valueForKey:@"NSApplicationName"] isEqualToString:@"HandBrake"]) { hbInstances++; } } return hbInstances; } +/* Gets the Process Identifer (PID) for this instance and returns it as an integer */ +- (int) getThisHBInstancePID +{ + /* Get the PID of this HB instance */ + int hbInstancePID = [[NSRunningApplication currentApplication] processIdentifier]; + return hbInstancePID; +} + +#pragma mark - - (void) didDimissReloadQueue: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo { if (returnCode == NSAlertOtherReturn) { [self clearQueueAllItems]; + /* We show whichever open source window specified in LaunchSourceBehavior preference key */ if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source"]) { @@ -302,7 +327,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It - (void)applicationWillTerminate:(NSNotification *)aNotification { - + [currentQueueEncodeNameString release]; [browsedSourceDisplayName release]; [outputPanel release]; [fQueueController release]; @@ -336,9 +361,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /* Init UserPresets .plist */ [self loadPresets]; - - /* Init QueueFile .plist */ - [self loadQueueFile]; fRipIndicatorShown = NO; // initially out of view in the nib @@ -490,8 +512,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [self getDefaultPresets:nil]; /* lets initialize the current successful scancount here to 0 */ currentSuccessfulScanCount = 0; - - } - (void) enableUI: (bool) b @@ -758,10 +778,10 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It break; } #undef p - + #define p s.param.working - + case HB_STATE_SEARCHING: { NSMutableString * string; @@ -808,7 +828,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It break; } - + case HB_STATE_WORKING: { NSMutableString * string; @@ -840,8 +860,12 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } [fStatusField setStringValue: string]; - /* Set the status string in fQueueController as well */ - [fQueueController setQueueStatusString: string]; + /* Set the status string in fQueueController as well but add currentQueueEncodeNameString to delineate + * which encode is being worked on by this instance in a multiple instance situation + */ + NSString * queueStatusString = [NSString stringWithFormat:@"%@ -> %@",string,currentQueueEncodeNameString]; + [fQueueController setQueueStatusString:queueStatusString]; + /* Update slider */ CGFloat progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count; [fRipIndicator setIndeterminate: NO]; @@ -862,14 +886,14 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It fRipIndicatorShown = YES; } - + /* Update dock icon */ if( dockIconProgress < 100.0 * progress_total ) { [self UpdateDockIcon: progress_total]; dockIconProgress += 5; } - + break; } #undef p @@ -946,7 +970,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [self sendToMetaX:pathOfFinishedEncode]; /* since we have successfully completed an encode, we increment the queue counter */ - [self incrementQueueItemDone:nil]; + [self incrementQueueItemDone:currentQueueEncodeIndex]; /* all end of queue actions below need to be done after all queue encodes have finished * and there are no pending jobs left to process @@ -986,16 +1010,23 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It returnDescriptor = [scriptObject executeAndReturnError: &errorDict]; [scriptObject release]; } - } - - } break; } } + /* Since we can use multiple instance off of the same queue file it is imperative that we keep the QueueFileArray updated off of the QueueFile.plist + * so we go ahead and do it in this existing timer as opposed to using a new one */ + + NSMutableArray * tempQueueArray = [[NSMutableArray alloc] initWithContentsOfFile:QueueFile]; + [QueueFileArray setArray:tempQueueArray]; + [tempQueueArray release]; + /* Send Fresh QueueFileArray to fQueueController to update queue window */ + [fQueueController setQueueArray: QueueFileArray]; + [self getQueueStats]; + } /* We use this to write messages to stderr from the macgui which show up in the activity window and log*/ @@ -1887,53 +1918,38 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /*We define the location of the user presets file */ QueueFile = @"~/Library/Application Support/HandBrake/Queue.plist"; QueueFile = [[QueueFile stringByExpandingTildeInPath]retain]; - /* We check for the presets.plist */ + /* We check for the Queue.plist */ if ([fileManager fileExistsAtPath:QueueFile] == 0) { [fileManager createFileAtPath:QueueFile contents:nil attributes:nil]; } - + QueueFileArray = [[NSMutableArray alloc] initWithContentsOfFile:QueueFile]; /* lets check to see if there is anything in the queue file .plist */ if (nil == QueueFileArray) { /* if not, then lets initialize an empty array */ QueueFileArray = [[NSMutableArray alloc] init]; - - /* Initialize our curQueueEncodeIndex to 0 - * so we can use it to track which queue - * item is to be used to track our encodes */ - /* NOTE: this should be changed if and when we - * are able to get the last unfinished encode - * in the case of a crash or shutdown */ - - } + } else { - [self clearQueueEncodedItems]; + /* ONLY clear out encoded items if we are single instance */ + if ([self hbInstances] == 1) + { + [self clearQueueEncodedItems]; + } } - currentQueueEncodeIndex = 0; } - (void)addQueueFileItem { - [QueueFileArray addObject:[self createQueueFileItem]]; - [self saveQueueFileItem]; - + [QueueFileArray addObject:[self createQueueFileItem]]; + [self saveQueueFileItem]; + } - (void) removeQueueFileItem:(int) queueItemToRemove { - - /* Find out if the item we are removing is a cancelled (3) or a finished (0) item*/ - if ([[[QueueFileArray objectAtIndex:queueItemToRemove] objectForKey:@"Status"] intValue] == 3 || [[[QueueFileArray objectAtIndex:queueItemToRemove] objectForKey:@"Status"] intValue] == 0) - { - /* Since we are removing a cancelled or finished item, WE need to decrement the currentQueueEncodeIndex - * by one to keep in sync with the queue array - */ - currentQueueEncodeIndex--; - - } [QueueFileArray removeObjectAtIndex:queueItemToRemove]; [self saveQueueFileItem]; @@ -1977,7 +1993,13 @@ fWorkingCount = 0; if ([[thisQueueDict objectForKey:@"Status"] intValue] == 1) // being encoded { fWorkingCount++; - fEncodingQueueItem = i; + fEncodingQueueItem = i; + /* check to see if we are the instance doing this encoding */ + if ([thisQueueDict objectForKey:@"EncodingPID"] && [[thisQueueDict objectForKey:@"EncodingPID"] intValue] == pidNum) + { + currentQueueEncodeIndex = i; + } + } if ([[thisQueueDict objectForKey:@"Status"] intValue] == 2) // pending { @@ -2003,6 +2025,30 @@ fWorkingCount = 0; [fQueueStatus setStringValue:string]; } +/* Used to get the next pending queue item index and return it if found */ +- (int)getNextPendingQueueIndex +{ + /* initialize nextPendingIndex to -1, this value tells incrementQueueItemDone that there are no pending items in the queue */ + int nextPendingIndex = -1; + BOOL nextPendingFound = NO; + NSEnumerator *enumerator = [QueueFileArray objectEnumerator]; + id tempObject; + int i = 0; + while (tempObject = [enumerator nextObject]) + { + NSDictionary *thisQueueDict = tempObject; + if ([[thisQueueDict objectForKey:@"Status"] intValue] == 2 && nextPendingFound == NO) // pending + { + nextPendingFound = YES; + nextPendingIndex = [QueueFileArray indexOfObject: tempObject]; + [self writeToActivityLog: "getNextPendingQueueIndex next pending encod index is:%d", nextPendingIndex]; + } + i++; + } + return nextPendingIndex; +} + + /* This method will set any item marked as encoding back to pending * currently used right after a queue reload */ @@ -2401,8 +2447,8 @@ fWorkingCount = 0; - (void) incrementQueueItemDone:(int) queueItemDoneIndexNum { - int i = currentQueueEncodeIndex; - [[QueueFileArray objectAtIndex:i] setObject:[NSNumber numberWithInt:0] forKey:@"Status"]; + /* Mark the encode just finished as done (status 0)*/ + [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:0] forKey:@"Status"]; /* We save all of the Queue data here */ [self saveQueueFileItem]; @@ -2411,25 +2457,41 @@ fWorkingCount = 0; * 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++ ; int queueItems = [QueueFileArray count]; - /* If we still have more items in our queue, lets go to the next one */ - if (currentQueueEncodeIndex < queueItems) - { + /* Check to see if there are any more pending items in the queue */ + int newQueueItemIndex = [self getNextPendingQueueIndex]; + /* If we still have more pending items in our queue, lets go to the next one */ + if (newQueueItemIndex >= 0 && newQueueItemIndex < queueItems) + { + /*Set our currentQueueEncodeIndex now to the newly found Pending encode as we own it */ + currentQueueEncodeIndex = newQueueItemIndex; + /* now we mark the queue item as Status = 1 ( being encoded ) so another instance can not come along and try to scan it while we are scanning */ + [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:1] forKey:@"Status"]; + [self writeToActivityLog: "incrementQueueItemDone new pending items found: %d", currentQueueEncodeIndex]; + [self saveQueueFileItem]; + /* now we can go ahead and scan the new pending queue item */ [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; + } else { - [self writeToActivityLog: "incrementQueueItemDone the %d item queue is complete", currentQueueEncodeIndex - 1]; + [self writeToActivityLog: "incrementQueueItemDone there are no more pending encodes"]; } } /* Here we actually tell hb_scan to perform the source scan, using the path to source and title number*/ - (void) performNewQueueScan:(NSString *) scanPath scanTitleNum: (int) scanTitleNum { - /* Tell HB to output a new activity log file for this encode */ + /* Tell HB to output a new activity log file for this encode */ [outputPanel startEncodeLog:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"DestinationPath"]]; + /* We now flag the queue item as being owned by this instance of HB using the PID */ + [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:pidNum] forKey:@"EncodingPID"]; + /* Get the currentQueueEncodeNameString from the queue item to display in the status field */ + currentQueueEncodeNameString = [[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"DestinationPath"] lastPathComponent]retain]; + /* We save all of the Queue data here */ + [self saveQueueFileItem]; + /* use a bool to determine whether or not we can decrypt using vlc */ BOOL cancelScanDecrypt = 0; /* set the bool so that showNewScan knows to apply the appropriate queue @@ -3960,7 +4022,7 @@ bool one_burned = FALSE; /* addToQueue: puts up an alert before ultimately calling doAddToQueue -*/ + */ - (IBAction) addToQueue: (id) sender { /* We get the destination directory from the destination field here */ @@ -4010,7 +4072,7 @@ bool one_burned = FALSE; } else if (fileExistsInQueue == YES) { - NSBeginCriticalAlertSheet( NSLocalizedString( @"There is already a queue item for this destination.", @"" ), + NSBeginCriticalAlertSheet( NSLocalizedString( @"There is already a queue item for this destination.", @"" ), NSLocalizedString( @"Cancel", @"" ), NSLocalizedString( @"Overwrite", @"" ), nil, fWindow, self, @selector( overwriteAddToQueueAlertDone:returnCode:contextInfo: ), NULL, NULL, [NSString stringWithFormat: @@ -4062,6 +4124,7 @@ bool one_burned = FALSE; // If there are pending jobs in the queue, then this is a rip the queue if (fPendingCount > 0) { + currentQueueEncodeIndex = [self getNextPendingQueueIndex]; /* here lets start the queue with the first pending item */ [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; @@ -4099,6 +4162,7 @@ bool one_burned = FALSE; } /* go right to processing the new queue encode */ + currentQueueEncodeIndex = [self getNextPendingQueueIndex]; [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; } @@ -4236,23 +4300,29 @@ bool one_burned = FALSE; // and as always, save it in the queue .plist... /* We save all of the Queue data here */ [self saveQueueFileItem]; - // so now lets move to - currentQueueEncodeIndex++ ; + // ... and see if there are more items left in our queue int queueItems = [QueueFileArray count]; /* If we still have more items in our queue, lets go to the next one */ - if (currentQueueEncodeIndex < queueItems) - { - [self writeToActivityLog: "doCancelCurrentJob currentQueueEncodeIndex is incremented to: %d", currentQueueEncodeIndex]; - [self writeToActivityLog: "doCancelCurrentJob moving to the next job"]; - - [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; + /* Check to see if there are any more pending items in the queue */ + int newQueueItemIndex = [self getNextPendingQueueIndex]; + /* If we still have more pending items in our queue, lets go to the next one */ + if (newQueueItemIndex >= 0 && newQueueItemIndex < queueItems) + { + /*Set our currentQueueEncodeIndex now to the newly found Pending encode as we own it */ + currentQueueEncodeIndex = newQueueItemIndex; + /* now we mark the queue item as Status = 1 ( being encoded ) so another instance can not come along and try to scan it while we are scanning */ + [[QueueFileArray objectAtIndex:currentQueueEncodeIndex] setObject:[NSNumber numberWithInt:1] forKey:@"Status"]; + [self writeToActivityLog: "incrementQueueItemDone new pending items found: %d", currentQueueEncodeIndex]; + [self saveQueueFileItem]; + /* now we can go ahead and scan the new pending queue item */ + [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; + } else { - [self writeToActivityLog: "doCancelCurrentJob the item queue is complete"]; + [self writeToActivityLog: "incrementQueueItemDone there are no more pending encodes"]; } - } - (void) doCancelCurrentJobAndStop diff --git a/macosx/English.lproj/Queue.xib b/macosx/English.lproj/Queue.xib index 4baa5382..d834ed5f 100644 --- a/macosx/English.lproj/Queue.xib +++ b/macosx/English.lproj/Queue.xib @@ -2,17 +2,18 @@ 1050 - 10C540 - 732 - 1038.25 - 458.00 + 10F569 + 788 + 1038.29 + 461.00 com.apple.InterfaceBuilder.CocoaPlugin - 732 + 788 YES + YES @@ -41,7 +42,7 @@ 4111 2 - {{893, 137}, {574, 423}} + {{893, 130}, {594, 430}} 1886912512 Queue - HandBrake NSWindow @@ -51,7 +52,7 @@ {1.79769e+308, 1.79769e+308} {525, 340} - + 256 YES @@ -229,6 +230,7 @@ {{1, 1}, {517, 342}} + 6 @@ -263,6 +265,7 @@ {{20, 20}, {534, 344}} + 18 @@ -388,7 +391,7 @@ - {574, 371} + {{0, 7}, {574, 371}} NSView NSResponder @@ -396,7 +399,7 @@ 264 - {{17, 398}, {148, 14}} + {{17, 405}, {148, 14}} YES @@ -411,13 +414,13 @@ - 264 - {{17, 376}, {540, 14}} + 266 + {{17, 383}, {560, 14}} YES 67239424 - 272760832 + 4325376 There are no jobs currently encoding @@ -426,7 +429,8 @@ - {574, 423} + {594, 430} + {{0, 0}, {1920, 1178}} {525, 362} @@ -914,9 +918,9 @@ com.apple.InterfaceBuilder.CocoaPlugin - {{-1207, 366}, {574, 423}} + {{-1207, 359}, {594, 430}} com.apple.InterfaceBuilder.CocoaPlugin - {{-1207, 366}, {574, 423}} + {{-1207, 359}, {594, 430}} @@ -1033,6 +1037,45 @@ id + + YES + + YES + editSelectedQueueItem: + imageSpacingChanged: + indentChanged: + removeSelectedQueueItem: + revealSelectedQueueItem: + showQueueWindow: + + + YES + + editSelectedQueueItem: + id + + + imageSpacingChanged: + id + + + indentChanged: + id + + + removeSelectedQueueItem: + id + + + revealSelectedQueueItem: + id + + + showQueueWindow: + id + + + YES @@ -1062,6 +1105,65 @@ NSSlider + + YES + + YES + fCurrentJobPane + fIndentation + fJobDescTextField + fJobIconView + fOutlineView + fProgressBar + fProgressTextField + fQueueCountField + fQueuePane + fSpacing + + + YES + + fCurrentJobPane + NSView + + + fIndentation + NSSlider + + + fJobDescTextField + NSTextField + + + fJobIconView + NSImageView + + + fOutlineView + HBQueueOutlineView + + + fProgressBar + NSProgressIndicator + + + fProgressTextField + NSTextField + + + fQueueCountField + NSTextField + + + fQueuePane + NSView + + + fSpacing + NSSlider + + + IBProjectSource HBQueueController.h @@ -1087,6 +1189,35 @@ id + + YES + + YES + cancelCurrentJob: + revealSelectedJobGroups: + togglePauseResume: + toggleStartCancel: + + + YES + + cancelCurrentJob: + id + + + revealSelectedJobGroups: + id + + + togglePauseResume: + id + + + toggleStartCancel: + id + + + IBUserSource @@ -1749,6 +1880,13 @@ showWindow: id + + showWindow: + + showWindow: + id + + IBFrameworkSource AppKit.framework/Headers/NSWindowController.h @@ -1757,6 +1895,7 @@ 0 + IBCocoaFramework com.apple.InterfaceBuilder.CocoaPlugin.macosx @@ -1768,5 +1907,20 @@ YES ../HandBrake.xcodeproj 3 + + YES + + YES + Delete + NSMenuCheckmark + NSMenuMixedState + + + YES + {16, 16} + {9, 8} + {7, 2} + + diff --git a/macosx/HBQueueController.h b/macosx/HBQueueController.h index ddae3e66..8f1268e5 100644 --- a/macosx/HBQueueController.h +++ b/macosx/HBQueueController.h @@ -53,8 +53,9 @@ BOOL fIsDragging; hb_handle_t *fQueueEncodeLibhb; // reference to libhb HBController *fHBController; // reference to HBController NSMutableArray *fJobGroups; // mirror image of the queue array from controller.mm - - int fEncodingQueueItem; // corresponds to the index of fJobGroups encoding item + + int pidNum; // Records the PID number from HBController for this instance + 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; @@ -106,7 +107,6 @@ BOOL fIsDragging; #endif } - - (void)setHandle: (hb_handle_t *)handle; - (void)setHBController: (HBController *)controller; diff --git a/macosx/HBQueueController.mm b/macosx/HBQueueController.mm index 856f10fd..451d96ee 100644 --- a/macosx/HBQueueController.mm +++ b/macosx/HBQueueController.mm @@ -109,7 +109,8 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe nil]]; fJobGroups = [[NSMutableArray arrayWithCapacity:0] retain]; - } + } + return self; } @@ -118,14 +119,13 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe [fJobGroups setArray:QueueFileArray]; fIsDragging = NO; /* First stop any timer working now */ - [self stopAnimatingCurrentJobGroupInQueue]; + //[self stopAnimatingCurrentJobGroupInQueue]; [fOutlineView reloadData]; /* lets get the stats on the status of the queue array */ - fEncodingQueueItem = 0; fPendingCount = 0; fCompletedCount = 0; fCanceledCount = 0; @@ -138,11 +138,11 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe * 2 == is yet to be encoded * 3 == cancelled */ - int i = 0; + NSDictionary *thisQueueDict = nil; for(id tempObject in fJobGroups) { - NSDictionary *thisQueueDict = tempObject; + thisQueueDict = tempObject; if ([[thisQueueDict objectForKey:@"Status"] intValue] == 0) // Completed { fCompletedCount++; @@ -150,7 +150,11 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe if ([[thisQueueDict objectForKey:@"Status"] intValue] == 1) // being encoded { fWorkingCount++; - fEncodingQueueItem = i; + /* we have an encoding job so, lets start the animation timer */ + if ([thisQueueDict objectForKey:@"EncodingPID"] && [[thisQueueDict objectForKey:@"EncodingPID"] intValue] == pidNum) + { + fEncodingQueueItem = i; + } } if ([[thisQueueDict objectForKey:@"Status"] intValue] == 2) // pending { @@ -163,14 +167,6 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe i++; } - /* We should fire up the encoding timer here based on fWorkingCount */ - - if (fWorkingCount > 0) - { - /* we have an encoding job so, lets start the animation timer */ - [self startAnimatingCurrentWorkingEncodeInQueue]; - } - /* Set the queue status field in the queue window */ NSMutableString * string; if (fPendingCount == 1) @@ -184,6 +180,7 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe [fQueueCountField setStringValue:string]; } + /* This method sets the status string in the queue window * and is called from Controller.mm (fHBController) * instead of running another timer here polling libhb @@ -191,7 +188,9 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe */ - (void)setQueueStatusString: (NSString *)statusString { -[fProgressTextField setStringValue:statusString]; + + [fProgressTextField setStringValue:statusString]; + } //------------------------------------------------------------------------------------ @@ -227,6 +226,9 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe - (void)setHBController: (HBController *)controller { fHBController = controller; + /* Now get this pidnum from HBController */ + pidNum = [fHBController getThisHBInstancePID]; + [fHBController writeToActivityLog: "HBQueueController : My Pidnum is %d", pidNum]; } #pragma mark - @@ -238,6 +240,7 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe { [self showWindow:sender]; [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"QueueWindowIsOpen"]; + [self startAnimatingCurrentWorkingEncodeInQueue]; } @@ -252,7 +255,6 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe if( ![[self window] setFrameUsingName:@"Queue"] ) [[self window] center]; [self setWindowFrameAutosaveName:@"Queue"]; - //[[self window] setExcludedFromWindowsMenu:YES]; /* lets setup our queue list outline view for drag and drop here */ [fOutlineView registerForDraggedTypes: [NSArray arrayWithObject:DragDropSimplePboardType] ]; @@ -273,9 +275,7 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe // Show/hide UI elements fCurrentJobPaneShown = NO; // it's shown in the nib - //[self showCurrentJobPane:NO]; - //[self updateQueueCountField]; } @@ -285,6 +285,7 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe - (void)windowWillClose:(NSNotification *)aNotification { [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"QueueWindowIsOpen"]; + [self stopAnimatingCurrentJobGroupInQueue]; } #pragma mark Toolbar @@ -507,7 +508,7 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe } else { - /* since we are not a currently encoding item, we can just be cancelled */ + /* since we are not a currently encoding item, we can just be removed */ [fHBController removeQueueFileItem:row]; } } @@ -520,19 +521,19 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe * In this case, we are paused from the calling window, so calling * [fHBController Pause:NULL]; Again will resume encoding */ - [fHBController Pause:NULL]; + [fHBController Pause:NULL]; if (returnCode == NSAlertOtherReturn) { - /* We need to save the currently encoding item number first */ - int encodingItemToRemove = fEncodingQueueItem; - /* Since we are encoding, we need to let fHBController Cancel this job - * upon which it will move to the next one if there is one - */ - [fHBController doCancelCurrentJob]; - /* Now, we can go ahead and remove the job we just cancelled since - * we have its item number from above - */ - [fHBController removeQueueFileItem:encodingItemToRemove]; + /* We need to save the currently encoding item number first */ + int encodingItemToRemove = fEncodingQueueItem; + /* Since we are encoding, we need to let fHBController Cancel this job + * upon which it will move to the next one if there is one + */ + [fHBController doCancelCurrentJob]; + /* Now, we can go ahead and remove the job we just cancelled since + * we have its item number from above + */ + [fHBController removeQueueFileItem:encodingItemToRemove]; } } @@ -676,7 +677,7 @@ static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseRe } } - +/* We need to make sure we denote only working encodes even for multiple instances */ - (void) animateWorkingEncodeIconInQueue { NSInteger row = fEncodingQueueItem; /// need to set to fEncodingQueueItem @@ -959,9 +960,6 @@ return ![(HBQueueOutlineView*)outlineView isDragging]; - (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"]) { @@ -996,7 +994,6 @@ return ![(HBQueueOutlineView*)outlineView isDragging]; 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]]; @@ -1448,7 +1445,7 @@ return ![(HBQueueOutlineView*)outlineView isDragging]; return @""; } } - +/* This method inserts the proper action icons into the far right of the queue window */ - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item { if ([[tableColumn identifier] isEqualToString:@"desc"]) @@ -1465,7 +1462,8 @@ return ![(HBQueueOutlineView*)outlineView isDragging]; { [cell setEnabled: YES]; BOOL highlighted = [outlineView isRowSelected:[outlineView rowForItem: item]] && [[outlineView window] isKeyWindow] && ([[outlineView window] firstResponder] == outlineView); - if ([[item objectForKey:@"Status"] intValue] == 0) + + if ([[item objectForKey:@"Status"] intValue] == 0 || ([[item objectForKey:@"Status"] intValue] == 1 && [[item objectForKey:@"EncodingPID"] intValue] != pidNum)) { [cell setAction: @selector(revealSelectedQueueItem:)]; if (highlighted) @@ -1478,21 +1476,23 @@ return ![(HBQueueOutlineView*)outlineView isDragging]; } else { - [cell setAction: @selector(removeSelectedQueueItem:)]; - if (highlighted) - { - [cell setImage:[NSImage imageNamed:@"DeleteHighlight"]]; - [cell setAlternateImage:[NSImage imageNamed:@"DeleteHighlightPressed"]]; - } - else - [cell setImage:[NSImage imageNamed:@"Delete"]]; + + [cell setAction: @selector(removeSelectedQueueItem:)]; + if (highlighted) + { + [cell setImage:[NSImage imageNamed:@"DeleteHighlight"]]; + [cell setAlternateImage:[NSImage imageNamed:@"DeleteHighlightPressed"]]; + } + else + [cell setImage:[NSImage imageNamed:@"Delete"]]; + } } } - (void)outlineView:(NSOutlineView *)outlineView willDisplayOutlineCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item { - // By default, the discolsure image gets centered vertically in the cell. We want + // By default, the disclosure image gets centered vertically in the cell. We want // always at the top. if ([outlineView isItemExpanded: item]) [cell setImagePosition: NSImageAbove]; -- 2.11.0