</buttonCell>
<connections>
<action selector="resetItem:" target="-2" id="42R-t4-FxO"/>
+ <binding destination="-2" name="enabled" keyPath="self.canReset" id="Rte-cy-Bzo"/>
</connections>
</button>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MXt-Cb-20x">
[HBCore registerErrorHandler:^(NSString *error) {
fprintf(stderr, "error: %s\n", error.UTF8String);
}];
- [HBCore setDVDNav:[[NSUserDefaults standardUserDefaults] boolForKey:@"UseDvdNav"]];
+ [HBCore setDVDNav:[NSUserDefaults.standardUserDefaults boolForKey:HBUseDvdNav]];
_outputPanel = [[HBOutputPanelController alloc] init];
NSUserDefaults *ud = NSUserDefaults.standardUserDefaults;
// Reset "When done" action
- if ([ud boolForKey:@"HBResetWhenDoneOnLaunch"])
+ if ([ud boolForKey:HBResetWhenDoneOnLaunch])
{
- [ud setInteger:HBDoneActionDoNothing forKey:@"HBAlertWhenDone"];
+ [ud setInteger:HBDoneActionDoNothing forKey:HBAlertWhenDone];
}
if (@available (macOS 10.12.2, *))
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
// Remove encodes logs older than a month
- if ([ud boolForKey:@"HBClearOldLogs"])
+ if ([ud boolForKey:HBClearOldLogs])
{
[self cleanEncodeLogs];
}
#import <Cocoa/Cocoa.h>
+NS_ASSUME_NONNULL_BEGIN
+
@interface NSString (HBAttributedStringAdditions)
- (NSAttributedString *)HB_monospacedString;
@end
+NS_ASSUME_NONNULL_END
@property (nonatomic, readwrite, weak, nullable) NSUndoManager *undo;
-@end
-
-@interface HBAudio (KVC)
-
@property (nonatomic, readonly) NSUInteger countOfTracks;
- (HBAudioTrack *)objectInTracksAtIndex:(NSUInteger)index;
- (void)insertObject:(HBAudioTrack *)track inTracksAtIndex:(NSUInteger)index;
#import "HBAutoNamer.h"
-#import <AppKit/AppKit.h>
-
#import "HBJob.h"
-#import "HBUtilities.h"
+#import "HBJob+HBAdditions.h"
+#import "HBPreferencesKeys.h"
static void *HBAutoNamerPrefsContext = &HBAutoNamerPrefsContext;
static void *HBAutoNamerContext = &HBAutoNamerContext;
if (self)
{
_job = job;
- _format = [[NSUserDefaults standardUserDefaults] objectForKey:@"HBAutoNamingFormat"];
+ _format = [NSUserDefaults.standardUserDefaults objectForKey:HBAutoNamingFormat];
[self addFormatObservers];
[self addJobObservers];
[self addPrefsObservers];
else if (context == HBAutoNamerPrefsContext)
{
[self removeJobObservers];
- self.format = [[NSUserDefaults standardUserDefaults] objectForKey:@"HBAutoNamingFormat"];
+ self.format = [NSUserDefaults.standardUserDefaults objectForKey:HBAutoNamingFormat];
[self addJobObservers];
[self updateFileName];
[self updateFileExtension];
if (self.job && !(undo.isUndoing || undo.isRedoing))
{
- NSString *extension = [HBUtilities automaticExtForJob:self.job];
+ NSString *extension = self.job.automaticExt;
if (![extension isEqualTo:self.job.outputFileName.pathExtension])
{
self.job.outputFileName = [[self.job.outputFileName stringByDeletingPathExtension] stringByAppendingPathExtension:extension];
{
NSUndoManager *undo = self.job.undo;
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"] && self.job && !(undo.isUndoing || undo.isRedoing))
+ if ([NSUserDefaults.standardUserDefaults boolForKey:HBDefaultAutoNaming] && self.job && !(undo.isUndoing || undo.isRedoing))
{
// Generate a new file name
- NSString *fileName = [HBUtilities automaticNameForJob:self.job];
+ NSString *fileName = self.job.automaticName;
// Swap the old one with the new one
self.job.outputFileName = [NSString stringWithFormat:@"%@.%@", fileName, self.job.outputFileName.pathExtension];
It may be used under the terms of the GNU General Public License. */
#import "HBChapterTitlesController.h"
-
+#import "HBPreferencesKeys.h"
@import HandBrakeKit;
@interface NSArray (HBCSVAdditions)
- (IBAction)browseForChapterFile:(id)sender
{
// We get the current file name and path from the destination field here
- NSURL *sourceDirectory = [[NSUserDefaults standardUserDefaults] URLForKey:@"HBLastDestinationDirectory"];
+ NSURL *sourceDirectory = [NSUserDefaults.standardUserDefaults URLForKey:HBLastDestinationDirectoryURL];
// Open a panel to let the user choose the file
NSOpenPanel *panel = [NSOpenPanel openPanel];
- (IBAction)browseForChapterFileSave:(id)sender
{
- NSURL *destinationDirectory = [[NSUserDefaults standardUserDefaults] URLForKey:@"HBLastDestinationDirectory"];
+ NSURL *destinationDirectory = [NSUserDefaults.standardUserDefaults URLForKey:HBLastDestinationDirectoryURL];
NSSavePanel *panel = [NSSavePanel savePanel];
panel.allowedFileTypes = @[@"csv"];
#import "HBRenamePresetController.h"
#import "HBAutoNamer.h"
+#import "HBJob+HBAdditions.h"
#import "HBAttributedStringAdditions.h"
-@import HandBrakeKit;
+#import "HBPreferencesKeys.h"
static void *HBControllerScanCoreContext = &HBControllerScanCoreContext;
static void *HBControllerQueueCoreContext = &HBControllerQueueCoreContext;
if (self)
{
// Init libhb
- NSInteger loggingLevel = [[NSUserDefaults standardUserDefaults] integerForKey:@"LoggingLevel"];
+ NSInteger loggingLevel = [NSUserDefaults.standardUserDefaults integerForKey:HBLoggingLevel];
_core = [[HBCore alloc] initWithLogLevel:loggingLevel name:@"ScanCore"];
// Inits the controllers
// Check to see if the last destination has been set, use if so, if not, use Movies
#ifdef __SANDBOX_ENABLED__
- NSData *bookmark = [[NSUserDefaults standardUserDefaults] objectForKey:@"HBLastDestinationDirectoryBookmark"];
+ NSData *bookmark = [NSUserDefaults.standardUserDefaults objectForKey:HBLastDestinationDirectoryBookmark];
if (bookmark)
{
_currentDestination = [HBUtilities URLFromBookmark:bookmark];
}
#else
- _currentDestination = [[NSUserDefaults standardUserDefaults] URLForKey:@"HBLastDestinationDirectoryURL"];
+ _currentDestination = [NSUserDefaults.standardUserDefaults URLForKey:HBLastDestinationDirectoryURL];
#endif
if (!_currentDestination || [[NSFileManager defaultManager] fileExistsAtPath:_currentDestination.path isDirectory:nil] == NO)
return self;
}
-- (void)dealloc
-{
- [[NSNotificationCenter defaultCenter] removeObserver:self];
-}
-
- (void)windowDidLoad
{
if (@available (macOS 10.12, *))
{
if (self.core.state != HBStateScanning && !self.job)
{
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HBShowOpenPanelAtLaunch"])
+ if ([NSUserDefaults.standardUserDefaults boolForKey:HBShowOpenPanelAtLaunch])
{
[self browseSources:nil];
}
if (canScan)
{
- NSUInteger hb_num_previews = [[NSUserDefaults standardUserDefaults] integerForKey:@"PreviewsNumber"];
- NSUInteger min_title_duration_seconds = [[NSUserDefaults standardUserDefaults] integerForKey:@"MinTitleScanSeconds"];
+ NSUInteger hb_num_previews = [NSUserDefaults.standardUserDefaults integerForKey:HBPreviewsNumber];
+ NSUInteger min_title_duration_seconds = [NSUserDefaults.standardUserDefaults integerForKey:HBMinTitleScanSeconds];
[self.core scanURL:mediaURL
titleIndex:index
}
// Set the last searched source directory in the prefs here
- if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:mediaURL.URLByDeletingLastPathComponent.path])
+ if ([NSWorkspace.sharedWorkspace isFilePackageAtPath:mediaURL.URLByDeletingLastPathComponent.path])
{
- [[NSUserDefaults standardUserDefaults] setURL:mediaURL.URLByDeletingLastPathComponent.URLByDeletingLastPathComponent forKey:@"HBLastSourceDirectoryURL"];
+ [NSUserDefaults.standardUserDefaults setURL:mediaURL.URLByDeletingLastPathComponent.URLByDeletingLastPathComponent forKey:HBLastSourceDirectoryURL];
}
else
{
- [[NSUserDefaults standardUserDefaults] setURL:mediaURL.URLByDeletingLastPathComponent forKey:@"HBLastSourceDirectoryURL"];
+ [NSUserDefaults.standardUserDefaults setURL:mediaURL.URLByDeletingLastPathComponent forKey:HBLastSourceDirectoryURL];
}
completionHandler(self.core.titles);
// If the source is not a stream, and autonaming is disabled,
// keep the existing file name.
- if (self.job.outputFileName.length == 0 || title.isStream || [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"])
+ if (self.job.outputFileName.length == 0 || title.isStream || [NSUserDefaults.standardUserDefaults boolForKey:HBDefaultAutoNaming])
{
- job.outputFileName = [HBUtilities defaultNameForJob:job];
+ job.outputFileName = job.defaultName;
}
else
{
{
if (self.job)
{
- [[NSNotificationCenter defaultCenter] removeObserver:self name:HBContainerChangedNotification object:_job];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:HBPictureChangedNotification object:_job.picture];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:HBFiltersChangedNotification object:_job.filters];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:HBVideoChangedNotification object:_job.video];
+ NSNotificationCenter *center = NSNotificationCenter.defaultCenter;
+ [center removeObserver:self name:HBContainerChangedNotification object:_job];
+ [center removeObserver:self name:HBPictureChangedNotification object:_job.picture];
+ [center removeObserver:self name:HBFiltersChangedNotification object:_job.filters];
+ [center removeObserver:self name:HBVideoChangedNotification object:_job.video];
self.autoNamer = nil;
}
}
{
if (self.job)
{
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(formatChanged:) name:HBContainerChangedNotification object:_job];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(customSettingUsed) name:HBPictureChangedNotification object:_job.picture];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(customSettingUsed) name:HBFiltersChangedNotification object:_job.filters];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(customSettingUsed) name:HBVideoChangedNotification object:_job.video];
+ NSNotificationCenter *center = NSNotificationCenter.defaultCenter;
+ [center addObserver:self selector:@selector(formatChanged:) name:HBContainerChangedNotification object:_job];
+ [center addObserver:self selector:@selector(customSettingUsed) name:HBPictureChangedNotification object:_job.picture];
+ [center addObserver:self selector:@selector(customSettingUsed) name:HBFiltersChangedNotification object:_job.filters];
+ [center addObserver:self selector:@selector(customSettingUsed) name:HBVideoChangedNotification object:_job.video];
self.autoNamer = [[HBAutoNamer alloc] initWithJob:self.job];
}
}
[panel setCanChooseDirectories:YES];
NSURL *sourceDirectory;
- if ([[NSUserDefaults standardUserDefaults] URLForKey:@"HBLastSourceDirectoryURL"])
+ if ([NSUserDefaults.standardUserDefaults URLForKey:HBLastSourceDirectoryURL])
{
- sourceDirectory = [[NSUserDefaults standardUserDefaults] URLForKey:@"HBLastSourceDirectoryURL"];
+ sourceDirectory = [NSUserDefaults.standardUserDefaults URLForKey:HBLastSourceDirectoryURL];
}
else
{
self.currentDestination = panel.URL;
// Save this path to the prefs so that on next browse destination window it opens there
- [[NSUserDefaults standardUserDefaults] setObject:[HBUtilities bookmarkFromURL:panel.URL]
- forKey:@"HBLastDestinationDirectoryBookmark"];
- [[NSUserDefaults standardUserDefaults] setURL:panel.URL
- forKey:@"HBLastDestinationDirectoryURL"];
+ [NSUserDefaults.standardUserDefaults setObject:[HBUtilities bookmarkFromURL:panel.URL]
+ forKey:HBLastDestinationDirectoryBookmark];
+ [NSUserDefaults.standardUserDefaults setURL:panel.URL
+ forKey:HBLastDestinationDirectoryURL];
}
}];
{
HBJob *job = [[HBJob alloc] initWithTitle:title andPreset:preset];
job.outputURL = self.currentDestination;
- job.outputFileName = [HBUtilities defaultNameForJob:job];
+ job.outputFileName = job.defaultName;
job.title = nil;
[jobs addObject:job];
}
*/
- (void)reload
{
- NSMutableArray *jobsArray = nil;
+ NSMutableArray<HBUniqueObject> *jobsArray = nil;
@try
{
NSData *queue = [NSData dataWithContentsOfURL:self.fileURL];
// Swap the proxy objects representation with the new
// one read from disk
NSMutableArray *proxyArray = [NSMutableArray array];
- for (id anObject in jobsArray)
+ for (id<HBUniqueObject> anObject in jobsArray)
{
- NSString *uuid = [anObject uuid];
+ NSString *uuid = anObject.uuid;
HBProxyArrayObject *proxy = nil;
for (HBProxyArrayObject *temp in self.array)
{
- if ([[temp uuid] isEqualToString:uuid])
+ if ([temp.uuid isEqualToString:uuid])
{
temp.representedObject = anObject;
proxy = temp;
--- /dev/null
+/* HBJob+HBAdditions.h $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#import <Foundation/Foundation.h>
+
+@import HandBrakeKit;
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HBJob (HBAdditions)
+
+@property (nonatomic, readonly) NSString *automaticName;
+@property (nonatomic, readonly) NSString *automaticExt;
+@property (nonatomic, readonly) NSString *defaultName;
+
+/**
+ * Generates a file name automatically based on the inputs,
+ * it can be configured with NSUserDefaults.
+ *
+ * @param sourceName the name of the source file
+ * @param title the title number
+ * @param chaptersRange the selected chapters range
+ * @param quality the video encoder quality
+ * @param bitrate the video encoder bitrate
+ * @param videoCodec the video encoder type
+ *
+ * @return a NSString containing the required info
+ */
+- (NSString *)automaticNameForSource:(NSString *)sourceName
+ title:(NSUInteger)title
+ chapters:(NSRange)chaptersRange
+ quality:(double)quality
+ bitrate:(int)bitrate
+ videoCodec:(uint32_t)codec
+ creationDate:(NSDate *)creationDate;
+
+@end
+
+NS_ASSUME_NONNULL_END
--- /dev/null
+/* HBJob+HBAdditions.m $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ 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<NSString *> *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
decodeInt(_titleIdx); if (_titleIdx < 0) { goto fail; }
#ifdef __SANDBOX_ENABLED__
- _fileURLBookmark = [decoder decodeObjectOfClass:[NSData class] forKey:@"_fileURLBookmark"];
+ decodeObject(_fileURLBookmark, NSData)
if (_fileURLBookmark)
{
decodeObjectOrFail(_fileURL, NSURL);
}
- _outputURLFolderBookmark = [decoder decodeObjectOfClass:[NSData class] forKey:@"_outputURLFolderBookmark"];
+ decodeObject(_outputURLFolderBookmark, NSData)
if (_outputURLFolderBookmark)
{
#import "HBJobOutputFileWriter.h"
#import "HBJob.h"
#import "HBUtilities.h"
+#import "HBPreferencesKeys.h"
@interface HBJobOutputFileWriter ()
NSURL *outputURL = nil;
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EncodeLogLocation"])
+ if ([NSUserDefaults.standardUserDefaults boolForKey:HBEncodeLogLocation])
{
// if we are putting it in the same directory with the movie
outputURL = [job.outputURL URLByAppendingPathComponent:outputDateFileName];
#import <Cocoa/Cocoa.h>
-typedef NS_ENUM(NSUInteger, HBDoneAction) {
- HBDoneActionDoNothing = 0,
- HBDoneActionAlert = 1,
- HBDoneActionNotification = 2,
- HBDoneActionAlertAndNotification = 3,
- HBDoneActionSleep = 4,
- HBDoneActionShutDown = 5,
-};
+#import "HBPreferencesKeys.h"
-@interface HBPreferencesController : NSWindowController <NSToolbarDelegate>
+@interface HBPreferencesController : NSWindowController
+ (void)registerUserDefaults;
#import "HBPreferencesController.h"
+NSString * const HBShowOpenPanelAtLaunch = @"HBShowOpenPanelAtLaunch";
+NSString * const HBLastDestinationDirectoryURL = @"HBLastDestinationDirectoryURL";
+NSString * const HBLastDestinationDirectoryBookmark = @"HBLastDestinationDirectoryBookmark";
+NSString * const HBLastSourceDirectoryURL = @"HBLastSourceDirectoryURL";
+
+NSString * const HBDefaultMpegExtension = @"DefaultMpegExtension";
+
+NSString * const HBAlertWhenDone = @"HBAlertWhenDone";
+NSString * const HBResetWhenDoneOnLaunch = @"HBResetWhenDoneOnLaunch";
+NSString * const HBAlertWhenDoneSound = @"HBAlertWhenDoneSound";
+NSString * const HBSendToAppEnabled = @"HBSendToAppEnabled";
+NSString * const HBSendToApp = @"HBSendToApp";
+
+NSString * const HBDefaultAutoNaming = @"DefaultAutoNaming";
+NSString * const HBAutoNamingFormat = @"HBAutoNamingFormat";
+NSString * const HBAutoNamingRemoveUnderscore = @"HBAutoNamingRemoveUnderscore";
+NSString * const HBAutoNamingRemovePunctuation = @"HBAutoNamingRemovePunctuation";
+NSString * const HBAutoNamingTitleCase = @"HBAutoNamingTitleCase";
+
+NSString * const HBCqSliderFractional = @"HBx264CqSliderFractional";
+NSString * const HBUseDvdNav = @"UseDvdNav";
+NSString * const HBMinTitleScanSeconds = @"MinTitleScanSeconds";
+NSString * const HBPreviewsNumber = @"PreviewsNumber";
+
+NSString * const HBLoggingLevel = @"LoggingLevel";
+NSString * const HBEncodeLogLocation = @"HBEncodeLogLocation";
+NSString * const HBClearOldLogs = @"HBClearOldLogs";
+
+NSString * const HBQueuePauseIfLowSpace = @"HBQueuePauseIfLowSpace";
+NSString * const HBQueueMinFreeSpace = @"HBQueueMinFreeSpace";
+
#define TOOLBAR_GENERAL @"TOOLBAR_GENERAL"
#define TOOLBAR_ADVANCED @"TOOLBAR_ADVANCED"
* preference settings are added that cannot be handled with Cocoa bindings).
*/
-@interface HBPreferencesController () <NSTokenFieldDelegate>
+@interface HBPreferencesController () <NSTokenFieldDelegate, NSToolbarDelegate>
{
IBOutlet NSView * fGeneralView, * fAdvancedView;
IBOutlet NSTextField * fSendEncodeToAppField;
}
-/* Manage the send encode to xxx.app windows and field */
-- (IBAction) browseSendToApp: (id) sender;
-
-- (void) setPrefView: (id) sender;
-- (NSToolbarItem *)toolbarItemWithIdentifier: (NSString *)identifier
- label: (NSString *)label
- image: (NSImage *)image;
-
@property (unsafe_unretained) IBOutlet NSTokenField *formatTokenField;
@property (unsafe_unretained) IBOutlet NSTokenField *builtInTokenField;
@property (nonatomic, readonly, strong) NSArray *buildInFormatTokens;
NSURL *desktopURL = [NSURL fileURLWithPath:desktopDirectory isDirectory:YES];
[[NSUserDefaults standardUserDefaults] registerDefaults:@{
- @"HBShowOpenPanelAtLaunch": @YES,
- @"DefaultMpegExtension": @"Auto",
- @"UseDvdNav": @"YES",
- // Archive the URL because they aren't supported in plist.
- @"HBLastDestinationDirectory": [NSKeyedArchiver archivedDataWithRootObject:desktopURL],
- @"HBLastSourceDirectory": [NSKeyedArchiver archivedDataWithRootObject:desktopURL],
- @"DefaultAutoNaming": @NO,
- @"HBAlertWhenDone": @(HBDoneActionNotification),
- @"HBResetWhenDoneOnLaunch": @NO,
- @"HBAlertWhenDoneSound": @YES,
- @"LoggingLevel": @"1",
- @"HBClearOldLogs": @YES,
- @"EncodeLogLocation": @"NO",
- @"MinTitleScanSeconds": @"10",
- @"PreviewsNumber": @"10",
- @"HBx264CqSliderFractional": @2,
- @"HBShowAdvancedTab": @NO,
- @"HBAutoNamingFormat": @[@"{Source}", @" ", @"{Title}"],
- @"HBQueuePauseIfLowSpace": @YES,
- @"HBQueueMinFreeSpace": @"2"
+ HBShowOpenPanelAtLaunch: @YES,
+ HBDefaultMpegExtension: @"Auto",
+ HBUseDvdNav: @YES,
+ HBLastDestinationDirectoryURL: [NSKeyedArchiver archivedDataWithRootObject:desktopURL],
+ HBLastSourceDirectoryURL: [NSKeyedArchiver archivedDataWithRootObject:desktopURL],
+ HBDefaultAutoNaming: @NO,
+ HBAutoNamingFormat: @[@"{Source}", @" ", @"{Title}"],
+ HBAlertWhenDone: @(HBDoneActionNotification),
+ HBResetWhenDoneOnLaunch: @NO,
+ HBAlertWhenDoneSound: @YES,
+ HBLoggingLevel: @1,
+ HBClearOldLogs: @YES,
+ HBEncodeLogLocation: @NO,
+ HBMinTitleScanSeconds: @10,
+ HBPreviewsNumber: @10,
+ HBCqSliderFractional: @2,
+ HBQueuePauseIfLowSpace: @YES,
+ HBQueueMinFreeSpace: @"2"
}];
// Overwrite the update check interval because previous versions
/*Opens the app browse window*/
- (IBAction) browseSendToApp: (id) sender
{
+ NSUserDefaults *ud = NSUserDefaults.standardUserDefaults;
NSOpenPanel *panel = [NSOpenPanel openPanel];
+
[panel setAllowsMultipleSelection:NO];
[panel setCanChooseFiles:YES];
[panel setCanChooseDirectories:NO];
[panel setAllowedFileTypes:@[@"app"]];
[panel setMessage:NSLocalizedString(@"Select the desired external application", @"Preferences -> send to app destination open panel")];
- NSString *sendToAppDirectory;
- if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastSendToAppDirectory"])
+ NSURL *sendToAppDirectory;
+ if ([ud stringForKey:@"HBLastSendToAppDirectory"])
{
- sendToAppDirectory = [[NSUserDefaults standardUserDefaults] stringForKey:@"LastSendToAppDirectory"];
+ sendToAppDirectory = [ud URLForKey:@"HBLastSendToAppDirectory"];
}
else
{
- sendToAppDirectory = @"/Applications";
+ sendToAppDirectory = [NSURL fileURLWithPath:@"/Applications" isDirectory:YES];
}
- [panel setDirectoryURL:[NSURL fileURLWithPath:sendToAppDirectory]];
+ [panel setDirectoryURL:sendToAppDirectory];
[panel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result) {
if (result == NSModalResponseOK)
{
NSURL *sendToAppURL = [panel URL];
NSURL *sendToAppDirectoryURL = [sendToAppURL URLByDeletingLastPathComponent];
- [[NSUserDefaults standardUserDefaults] setObject:[sendToAppDirectoryURL path] forKey:@"LastSendToAppDirectory"];
+ [ud setURL:sendToAppDirectoryURL forKey:@"HBLastSendToAppDirectory"];
// We set the name of the app to send to in the display field
- NSString *sendToAppName = [[sendToAppURL lastPathComponent] stringByDeletingPathExtension];
+ NSString *sendToAppName = sendToAppURL.lastPathComponent.stringByDeletingPathExtension;
[self->fSendEncodeToAppField setStringValue:sendToAppName];
- [[NSUserDefaults standardUserDefaults] setObject:self->fSendEncodeToAppField.stringValue forKey:@"HBSendToApp"];
+ [ud setObject:self->fSendEncodeToAppField.stringValue forKey:HBSendToApp];
}
}];
}
return YES;
}
-
#pragma mark - Private methods
- (void) setPrefView: (id) sender
--- /dev/null
+/* HBPreferencesKeys.h $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HBPreferencesKeys_h
+#define HBPreferencesKeys_h
+
+typedef NS_ENUM(NSUInteger, HBDoneAction) {
+ HBDoneActionDoNothing = 0,
+ HBDoneActionAlert = 1,
+ HBDoneActionNotification = 2,
+ HBDoneActionAlertAndNotification = 3,
+ HBDoneActionSleep = 4,
+ HBDoneActionShutDown = 5,
+};
+
+extern NSString * const HBShowOpenPanelAtLaunch;
+
+extern NSString * const HBLastDestinationDirectoryURL;
+extern NSString * const HBLastDestinationDirectoryBookmark;
+extern NSString * const HBLastSourceDirectoryURL;
+
+extern NSString * const HBDefaultMpegExtension;
+
+extern NSString * const HBAlertWhenDone;
+extern NSString * const HBResetWhenDoneOnLaunch;
+extern NSString * const HBAlertWhenDoneSound;
+extern NSString * const HBSendToAppEnabled;
+extern NSString * const HBSendToApp;
+
+extern NSString * const HBDefaultAutoNaming;
+extern NSString * const HBAutoNamingFormat;
+extern NSString * const HBAutoNamingRemoveUnderscore;
+extern NSString * const HBAutoNamingRemovePunctuation;
+extern NSString * const HBAutoNamingTitleCase;
+
+extern NSString * const HBCqSliderFractional;
+extern NSString * const HBUseDvdNav;
+extern NSString * const HBMinTitleScanSeconds;
+extern NSString * const HBPreviewsNumber;
+
+extern NSString * const HBLoggingLevel;
+extern NSString * const HBEncodeLogLocation;
+extern NSString * const HBClearOldLogs;
+
+extern NSString * const HBQueuePauseIfLowSpace;
+extern NSString * const HBQueueMinFreeSpace;
+
+#endif /* HBPreferencesKeys_h */
//
#import "HBPreviewGenerator.h"
+#import "HBPreferencesKeys.h"
+#import "HBJob+HBAdditions.h"
@import HandBrakeKit;
}
// Generate the file url and directories.
- NSString *extension = [HBUtilities automaticExtForJob:self.job];
+ NSString *extension = self.job.automaticExt;
NSURL *destURL = [HBPreviewGenerator generateFileURLForType:extension];
// return if we couldn't get the fileURL.
job.video.twoPass = NO;
// Init the libhb core
- NSInteger level = [[NSUserDefaults standardUserDefaults] integerForKey:@"LoggingLevel"];
+ NSInteger level = [NSUserDefaults.standardUserDefaults integerForKey:HBLoggingLevel];
self.core = [[HBCore alloc] initWithLogLevel:level name:@"PreviewCore"];
HBStateFormatter *formatter = [[HBStateFormatter alloc] init];
#import "HBQueue.h"
#import "NSArray+HBAdditions.h"
+#import "HBPreferencesKeys.h"
NSString * const HBQueueDidAddItemNotification = @"HBQueueDidAddItemNotification";
NSString * const HBQueueDidRemoveItemNotification = @"HBQueueDidRemoveItemNotification";
self = [super init];
if (self)
{
- NSInteger loggingLevel = [NSUserDefaults.standardUserDefaults integerForKey:@"LoggingLevel"];
+ NSInteger loggingLevel = [NSUserDefaults.standardUserDefaults integerForKey:HBLoggingLevel];
// Init a separate instance of libhb for the queue
_core = [[HBCore alloc] initWithLogLevel:loggingLevel name:@"QueueCore"];
_core.automaticallyPreventSleep = NO;
_items = [[HBDistributedArray alloc] initWithURL:queueURL class:[HBQueueItem class]];
+ _undoManager = [[NSUndoManager alloc] init];
// Set up the observers
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadQueue) name:HBDistributedArrayChanged object:_items];
NSIndexSet *indexes = [self.items indexesOfObjectsUsingBlock:^BOOL(HBQueueItem *item) {
return (item.state == HBQueueItemStateCompleted || item.state == HBQueueItemStateCanceled);
}];
+ [self removeItemsAtIndexes:indexes];
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidRemoveItemNotification object:self userInfo:@{@"indexes": indexes}];
[self.items commit];
}
idx++;
}
+ [self updateStats];
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidChangeItemNotification object:self userInfo:@{HBQueueItemNotificationIndexesKey: indexes}];
[self.items commit];
}
- (BOOL)isDiskSpaceLowAtURL:(NSURL *)url
{
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HBQueuePauseIfLowSpace"])
+ if ([NSUserDefaults.standardUserDefaults boolForKey:HBQueuePauseIfLowSpace])
{
NSURL *volumeURL = nil;
NSDictionary<NSURLResourceKey, id> *attrs = [url resourceValuesForKeys:@[NSURLIsVolumeKey, NSURLVolumeURLKey] error:NULL];
- long long minCapacity = [[[NSUserDefaults standardUserDefaults] stringForKey:@"HBQueueMinFreeSpace"] longLongValue] * 1000000000;
+ long long minCapacity = [[NSUserDefaults.standardUserDefaults stringForKey:HBQueueMinFreeSpace] longLongValue] * 1000000000;
volumeURL = [attrs[NSURLIsVolumeKey] boolValue] ? url : attrs[NSURLVolumeURLKey];
else if (nextItem)
{
// now we mark the queue item as working so another instance can not come along and try to scan it while we are scanning
- nextItem.state = HBQueueItemStateWorking;
nextItem.startedDate = [NSDate date];
+ nextItem.state = HBQueueItemStateWorking;
// Tell HB to output a new activity log file for this encode
self.currentLog = [[HBJobOutputFileWriter alloc] initWithJob:nextItem.job];
#import "HBQueueMultiSelectionViewController.h"
#import "HBDockTile.h"
-#import "HBPreferencesController.h"
+#import "HBPreferencesKeys.h"
#import "NSArray+HBAdditions.h"
@import HandBrakeKit;
@interface HBQueueController (TouchBar) <NSTouchBarProvider, NSTouchBarDelegate>
- (void)_touchBar_updateButtonsState;
- (void)_touchBar_validateUserInterfaceItems;
+- (IBAction)_touchBar_toggleStartCancel:(id)sender;
@end
@implementation HBQueueController
if (self = [super initWithWindowNibName:@"Queue"])
{
+ _queue = queue;
+
// Load the dockTile and instantiate initial text fields
_dockTile = [[HBDockTile alloc] initWithDockTile:NSApplication.sharedApplication.dockTile
image:NSApplication.sharedApplication.applicationIconImage];
- // Init state
- _queue = queue;
- _queue.undoManager = [[NSUndoManager alloc] init];
-
[NSNotificationCenter.defaultCenter addObserverForName:HBQueueLowSpaceAlertNotification object:_queue queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note) {
[self queueLowDiskSpaceAlert];
}];
- (BOOL)validateUserIterfaceItemForAction:(SEL)action
{
- if (action == @selector(toggleStartCancel:))
+ if (action == @selector(toggleStartCancel:) || action == @selector(_touchBar_toggleStartCancel:))
{
return self.queue.isEncoding || self.queue.canEncode;
}
NSParameterAssert(item);
[self.queue.items beginTransaction];
- if (item != self.queue.currentItem)
+ if (item == self.queue.currentItem)
{
- item.state = HBQueueItemStateWorking;
-
- // NSUInteger row = [self.queue.items indexOfObject:item];
- //FIXME
- //[self reloadQueueItemAtIndex:row];
-
- [self.delegate openJob:[item.job copy] completionHandler:^(BOOL result) {
- [self.queue.items beginTransaction];
- if (result)
- {
- // Now that source is loaded and settings applied, delete the queue item from the queue
- NSInteger index = [self.queue.items indexOfObject:item];
- item.state = HBQueueItemStateReady;
- [self.queue removeItemAtIndex:index];
- }
- else
- {
- item.state = HBQueueItemStateFailed;
- NSBeep();
- }
- [self.queue.items commit];
- }];
+ [self.queue cancelCurrentItemAndContinue];
}
else
{
- NSBeep();
+ item.state = HBQueueItemStateWorking;
}
+ [self.delegate openJob:[item.job copy] completionHandler:^(BOOL result) {
+ [self.queue.items beginTransaction];
+ if (result)
+ {
+ // Now that source is loaded and settings applied, delete the queue item from the queue
+ NSInteger index = [self.queue.items indexOfObject:item];
+ item.state = HBQueueItemStateReady;
+ [self.queue removeItemAtIndex:index];
+ }
+ else
+ {
+ item.state = HBQueueItemStateFailed;
+ NSBeep();
+ }
+ [self.queue.items commit];
+ }];
+
[self.queue.items commit];
}
[self doEditQueueItem:item];
}
-
[self.queue.items commit];
}
- (void)sendToExternalApp:(HBQueueItem *)item
{
// This end of encode action is called as each encode rolls off of the queue
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HBSendToAppEnabled"] == YES)
+ if ([NSUserDefaults.standardUserDefaults boolForKey:HBSendToAppEnabled] == YES)
{
#ifdef __SANDBOX_ENABLED__
BOOL accessingSecurityScopedResource = [item.outputURL startAccessingSecurityScopedResource];
#endif
- NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
- NSString *app = [workspace fullPathForApplication:[[NSUserDefaults standardUserDefaults] objectForKey:@"HBSendToApp"]];
+ NSWorkspace *workspace = NSWorkspace.sharedWorkspace;
+ NSString *app = [workspace fullPathForApplication:[NSUserDefaults.standardUserDefaults objectForKey:HBSendToApp]];
if (app)
{
NSUserDefaults *ud = NSUserDefaults.standardUserDefaults;
// Both the Notification and Sending to tagger can be done as encodes roll off the queue
- if ([ud integerForKey:@"HBAlertWhenDone"] == HBDoneActionNotification ||
- [ud integerForKey:@"HBAlertWhenDone"] == HBDoneActionAlertAndNotification)
+ if ([ud integerForKey:HBAlertWhenDone] == HBDoneActionNotification ||
+ [ud integerForKey:HBAlertWhenDone] == HBDoneActionAlertAndNotification)
{
// If Play System Alert has been selected in Preferences
- bool playSound = [ud boolForKey:@"HBAlertWhenDoneSound"];
+ bool playSound = [ud boolForKey:HBAlertWhenDoneSound];
NSString *title;
NSString *description;
[self showNotificationWithTitle:title
description:description
url:item.completeOutputURL
- playSound:playSound];
+ playSound:playSound];
}
}
{
NSUserDefaults *ud = NSUserDefaults.standardUserDefaults;
// If Play System Alert has been selected in Preferences
- if ([ud boolForKey:@"HBAlertWhenDoneSound"] == YES)
+ if ([ud boolForKey:HBAlertWhenDoneSound] == YES)
{
NSBeep();
}
// If Alert Window or Window and Notification has been selected
- if ([ud integerForKey:@"HBAlertWhenDone"] == HBDoneActionAlert ||
- [ud integerForKey:@"HBAlertWhenDone"] == HBDoneActionAlertAndNotification)
+ if ([ud integerForKey:HBAlertWhenDone] == HBDoneActionAlert ||
+ [ud integerForKey:HBAlertWhenDone] == HBDoneActionAlertAndNotification)
{
// On Screen Notification
NSAlert *alert = [[NSAlert alloc] init];
}
// If sleep has been selected
- if ([ud integerForKey:@"HBAlertWhenDone"] == HBDoneActionSleep)
+ if ([ud integerForKey:HBAlertWhenDone] == HBDoneActionSleep)
{
// Sleep
- NSDictionary *errorDict;
NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithSource:
@"tell application \"System Events\" to sleep"];
- [scriptObject executeAndReturnError: &errorDict];
+ [scriptObject executeAndReturnError:NULL];
}
+
// If Shutdown has been selected
- if ([ud integerForKey:@"HBAlertWhenDone"] == HBDoneActionShutDown)
+ if ([ud integerForKey:HBAlertWhenDone] == HBDoneActionShutDown)
{
// Shut Down
- NSDictionary *errorDict;
NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithSource:@"tell application \"System Events\" to shut down"];
- [scriptObject executeAndReturnError: &errorDict];
+ [scriptObject executeAndReturnError:NULL];
}
}
{
NSUserDefaults *ud = NSUserDefaults.standardUserDefaults;
- if ([ud integerForKey:@"HBAlertWhenDone"] == HBDoneActionSleep)
+ if ([ud integerForKey:HBAlertWhenDone] == HBDoneActionSleep)
{
// Warn that computer will sleep after encoding
NSBeep();
[self promptForAppleEventAuthorization];
}
- else if ([ud integerForKey:@"HBAlertWhenDone"] == HBDoneActionShutDown)
+ else if ([ud integerForKey:HBAlertWhenDone] == HBDoneActionShutDown)
{
// Warn that computer will shut down after encoding
NSBeep();
return bar;
}
+- (IBAction)_touchBar_toggleStartCancel:(id)sender
+{
+ [self toggleStartCancel:self];
+}
+
- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier
{
if ([identifier isEqualTo:HBTouchBarRip])
NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
item.customizationLabel = NSLocalizedString(@"Start/Stop Encoding", @"Touch bar");
- NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarPlayTemplate] target:self action:@selector(toggleStartCancel:)];
+ NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarPlayTemplate] target:self action:@selector(_touchBar_toggleStartCancel:)];
item.view = button;
return item;
-//
-// HBDetailsViewController.h
-// HandBrake
-//
-// Created by Damiano Galassi on 27/07/2019.
-//
+/* HBDetailsViewController.h $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
#import <Cocoa/Cocoa.h>
NS_ASSUME_NONNULL_BEGIN
@interface HBQueueDetailsViewController : NSViewController
-
@end
NS_ASSUME_NONNULL_END
-//
-// HBDetailsViewController.m
-// HandBrake
-//
-// Created by Damiano Galassi on 27/07/2019.
-//
+/* HBDetailsViewController.m $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
#import "HBQueueDetailsViewController.h"
@property (weak) id<HBQueueDetailsViewControllerDelegate> delegate;
+@property (nonatomic) BOOL canReset;
+
@end
@implementation HBQueueInfoViewController
{
NSNotificationCenter * __weak center = NSNotificationCenter.defaultCenter;
- [center addObserverForName:HBQueueDidCompleteItemNotification
+ [center addObserverForName:HBQueueDidStartItemNotification
object:nil
queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note)
{
- HBQueueItem *completedItem = note.userInfo[HBQueueItemNotificationItemKey];
+ HBQueueItem *startedItem = note.userInfo[HBQueueItemNotificationItemKey];
- if (completedItem == self.item)
+ if (startedItem == self.item)
{
[self updateLabels];
+ [self updateReset];
}
}];
if (completedItem == self.item)
{
[self updateLabels];
+ [self updateReset];
}
}];
+}
+- (void)updateReset
+{
+ self.canReset = self.item && (self.item.state != HBQueueItemStateWorking && self.item.state != HBQueueItemStateReady);
}
- (void)updateLabels
{
if (self.item)
{
- self.statisticsLabel.hidden = self.item.endedDate == nil;
- self.statisticsHeader.hidden = self.item.endedDate == nil;
+ self.statisticsLabel.hidden = self.item.startedDate == nil;
+ self.statisticsHeader.hidden = self.item.startedDate == nil;
self.summaryLabel.hidden = NO;
self.statisticsLabel.attributedStringValue = self.item.attributedStatistics;
{
_item = item;
[self updateLabels];
+ [self updateReset];
}
- (IBAction)editItem:(id)sender
[self.delegate detailsViewResetItem:self.item];
}
-
@end
- (NSAttributedString *)attributedStatistics
{
- if (self.endedDate == nil)
+ if (self.endedDate == nil && self.startedDate == nil)
{
return nil;
}
{
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
- [attrString appendString:@"\t" withAttributes:detailAttr];
- [attrString appendString:NSLocalizedString(@"Started at:", @"Job statistics") withAttributes:detailBoldAttr];
- [attrString appendString:@" \t" withAttributes:detailAttr];
- [attrString appendString:[_dateFormatter stringFromDate:self.startedDate] withAttributes:detailAttr];
- [attrString appendString:@"\n\t" withAttributes:detailAttr];
- [attrString appendString:NSLocalizedString(@"Ended at:", @"Job statistics") withAttributes:detailBoldAttr];
- [attrString appendString:@" \t" withAttributes:detailAttr];
- [attrString appendString:[_dateFormatter stringFromDate:self.endedDate] withAttributes:detailAttr];
- [attrString appendString:@"\n\n" withAttributes:shortHeightAttr];
- [attrString appendString:@"\t" withAttributes:detailAttr];
-
- [attrString appendString:NSLocalizedString(@"Run time:", @"Job statistics") withAttributes:detailBoldAttr];
- [attrString appendString:@" \t" withAttributes:detailAttr];
- uint64_t encodeDuration = (uint64_t)self.encodeDuration;
- [attrString appendString:[NSString stringWithFormat:@"%02lld:%02lld:%02lld", encodeDuration / 3600, (encodeDuration/ 60) % 60, encodeDuration % 60] withAttributes:detailAttr];
- [attrString appendString:@"\n\t" withAttributes:detailAttr];
- [attrString appendString:NSLocalizedString(@"Paused time:", @"Job statistics") withAttributes:detailBoldAttr];
- [attrString appendString:@" \t" withAttributes:detailAttr];
- uint64_t pauseDuration = (uint64_t)self.pauseDuration;
- [attrString appendString:[NSString stringWithFormat:@"%02lld:%02lld:%02lld", pauseDuration / 3600, (pauseDuration/ 60) % 60, pauseDuration % 60] withAttributes:detailAttr];
-
- [attrString appendString:@"\n\n" withAttributes:shortHeightAttr];
- [attrString appendString:@"\t" withAttributes:detailAttr];
-
- [attrString appendString:NSLocalizedString(@"Size:", @"Job statistics") withAttributes:detailBoldAttr];
- [attrString appendString:@" \t" withAttributes:detailAttr];
- [attrString appendString:[_byteFormatter stringFromByteCount:self.fileSize] withAttributes:detailAttr];
+ if (self.startedDate)
+ {
+ [attrString appendString:@"\t" withAttributes:detailAttr];
+ [attrString appendString:NSLocalizedString(@"Started at:", @"Job statistics") withAttributes:detailBoldAttr];
+ [attrString appendString:@" \t" withAttributes:detailAttr];
+ [attrString appendString:[_dateFormatter stringFromDate:self.startedDate] withAttributes:detailAttr];
+ }
+
+ if (self.startedDate && self.endedDate)
+ {
+ [attrString appendString:@"\n\t" withAttributes:detailAttr];
+ [attrString appendString:NSLocalizedString(@"Ended at:", @"Job statistics") withAttributes:detailBoldAttr];
+ [attrString appendString:@" \t" withAttributes:detailAttr];
+ [attrString appendString:[_dateFormatter stringFromDate:self.endedDate] withAttributes:detailAttr];
+ [attrString appendString:@"\n\n" withAttributes:shortHeightAttr];
+ [attrString appendString:@"\t" withAttributes:detailAttr];
+
+ [attrString appendString:NSLocalizedString(@"Run time:", @"Job statistics") withAttributes:detailBoldAttr];
+ [attrString appendString:@" \t" withAttributes:detailAttr];
+ uint64_t encodeDuration = (uint64_t)self.encodeDuration;
+ [attrString appendString:[NSString stringWithFormat:@"%02lld:%02lld:%02lld", encodeDuration / 3600, (encodeDuration/ 60) % 60, encodeDuration % 60] withAttributes:detailAttr];
+ [attrString appendString:@"\n\t" withAttributes:detailAttr];
+ [attrString appendString:NSLocalizedString(@"Paused time:", @"Job statistics") withAttributes:detailBoldAttr];
+ [attrString appendString:@" \t" withAttributes:detailAttr];
+ uint64_t pauseDuration = (uint64_t)self.pauseDuration;
+ [attrString appendString:[NSString stringWithFormat:@"%02lld:%02lld:%02lld", pauseDuration / 3600, (pauseDuration/ 60) % 60, pauseDuration % 60] withAttributes:detailAttr];
+
+ [attrString appendString:@"\n\n" withAttributes:shortHeightAttr];
+ [attrString appendString:@"\t" withAttributes:detailAttr];
+
+ [attrString appendString:NSLocalizedString(@"Size:", @"Job statistics") withAttributes:detailBoldAttr];
+ [attrString appendString:@" \t" withAttributes:detailAttr];
+ [attrString appendString:[_byteFormatter stringFromByteCount:self.fileSize] withAttributes:detailAttr];
+ }
_attributedStatistics = attrString;
}
self.pausedDate = nil;
}
+- (void)setStartedDate:(NSDate *)startedDate
+{
+ _startedDate = startedDate;
+ self.attributedStatistics = nil;
+}
+
- (void)setEndedDate:(NSDate *)endedDate
{
_endedDate = endedDate;
NSDictionary<NSURLResourceKey, id> *values = [self.completeOutputURL resourceValuesForKeys:@[NSURLFileSizeKey] error:NULL];
self.fileSize = [values[NSURLFileSizeKey] integerValue];
+
+ self.attributedStatistics = nil;
}
#pragma mark - NSSecureCoding
- (void)setItem:(HBQueueItem *)item
{
[super setItem:item];
+ [self removeObservers];
if (item.state == HBQueueItemStateWorking)
{
- [self removeObservers];
[self setUpObservers];
}
}
-//
-// HBQueueEmptyViewController.h
-// HandBrake
-//
-// Created by Damiano Galassi on 27/07/2019.
-//
+/* HBQueueEmptyViewController.h $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
#import <Cocoa/Cocoa.h>
-//
-// HBQueueEmptyViewController.m
-// HandBrake
-//
-// Created by Damiano Galassi on 27/07/2019.
-//
+/* HBQueueEmptyViewController.m $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
#import "HBQueueMultiSelectionViewController.h"
{
self.label.stringValue = [NSString stringWithFormat:NSLocalizedString(@"%llu jobs selected", @""), self.count];
}
-
}
- (void)setCount:(NSUInteger)count
HBQueueItem *item = self.queue.items[row];
- HBQueueItemView *view = item.state == HBQueueItemStateWorking ? [tableView makeViewWithIdentifier:@"MainWorkingCell" owner:self] : [tableView makeViewWithIdentifier:@"MainCell" owner:self];
+ HBQueueItemView *view = item.state == HBQueueItemStateWorking && item == self.queue.currentItem ?
+ [tableView makeViewWithIdentifier:@"MainWorkingCell" owner:self] :
+ [tableView makeViewWithIdentifier:@"MainCell" owner:self];
view.delegate = self;
view.item = item;
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
HBQueueItem *item = self.queue.items[row];
- return item.state == HBQueueItemStateWorking ? 58 : 22;
+ return item.state == HBQueueItemStateWorking && item == self.queue.currentItem ? 58 : 22;
}
#pragma mark NSQueueItemView delegate
@property (nonatomic, readwrite, weak, nullable) NSUndoManager *undo;
-@end
-
-@interface HBSubtitles (KVC)
-
@property (nonatomic, readonly) NSUInteger countOfTracks;
- (HBSubtitlesTrack *)objectInTracksAtIndex:(NSUInteger)index;
- (void)insertObject:(HBSubtitlesTrack *)audioObject inTracksAtIndex:(NSUInteger)index;
NS_ASSUME_NONNULL_BEGIN
-@class HBJob;
-
@interface HBUtilities : NSObject
/**
+ (NSURL *)mediaURLFromURL:(NSURL *)URL;
-+ (NSString *)automaticNameForJob:(HBJob *)job;
-+ (NSString *)automaticExtForJob:(HBJob *)job;
-+ (NSString *)defaultNameForJob:(HBJob *)job;
-
-/**
- * Generates a file name automatically based on the inputs,
- * it can be configured with NSUserDefaults.
- *
- * @param sourceName the name of the source file
- * @param title the title number
- * @param chaptersRange the selected chapters range
- * @param quality the video encoder quality
- * @param bitrate the video encoder bitrate
- * @param videoCodec the video encoder type
- *
- * @return a NSString containing the required info
- */
-+ (NSString *)automaticNameForSource:(NSString *)sourceName
- title:(NSUInteger)title
- chapters:(NSRange)chaptersRange
- quality:(double)quality
- bitrate:(int)bitrate
- videoCodec:(uint32_t)codec
- creationDate:(NSDate *)creationDate;
-
+ (NSString *)isoCodeForNativeLang:(NSString *)language;
+ (NSString *)iso6392CodeFor:(NSString *)language;
+ (NSString *)languageCodeForIso6392Code:(NSString *)language;
#import "HBUtilities.h"
#import <Cocoa/Cocoa.h>
-#import "HBTitle.h"
-#import "HBJob.h"
-
-#include "common.h"
#include "lang.h"
-static NSDateFormatter *_timeFormatter = nil;
-static NSDateFormatter *_dateFormatter = nil;
-static NSDateFormatter *_releaseDateFormatter = nil;
-
@implementation HBUtilities
-+ (void)initialize
-{
- if (self == [HBUtilities 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 *)handBrakeVersion
{
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSURL *mediaURL = URL;
// We check to see if the chosen file at path is a package
- if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:URL.path])
+ if ([NSWorkspace.sharedWorkspace isFilePackageAtPath:URL.path])
{
[HBUtilities writeToActivityLog:"trying to open a package at: %s", URL.path.UTF8String];
// We check to see if this is an .eyetv package
return mediaURL;
}
-+ (nullable NSDate *)releaseDate:(HBTitle *)title
-{
- if ([title.metadata.releaseDate length] == 0)
- {
- return nil;
- }
- else
- {
- return [_releaseDateFormatter dateFromString:title.metadata.releaseDate];
- }
-}
-
-+ (NSString *)automaticNameForJob:(HBJob *)job
-{
- HBTitle *title = job.title;
-
- NSDate *releaseDate = [self releaseDate:title];
- if (releaseDate == nil)
- {
- NSDictionary* fileAttribs = [[NSFileManager defaultManager] attributesOfItemAtPath:job.fileURL.path error:nil];
- releaseDate = [fileAttribs objectForKey:NSFileCreationDate];
- }
-
- // Generate a new file name
- NSString *fileName = [HBUtilities automaticNameForSource:title.name
- title:title.index
- chapters:NSMakeRange(job.range.chapterStart + 1, job.range.chapterStop + 1)
- quality:job.video.qualityType ? job.video.quality : 0
- bitrate:!job.video.qualityType ? job.video.avgBitrate : 0
- videoCodec:job.video.encoder
- creationDate:releaseDate];
- return fileName;
-}
-
-+ (NSString *)automaticExtForJob:(HBJob *)job
-{
- NSString *extension = @(hb_container_get_default_extension(job.container));
-
- if (job.container & HB_MUX_MASK_MP4)
- {
- BOOL anyCodecAC3 = [job.audio anyCodecMatches:HB_ACODEC_AC3] || [job.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 = (job.chaptersEnabled) &&
- (job.range.type != HBRangeTypeChapters || job.range.chapterStart < job.range.chapterStop);
-
- NSString *defaultExtension = [[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultMpegExtension"];
-
- if ([defaultExtension isEqualToString:@".m4v"] ||
- ((YES == anyCodecAC3 || YES == chapterMarkers) && [defaultExtension isEqualToString:@"Auto"]))
- {
- extension = @"m4v";
- }
- }
-
- return extension;
-}
-
-+ (NSString *)defaultNameForJob:(HBJob *)job
-{
- // Generate a new file name
- NSString *fileName = job.title.name;
-
- // If Auto Naming is on. We create an output filename by using the
- // format set int he preferences.
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"])
- {
- fileName = [self automaticNameForJob:job];
- }
-
- // use the correct extension based on the container
- NSString *ext = [self automaticExtForJob:job];
- 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
-{
- NSMutableString *name = [[NSMutableString alloc] init];
- // The format array contains the tokens as NSString
- NSArray<NSString *> *format = [[NSUserDefaults standardUserDefaults] objectForKey:@"HBAutoNamingFormat"];
-
- for (NSString *formatKey in format)
- {
- if ([formatKey isEqualToString:@"{Source}"])
- {
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HBAutoNamingRemoveUnderscore"])
- {
- sourceName = [sourceName stringByReplacingOccurrencesOfString:@"_" withString:@" "];
- }
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HBAutoNamingRemovePunctuation"])
- {
- sourceName = [sourceName stringByReplacingOccurrencesOfString:@"-" withString:@""];
- sourceName = [sourceName stringByReplacingOccurrencesOfString:@"." withString:@""];
- sourceName = [sourceName stringByReplacingOccurrencesOfString:@"," withString:@""];
- sourceName = [sourceName stringByReplacingOccurrencesOfString:@";" withString:@""];
- }
- if ([[NSUserDefaults standardUserDefaults] 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];
-}
-
+ (NSString *)isoCodeForNativeLang:(NSString *)language
{
const iso639_lang_t *lang = lang_get_next(NULL);
It may be used under the terms of the GNU General Public License. */
#import "HBVideoController.h"
+#import "HBPreferencesKeys.h"
@import HandBrakeKit;
{
// Encoders that allow fractional CQ values often have a low granularity
// which makes the slider hard to use, so use a value from preferences.
- granularity = 1.0f / [[NSUserDefaults standardUserDefaults]
- integerForKey:@"HBx264CqSliderFractional"];
+ granularity = 1.0f / [NSUserDefaults.standardUserDefaults
+ integerForKey:HBCqSliderFractional];
}
fVidQualitySlider.minValue = minValue;
fVidQualitySlider.maxValue = maxValue;
A939DD8B1FC8826A00135F2A /* HBPresetsMenuBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = A939DD8A1FC8826A00135F2A /* HBPresetsMenuBuilder.m */; };
A93B49221DA3AA6900DD70A3 /* HBToolbarBadgedItem.m in Sources */ = {isa = PBXBuildFile; fileRef = A93B49211DA3AA6900DD70A3 /* HBToolbarBadgedItem.m */; };
A93E0ED31972957000FD67FB /* HBVideoController.m in Sources */ = {isa = PBXBuildFile; fileRef = A93E0ED11972957000FD67FB /* HBVideoController.m */; };
+ A943874122ED911B005F701B /* HBJob+HBAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A943874022ED911B005F701B /* HBJob+HBAdditions.m */; };
A94A98F51C858EFB004BA9BA /* HBDictTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A94A98F41C858EFB004BA9BA /* HBDictTests.m */; };
A94DC2DE20CADA2C00EAC8FD /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = A94DC2DC20CADA2C00EAC8FD /* MainWindow.xib */; };
A95121E61B5F7BE700FD773D /* NSArray+HBAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A95121E51B5F7BE700FD773D /* NSArray+HBAdditions.m */; };
A93FD4731A62ABE800A6AC43 /* HBAudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBAudio.h; sourceTree = "<group>"; };
A93FD4741A62ABE800A6AC43 /* HBAudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBAudio.m; sourceTree = "<group>"; };
A941ACB91CD75B4E0029D06A /* HBHUD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBHUD.h; sourceTree = "<group>"; };
+ A943873F22ED911B005F701B /* HBJob+HBAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HBJob+HBAdditions.h"; sourceTree = "<group>"; };
+ A943874022ED911B005F701B /* HBJob+HBAdditions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "HBJob+HBAdditions.m"; sourceTree = "<group>"; };
+ A945CC3122ED7C6A00E9C2E3 /* HBPreferencesKeys.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HBPreferencesKeys.h; sourceTree = "<group>"; };
A94A98F41C858EFB004BA9BA /* HBDictTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBDictTests.m; sourceTree = "<group>"; };
A94DC2DD20CADA2C00EAC8FD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainWindow.xib; sourceTree = "<group>"; };
A95121E41B5F7BE700FD773D /* NSArray+HBAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+HBAdditions.h"; sourceTree = "<group>"; };
A9E52CD6218DD52A00E17B86 /* ExceptionAlert.xib */,
A95121E41B5F7BE700FD773D /* NSArray+HBAdditions.h */,
A95121E51B5F7BE700FD773D /* NSArray+HBAdditions.m */,
+ A943873F22ED911B005F701B /* HBJob+HBAdditions.h */,
+ A943874022ED911B005F701B /* HBJob+HBAdditions.m */,
273F20BD14ADC09F0021BE6D /* main.mm */,
);
name = Others;
273F209B14ADBE670021BE6D /* HBOutputPanelController.h */,
273F209C14ADBE670021BE6D /* HBOutputPanelController.m */,
A9A96BDB20CAD66000A39AFB /* OutputPanel.xib */,
+ A945CC3122ED7C6A00E9C2E3 /* HBPreferencesKeys.h */,
273F209F14ADBE670021BE6D /* HBPreferencesController.h */,
273F20A014ADBE670021BE6D /* HBPreferencesController.m */,
A9A96BDE20CAD66500A39AFB /* Preferences.xib */,
A916C9991C8449E200C7B560 /* main.mm in Sources */,
A973E10C216E74E900D498EC /* HBThumbnailItemView.m in Sources */,
A916C9981C8449DB00C7B560 /* HBTitleSelectionController.m in Sources */,
+ A943874122ED911B005F701B /* HBJob+HBAdditions.m in Sources */,
A96127E422E09ADD0086E6DC /* HBQueueTableViewController.m in Sources */,
A903C5601CCE78060026B0ED /* NSWindow+HBAdditions.m in Sources */,
A9A0CBE81CCEA3670045B3DF /* HBPlayerTrack.m in Sources */,