/* HBJob+HBAdditions.m $
This file is part of the HandBrake source code.
Homepage: .
It may be used under the terms of the GNU General Public License. */
#import "HBJob+HBAdditions.h"
#import "HBPreferencesKeys.h"
#import "hb.h"
static NSDateFormatter *_timeFormatter = nil;
static NSDateFormatter *_dateFormatter = nil;
static NSDateFormatter *_releaseDateFormatter = nil;
@implementation HBJob (HBAdditions)
+ (void)initialize
{
if (self == [HBJob class]) {
_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setDateStyle:NSDateFormatterShortStyle];
[_dateFormatter setTimeStyle:NSDateFormatterNoStyle];
_timeFormatter = [[NSDateFormatter alloc] init];
[_timeFormatter setDateStyle:NSDateFormatterNoStyle];
[_timeFormatter setTimeStyle:NSDateFormatterShortStyle];
_releaseDateFormatter = [[NSDateFormatter alloc] init];
[_releaseDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
}
}
- (NSString *)automaticName
{
HBTitle *title = self.title;
NSDate *releaseDate = title.metadata.releaseDate.length ? [_releaseDateFormatter dateFromString:title.metadata.releaseDate] : nil;
if (releaseDate == nil)
{
NSDictionary *fileAttribs = [[NSFileManager defaultManager] attributesOfItemAtPath:self.fileURL.path error:nil];
releaseDate = [fileAttribs objectForKey:NSFileCreationDate];
}
// Generate a new file name
NSString *fileName = [self automaticNameForSource:title.name
title:title.index
chapters:NSMakeRange(self.range.chapterStart + 1, self.range.chapterStop + 1)
quality:self.video.qualityType ? self.video.quality : 0
bitrate:!self.video.qualityType ? self.video.avgBitrate : 0
videoCodec:self.video.encoder
creationDate:releaseDate];
return fileName;
}
- (NSString *)automaticExt
{
NSString *extension = @(hb_container_get_default_extension(self.container));
if (self.container & HB_MUX_MASK_MP4)
{
BOOL anyCodecAC3 = [self.audio anyCodecMatches:HB_ACODEC_AC3] || [self.audio anyCodecMatches:HB_ACODEC_AC3_PASS];
// Chapter markers are enabled if the checkbox is ticked and we are doing p2p or we have > 1 chapter
BOOL chapterMarkers = (self.chaptersEnabled) &&
(self.range.type != HBRangeTypeChapters || self.range.chapterStart < self.range.chapterStop);
NSString *defaultExtension = [NSUserDefaults.standardUserDefaults stringForKey:HBDefaultMpegExtension];
if ([defaultExtension isEqualToString:@".m4v"] ||
((YES == anyCodecAC3 || YES == chapterMarkers) && [defaultExtension isEqualToString:@"Auto"]))
{
extension = @"m4v";
}
}
return extension;
}
- (NSString *)defaultName
{
// Generate a new file name
NSString *fileName = self.title.name;
// If Auto Naming is on. We create an output filename by using the
// format set int he preferences.
if ([NSUserDefaults.standardUserDefaults boolForKey:HBDefaultAutoNaming])
{
fileName = [self automaticName];
}
// use the correct extension based on the container
NSString *ext = [self automaticExt];
fileName = [fileName stringByAppendingPathExtension:ext];
return fileName;
}
- (NSString *)automaticNameForSource:(NSString *)sourceName
title:(NSUInteger)title
chapters:(NSRange)chaptersRange
quality:(double)quality
bitrate:(int)bitrate
videoCodec:(uint32_t)codec
creationDate:(NSDate *)creationDate
{
NSUserDefaults *ud = NSUserDefaults.standardUserDefaults;
NSMutableString *name = [[NSMutableString alloc] init];
// The format array contains the tokens as NSString
NSArray *format = [ud objectForKey:HBAutoNamingFormat];
for (NSString *formatKey in format)
{
if ([formatKey isEqualToString:@"{Source}"])
{
if ([ud boolForKey:HBAutoNamingRemoveUnderscore])
{
sourceName = [sourceName stringByReplacingOccurrencesOfString:@"_" withString:@" "];
}
if ([ud boolForKey:HBAutoNamingRemovePunctuation])
{
sourceName = [sourceName stringByReplacingOccurrencesOfString:@"-" withString:@""];
sourceName = [sourceName stringByReplacingOccurrencesOfString:@"." withString:@""];
sourceName = [sourceName stringByReplacingOccurrencesOfString:@"," withString:@""];
sourceName = [sourceName stringByReplacingOccurrencesOfString:@";" withString:@""];
}
if ([ud boolForKey:HBAutoNamingTitleCase])
{
sourceName = [sourceName capitalizedString];
}
[name appendString:sourceName];
}
else if ([formatKey isEqualToString:@"{Title}"])
{
[name appendFormat:@"%lu", (unsigned long)title];
}
else if ([formatKey isEqualToString:@"{Date}"])
{
NSDate *date = [NSDate date];
NSString *dateString = [[_dateFormatter stringFromDate:date] stringByReplacingOccurrencesOfString:@"/" withString:@"-"];
[name appendString:dateString];
}
else if ([formatKey isEqualToString:@"{Time}"])
{
NSDate *date = [NSDate date];
[name appendString:[_timeFormatter stringFromDate:date]];
}
else if ([formatKey isEqualToString:@"{Creation-Date}"])
{
NSString *dateString = [[_dateFormatter stringFromDate:creationDate] stringByReplacingOccurrencesOfString:@"/" withString:@"-"];
[name appendString:dateString];
}
else if ([formatKey isEqualToString:@"{Creation-Time}"])
{
[name appendString:[_timeFormatter stringFromDate:creationDate]];
}
else if ([formatKey isEqualToString:@"{Chapters}"])
{
if (chaptersRange.location == chaptersRange.length)
{
[name appendFormat:@"%lu", (unsigned long)chaptersRange.location];
}
else
{
[name appendFormat:@"%lu-%lu", (unsigned long)chaptersRange.location, (unsigned long)chaptersRange.length];
}
}
else if ([formatKey isEqualToString:@"{Quality/Bitrate}"])
{
if (bitrate)
{
[name appendString:@"abr"];
[name appendString:[NSString stringWithFormat:@"%d", bitrate]];
}
else
{
// Append the right quality suffix for the selected codec (rf/qp)
[name appendString:[@(hb_video_quality_get_name(codec)) lowercaseString]];
[name appendString:[NSString stringWithFormat:@"%0.2f", quality]];
}
}
else
{
[name appendString:formatKey];
}
}
return [name copy];
}
@end