-@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++;
- }
-}
-
-/**
- * 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 -
-
-//------------------------------------------------------------------------------------
-// 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 -
-
-//------------------------------------------------------------------------------------
-// HBJobGroup
-//------------------------------------------------------------------------------------
-
-@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];
- }
- return self;
-}
-
-- (void) dealloc
-{
- [fJobs release];
- [super dealloc];
-}