summaryrefslogtreecommitdiffstats
path: root/macosx/HBQueueController.mm
diff options
context:
space:
mode:
authordynaflash <[email protected]>2008-09-16 20:57:13 +0000
committerdynaflash <[email protected]>2008-09-16 20:57:13 +0000
commitab154ca5555a0b04a5ee4f00bf65b27a57f64471 (patch)
tree45d7fe81a0382edc928161028fe469142ef47474 /macosx/HBQueueController.mm
parentf1809fae2b817c697ae663167f0ab31c2e0aa676 (diff)
MacGui: Resilient Queue: Initial Implementation
- Completely overhauls how encodes are setup by the MacGui - All encodes are now stored in an NSMutableArray (QueueFileArray) and saved in a plist (~/Library/Application Support/HandBrake/Queue.plist) - A separate instance of libhb (fQueueEncodeLibhb) is used for queue processing (includes single encodes) - fHandle still takes care of all user intiated scans and encode parameters - libhb now only stores multiple passes for a single encode instead of storing the entire queue - If HB crashes, or if you stop encoding while there are still pending encodes in your queue, upon next launch you will be prompted to reload the previous queue from the Queue.plist - Removed the current encoding information at the top of the queue window to make room for a larger list as I thought it to be redundant - The queue list is now re-arrangeable via drag-n-drop (pending encodes only) - Known issues and bugs: -- If you delete a previously cancelled encode then try to restart with a new encode, nothing happens. Throw off the sync of the currently encoding job. -- Probably alot more since its a total overhaul of how the MacGui has handled encoding since titer originally wrote it :) git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1703 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'macosx/HBQueueController.mm')
-rw-r--r--macosx/HBQueueController.mm2503
1 files changed, 676 insertions, 1827 deletions
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