X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=macosx%2FHBQueueController.mm;h=45d2f83a5e3e5615191f0d9007aabadacbf509bb;hb=8425b4e14041ee668806cff29e458ae73bcd894f;hp=fa307e837d64275cb9f0a66dad6ca1e3ef4fcf60;hpb=5dcd710f9a2dce7ef7fe874f4afb22695b49ae54;p=handbrake-jp%2Fhandbrake-jp-git.git
diff --git a/macosx/HBQueueController.mm b/macosx/HBQueueController.mm
index fa307e83..45d2f83a 100644
--- a/macosx/HBQueueController.mm
+++ b/macosx/HBQueueController.mm
@@ -1,18 +1,21 @@
/* HBQueueController
This file is part of the HandBrake source code.
- Homepage: .
+ Homepage: .
It may be used under the terms of the GNU General Public License. */
-#include "HBQueueController.h"
-#include "Controller.h"
+#import "HBQueueController.h"
+#import "Controller.h"
#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"
+//------------------------------------------------------------------------------------
+#pragma mark -
+//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
// NSMutableAttributedString (HBAdditions)
@@ -32,9 +35,6 @@
}
@end
-//------------------------------------------------------------------------------------
-#pragma mark -
-//------------------------------------------------------------------------------------
@implementation HBQueueOutlineView
@@ -47,1618 +47,250 @@
[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;
+ 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 -
-#pragma mark Job group functions
-//------------------------------------------------------------------------------------
-// These could be part of hblib if we think hblib should have knowledge of groups.
-// For now, I see groups as a metaphor that HBQueueController provides.
-
-/**
- * Returns the number of jobs groups in the queue.
- * @param h Handle to hb_handle_t.
- * @return Number of job groups.
- */
-static int hb_group_count(hb_handle_t * h)
-{
- hb_job_t * job;
- int count = 0;
- int index = 0;
- while( ( job = hb_job( h, index++ ) ) )
- {
- if (job->sequence_id == 0)
- count++;
- }
- return count;
-}
-/**
- * Returns handle to the first job in the i-th group within the job list.
- * @param h Handle to hb_handle_t.
- * @param i Index of group.
- * @returns Handle to hb_job_t of desired job.
- */
-static hb_job_t * hb_group(hb_handle_t * h, int i)
-{
- hb_job_t * job;
- int count = 0;
- int index = 0;
- while( ( job = hb_job( h, index++ ) ) )
- {
- if (job->sequence_id == 0)
- {
- if (count == i)
- return job;
- count++;
- }
- }
- return NULL;
-}
-/**
- * Removes a groups of jobs from the job list.
- * @param h Handle to hb_handle_t.
- * @param job Handle to the first job in the group.
- */
-static void hb_rem_group( hb_handle_t * h, hb_job_t * job )
-{
- // Find job in list
- hb_job_t * j;
- int index = 0;
- while( ( j = hb_job( h, index ) ) )
- {
- if (j == job)
- {
- // Delete this job plus the following ones in the sequence
- hb_rem( h, job );
- while( ( j = hb_job( h, index ) ) && (j->sequence_id != 0) )
- hb_rem( h, j );
- return;
- }
- else
- index++;
- }
-}
+@end
-/**
- * Returns handle to the next job after the given job.
- * @param h Handle to hb_handle_t.
- * @param job Handle to the a job in the group.
- * @returns Handle to hb_job_t of desired job or NULL if no such job.
- */
-static hb_job_t * hb_next_job( hb_handle_t * h, hb_job_t * job )
-{
- hb_job_t * j = NULL;
- int index = 0;
- while( ( j = hb_job( h, index++ ) ) )
- {
- if (j == job)
- return hb_job( h, index );
- }
- return NULL;
-}
+#pragma mark Toolbar Identifiers
+// Toolbar identifiers
+static NSString* HBQueueToolbar = @"HBQueueToolbar1";
+static NSString* HBQueueStartCancelToolbarIdentifier = @"HBQueueStartCancelToolbarIdentifier";
+static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseResumeToolbarIdentifier";
#pragma mark -
-//------------------------------------------------------------------------------------
-// HBJob
-//------------------------------------------------------------------------------------
-
-@implementation HBJob
-
-+ (HBJob*) jobWithJob: (hb_job_t *) job
-{
- return [[[HBJob alloc] initWithJob:job] autorelease];
-}
-
-- (id) initWithJob: (hb_job_t *) job
-{
- if (self = [super init])
- {
- // job is not owned by HBJob. It does not get dealloacted when HBJob is released.
- hbJob = job;
- }
- return self;
-}
-
-- (hb_job_t*) job
-{
- return hbJob;
-}
-
-//------------------------------------------------------------------------------------
-// Generate string to display in UI.
-//------------------------------------------------------------------------------------
-
-- (NSMutableAttributedString *) attributedDescriptionWithHBHandle: (hb_handle_t *)handle
- withIcon: (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];
-
- hb_title_t * title = hbJob->title;
-
- // Attributes
- static NSMutableParagraphStyle * ps = NULL;
- if (!ps)
- {
- 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]];
- }
-
- static NSDictionary* detailAttribute = [[NSDictionary dictionaryWithObjectsAndKeys:
- [NSFont systemFontOfSize:10.0], NSFontAttributeName,
- ps, NSParagraphStyleAttributeName,
- nil] retain];
- static NSDictionary* detailBoldAttribute = [[NSDictionary dictionaryWithObjectsAndKeys:
- [NSFont boldSystemFontOfSize:10.0], NSFontAttributeName,
- ps, NSParagraphStyleAttributeName,
- nil] retain];
- static NSDictionary* titleAttribute = [[NSDictionary dictionaryWithObjectsAndKeys:
- [NSFont systemFontOfSize:[NSFont systemFontSize]], NSFontAttributeName,
- ps, NSParagraphStyleAttributeName,
- nil] retain];
- static NSDictionary* shortHeightAttribute = [[NSDictionary dictionaryWithObjectsAndKeys:
- [NSFont systemFontOfSize:2.0], NSFontAttributeName,
- nil] retain];
-
- // 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:[NSString stringWithUTF8String:title->name] withAttributes:titleAttribute];
-
- NSString * summaryInfo;
-
- NSString * chapterString = (hbJob->chapter_start == hbJob->chapter_end) ?
- [NSString stringWithFormat:@"Chapter %d", hbJob->chapter_start] :
- [NSString stringWithFormat:@"Chapters %d through %d", hbJob->chapter_start, hbJob->chapter_end];
-
- BOOL hasIndepthScan = (hbJob->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.
- hb_job_t * nextjob;
- if (hbJob == hb_current_job(handle))
- nextjob = hb_job(handle, 0);
- else
- nextjob = hb_next_job(handle, hbJob);
- if (nextjob) // Overly cautious in case there is no next job!
- numVideoPasses = MIN( 2, nextjob->pass + 1 );
- }
- else
- numVideoPasses = MIN( 2, hbJob->pass + 1 );
-
- if (hasIndepthScan && numVideoPasses == 1)
- summaryInfo = [NSString stringWithFormat: @" (Title %d, %@, Deep Scan, Single Video Pass)", title->index, chapterString];
- else if (hasIndepthScan && numVideoPasses > 1)
- summaryInfo = [NSString stringWithFormat: @" (Title %d, %@, Deep Scan, %d Video Passes)", title->index, chapterString, numVideoPasses];
- else if (numVideoPasses == 1)
- summaryInfo = [NSString stringWithFormat: @" (Title %d, %@, Single Video Pass)", title->index, chapterString];
- else
- summaryInfo = [NSString stringWithFormat: @" (Title %d, %@, %d Video Passes)", title->index, chapterString, numVideoPasses];
-
- [finalString appendString:[NSString stringWithFormat:@"%@\n", summaryInfo] withAttributes:detailAttribute];
-
- // Insert a short-in-height line to put some white space after the title
- [finalString appendString:@"\n" withAttributes:shortHeightAttribute];
- }
-
- // End of title stuff
-
-
- // Pass Name
- if (withPassName)
- {
- if (withIcon)
- {
- NSString * imageName;
- switch (hbJob->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 (hbJob->pass == -1)
- jobPassName = NSLocalizedString (@"Deep Scan", nil);
- else
- {
- int passNum = MAX( 1, hbJob->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:detailBoldAttribute];
- }
-
- // Video Codec needed by FormatInfo and withVideoInfo
- NSString * jobVideoCodec = nil;
- if (withFormatInfo || withVideoInfo)
- {
- // 2097152
- // Video Codec settings (Encoder in the gui)
- if (hbJob->vcodec == HB_VCODEC_FFMPEG)
- jobVideoCodec = @"FFmpeg"; // HB_VCODEC_FFMPEG
- else if (hbJob->vcodec == HB_VCODEC_XVID)
- jobVideoCodec = @"XviD"; // HB_VCODEC_XVID
- else if (hbJob->vcodec == HB_VCODEC_X264)
- {
- // Deterimine for sure how we are now setting iPod uuid atom
- if (hbJob->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";
-
- // Audio Codec needed by FormatInfo and AudioInfo
- NSString * jobAudioCodec = nil;
- if (withFormatInfo || withAudioInfo)
- {
- if (hbJob->acodec == 256)
- jobAudioCodec = @"AAC"; // HB_ACODEC_FAAC
- else if (hbJob->acodec == 512)
- jobAudioCodec = @"MP3"; // HB_ACODEC_LAME
- else if (hbJob->acodec == 1024)
- jobAudioCodec = @"Vorbis"; // HB_ACODEC_VORBIS
- else if (hbJob->acodec == 2048)
- jobAudioCodec = @"AC3"; // HB_ACODEC_AC3
- }
- if (jobAudioCodec == nil)
- jobAudioCodec = @"unknown";
-
-
- if (withFormatInfo)
- {
- NSString * jobFormatInfo;
- // Muxer settings (File Format in the gui)
- if (hbJob->mux == 65536 || hbJob->mux == 131072 || hbJob->mux == 1048576)
- jobFormatInfo = @"MP4"; // HB_MUX_MP4,HB_MUX_PSP,HB_MUX_IPOD
- else if (hbJob->mux == 262144)
- jobFormatInfo = @"AVI"; // HB_MUX_AVI
- else if (hbJob->mux == 524288)
- jobFormatInfo = @"OGM"; // HB_MUX_OGM
- else if (hbJob->mux == 2097152)
- jobFormatInfo = @"MKV"; // HB_MUX_MKV
- else
- jobFormatInfo = @"unknown";
-
- if (hbJob->chapter_markers == 1)
- jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video + %@ Audio, Chapter Markers\n", jobFormatInfo, jobVideoCodec, jobAudioCodec];
- else
- jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video + %@ Audio\n", jobFormatInfo, jobVideoCodec, jobAudioCodec];
-
- [finalString appendString: @"Format: " withAttributes:detailBoldAttribute];
- [finalString appendString: jobFormatInfo withAttributes:detailAttribute];
- }
-
- if (withDestination)
- {
- [finalString appendString: @"Destination: " withAttributes:detailBoldAttribute];
- [finalString appendString:[NSString stringWithFormat:@"%@\n", [NSString stringWithUTF8String:hbJob->file]] withAttributes:detailAttribute];
- }
-
-
- if (withPictureInfo)
- {
- NSString * jobPictureInfo;
- // integers for picture values deinterlace, crop[4], keep_ratio, grayscale, pixel_ratio, pixel_aspect_width, pixel_aspect_height,
- // maxWidth, maxHeight
- if (hbJob->pixel_ratio == 1)
- {
- int titlewidth = title->width - hbJob->crop[2] - hbJob->crop[3];
- int displayparwidth = titlewidth * hbJob->pixel_aspect_width / hbJob->pixel_aspect_height;
- int displayparheight = title->height - hbJob->crop[0] - hbJob->crop[1];
- jobPictureInfo = [NSString stringWithFormat:@"%dx%d (%dx%d Anamorphic)", displayparwidth, displayparheight, hbJob->width, displayparheight];
- }
- else
- jobPictureInfo = [NSString stringWithFormat:@"%dx%d", hbJob->width, hbJob->height];
- if (hbJob->keep_ratio == 1)
- jobPictureInfo = [jobPictureInfo stringByAppendingString:@" Keep Aspect Ratio"];
-
- if (hbJob->grayscale == 1)
- jobPictureInfo = [jobPictureInfo stringByAppendingString:@", Grayscale"];
-
- if (hbJob->deinterlace == 1)
- jobPictureInfo = [jobPictureInfo stringByAppendingString:@", Deinterlace"];
- if (withIcon) // implies indent the info
- [finalString appendString: @"\t" withAttributes:detailBoldAttribute];
- [finalString appendString: @"Picture: " withAttributes:detailBoldAttribute];
- [finalString appendString:[NSString stringWithFormat:@"%@\n", jobPictureInfo] withAttributes:detailAttribute];
- }
-
- if (withVideoInfo)
- {
- NSString * jobVideoQuality;
- NSString * jobVideoDetail;
-
- if (hbJob->vquality <= 0 || hbJob->vquality >= 1)
- jobVideoQuality = [NSString stringWithFormat:@"%d kbps", hbJob->vbitrate];
- else
- {
- NSNumber * vidQuality;
- vidQuality = [NSNumber numberWithInt:hbJob->vquality * 100];
- // this is screwed up kind of. Needs to be formatted properly.
- if (hbJob->crf == 1)
- jobVideoQuality = [NSString stringWithFormat:@"%@%% CRF", vidQuality];
- else
- jobVideoQuality = [NSString stringWithFormat:@"%@%% CQP", vidQuality];
- }
-
- if (hbJob->vrate_base == 1126125)
- {
- // NTSC FILM 23.976
- jobVideoDetail = [NSString stringWithFormat:@"%@, %@, 23.976 fps", jobVideoCodec, jobVideoQuality];
- }
- else if (hbJob->vrate_base == 900900)
- {
- // NTSC 29.97
- jobVideoDetail = [NSString stringWithFormat:@"%@, %@, 29.97 fps", jobVideoCodec, jobVideoQuality];
- }
- else
- {
- // Everything else
- jobVideoDetail = [NSString stringWithFormat:@"%@, %@, %d fps", jobVideoCodec, jobVideoQuality, hbJob->vrate / hbJob->vrate_base];
- }
- if (withIcon) // implies indent the info
- [finalString appendString: @"\t" withAttributes:detailBoldAttribute];
- [finalString appendString: @"Video: " withAttributes:detailBoldAttribute];
- [finalString appendString:[NSString stringWithFormat:@"%@\n", jobVideoDetail] withAttributes:detailAttribute];
- }
-
- if (withx264Info)
- {
- if (hbJob->vcodec == HB_VCODEC_X264 && hbJob->x264opts)
- {
- if (withIcon) // implies indent the info
- [finalString appendString: @"\t" withAttributes:detailBoldAttribute];
- [finalString appendString: @"x264 Options: " withAttributes:detailBoldAttribute];
- [finalString appendString:[NSString stringWithFormat:@"%@\n", [NSString stringWithUTF8String:hbJob->x264opts]] withAttributes:detailAttribute];
- }
- }
-
- if (withAudioInfo)
- {
- NSString * jobAudioInfo;
- if ([jobAudioCodec isEqualToString: @"AC3"])
- jobAudioInfo = [NSString stringWithFormat:@"%@, Pass-Through", jobAudioCodec];
- else
- jobAudioInfo = [NSString stringWithFormat:@"%@, %d kbps, %d Hz", jobAudioCodec, hbJob->abitrate, hbJob->arate];
-
- // we now get the audio mixdown info for each of the two gui audio tracks
- // lets do it the long way here to get a handle on things.
- // Hardcoded for two tracks for gui: audio_mixdowns[i] audio_mixdowns[i]
- int ai; // counter for each audios [] , macgui only allows for two audio tracks currently
- for( ai = 0; ai < 2; ai++ )
- {
- if (hbJob->audio_mixdowns[ai] == HB_AMIXDOWN_MONO)
- jobAudioInfo = [jobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", Track %d: Mono", ai + 1]];
- if (hbJob->audio_mixdowns[ai] == HB_AMIXDOWN_STEREO)
- jobAudioInfo = [jobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", Track %d: Stereo", ai + 1]];
- if (hbJob->audio_mixdowns[ai] == HB_AMIXDOWN_DOLBY)
- jobAudioInfo = [jobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", Track %d: Dolby Surround", ai + 1]];
- if (hbJob->audio_mixdowns[ai] == HB_AMIXDOWN_DOLBYPLII)
- jobAudioInfo = [jobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", Track %d: Dolby Pro Logic II", ai + 1]];
- if (hbJob->audio_mixdowns[ai] == HB_AMIXDOWN_6CH)
- jobAudioInfo = [jobAudioInfo stringByAppendingString:[NSString stringWithFormat:@", Track %d: 6-channel discreet", ai + 1]];
- }
- if (withIcon) // implies indent the info
- [finalString appendString: @"\t" withAttributes:detailBoldAttribute];
- [finalString appendString: @"Audio: " withAttributes:detailBoldAttribute];
- [finalString appendString:[NSString stringWithFormat:@"%@\n", jobAudioInfo] withAttributes:detailAttribute];
- }
-
- if (withSubtitleInfo)
- {
- // hbJob->subtitle can == -1 in two cases:
- // autoselect: when pass == -1
- // none: when pass != -1
- if ((hbJob->subtitle == -1) && (hbJob->pass == -1))
- {
- if (withIcon) // implies indent the info
- [finalString appendString: @"\t" withAttributes:detailBoldAttribute];
- [finalString appendString: @"Subtitles: " withAttributes:detailBoldAttribute];
- [finalString appendString: @"Autoselect " withAttributes:detailAttribute];
- }
- else if (hbJob->subtitle >= 0)
- {
- hb_subtitle_t * subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, 0 );
- if (subtitle)
- {
- if (withIcon) // implies indent the info
- [finalString appendString: @"\t" withAttributes:detailBoldAttribute];
- [finalString appendString: @"Subtitles: " withAttributes:detailBoldAttribute];
- [finalString appendString: [NSString stringWithCString: subtitle->lang] withAttributes:detailAttribute];
- }
- }
- }
-
-
- if ([[finalString string] hasSuffix: @"\n"])
- [finalString deleteCharactersInRange: NSMakeRange([[finalString string] length]-1, 1)];
-
- return finalString;
-}
-
-@end
-
-#pragma mark -
+@implementation HBQueueController
//------------------------------------------------------------------------------------
-// HBJobGroup
+// init
//------------------------------------------------------------------------------------
-
-@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
-{
- [fJobs release];
- [fPath release];
- [super dealloc];
-}
-
-- (unsigned int) count
-{
- return [fJobs count];
-}
-
-- (void) addJob: (HBJob *)aJob
-{
- [fJobs addObject: aJob];
- [self setNeedsDescription: YES];
- fLastDescriptionHeight = 0;
- fLastDescriptionWidth = 0;
-}
-
-- (void) removeAllJobs
-{
- [fJobs removeAllObjects];
-}
-
-- (HBJob *) jobAtIndex: (unsigned)index
-{
- return [fJobs objectAtIndex: index];
-}
-
-- (unsigned) indexOfJob: (HBJob *)aJob;
-{
- return [fJobs indexOfObject: aJob];
-}
-
-- (NSEnumerator *) jobEnumerator
-{
- return [fJobs objectEnumerator];
-}
-
-- (void) setNeedsDescription: (BOOL)flag
-{
- fNeedsDescription = flag;
-}
-
-- (void) updateDescriptionWithHBHandle: (hb_handle_t *)handle
+- (id)init
{
- fNeedsDescription = NO;
-
- [fDescription deleteCharactersInRange: NSMakeRange(0, [fDescription length])];
-
- if ([self count] == 0)
- {
- NSAssert(NO, @" jobgroup with no jobs");
- return;
- }
-
- HBJob * job = [self jobAtIndex:0];
-
- [fDescription appendAttributedString: [job attributedDescriptionWithHBHandle: handle
- withIcon: NO
- withTitle: YES
- withPassName: NO
- withFormatInfo: YES
- withDestination: YES
- withPictureInfo: NO
- withVideoInfo: NO
- withx264Info: NO
- withAudioInfo: NO
- withSubtitleInfo: NO]];
-
- static NSAttributedString * carriageReturn = [[NSAttributedString alloc] initWithString:@"\n"];
-
- NSEnumerator * e = [self jobEnumerator];
- while ( (job = [e nextObject]) )
+ if (self = [super initWithWindowNibName:@"Queue"])
{
- int pass = [job job]->pass;
- [fDescription appendAttributedString:carriageReturn];
- [fDescription appendAttributedString:
- [job attributedDescriptionWithHBHandle: handle
- withIcon: 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 *) attributedDescriptionWithHBHandle: (hb_handle_t *)handle
-{
- if (fNeedsDescription)
- [self updateDescriptionWithHBHandle: handle];
- return fDescription;
-}
-
-- (float) heightOfDescriptionForWidth:(float)width withHBHandle: (hb_handle_t *)handle
-{
- // 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 updateDescriptionWithHBHandle: handle];
-
- // 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;
+ // NSWindowController likes to lazily load its window nib. Since this
+ // controller tries to touch the outlets before accessing the window, we
+ // need to force it to load immadiately by invoking its accessor.
+ //
+ // If/when we switch to using bindings, this can probably go away.
+ [self window];
-/* 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;
-*/
-}
-
-- (float) lastDescriptionHeight
-{
- return fLastDescriptionHeight;
-}
-
-- (void) setStatus: (HBQueueJobGroupStatus)status
-{
- self->fStatus = status;
-}
-
-- (HBQueueJobGroupStatus) status
-{
- return self->fStatus;
-}
-
-- (void) setPath: (NSString *)path
-{
- [path retain];
- [fPath release];
- fPath = path;
-}
-
-- (NSString *) path
-{
- return fPath;
-}
-
-@end
-
-
-#pragma mark -
-
-@interface HBQueueController (Private)
-- (void)updateQueueUI;
-@end
-
-// Toolbar identifiers
-static NSString* HBQueueToolbar = @"HBQueueToolbar1";
-static NSString* HBQueueStartCancelToolbarIdentifier = @"HBQueueStartCancelToolbarIdentifier";
-static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseResumeToolbarIdentifier";
-
-#pragma mark -
-
-@implementation HBQueueController
-
-//------------------------------------------------------------------------------------
-// init
-//------------------------------------------------------------------------------------
-- (id)init
-{
- if (self = [super init])
- {
- // Our defaults
- [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
- @"NO", @"QueueWindowIsOpen",
- @"NO", @"QueueShowsDetail",
- @"YES", @"QueueShowsJobsAsGroups",
- nil]];
-
- fJobGroups = [[NSMutableArray arrayWithCapacity:0] retain];
- fCompleted = [[NSMutableArray arrayWithCapacity:0] retain];
-
- BOOL loadSucceeded = [NSBundle loadNibNamed:@"Queue" owner:self] && fQueueWindow;
- NSAssert(loadSucceeded, @"Could not open Queue nib");
- NSAssert(fQueueWindow, @"fQueueWindow not found in Queue nib");
- }
- return self;
-}
-
-//------------------------------------------------------------------------------------
-// dealloc
-//------------------------------------------------------------------------------------
-- (void)dealloc
-{
- // clear the delegate so that windowWillClose is not attempted
- if ([fQueueWindow delegate] == self)
- [fQueueWindow setDelegate:nil];
-
- [fJobGroups release];
- [fCompleted release];
- [fCurrentJobGroup release];
- [fSavedExpandedItems release];
- [fSavedSelectedItems release];
-
- [super dealloc];
-}
-
-//------------------------------------------------------------------------------------
-// Receive HB handle
-//------------------------------------------------------------------------------------
-- (void)setHandle: (hb_handle_t *)handle
-{
- fHandle = handle;
-}
-
-//------------------------------------------------------------------------------------
-// Receive HBController
-//------------------------------------------------------------------------------------
-- (void)setHBController: (HBController *)controller
-{
- fHBController = controller;
-}
-
-//------------------------------------------------------------------------------------
-// Displays and brings the queue window to the front
-//------------------------------------------------------------------------------------
-- (IBAction) showQueueWindow: (id)sender
-{
- [self updateQueueUI];
- [fQueueWindow makeKeyAndOrderFront: self];
- [[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;
-}
-
-//------------------------------------------------------------------------------------
-// Rebuilds the contents of fJobGroups which is a hierarchy of HBJobGroup and HBJobs.
-//------------------------------------------------------------------------------------
-- (void)rebuildJobGroups
-{
- // Currently, job groups are rdered like this:
- // Completed job groups
- // Current job group
- // Pending job groups
-
- [fJobGroups autorelease];
- fJobGroups = [[NSMutableArray arrayWithCapacity:0] retain];
-
- // Add all the completed job groups
- [fJobGroups addObjectsFromArray: fCompleted];
-
- // Add all the completed job groups
- if (fCurrentJobGroup)
- [fJobGroups addObject: fCurrentJobGroup];
-
- // Add all the pending job groups. These come from hblib
- HBJobGroup * aJobGroup = [HBJobGroup jobGroup];
-
- // If hblib is currently processing something, hb_group will skip over that group.
- // And that's exactly what we want -- fJobGroups contains only pending job groups.
-
- hb_job_t * nextJob = hb_group( fHandle, 0 );
- while( nextJob )
- {
- if (nextJob->sequence_id == 0)
- {
- // Encountered a new group. Add the current one to fJobGroups and then start a new one.
- if ([aJobGroup count] > 0)
- {
- [aJobGroup setStatus: HBStatusPending];
- [fJobGroups addObject: aJobGroup];
- aJobGroup = [HBJobGroup jobGroup];
- }
- }
- [aJobGroup addJob: [HBJob jobWithJob:nextJob]];
- [aJobGroup setPath: [NSString stringWithUTF8String:nextJob->file]];
- nextJob = hb_next_job (fHandle, nextJob);
- }
- if ([aJobGroup count] > 0)
- {
- [aJobGroup setStatus: HBStatusPending];
- [fJobGroups addObject:aJobGroup];
- }
-}
-
-//------------------------------------------------------------------------------------
-// Adds aJobGroup to the list of completed job groups, marking its status as
-// HBStatusComplete.
-//------------------------------------------------------------------------------------
-- (void) addCompletedJobGroup: (HBJobGroup *)aJobGroup
-{
- // Once hblib has completed its work, the hb_job_t objects will be freed, so we
- // can't keep a reference to them.
- [aJobGroup removeAllJobs];
-
- [aJobGroup setStatus: HBStatusComplete];
-
- // Put the group in the completed list for permanent storage, and also rebuild
- // the master job group list which contains completed and pending groups.
- [fCompleted addObject: aJobGroup];
-}
-
-- (void) setCurrentJobGroupFromJob: (hb_job_t *)aJob
-{
- HBJobGroup * aJobGroup = nil;
-
- // Try to find this new group in our existing job groups.
- if (aJob)
- {
- BOOL found = NO;
- NSEnumerator * groupEnum = [fJobGroups objectEnumerator];
- while ( !found && (aJobGroup = [groupEnum nextObject]) )
- {
- HBJob * j;
- NSEnumerator * jobEnum = [aJobGroup jobEnumerator];
- while ( !found && (j = [jobEnum nextObject]) )
- {
- if ([j job] == aJob)
- found = YES;
- }
- }
-
- // Or create the job group.
- if (!aJobGroup)
- {
- aJobGroup = [HBJobGroup jobGroup];
- [aJobGroup addJob: [HBJob jobWithJob: aJob]];
- [aJobGroup setPath: [NSString stringWithUTF8String:aJob->file]];
- while ( (aJob = hb_next_job(fHandle, aJob)) && (aJob->sequence_id != 0) )
- [aJobGroup addJob: [HBJob jobWithJob: aJob]];
-
- [aJobGroup updateDescriptionWithHBHandle: fHandle];
- }
-
- [aJobGroup setStatus: HBStatusWorking];
- }
-
- [aJobGroup retain];
- [fCurrentJobGroup release];
- fCurrentJobGroup = aJobGroup;
-}
-
-#pragma mark -
-#pragma mark UI Updating
-
-//------------------------------------------------------------------------------------
-// Saves the state of the items that are currently expanded. Calling restoreOutlineViewState
-// will restore the state of all items to match what was saved by saveOutlineViewState.
-//------------------------------------------------------------------------------------
-- (void) saveOutlineViewState
-{
- if (!fSavedExpandedItems)
- fSavedExpandedItems = [[NSMutableIndexSet alloc] init];
- else
- [fSavedExpandedItems removeAllIndexes];
-
- // NB: This code is stuffing the address of each job into an index set. While it
- // works 99.9% of the time, it's not the ideal solution. We need unique ids in
- // each job, possibly using the existing sequence_id field. Could use the high
- // word as a unique encode id and the low word the sequence number.
-
- HBJobGroup * aJobGroup;
- NSEnumerator * e = [fJobGroups objectEnumerator];
- while ( (aJobGroup = [e nextObject]) )
- {
- if ([fOutlineView isItemExpanded: aJobGroup])
- {
- if ([aJobGroup status] == HBStatusComplete)
- [fSavedExpandedItems addIndex: (unsigned int)aJobGroup];
- else
- [fSavedExpandedItems addIndex: (unsigned int)[[aJobGroup jobAtIndex:0] job]];
- }
- }
-
- // Save the selection also. This is really UGLY code. Since I have to rebuild the
- // entire outline hierachy every time hblib changes its job list, there's no easy
- // way for me to remember the selection state other than saving off the first
- // hb_job_t item in each selected group. This is done by saving the object's
- // address. This could go away if I'd save a unique id in each job object.
-
- if (!fSavedSelectedItems)
- fSavedSelectedItems = [[NSMutableIndexSet alloc] init];
- else
- [fSavedSelectedItems removeAllIndexes];
-
- NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes];
- int row = [selectedRows firstIndex];
- while (row != NSNotFound)
- {
- aJobGroup = [fOutlineView itemAtRow: row];
- if ([aJobGroup status] == HBStatusComplete)
- [fSavedSelectedItems addIndex: (unsigned int)aJobGroup];
- else
- [fSavedSelectedItems addIndex: (unsigned int)[[aJobGroup jobAtIndex:0] job]];
- 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)
- {
- HBJobGroup * aJobGroup;
- NSEnumerator * e = [fJobGroups objectEnumerator];
- while ( (aJobGroup = [e nextObject]) )
- {
- if ([aJobGroup status] == HBStatusComplete)
- {
- if ([fSavedExpandedItems containsIndex: (unsigned int)aJobGroup])
- [fOutlineView expandItem: aJobGroup];
- }
- else
- {
- hb_job_t * j = [[aJobGroup jobAtIndex:0] job];
- if ([fSavedExpandedItems containsIndex: (unsigned int)j])
- [fOutlineView expandItem: aJobGroup];
- }
- }
- }
-
- if (fSavedSelectedItems)
- {
- // Ugh. Have to cycle through each row looking for the previously selected job.
- // See the explanation in saveOutlineViewState about the logic here.
-
- NSMutableIndexSet * rowsToSelect = [[[NSMutableIndexSet alloc] init] autorelease];
- for (int i = 0; i < [fOutlineView numberOfRows]; i++)
- {
- HBJobGroup * aJobGroup = [fOutlineView itemAtRow: i];
- // Test to see if the group or the group's first job is a match
- if ([aJobGroup status] == HBStatusComplete)
- {
- if ([fSavedSelectedItems containsIndex: (unsigned int)aJobGroup])
- [rowsToSelect addIndex: i];
- }
- else
- {
- if ([fSavedSelectedItems containsIndex: (unsigned int)[[aJobGroup jobAtIndex:0] job]])
- [rowsToSelect addIndex: i];
- }
- }
- if ([rowsToSelect count] == 0)
- [fOutlineView deselectAll: nil];
- else
- [fOutlineView selectRowIndexes:rowsToSelect byExtendingSelection:NO];
- }
-}
-
-//------------------------------------------------------------------------------------
-// If a job is currently processing, its job icon in the queue outline view is
-// animated to its next state.
-//------------------------------------------------------------------------------------
-- (void) animateCurrentJobGroupInQueue:(NSTimer*)theTimer
-{
- int row = [fOutlineView rowForItem: fCurrentJobGroup];
- int col = [fOutlineView columnWithIdentifier: @"icon"];
- if (row != -1 && col != -1)
- {
- fAnimationIndex++;
- fAnimationIndex %= 6; // there are 6 animation images; see outlineView:objectValueForTableColumn:byItem: below.
- NSRect frame = [fOutlineView frameOfCellAtColumn:col row:row];
- [fOutlineView setNeedsDisplayInRect: frame];
- }
-}
-
-//------------------------------------------------------------------------------------
-// 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];
-}
-
-//------------------------------------------------------------------------------------
-// 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: (hb_job_t *)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: (hb_job_t *)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];
- }
-
- else
- {
- 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 )
- {
- 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
- }
-
- return @"";
-}
-
-//------------------------------------------------------------------------------------
-// Refresh progress bar (fProgressTextField) from current state.
-//------------------------------------------------------------------------------------
-- (void) updateProgressTextForJob: (hb_job_t *)job state: (hb_state_t *)s
-{
- 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];
-}
-
-//------------------------------------------------------------------------------------
-// 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)
- {
- #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;
-
- jobCount = fHandle ? hb_group_count(fHandle) : 0;
- if (jobCount == 1)
- msg = NSLocalizedString(@"1 pending encode", nil);
- else
- msg = [NSString stringWithFormat:NSLocalizedString(@"%d pending encodes", nil), jobCount];
-
- [fQueueCountField setStringValue:msg];
-}
-
-//------------------------------------------------------------------------------------
-// Refresh the UI in the current job pane. Should be called whenever the current job
-// being processed has changed.
-//------------------------------------------------------------------------------------
-- (void)updateCurrentJobDescription
-{
- hb_job_t * job = fHandle ? hb_current_job(fHandle) : nil;
-
- if (job)
- {
- HBJob * currentJob = [HBJob jobWithJob: job];
- switch (job->pass)
- {
- case -1: // Subtitle scan
- [fJobDescTextField setAttributedStringValue:
- [currentJob attributedDescriptionWithHBHandle:fHandle
- withIcon: 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:
- [currentJob attributedDescriptionWithHBHandle:fHandle
- withIcon: 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:
- [currentJob attributedDescriptionWithHBHandle:fHandle
- withIcon: NO
- withTitle: YES
- withPassName: YES
- withFormatInfo: NO
- withDestination: NO
- withPictureInfo: YES
- withVideoInfo: YES
- withx264Info: YES
- withAudioInfo: YES
- withSubtitleInfo: YES]];
- break;
-
- default: // unknown
- [fJobDescTextField setAttributedStringValue:
- [currentJob attributedDescriptionWithHBHandle:fHandle
- withIcon: NO
- withTitle: YES
- withPassName: YES
- withFormatInfo: NO
- withDestination: NO
- withPictureInfo: YES
- withVideoInfo: YES
- withx264Info: YES
- withAudioInfo: YES
- withSubtitleInfo: YES]];
- }
- }
-
- else
- [fJobDescTextField setStringValue: @"No encodes pending"];
-}
-
-//------------------------------------------------------------------------------------
-// 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_job_t * job = fHandle ? hb_current_job(fHandle) : nil;
- hb_state_t s;
- hb_get_state2( fHandle, &s );
- [self updateProgressTextForJob: job state: &s];
- [self updateProgressBarWithState:&s];
-}
-
-//------------------------------------------------------------------------------------
-// Refresh the UI in the queue pane. Should be called whenever the content of HB's job
-// list has changed so that HBQueueController can sync up.
-//------------------------------------------------------------------------------------
-- (void)updateQueueUI
-{
- [self saveOutlineViewState];
- [self rebuildJobGroups];
- [fOutlineView noteNumberOfRowsChanged];
- [fOutlineView reloadData];
- [self restoreOutlineViewState];
- [self updateQueueCountField];
-}
-
-#pragma mark -
-#pragma mark Actions
-
-//------------------------------------------------------------------------------------
-// Deletes the selected jobs from HB and the queue UI
-//------------------------------------------------------------------------------------
-- (IBAction)removeSelectedJobGroups: (id)sender
-{
- if (!fHandle) return;
-
- NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes];
- int row = [selectedRows firstIndex];
- if (row != NSNotFound)
- {
- while (row != NSNotFound)
- {
- HBJobGroup * jobGroup = [fOutlineView itemAtRow: row];
- switch ([jobGroup status])
- {
- case HBStatusComplete:
- case HBStatusCanceled:
- [fCompleted removeObject: jobGroup];
- break;
- case HBStatusWorking:
- [self cancelCurrentJob: sender];
- break;
- case HBStatusPending:
- hb_job_t * job = [[jobGroup jobAtIndex: 0] job];
- hb_rem_group( fHandle, job );
- break;
- case HBStatusNone:
- break;
- }
-
- row = [selectedRows indexGreaterThanIndex: row];
- }
+ // Our defaults
+ [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
+ @"NO", @"QueueWindowIsOpen",
+ @"NO", @"QueueShowsDetail",
+ @"YES", @"QueueShowsJobsAsGroups",
+ nil]];
- [self hblibJobListChanged];
- }
+ fJobGroups = [[NSMutableArray arrayWithCapacity:0] retain];
+ }
+ return self;
}
-//------------------------------------------------------------------------------------
-// Reveals the file icons in the Finder of the selected job groups.
-//------------------------------------------------------------------------------------
-- (IBAction)revealSelectedJobGroups: (id)sender
+- (void)setQueueArray: (NSMutableArray *)QueueFileArray
{
- if (!fHandle) return;
+ [fJobGroups setArray:QueueFileArray];
+ fIsDragging = NO;
+ /* First stop any timer working now */
+ [self stopAnimatingCurrentJobGroupInQueue];
+ [fOutlineView reloadData];
- NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes];
- int row = [selectedRows firstIndex];
- if (row != NSNotFound)
- {
- while (row != NSNotFound)
+
+
+ /* lets get the stats on the status of the queue array */
+
+ fEncodingQueueItem = 0;
+ fPendingCount = 0;
+ fCompletedCount = 0;
+ fCanceledCount = 0;
+ fWorkingCount = 0;
+
+ /* We use a number system to set the encode status of the queue item
+ * in controller.mm
+ * 0 == already encoded
+ * 1 == is being encoded
+ * 2 == is yet to be encoded
+ * 3 == cancelled
+ */
+
+ int i = 0;
+ NSEnumerator *enumerator = [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
{
- HBJobGroup * jobGroup = [fOutlineView itemAtRow: row];
- if ([[jobGroup path] length])
- [[NSWorkspace sharedWorkspace] selectFile:[jobGroup path] inFileViewerRootedAtPath:nil];
-
- row = [selectedRows indexGreaterThanIndex: row];
- }
- }
+ fPendingCount++;
+ }
+ if ([[thisQueueDict objectForKey:@"Status"] intValue] == 3) // cancelled
+ {
+ fCanceledCount++;
+ }
+ i++;
+ }
+
+ /* We should fire up the encoding timer here based on fWorkingCount */
+
+ if (fWorkingCount > 0)
+ {
+ /* we have an encoding job so, lets start the animation timer */
+ [self startAnimatingCurrentWorkingEncodeInQueue];
+ }
+
+ /* Set the queue status field in the queue window */
+ NSMutableString * string;
+ if (fPendingCount == 1)
+ {
+ string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode pending", @"" ), fPendingCount];
+ }
+ else
+ {
+ string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode(s) pending", @"" ), fPendingCount];
+ }
+ [fQueueCountField setStringValue:string];
+
}
-
-//------------------------------------------------------------------------------------
-// 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
-// hblib to cancel the job.
-//------------------------------------------------------------------------------------
-- (IBAction)cancelCurrentJob: (id)sender
+/* This method sets the status string in the queue window
+ * and is called from Controller.mm (fHBController)
+ * instead of running another timer here polling libhb
+ * for encoding status
+ */
+- (void)setQueueStatusString: (NSString *)statusString
{
- [fHBController Cancel:sender];
+[fProgressTextField setStringValue:statusString];
}
//------------------------------------------------------------------------------------
-// Starts or cancels the processing of jobs depending on the current state
+// dealloc
//------------------------------------------------------------------------------------
-- (IBAction)toggleStartCancel: (id)sender
+- (void)dealloc
{
- if (!fHandle) return;
-
- hb_state_t s;
- hb_get_state2 (fHandle, &s);
+ // clear the delegate so that windowWillClose is not attempted
+ if( [[self window] delegate] == self )
+ [[self window] setDelegate:nil];
- 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
+ [fJobGroups release];
- else if (hb_group_count(fHandle) > 0)
- [fHBController doRip];
-}
+ [fSavedExpandedItems release];
+ [fSavedSelectedItems release];
-//------------------------------------------------------------------------------------
-// Toggles the pause/resume state of hblib
-//------------------------------------------------------------------------------------
-- (IBAction)togglePauseResume: (id)sender
-{
- if (!fHandle) return;
-
- hb_state_t s;
- hb_get_state2 (fHandle, &s);
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
- if (s.state == HB_STATE_PAUSED)
- hb_resume (fHandle);
- else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
- hb_pause (fHandle);
+ [super dealloc];
}
-#pragma mark -
-#pragma mark Synchronizing with hblib
-
//------------------------------------------------------------------------------------
-// Notifies HBQueueController that hblib's current job has changed
+// Receive HB handle
//------------------------------------------------------------------------------------
-- (void)currentJobGroupChanged: (hb_job_t *) currentJob
+- (void)setHandle: (hb_handle_t *)handle
{
- if (fCurrentJobGroup && [fCurrentJobGroup status] != HBStatusCanceled)
- [self addCompletedJobGroup: fCurrentJobGroup];
- [self setCurrentJobGroupFromJob: currentJob];
- [self updateCurrentJobDescription];
- [self updateCurrentJobProgress];
- [self showCurrentJobPane: fCurrentJobGroup != nil];
- if (fCurrentJobGroup)
- [self startAnimatingCurrentJobGroupInQueue];
- else
- [self stopAnimatingCurrentJobGroupInQueue];
+ fQueueEncodeLibhb = handle;
}
//------------------------------------------------------------------------------------
-// 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.
+// Receive HBController
//------------------------------------------------------------------------------------
-- (void)hblibWillStop
+- (void)setHBController: (HBController *)controller
{
- if (fCurrentJobGroup)
- [fCurrentJobGroup setStatus: HBStatusCanceled];
+ fHBController = controller;
}
+#pragma mark -
+
//------------------------------------------------------------------------------------
-// Notifies HBQueueController that hblib's job list has been modified
+// Displays and brings the queue window to the front
//------------------------------------------------------------------------------------
-- (void)hblibJobListChanged
+- (IBAction) showQueueWindow: (id)sender
{
- // This message is received from HBController after it has added a job group to
- // hblib's job list. It is also received from self when a job group is deleted by
- // the user.
- [self updateQueueUI];
+ [self showWindow:sender];
+ [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"QueueWindowIsOpen"];
}
+
+
//------------------------------------------------------------------------------------
-// Notifies HBQueueController that hblib's state has changed
+// awakeFromNib
//------------------------------------------------------------------------------------
-- (void)hblibStateChanged: (hb_state_t &)state
+- (void)awakeFromNib
{
- // First check to see if hblib 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 (fLastKnownCurrentJob != hb_current_job(fHandle))
- {
- hb_job_t * currentJob = hb_current_job(fHandle);
- if (!currentJob || currentJob->sequence_id == 0) // start of a new group
- {
- [self currentJobGroupChanged: currentJob];
- [self hblibJobListChanged];
- }
- else
- {
- [self updateCurrentJobDescription];
- [self updateCurrentJobProgress];
- }
+ [self setupToolbar];
- fLastKnownCurrentJob = currentJob;
- }
+ if( ![[self window] setFrameUsingName:@"Queue"] )
+ [[self window] center];
+ [self setWindowFrameAutosaveName:@"Queue"];
+ [[self window] setExcludedFromWindowsMenu:YES];
- switch( state.state )
- {
- case HB_STATE_WORKING:
- {
- [self updateCurrentJobProgress];
- [self startAnimatingCurrentJobGroupInQueue];
- 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_MUXING:
- {
- [self updateCurrentJobProgress];
- break;
- }
- case HB_STATE_PAUSED:
- {
- [self updateCurrentJobProgress];
- [self stopAnimatingCurrentJobGroupInQueue];
- break;
- }
+ // Don't allow autoresizing of main column, else the "delete" column will get
+ // pushed out of view.
+ [fOutlineView setAutoresizesOutlineColumn: NO];
- case HB_STATE_WORKDONE:
- {
- // HB_STATE_WORKDONE means that hblib has finished processing all the jobs
- // in *its* queue. This message is NOT sent as each individual job is
- // completed.
- }
+#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];
+ //[self updateQueueCountField];
}
-#if HB_OUTLINE_METRIC_CONTROLS
-static float spacingWidth = 3.0;
-- (IBAction)imageSpacingChanged: (id)sender;
-{
- spacingWidth = [sender floatValue];
- [fOutlineView setNeedsDisplay: YES];
-}
-- (IBAction)indentChanged: (id)sender
+
+//------------------------------------------------------------------------------------
+// windowWillClose
+//------------------------------------------------------------------------------------
+- (void)windowWillClose:(NSNotification *)aNotification
{
- [fOutlineView setIndentationPerLevel: [sender floatValue]];
- [fOutlineView setNeedsDisplay: YES];
+ [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"QueueWindowIsOpen"];
}
-#endif
-
-#pragma mark -
#pragma mark Toolbar
//------------------------------------------------------------------------------------
@@ -1666,19 +298,19 @@ static float spacingWidth = 3.0;
//------------------------------------------------------------------------------------
- (void)setupToolbar
{
- // Create a new toolbar instance, and attach it to our window
+ // Create a new toolbar instance, and attach it to our window
NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier: HBQueueToolbar] autorelease];
-
- // Set up toolbar properties: Allow customization, give a default display mode, and remember state in user defaults
+
+ // Set up toolbar properties: Allow customization, give a default display mode, and remember state in user defaults
[toolbar setAllowsUserCustomization: YES];
[toolbar setAutosavesConfiguration: YES];
[toolbar setDisplayMode: NSToolbarDisplayModeIconAndLabel];
-
+
// We are the delegate
[toolbar setDelegate: self];
-
- // Attach the toolbar to our window
- [fQueueWindow setToolbar: toolbar];
+
+ // Attach the toolbar to our window
+ [[self window] setToolbar:toolbar];
}
//------------------------------------------------------------------------------------
@@ -1691,43 +323,43 @@ static float spacingWidth = 3.0;
// Required delegate method: Given an item identifier, this method returns an item.
// The toolbar will use this method to obtain toolbar items that can be displayed
// in the customization sheet, or in the toolbar itself.
-
+
NSToolbarItem *toolbarItem = nil;
-
+
if ([itemIdentifier isEqual: HBQueueStartCancelToolbarIdentifier])
{
toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
-
- // Set the text label to be displayed in the toolbar and customization palette
+
+ // Set the text label to be displayed in the toolbar and customization palette
[toolbarItem setLabel: @"Start"];
[toolbarItem setPaletteLabel: @"Start/Cancel"];
-
+
// Set up a reasonable tooltip, and image
[toolbarItem setToolTip: @"Start Encoding"];
[toolbarItem setImage: [NSImage imageNamed: @"Play"]];
-
- // Tell the item what message to send when it is clicked
+
+ // Tell the item what message to send when it is clicked
[toolbarItem setTarget: self];
[toolbarItem setAction: @selector(toggleStartCancel:)];
}
-
+
if ([itemIdentifier isEqual: HBQueuePauseResumeToolbarIdentifier])
{
toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
-
- // Set the text label to be displayed in the toolbar and customization palette
+
+ // Set the text label to be displayed in the toolbar and customization palette
[toolbarItem setLabel: @"Pause"];
[toolbarItem setPaletteLabel: @"Pause/Resume"];
-
+
// Set up a reasonable tooltip, and image
[toolbarItem setToolTip: @"Pause Encoding"];
[toolbarItem setImage: [NSImage imageNamed: @"Pause"]];
-
- // Tell the item what message to send when it is clicked
+
+ // Tell the item what message to send when it is clicked
[toolbarItem setTarget: self];
[toolbarItem setAction: @selector(togglePauseResume:)];
}
-
+
return toolbarItem;
}
@@ -1738,7 +370,7 @@ static float spacingWidth = 3.0;
{
// Required delegate method: Returns the ordered list of items to be shown in the
// toolbar by default.
-
+
return [NSArray arrayWithObjects:
HBQueueStartCancelToolbarIdentifier,
HBQueuePauseResumeToolbarIdentifier,
@@ -1772,12 +404,12 @@ static float 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])
{
@@ -1789,7 +421,7 @@ static float spacingWidth = 3.0;
[toolbarItem setToolTip: @"Stop Encoding"];
}
- else if (hb_count(fHandle) > 0)
+ else if (fPendingCount > 0)
{
enable = YES;
[toolbarItem setImage:[NSImage imageNamed: @"Play"]];
@@ -1805,7 +437,7 @@ static float spacingWidth = 3.0;
[toolbarItem setToolTip: @"Start Encoding"];
}
}
-
+
if ([[toolbarItem itemIdentifier] isEqual: HBQueuePauseResumeToolbarIdentifier])
{
if (s.state == HB_STATE_PAUSED)
@@ -1815,7 +447,7 @@ static float spacingWidth = 3.0;
[toolbarItem setLabel: @"Resume"];
[toolbarItem setToolTip: @"Resume Encoding"];
}
-
+
else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
{
enable = YES;
@@ -1831,66 +463,209 @@ static float spacingWidth = 3.0;
[toolbarItem setToolTip: @"Pause Encoding"];
}
}
-
+
return enable;
}
#pragma mark -
+
+#pragma mark Queue Item Controls
//------------------------------------------------------------------------------------
-// awakeFromNib
+// Delete encodes from the queue window and accompanying array
+// Also handling first cancelling the encode if in fact its currently encoding.
//------------------------------------------------------------------------------------
-- (void)awakeFromNib
+- (IBAction)removeSelectedQueueItem: (id)sender
{
- [self setupToolbar];
+ NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes];
+ int row = [selectedRows firstIndex];
+ /* if this is a currently encoding job, we need to be sure to alert the user,
+ * to let them decide to cancel it first, then if they do, we can come back and
+ * remove it */
- if (![fQueueWindow setFrameUsingName:@"Queue"])
- [fQueueWindow center];
- [fQueueWindow setFrameAutosaveName: @"Queue"];
- [fQueueWindow setExcludedFromWindowsMenu:YES];
+ if ([[[fJobGroups objectAtIndex:row] objectForKey:@"Status"] intValue] == 1)
+ {
+ /* We pause the encode here so that it doesn't finish right after and then
+ * screw up the sync while the window is open
+ */
+ [fHBController Pause:NULL];
+ NSString * alertTitle = [NSString stringWithFormat:NSLocalizedString(@"Stop This Encode and Remove It ?", nil)];
+ // Which window to attach the sheet to?
+ NSWindow * docWindow;
+ if ([sender respondsToSelector: @selector(window)])
+ docWindow = [sender window];
+
+
+ NSBeginCriticalAlertSheet(
+ alertTitle,
+ NSLocalizedString(@"Keep Encoding", nil),
+ nil,
+ NSLocalizedString(@"Stop Encoding and Delete", nil),
+ docWindow, self,
+ nil, @selector(didDimissCancelCurrentJob:returnCode:contextInfo:), nil,
+ NSLocalizedString(@"Your movie will be lost if you don't continue encoding.", nil));
+
+ // didDimissCancelCurrentJob:returnCode:contextInfo: will be called when the dialog is dismissed
+ }
+ else
+ {
+ /* since we are not a currently encoding item, we can just be cancelled */
+ [fHBController removeQueueFileItem:row];
+ }
+}
-#if HB_QUEUE_DRAGGING
- [fOutlineView registerForDraggedTypes: [NSArray arrayWithObject:HBQueuePboardType] ];
- [fOutlineView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES];
- [fOutlineView setVerticalMotionCanBeginDrag: YES];
-#endif
+- (void) didDimissCancelCurrentJob: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo
+{
+ /* We resume encoding and perform the appropriate actions
+ * Note: Pause: is a toggle type method based on hb's current
+ * state, if it paused, it will resume encoding and vice versa.
+ * In this case, we are paused from the calling window, so calling
+ * [fHBController Pause:NULL]; Again will resume encoding
+ */
+ [fHBController Pause:NULL];
+ if (returnCode == NSAlertOtherReturn)
+ {
+ /* We need to save the currently encoding item number first */
+ int encodingItemToRemove = fEncodingQueueItem;
+ /* Since we are encoding, we need to let fHBController Cancel this job
+ * upon which it will move to the next one if there is one
+ */
+ [fHBController doCancelCurrentJob];
+ /* Now, we can go ahead and remove the job we just cancelled since
+ * we have its item number from above
+ */
+ [fHBController removeQueueFileItem:encodingItemToRemove];
+ }
+
+}
- // Don't allow autoresizing of main column, else the "delete" column will get
- // pushed out of view.
- [fOutlineView setAutoresizesOutlineColumn: NO];
+//------------------------------------------------------------------------------------
+// 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_OUTLINE_METRIC_CONTROLS
- [fIndentation setHidden: NO];
- [fSpacing setHidden: NO];
- [fIndentation setIntValue:[fOutlineView indentationPerLevel]]; // debug
- [fSpacing setIntValue:3]; // debug
-#endif
+ row = [selectedRows indexGreaterThanIndex: row];
+ }
+ }
+}
- // Show/hide UI elements
- fCurrentJobPaneShown = YES; // it's shown in the nib
- [self showCurrentJobPane:NO];
+
+//------------------------------------------------------------------------------------
+// Starts or cancels the processing of jobs depending on the current state
+//------------------------------------------------------------------------------------
+- (IBAction)toggleStartCancel: (id)sender
+{
+ if (!fQueueEncodeLibhb) return;
+
+ 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
+
+ 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
+
+
+
+
+//------------------------------------------------------------------------------------
+// Starts animating the job icon of the currently processing job in the queue outline
+// view.
+//------------------------------------------------------------------------------------
+- (void) startAnimatingCurrentWorkingEncodeInQueue
+{
+ 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];
+ }
}
-
//------------------------------------------------------------------------------------
-// windowWillClose
+// Stops animating the job icon of the currently processing job in the queue outline
+// view.
//------------------------------------------------------------------------------------
-- (void)windowWillClose:(NSNotification *)aNotification
+- (void) stopAnimatingCurrentJobGroupInQueue
{
- [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"QueueWindowIsOpen"];
+ if (fAnimationTimer && [fAnimationTimer isValid])
+ {
+ [fAnimationTimer invalidate];
+ [fAnimationTimer release];
+ fAnimationTimer = nil;
+ }
}
+
#pragma mark -
-- (void)moveObjectsInArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(unsigned)insertIndex
+- (void)moveObjectsInArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex
{
- unsigned index = [indexSet lastIndex];
- unsigned aboveInsertIndexCount = 0;
-
+ NSUInteger index = [indexSet lastIndex];
+ NSUInteger aboveInsertIndexCount = 0;
+
while (index != NSNotFound)
{
- unsigned removeIndex;
-
+ NSUInteger removeIndex;
+
if (index >= insertIndex)
{
removeIndex = index + aboveInsertIndexCount;
@@ -1901,30 +676,32 @@ static float spacingWidth = 3.0;
removeIndex = index;
insertIndex--;
}
-
+
id object = [[array objectAtIndex:removeIndex] retain];
[array removeObjectAtIndex:removeIndex];
[array insertObject:object atIndex:insertIndex];
[object release];
-
+
index = [indexSet indexLessThanIndex:index];
}
}
+
#pragma mark -
#pragma mark NSOutlineView delegate
-- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
+
+- (id)outlineView:(NSOutlineView *)fOutlineView child:(NSInteger)index ofItem:(id)item
{
if (item == nil)
return [fJobGroups objectAtIndex:index];
-
+
// We are only one level deep, so we can't be asked about children
NSAssert (NO, @"HBQueueController outlineView:child:ofItem: can't handle nested items.");
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.
@@ -1935,15 +712,10 @@ static float spacingWidth = 3.0;
{
// 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*)outlineView isDragging];
}
-- (int)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.
@@ -1956,18 +728,18 @@ static float spacingWidth = 3.0;
- (void)outlineViewItemDidCollapse:(NSNotification *)notification
{
id item = [[notification userInfo] objectForKey:@"NSObject"];
- int row = [fOutlineView rowForItem:item];
+ NSInteger row = [fOutlineView rowForItem:item];
[fOutlineView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row,1)]];
}
- (void)outlineViewItemDidExpand:(NSNotification *)notification
{
id item = [[notification userInfo] objectForKey:@"NSObject"];
- int row = [fOutlineView rowForItem:item];
+ NSInteger row = [fOutlineView rowForItem:item];
[fOutlineView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row,1)]];
}
-- (float)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
+- (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
{
if ([outlineView isItemExpanded: item])
{
@@ -1977,70 +749,471 @@ static float 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];
-
- float width = [[outlineView tableColumnWithIdentifier: @"desc"] width];
- // Column width is NOT what is ultimately used
- width -= 47; // 26 pixels for disclosure triangle, 20 for icon, 1 for intercell spacing
+ // if ([outlineView inLiveResize] && [item lastDescriptionHeight] > 0)
+ // return [item lastDescriptionHeight];
+
+ // 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
+
+ // CGFloat height = [item heightOfDescriptionForWidth: width];
+ // return height;
- float height = [item heightOfDescriptionForWidth: width withHBHandle: fHandle];
- 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.
-
+ // 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 attributedDescriptionWithHBHandle: fHandle];
+ {
+ /* 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];
+
+ /* lets add the output file name to the title string here */
+ NSString * outputFilenameString = [[item objectForKey:@"DestinationPath"] lastPathComponent];
+
+ summaryInfo = [NSString stringWithFormat: @" (%@, %@, %@) -> %@", titleString, chapterString, passesString, outputFilenameString];
+
+ [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:@"Audio1TrackDRCSlider"] floatValue] > 1.00)
+ {
+ audioDetail1 = [NSString stringWithFormat:@"%@, DRC: %@",audioDetail1,[item objectForKey:@"Audio1TrackDRCSlider"]];
+ }
+ else
+ {
+ audioDetail1 = [NSString stringWithFormat:@"%@, DRC: Off",audioDetail1];
+ }
+ }
+
+ 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:@"Audio2TrackDRCSlider"] floatValue] > 1.00)
+ {
+ audioDetail2 = [NSString stringWithFormat:@"%@, DRC: %@",audioDetail2,[item objectForKey:@"Audio2TrackDRCSlider"]];
+ }
+ else
+ {
+ audioDetail2 = [NSString stringWithFormat:@"%@, DRC: Off",audioDetail2];
+ }
+ }
+
+ 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:@"Audio3TrackDRCSlider"] floatValue] > 1.00)
+ {
+ audioDetail3 = [NSString stringWithFormat:@"%@, DRC: %@",audioDetail3,[item objectForKey:@"Audio3TrackDRCSlider"]];
+ }
+ else
+ {
+ audioDetail3 = [NSString stringWithFormat:@"%@, DRC: Off",audioDetail3];
+ }
+ }
+
+ 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"]];
+
+ if ([[item objectForKey:@"Audio4TrackDRCSlider"] floatValue] > 1.00)
+ {
+ audioDetail4 = [NSString stringWithFormat:@"%@, DRC: %@",audioDetail4,[item objectForKey:@"Audio4TrackDRCSlider"]];
+ }
+ else
+ {
+ audioDetail4 = [NSString stringWithFormat:@"%@, DRC: Off",audioDetail4];
+ }
+ }
+
+ 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:@" - Large file size"];
+ }
+ if( [[item objectForKey:@"Mp4HttpOptimize"] intValue] == 1)
+ {
+ mp4OptsPresent = YES;
+ MP4Opts = [MP4Opts stringByAppendingString:@" - Web optimized"];
+ }
+
+ if( [[item objectForKey:@"Mp4iPodCompatible"] intValue] == 1)
+ {
+ mp4OptsPresent = YES;
+ MP4Opts = [MP4Opts stringByAppendingString:@" - iPod 5G support "];
+ }
+ 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 Picture Filters */
+
+ 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:@" - Deinterlace: Fast "];
+ }
+ else if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 2)
+ {
+ pictureFilters = [pictureFilters stringByAppendingString:@" - Deinterlace: Slow "];
+ }
+ else if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 3)
+ {
+ pictureFilters = [pictureFilters stringByAppendingString:@" - Deinterlace: 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] != 0)
+ {
+ pictureFiltersPresent = YES;
+ pictureFilters = [pictureFilters stringByAppendingString: [NSString stringWithFormat:@" - Deblock (pp7) (%d) ",[[item objectForKey:@"PictureDeblock"] intValue]]];
+ }
+ 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"]];
+
+ /* for framerate look to see if we are using vfr detelecine */
+ if ([[item objectForKey:@"JobIndexVideoFramerate"] intValue] == 0)
+ {
+ if ([[item objectForKey:@"PictureDetelecine"] intValue] == 1)
+ {
+ /* we are using same as source with vfr detelecine */
+ videoInfo = [NSString stringWithFormat:@"%@ Framerate: Same as source (vfr detelecine)", videoInfo];
+ }
+ else
+ {
+ /* we are using a variable framerate without dropping frames */
+ videoInfo = [NSString stringWithFormat:@"%@ Framerate: Same as source (variable)", videoInfo];
+ }
+ }
+ else
+ {
+ /* we have a specified, constant framerate */
+ videoInfo = [NSString stringWithFormat:@"%@ Framerate: %@ (constant framerate)", videoInfo ,[item objectForKey:@"VideoFramerate"]];
+ }
+
+ if ([[item objectForKey:@"VideoQualityType"] intValue] == 0)// Target Size MB
+ {
+ videoInfo = [NSString stringWithFormat:@"%@ Target Size: %@(MB) (%d(kbps) abr)", videoInfo ,[item objectForKey:@"VideoTargetSize"],[[item objectForKey:@"VideoAvgBitrate"] intValue]];
+ }
+ 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];
+
+ return finalString;
+ }
else if ([[tableColumn identifier] isEqualToString:@"icon"])
{
- switch ([(HBJobGroup*)item status])
+ if ([[item objectForKey:@"Status"] intValue] == 0)
{
- case HBStatusComplete:
- 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:@"EncodeComplete"];
}
+ else if ([[item objectForKey:@"Status"] intValue] == 1)
+ {
+ 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.
+
+
+ // 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.
// 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] == HBStatusComplete)
+ if ([[item objectForKey:@"Status"] intValue] == 0)
{
- [cell setAction: @selector(revealSelectedJobGroups:)];
+ [cell setAction: @selector(revealSelectedQueueItem:)];
if (highlighted)
{
[cell setImage:[NSImage imageNamed:@"RevealHighlight"]];
@@ -2051,7 +1224,7 @@ static float spacingWidth = 3.0;
}
else
{
- [cell setAction: @selector(removeSelectedJobGroups:)];
+ [cell setAction: @selector(removeSelectedQueueItem:)];
if (highlighted)
{
[cell setImage:[NSImage imageNamed:@"DeleteHighlight"]];
@@ -2080,62 +1253,65 @@ static float 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.
- NSEnumerator * e = [items objectEnumerator];
- HBJobGroup * group;
- while ( (group = [e nextObject]) )
- {
- if ([group status] != HBStatusPending)
- return NO;
- }
-
+ // Dragging is only allowed of the pending items.
+ if ([[[fJobGroups objectAtIndex:[outlineView selectedRow]] objectForKey:@"Status"] intValue] != 2) // 2 is pending
+ {
+ 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
-- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(int)index
+
+/* This method is used to validate the drops. */
+- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(NSInteger)index
{
- // Don't allow dropping ONTO an item since they can't really contain any children.
+ // Don't allow dropping ONTO an item since they can't really contain any children.
BOOL isOnDropTypeProposal = index == NSOutlineViewDropOnItemIndex;
if (isOnDropTypeProposal)
+ {
return NSDragOperationNone;
-
- // Don't allow dropping INTO an item since they can't really contain any children.
- if (item != nil)
- {
- index = [fOutlineView rowForItem: item] + 1;
- item = nil;
+ }
+
+ // Don't allow dropping INTO an item since they can't really contain any children.
+ if (item != nil)
+ {
+ index = [fOutlineView rowForItem: item] + 1;
+ item = nil;
+ }
+
+ // 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);
}
-
- // Prevent dragging into the completed or current job.
- int firstPendingIndex = [fCompleted count];
- if (fCurrentJobGroup)
- firstPendingIndex++;
- index = MAX (index, firstPendingIndex);
-
- [outlineView setDropItem:item dropChildIndex:index];
+
+ [outlineView setDropItem:item dropChildIndex:index];
return NSDragOperationGeneric;
}
-#endif
-#if HB_QUEUE_DRAGGING
-- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id )info item:(id)item childIndex:(int)index
+
+
+- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id )info item:(id)item childIndex:(NSInteger)index
{
- NSMutableIndexSet *moveItems = [NSMutableIndexSet indexSet];
+ NSMutableIndexSet *moveItems = [NSMutableIndexSet indexSet];
id obj;
NSEnumerator *enumerator = [fDraggedNodes objectEnumerator];
@@ -2143,16 +1319,13 @@ static float spacingWidth = 3.0;
{
[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
@end