summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--macosx/Controller.h31
-rw-r--r--macosx/Controller.mm1826
-rw-r--r--macosx/English.lproj/MainMenu.xib12
-rw-r--r--macosx/English.lproj/Queue.xib908
-rw-r--r--macosx/HBQueueController.h223
-rw-r--r--macosx/HBQueueController.mm2503
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