]> granicus.if.org Git - handbrake/commitdiff
MacGui: improve the job description in the queue.
authorDamiano Galassi <damiog@gmail.com>
Fri, 17 Mar 2017 14:00:26 +0000 (15:00 +0100)
committerDamiano Galassi <damiog@gmail.com>
Fri, 17 Mar 2017 14:00:26 +0000 (15:00 +0100)
macosx/HBFilters+UIAdditions.h
macosx/HBFilters+UIAdditions.m
macosx/HBJob+UIAdditions.m

index 6600e7930ba3c056a950874297123e8a866dfdc0..9e70e139d8c5131fb6663afe239cf0ece9778099 100644 (file)
 @property (nonatomic, readonly) NSArray *denoisePresets;
 @property (nonatomic, readonly) NSArray *denoiseTunes;
 
-/**
- *  A textual summary of the filters settings.
- */
-@property (nonatomic, readonly) NSString *summary;
-
 @end
 
 /**
index 8141881ccbcc6806d2a2af7071d4ced708b43784..1ee7cd62837aae871aac4b159b002230c66652e2 100644 (file)
@@ -359,84 +359,4 @@ static NSDictionary *denoiseTypesDict = nil;
     }
 }
 
-- (NSString *)summary
-{
-    NSMutableString *summary = [NSMutableString string];
-
-    // Detelecine
-    if (![self.detelecine isEqualToString:@"off"])
-    {
-        if ([self.detelecine isEqualToString:@"custom"])
-        {
-            [summary appendFormat:@" - Detelecine (%@)", self.detelecineCustomString];
-        }
-        else
-        {
-            [summary appendFormat:@" - Detelecine (%@)", [[[HBFilters detelecinePresetsDict] allKeysForObject:self.detelecine] firstObject]];
-        }
-    }
-    else if (![self.deinterlace isEqualToString:@"off"])
-    {
-        // Deinterlace or Decomb
-        NSString *type =  [[[HBFilters deinterlaceTypesDict] allKeysForObject:self.deinterlace] firstObject];
-
-        if ([self.deinterlacePreset isEqualToString:@"custom"])
-        {
-            [summary appendFormat:@" - %@ (%@)", type, self.deinterlaceCustomString];
-        }
-        else
-        {
-            if ([self.deinterlace isEqualToString:@"decomb"])
-            {
-                [summary appendFormat:@" - %@ (%@)", type, [[[HBFilters decombPresetsDict] allKeysForObject:self.deinterlacePreset] firstObject]];
-            }
-            else if ([self.deinterlace isEqualToString:@"deinterlace"])
-            {
-                [summary appendFormat:@" - %@ (%@)", type, [[[HBFilters deinterlacePresetsDict] allKeysForObject:self.deinterlacePreset] firstObject]];
-            }
-        }
-    }
-
-    // Deblock
-    if (self.deblock > 0)
-    {
-        [summary appendFormat:@" - Deblock (%d)", self.deblock];
-    }
-
-    // Denoise
-    if (![self.denoise isEqualToString:@"off"])
-    {
-        [summary appendFormat:@" - Denoise (%@", [[[HBFilters denoiseTypesDict] allKeysForObject:self.denoise] firstObject]];
-        if (![self.denoisePreset isEqualToString:@"custom"])
-        {
-            [summary appendFormat:@", %@", [[[HBFilters denoisePresetDict] allKeysForObject:self.denoisePreset] firstObject]];
-
-            if ([self.denoise isEqualToString:@"nlmeans"])
-            {
-                [summary appendFormat:@", %@", [[[HBFilters nlmeansTunesDict] allKeysForObject:self.denoiseTune] firstObject]];
-            }
-        }
-        else
-        {
-            [summary appendFormat:@", %@", self.denoiseCustomString];
-        }
-
-        [summary appendString:@")"];
-
-    }
-
-    // Grayscale
-    if (self.grayscale)
-    {
-        [summary appendString:@" - Grayscale"];
-    }
-    
-    if ([summary hasPrefix:@" - "])
-    {
-        [summary deleteCharactersInRange:NSMakeRange(0, 3)];
-    }
-    
-    return [NSString stringWithString:summary];
-}
-
 @end
index 5edf48a9b6538b3d3c3b7206f485ec6f99905142..de7ac410f0e2229948d23952497d75ef85e839a9 100644 (file)
@@ -86,16 +86,20 @@ static NSDictionary            *shortHeightAttr;
     return [containers copy];
 }
 
+#pragma mark - Attributed description
+
 - (void)initStyles
 {
     if (!ps)
     {
         // Attributes
         ps = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
-        [ps setHeadIndent: 40.0];
-        [ps setParagraphSpacing: 1.0];
-        [ps setTabStops:@[]];    // clear all tabs
-        [ps addTabStop: [[NSTextTab alloc] initWithType: NSLeftTabStopType location: 20.0]];
+        ps.headIndent = 88.0;
+        ps.paragraphSpacing = 1.0;
+        ps.tabStops = @[[[NSTextTab alloc] initWithType:
+                          NSRightTabStopType location: 88],
+                         [[NSTextTab alloc] initWithType:
+                          NSLeftTabStopType location: 90]];
 
         detailAttr = @{NSFontAttributeName: [NSFont systemFontOfSize:[NSFont smallSystemFontSize]],
                         NSParagraphStyleAttributeName: ps};
@@ -110,385 +114,477 @@ static NSDictionary            *shortHeightAttr;
     }
 }
 
-- (NSAttributedString *)attributedDescription
+- (NSAttributedString *)titleAttributedDescription
 {
-    // Below should be put into a separate method but I am way too f'ing lazy right now
-    NSMutableAttributedString *finalString = [[NSMutableAttributedString alloc] initWithString: @""];
+    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
 
-    [self initStyles];
+    // Job name
+    [attrString appendString:self.description withAttributes:titleAttr];
 
-    @autoreleasepool
+    // Range type
+    NSString *startStopString = @"";
+    if (self.range.type == HBRangeTypeChapters)
     {
-        // First line, we should strip the destination path and just show the file name and add the title num and chapters (if any)
-        NSString *summaryInfo;
-
-        NSString *titleString = [NSString stringWithFormat:@"Title %d", self.titleIdx];
+        startStopString = (self.range.chapterStart == self.range.chapterStop) ?
+        [NSString stringWithFormat:@"Chapter %d", self.range.chapterStart + 1] :
+        [NSString stringWithFormat:@"Chapters %d through %d", self.range.chapterStart + 1, self.range.chapterStop + 1];
+    }
+    else if (self.range.type == HBRangeTypeSeconds)
+    {
+        startStopString = [NSString stringWithFormat:@"Seconds %d through %d", self.range.secondsStart, self.range.secondsStop];
+    }
+    else if (self.range.type == HBRangeTypeFrames)
+    {
+        startStopString = [NSString stringWithFormat:@"Frames %d through %d", self.range.frameStart, self.range.frameStop];
+    }
 
-        NSString *startStopString = @"";
-        if (self.range.type == HBRangeTypeChapters)
+    NSMutableString *passesString = [NSMutableString string];
+    // check to see if our first subtitle track is Foreign Language Search, in which case there is an in depth scan
+    if (self.subtitles.tracks.firstObject.sourceTrackIdx == 1)
+    {
+        [passesString appendString:@"1 Foreign Language Search Pass - "];
+    }
+    if (self.video.qualityType != 1 && self.video.twoPass == YES)
+    {
+        if (self.video.turboTwoPass == YES)
         {
-            // Start Stop is chapters
-            startStopString = (self.range.chapterStart == self.range.chapterStop) ?
-            [NSString stringWithFormat:@"Chapter %d", self.range.chapterStart + 1] :
-            [NSString stringWithFormat:@"Chapters %d through %d", self.range.chapterStart + 1, self.range.chapterStop + 1];
+            [passesString appendString:@"2 Video Passes First Turbo"];
         }
-        else if (self.range.type == HBRangeTypeSeconds)
+        else
         {
-            // Start Stop is seconds
-            startStopString = [NSString stringWithFormat:@"Seconds %d through %d", self.range.secondsStart, self.range.secondsStop];
+            [passesString appendString:@"2 Video Passes"];
         }
-        else if (self.range.type == HBRangeTypeFrames)
+    }
+
+    if (passesString.length)
+    {
+        [attrString appendString:[NSString stringWithFormat:@" (Title %d, %@, %@) ▸ %@\n",
+                                  self.titleIdx, startStopString, passesString, self.outputFileName]
+                  withAttributes:detailAttr];
+    }
+    else
+    {
+        [attrString appendString:[NSString stringWithFormat:@" (Title %d, %@) ▸ %@\n",
+                                  self.titleIdx, startStopString, self.outputFileName]
+                  withAttributes:detailAttr];
+    }
+
+    return attrString;
+}
+
+- (NSAttributedString *)presetAttributedDescription
+{
+    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
+
+    [attrString appendString:@"\tPreset: " withAttributes:detailBoldAttr];
+    [attrString appendString:@"\t" withAttributes:detailAttr];
+    [attrString appendString:self.presetName withAttributes:detailAttr];
+    [attrString appendString:@"\n" withAttributes:detailAttr];
+
+    return attrString;
+}
+
+- (NSAttributedString *)formatAttributedDescription
+{
+    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
+    NSMutableString *options = [NSMutableString string];
+
+    [options appendString:@(hb_container_get_name(self.container))];
+
+    if (self.chaptersEnabled)
+    {
+        [options appendString:@", Chapter Markers"];
+    }
+
+    if ((self.container & HB_MUX_MASK_MP4) && self.mp4HttpOptimize)
+    {
+        [options appendString:@", Web optimized"];
+    }
+
+    if ((self.container & HB_MUX_MASK_MP4)  && self.mp4iPodCompatible)
+    {
+        [options appendString:@", iPod 5G support"];
+    }
+
+    if ([options hasPrefix:@", "])
+    {
+        [options deleteCharactersInRange:NSMakeRange(0, 2)];
+    }
+
+    [attrString appendString:@"\tFormat: \t" withAttributes:detailBoldAttr];
+    [attrString appendString:options withAttributes:detailAttr];
+    [attrString appendString:@"\n" withAttributes:detailAttr];
+
+    return attrString;
+}
+
+- (NSAttributedString *)destinationAttributedDescription
+{
+    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
+
+    [attrString appendString:@"\tDestination: "             withAttributes:detailBoldAttr];
+    [attrString appendString:@"\t"                          withAttributes:detailAttr];
+    [attrString appendString:self.completeOutputURL.path    withAttributes:detailAttr];
+    [attrString appendString:@"\n"                          withAttributes:detailAttr];
+
+    return attrString;
+}
+
+- (NSAttributedString *)pictureAttributedDescription
+{
+    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
+
+    NSString *pictureInfo = self.picture.summary;
+    if (self.picture.keepDisplayAspect)
+    {
+        pictureInfo = [pictureInfo stringByAppendingString:@" Keep Aspect Ratio"];
+    }
+    [attrString appendString:@"\tPicture: " withAttributes:detailBoldAttr];
+    [attrString appendString:@"\t"          withAttributes:detailAttr];
+    [attrString appendString:pictureInfo    withAttributes:detailAttr];
+    [attrString appendString:@"\n"          withAttributes:detailAttr];
+
+    return attrString;
+}
+
+- (NSAttributedString *)filtersAttributedDescription
+{
+    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
+
+    NSMutableString *summary = [NSMutableString string];
+    HBFilters *filters = self.filters;
+
+    // Detelecine
+    if (![filters.detelecine isEqualToString:@"off"])
+    {
+        if ([filters.detelecine isEqualToString:@"custom"])
         {
-            // Start Stop is Frames
-            startStopString = [NSString stringWithFormat:@"Frames %d through %d", self.range.frameStart, self.range.frameStop];
+            [summary appendFormat:@", Detelecine (%@)", filters.detelecineCustomString];
         }
-        NSString *passesString = @"";
-        // check to see if our first subtitle track is Foreign Language Search, in which case there is an in depth scan
-        if (self.subtitles.tracks.firstObject.sourceTrackIdx == 1)
+        else
         {
-            passesString = [passesString stringByAppendingString:@"1 Foreign Language Search Pass - "];
+            [summary appendFormat:@", Detelecine (%@)", [[[HBFilters detelecinePresetsDict] allKeysForObject:filters.detelecine] firstObject]];
         }
-        if (self.video.qualityType == 1 || self.video.twoPass == NO)
+    }
+    else if (![filters.deinterlace isEqualToString:@"off"])
+    {
+        // Deinterlace or Decomb
+        NSString *type =  [[[HBFilters deinterlaceTypesDict] allKeysForObject:filters.deinterlace] firstObject];
+
+        if ([filters.deinterlacePreset isEqualToString:@"custom"])
         {
-            passesString = [passesString stringByAppendingString:@"1 Video Pass"];
+            [summary appendFormat:@", %@ (%@)", type, filters.deinterlaceCustomString];
         }
         else
         {
-            if (self.video.turboTwoPass == YES)
+            if ([filters.deinterlace isEqualToString:@"decomb"])
             {
-                passesString = [passesString stringByAppendingString:@"2 Video Passes First Turbo"];
+                [summary appendFormat:@", %@ (%@)", type, [[[HBFilters decombPresetsDict] allKeysForObject:filters.deinterlacePreset] firstObject]];
             }
-            else
+            else if ([filters.deinterlace isEqualToString:@"deinterlace"])
             {
-                passesString = [passesString stringByAppendingString:@"2 Video Passes"];
+                [summary appendFormat:@", %@ (%@)", type, [[[HBFilters deinterlacePresetsDict] allKeysForObject:filters.deinterlacePreset] firstObject]];
             }
         }
+    }
 
-        [finalString appendString:[NSString stringWithFormat:@"%@", self.description] withAttributes:titleAttr];
+    // Deblock
+    if (filters.deblock > 0)
+    {
+        [summary appendFormat:@", Deblock (%d)", filters.deblock];
+    }
 
-        // lets add the output file name to the title string here
-        NSString *outputFilenameString = self.outputFileName;
+    // Denoise
+    if (![filters.denoise isEqualToString:@"off"])
+    {
+        [summary appendFormat:@", Denoise (%@", [[[HBFilters denoiseTypesDict] allKeysForObject:filters.denoise] firstObject]];
+        if (![filters.denoisePreset isEqualToString:@"custom"])
+        {
+            [summary appendFormat:@", %@", [[[HBFilters denoisePresetDict] allKeysForObject:filters.denoisePreset] firstObject]];
 
-        summaryInfo = [NSString stringWithFormat: @" (%@, %@, %@) -> %@", titleString, startStopString, passesString, outputFilenameString];
+            if ([filters.denoise isEqualToString:@"nlmeans"])
+            {
+                [summary appendFormat:@", %@", [[[HBFilters nlmeansTunesDict] allKeysForObject:filters.denoiseTune] firstObject]];
+            }
+        }
+        else
+        {
+            [summary appendFormat:@", %@", filters.denoiseCustomString];
+        }
 
-        [finalString appendString:[NSString stringWithFormat:@"%@\n", summaryInfo] withAttributes:detailAttr];
+        [summary appendString:@")"];
 
-        // 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", self.presetName] withAttributes:detailAttr];
+    // Grayscale
+    if (filters.grayscale)
+    {
+        [summary appendString:@", Grayscale"];
+    }
 
-        // Third Line  (Format Summary)
-        NSString *audioCodecSummary = @"";     //      This seems to be set by the last track we have available...
-        // Lets also get our audio track detail since we are going through the logic for use later
+    if ([summary hasPrefix:@", "])
+    {
+        [summary deleteCharactersInRange:NSMakeRange(0, 2)];
+    }
 
-        NSMutableArray *audioDetails = [NSMutableArray array];
-        BOOL autoPassthruPresent = NO;
+    // Optional String for Picture Filters
+    if (summary.length)
+    {
+        [attrString appendString:@"\tFilters: " withAttributes:detailBoldAttr];
+        [attrString appendString:@"\t"          withAttributes:detailAttr];
+        [attrString appendString:summary        withAttributes:detailAttr];
+        [attrString appendString:@"\n"          withAttributes:detailAttr];
+    }
+    
+    return attrString;
+}
 
-        for (HBAudioTrack *audioTrack in self.audio.tracks)
-        {
-            if (audioTrack.isEnabled)
-            {
-                const char *codecName = hb_audio_encoder_get_name(audioTrack.encoder);
-                const char *mixdownName = hb_mixdown_get_name(audioTrack.mixdown);
-                const char *sampleRateName = audioTrack.sampleRate ? hb_audio_samplerate_get_name(audioTrack.sampleRate) : "Auto";
-
-                audioCodecSummary = [NSString stringWithFormat: @"%@", @(codecName)];
-                NSString *detailString = [NSString stringWithFormat: @"%@ Encoder: %@, Mixdown: %@, SampleRate: %@ khz, Bitrate: %d kbps, DRC: %@, Gain: %@",
-                                          self.audio.sourceTracks[audioTrack.sourceTrackIdx][keyAudioTrackName],
-                                          @(codecName),
-                                          @(mixdownName),
-                                          @(sampleRateName),
-                                          audioTrack.bitRate,
-                                          (0.0 < audioTrack.drc) ? @(audioTrack.drc) : NSLocalizedString(@"Off", nil),
-                                          (0.0 != audioTrack.gain) ? @(audioTrack.gain) : NSLocalizedString(@"Off", nil)
-                                          ];
-                [audioDetails addObject: detailString];
-                // check if we have an Auto Passthru output track
-                if ([@(codecName) isEqualToString: @"Auto Passthru"])
-                {
-                    autoPassthruPresent = YES;
-                }
-            }
-        }
+- (NSAttributedString *)videoAttributedDescription
+{
+    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
+    NSMutableString *videoInfo = [NSMutableString string];
 
-        NSString *jobFormatInfo;
-        if (self.chaptersEnabled)
-            jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video  %@ Audio, Chapter Markers\n",
-                             @(hb_container_get_name(self.container)), @(hb_video_encoder_get_name(self.video.encoder)), audioCodecSummary];
-        else
-            jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video  %@ Audio\n",
-                             @(hb_container_get_name(self.container)), @(hb_video_encoder_get_name(self.video.encoder)), audioCodecSummary];
+    [videoInfo appendFormat:@"Encoder: %@, ", @(hb_video_encoder_get_name(self.video.encoder))];
 
-        [finalString appendString: @"Format: " withAttributes:detailBoldAttr];
-        [finalString appendString: jobFormatInfo withAttributes:detailAttr];
+    [videoInfo appendString:@"Framerate: "];
 
-        // Optional String for muxer options
-        NSMutableString *containerOptions = [NSMutableString stringWithString:@""];
-        if ((self.container & HB_MUX_MASK_MP4) && self.mp4HttpOptimize)
+    if (self.video.frameRate == 0)
+    {
+        if (self.video.frameRateMode == 0)
         {
-            [containerOptions appendString:@" - Web optimized"];
+            // we are using same as source with vfr
+            [videoInfo appendFormat:@"Same as source (variable)"];
         }
-        if ((self.container & HB_MUX_MASK_MP4)  && self.mp4iPodCompatible)
+        else
         {
-            [containerOptions appendString:@" - iPod 5G support"];
+            [videoInfo appendFormat:@"Same as source (constant)"];
         }
-        if ([containerOptions hasPrefix:@" - "])
+    }
+    else
+    {
+        // we have a specified, constant framerate
+        if (self.video.frameRateMode == 0)
         {
-            [containerOptions deleteCharactersInRange:NSMakeRange(0, 3)];
+            [videoInfo appendFormat:@"Peak %@ (may be lower)", @(hb_video_framerate_get_name(self.video.frameRate))];
         }
-        if (containerOptions.length)
+        else
         {
-            [finalString appendString:@"Container Options: " withAttributes:detailBoldAttr];
-            [finalString appendString:containerOptions       withAttributes:detailAttr];
-            [finalString appendString:@"\n"                  withAttributes:detailAttr];
+            [videoInfo appendFormat:@"Peak %@ (constant frame rate)", @(hb_video_framerate_get_name(self.video.frameRate))];
         }
+    }
 
-        // Fourth Line (Destination Path)
-        [finalString appendString: @"Destination: " withAttributes:detailBoldAttr];
-        [finalString appendString: self.completeOutputURL.path withAttributes:detailAttr];
-        [finalString appendString:@"\n" withAttributes:detailAttr];
-
-
-        // Fifth Line Picture Details
-        NSString *pictureInfo = [NSString stringWithFormat:@"%@", self.picture.summary];
-        if (self.picture.keepDisplayAspect)
-        {
-            pictureInfo = [pictureInfo stringByAppendingString:@" Keep Aspect Ratio"];
-        }
-        [finalString appendString:@"Picture: " withAttributes:detailBoldAttr];
-        [finalString appendString:pictureInfo  withAttributes:detailAttr];
-        [finalString appendString:@"\n"        withAttributes:detailAttr];
+    if (self.video.qualityType == 0) // ABR
+    {
+        [videoInfo appendFormat:@", Bitrate: %d kbps", self.video.avgBitrate];
+    }
+    else // CRF
+    {
+        [videoInfo appendFormat:@", Constant Quality: %.2f %s" ,self.video.quality, hb_video_quality_get_name(self.video.encoder)];
+    }
 
-        /* Optional String for Picture Filters */
-        if (self.filters.summary.length)
-        {
-            NSString *pictureFilters = [NSString stringWithFormat:@"%@", self.filters.summary];
-            [finalString appendString:@"Filters: "   withAttributes:detailBoldAttr];
-            [finalString appendString:pictureFilters withAttributes:detailAttr];
-            [finalString appendString:@"\n"          withAttributes:detailAttr];
-        }
+    [attrString appendString:@"\tVideo: " withAttributes:detailBoldAttr];
+    [attrString appendString:@"\t" withAttributes:detailAttr];
+    [attrString appendString:videoInfo withAttributes:detailAttr];
+    [attrString appendString:@"\n" withAttributes:detailAttr];
 
-        // Sixth Line Video Details
-        NSString * videoInfo = [NSString stringWithFormat:@"Encoder: %@", @(hb_video_encoder_get_name(self.video.encoder))];
+    if (hb_video_encoder_get_presets(self.video.encoder) != NULL)
+    {
+        NSMutableString *encoderPresetInfo = [NSMutableString string];
 
-        // for framerate look to see if we are using vfr detelecine
-        if (self.video.frameRate == 0)
+        if (self.video.advancedOptions)
         {
-            if (self.video.frameRateMode == 0)
+            // we are using the old advanced panel
+            if (self.video.videoOptionExtra.length)
             {
-                // we are using same as source with vfr detelecine
-                videoInfo = [NSString stringWithFormat:@"%@ Framerate: Same as source (Variable Frame Rate)", videoInfo];
+                [encoderPresetInfo appendString:self.video.videoOptionExtra];
             }
             else
             {
-                // we are using a variable framerate without dropping frames
-                videoInfo = [NSString stringWithFormat:@"%@ Framerate: Same as source (Constant Frame Rate)", videoInfo];
+                [encoderPresetInfo appendString:@"default settings"];
             }
         }
         else
         {
-            // we have a specified, constant framerate
-            if (self.video.frameRateMode == 0)
+            // we are using the x264 system
+            [encoderPresetInfo appendFormat:@"Preset: %@", self.video.preset];
+
+            if (self.video.tune.length || self.video.fastDecode)
+            {
+                [encoderPresetInfo appendString:@", Tune: "];
+
+                if (self.video.tune.length)
+                {
+                    [encoderPresetInfo appendString:self.video.tune];
+                }
+                if (self.video.fastDecode)
+                {
+                    [encoderPresetInfo appendString:@" - fastdecode"];
+                }
+            }
+            if (self.video.videoOptionExtra.length)
             {
-                videoInfo = [NSString stringWithFormat:@"%@ Framerate: %@ (Peak Frame Rate)", videoInfo, @(hb_video_framerate_get_name(self.video.frameRate))];
+                [encoderPresetInfo appendFormat:@", Options: %@", self.video.videoOptionExtra];
             }
-            else
+            if (self.video.profile.length)
+            {
+                [encoderPresetInfo appendFormat:@", Profile: %@", self.video.profile];
+            }
+            if (self.video.level.length)
             {
-                videoInfo = [NSString stringWithFormat:@"%@ Framerate: %@ (Constant Frame Rate)", videoInfo, @(hb_video_framerate_get_name(self.video.frameRate))];
+                [encoderPresetInfo appendFormat:@", Level: %@", self.video.level];
             }
         }
-
-
-        if (self.video.qualityType == 0) // ABR
+        [attrString appendString:@"\tVideo Options: "   withAttributes:detailBoldAttr];
+        [attrString appendString:@"\t"                  withAttributes:detailAttr];
+        [attrString appendString:encoderPresetInfo      withAttributes:detailAttr];
+        [attrString appendString:@"\n"                  withAttributes:detailAttr];
+    }
+    else
+    {
+        // we are using libavcodec
+        NSString *lavcInfo = @"";
+        if (self.video.videoOptionExtra.length)
         {
-            videoInfo = [NSString stringWithFormat:@"%@ Bitrate: %d(kbps)", videoInfo, self.video.avgBitrate];
+            lavcInfo = self.video.videoOptionExtra;
         }
-        else // CRF
+        else
         {
-            videoInfo = [NSString stringWithFormat:@"%@ Constant Quality: %.2f", videoInfo ,self.video.quality];
+            lavcInfo = @"default settings";
         }
 
-        [finalString appendString: @"Video: " withAttributes:detailBoldAttr];
-        [finalString appendString: videoInfo withAttributes:detailAttr];
-        [finalString appendString:@"\n" withAttributes:detailAttr];
+        [attrString appendString:@"\tVideo Options: " withAttributes:detailBoldAttr];
+        [attrString appendString:@"\t"                  withAttributes:detailAttr];
+        [attrString appendString:lavcInfo               withAttributes:detailAttr];
+        [attrString appendString:@"\n"                  withAttributes:detailAttr];
+    }
+    
+    return attrString;
+}
+
+- (NSAttributedString *)audioAttributedDescription
+{
+    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
+    BOOL secondLine = NO;
 
+    [attrString appendString:@"\tAudio: " withAttributes: detailBoldAttr];
 
-        if (hb_video_encoder_get_presets(self.video.encoder) != NULL)
+    for (HBAudioTrack *audioTrack in self.audio.tracks)
+    {
+        if (audioTrack.isEnabled)
         {
-            // we are using x264/x265
-            NSString *encoderPresetInfo = @"";
-            if (self.video.advancedOptions)
-            {
-                // we are using the old advanced panel
-                if (self.video.videoOptionExtra.length)
-                {
-                    encoderPresetInfo = [encoderPresetInfo stringByAppendingString:self.video.videoOptionExtra];
-                }
-                else
-                {
-                    encoderPresetInfo = [encoderPresetInfo stringByAppendingString:@"default settings"];
-                }
-            }
-            else
+            NSMutableString *detailString = [NSMutableString stringWithFormat:@"%@ ▸ Encoder: %@",
+                                      self.audio.sourceTracks[audioTrack.sourceTrackIdx][keyAudioTrackName],
+                                      @(hb_audio_encoder_get_name(audioTrack.encoder))];
+
+            if ((audioTrack.encoder  & HB_ACODEC_PASS_FLAG) == 0)
             {
-                // we are using the x264 system
-                encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@"Preset: %@", self.video.preset]];
+                [detailString appendFormat:@", Mixdown: %@, Samplerate: %@, Bitrate: %d kbps",
+                                            @(hb_mixdown_get_name(audioTrack.mixdown)),
+                                            audioTrack.sampleRate ? [NSString stringWithFormat:@"%@ khz", @(hb_audio_samplerate_get_name(audioTrack.sampleRate))] : @"Auto",
+                                            audioTrack.bitRate];
 
-                if (self.video.tune.length || self.video.fastDecode)
-                {
-                    encoderPresetInfo = [encoderPresetInfo stringByAppendingString:@" - Tune: "];
-
-                    if (self.video.tune.length)
-                    {
-                        encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@"%@", self.video.tune]];
-
-                        if (self.video.fastDecode)
-                        {
-                            encoderPresetInfo = [encoderPresetInfo stringByAppendingString:@","];
-                        }
-                    }
-                    if (self.video.fastDecode)
-                    {
-                        encoderPresetInfo = [encoderPresetInfo stringByAppendingString:@"fastdecode"];
-                    }
-                }
-                if (self.video.videoOptionExtra.length)
+                if (0.0 < audioTrack.drc)
                 {
-                    encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@" - Options: %@", self.video.videoOptionExtra]];
+                    [detailString appendFormat:@", DRC: %.2f", audioTrack.drc];
                 }
-                if (self.video.profile.length)
-                {
-                    encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@" - Profile: %@", self.video.profile]];
-                }
-                if (self.video.level.length)
+
+                if (0.0 != audioTrack.gain)
                 {
-                    encoderPresetInfo = [encoderPresetInfo stringByAppendingString: [NSString stringWithFormat:@" - Level: %@", self.video.level]];
+                    [detailString appendFormat:@", Gain: %.2f", audioTrack.gain];
                 }
             }
-            [finalString appendString: @"Video Options: " withAttributes:detailBoldAttr];
-            [finalString appendString: encoderPresetInfo withAttributes:detailAttr];
-            [finalString appendString:@"\n" withAttributes:detailAttr];
-        }
-        else
-        {
-            // we are using libavcodec
-            NSString *lavcInfo = @"";
-            if (self.video.videoOptionExtra.length)
+
+            [attrString appendString:@"\t" withAttributes: detailAttr];
+            if (secondLine)
             {
-                lavcInfo = [lavcInfo stringByAppendingString:self.video.videoOptionExtra];
+                [attrString appendString:@"\t" withAttributes: detailAttr];
             }
             else
             {
-                lavcInfo = [lavcInfo stringByAppendingString: @"default settings"];
+                secondLine = YES;
             }
-            [finalString appendString: @"Encoder Options: " withAttributes:detailBoldAttr];
-            [finalString appendString: lavcInfo withAttributes:detailAttr];
-            [finalString appendString:@"\n" withAttributes:detailAttr];
+            [attrString appendString:detailString withAttributes: detailAttr];
+            [attrString appendString:@"\n" withAttributes: detailAttr];
         }
+    }
 
+    return attrString;
+}
 
-        // Seventh Line Audio Details
-        for (NSString *anAudioDetail in audioDetails)
-        {
-            if (anAudioDetail.length)
-            {
-                [finalString appendString: [NSString stringWithFormat: @"Audio: "] withAttributes: detailBoldAttr];
-                [finalString appendString: anAudioDetail withAttributes: detailAttr];
-                [finalString appendString: @"\n" withAttributes: detailAttr];
-            }
-        }
+- (NSAttributedString *)subtitlesAttributedDescription
+{
+    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
+    BOOL secondLine = NO;
+
+    [attrString appendString:@"\tSubtitles: " withAttributes:detailBoldAttr];
 
-        // Eigth Line Auto Passthru Details
-        // only print Auto Passthru settings if we have an Auro Passthru output track
-        if (autoPassthruPresent == YES)
+    for (HBSubtitlesTrack *track in self.subtitles.tracks)
+    {
+        // Ignore the none track.
+        if (track.isEnabled)
         {
-            NSString *autoPassthruFallback = @"", *autoPassthruCodecs = @"";
-            HBAudioDefaults *audioDefaults = self.audio.defaults;
-            autoPassthruFallback = [autoPassthruFallback stringByAppendingString:@(hb_audio_encoder_get_name(audioDefaults.encoderFallback))];
-            if (audioDefaults.allowAACPassthru)
-            {
-                autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@"AAC"];
-            }
-            if (audioDefaults.allowAC3Passthru)
+            NSMutableString *detailString = [NSMutableString string];
+
+            // remember that index 0 of Subtitles can contain "Foreign Audio Search
+            [detailString appendString:self.subtitles.sourceTracks[track.sourceTrackIdx][@"keySubTrackName"]];
+
+            if (track.forcedOnly)
             {
-                if (autoPassthruCodecs.length)
-                {
-                    autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@", "];
-                }
-                autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@"AC3"];
+                [detailString appendString:@", Forced Only"];
             }
-            if (audioDefaults.allowDTSHDPassthru)
+            if (track.burnedIn)
             {
-                if (autoPassthruCodecs.length)
-                {
-                    autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@", "];
-                }
-                autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@"DTS-HD"];
+                [detailString appendString:@", Burned In"];
             }
-            if (audioDefaults.allowDTSPassthru)
+            if (track.def)
             {
-                if (autoPassthruCodecs.length)
-                {
-                    autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@", "];
-                }
-                autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@"DTS"];
+                [detailString appendString:@", Default"];
             }
-            if (audioDefaults.allowMP3Passthru)
-            {
-                if (autoPassthruCodecs.length)
-                {
-                    autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@", "];
-                }
-                autoPassthruCodecs = [autoPassthruCodecs stringByAppendingString:@"MP3"];
-            }
-            [finalString appendString: @"Auto Passthru Codecs: " withAttributes: detailBoldAttr];
-            if (autoPassthruCodecs.length)
+
+            [attrString appendString:@"\t" withAttributes: detailAttr];
+            if (secondLine)
             {
-                [finalString appendString: autoPassthruCodecs withAttributes: detailAttr];
+                [attrString appendString:@"\t" withAttributes: detailAttr];
             }
             else
             {
-                [finalString appendString: @"None" withAttributes: detailAttr];
+                secondLine = YES;
             }
-            [finalString appendString: @"\n" withAttributes: detailAttr];
-            [finalString appendString: @"Auto Passthru Fallback: " withAttributes: detailBoldAttr];
-            [finalString appendString: autoPassthruFallback withAttributes: detailAttr];
-            [finalString appendString: @"\n" withAttributes: detailAttr];
+            [attrString appendString:detailString withAttributes: detailAttr];
+            [attrString appendString:@"\n" withAttributes: detailAttr];
+        }
+    }
+
+    return attrString;
+}
+
+- (NSAttributedString *)attributedDescription
+{
+    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
+    [self initStyles];
+
+    @autoreleasepool
+    {
+        [attrString appendAttributedString:[self titleAttributedDescription]];
+        [attrString appendAttributedString:[self presetAttributedDescription]];
+        [attrString appendAttributedString:[self formatAttributedDescription]];
+        [attrString appendAttributedString:[self destinationAttributedDescription]];
+        [attrString appendAttributedString:[self pictureAttributedDescription]];
+        [attrString appendAttributedString:[self filtersAttributedDescription]];
+        [attrString appendAttributedString:[self videoAttributedDescription]];
+        if (self.audio.countOfTracks > 1)
+        {
+            [attrString appendAttributedString:[self audioAttributedDescription]];
         }
-        
-        // Ninth Line Subtitle Details
-        for (HBSubtitlesTrack *track in self.subtitles.tracks)
+        if (self.subtitles.countOfTracks > 1)
         {
-            // Ignore the none track.
-            if (track.isEnabled)
-            {
-                // remember that index 0 of Subtitles can contain "Foreign Audio Search
-                [finalString appendString: @"Subtitle: " withAttributes:detailBoldAttr];
-                [finalString appendString: self.subtitles.sourceTracks[track.sourceTrackIdx][@"keySubTrackName"] withAttributes:detailAttr];
-                if (track.forcedOnly)
-                {
-                    [finalString appendString: @" - Forced Only" withAttributes:detailAttr];
-                }
-                if (track.burnedIn)
-                {
-                    [finalString appendString: @" - Burned In" withAttributes:detailAttr];
-                }
-                if (track.def)
-                {
-                    [finalString appendString: @" - Default" withAttributes:detailAttr];
-                }
-                [finalString appendString:@"\n" withAttributes:detailAttr];
-            }
+            [attrString appendAttributedString:[self subtitlesAttributedDescription]];
         }
     }
 
-    [finalString deleteCharactersInRange:NSMakeRange(finalString.length - 1, 1)];
+    [attrString deleteCharactersInRange:NSMakeRange(attrString.length - 1, 1)];
 
-    return finalString;
+    return attrString;
 }
 
 @end