diff options
Diffstat (limited to 'macosx')
30 files changed, 1298 insertions, 290 deletions
diff --git a/macosx/HBAudio.m b/macosx/HBAudio.m index 231b7bc2e..cdd929efb 100644 --- a/macosx/HBAudio.m +++ b/macosx/HBAudio.m @@ -278,7 +278,7 @@ NSString *HBAudioEncoderChangedNotification = @"HBAudioEncoderChangedNotificatio self = [super init]; decodeInt(_container); if (_container != HB_MUX_MP4 && _container != HB_MUX_MKV && _container != HB_MUX_WEBM) { goto fail; } - decodeCollectionOfObjects(_sourceTracks, NSArray, NSDictionary); + decodeCollectionOfObjects3(_sourceTracks, NSArray, NSDictionary, NSString, NSNumber); decodeCollectionOfObjects(_tracks, NSMutableArray, HBAudioTrack); for (HBAudioTrack *track in _tracks) diff --git a/macosx/HBCodingUtilities.h b/macosx/HBCodingUtilities.h index 8635720ea..e0f3e1f04 100644 --- a/macosx/HBCodingUtilities.h +++ b/macosx/HBCodingUtilities.h @@ -25,5 +25,9 @@ #define decodeCollectionOfObjects3(x, cl, objectcl, objectcl2, objectcl3) x = [decoder decodeObjectOfClasses:[NSSet setWithObjects:[cl class], [objectcl class], [objectcl2 class], [objectcl3 class], nil] forKey:OBJC_STRINGIFY(x)]; +#define decodeCollectionOfObjects4(x, cl, objectcl, objectcl2, objectcl3, objectcl4) x = [decoder decodeObjectOfClasses:[NSSet setWithObjects:[cl class], [objectcl class], [objectcl2 class], [objectcl3 class], [objectcl4 class], nil] forKey:OBJC_STRINGIFY(x)]; + +#define decodeCollectionOfObjects5(x, cl, objectcl, objectcl2, objectcl3, objectcl4, objectcl5) x = [decoder decodeObjectOfClasses:[NSSet setWithObjects:[cl class], [objectcl class], [objectcl2 class], [objectcl3 class], [objectcl4 class], [objectcl5 class], nil] forKey:OBJC_STRINGIFY(x)]; + #define decodeObjectOrFail(x, cl) x = [decoder decodeObjectOfClass:[cl class] forKey:OBJC_STRINGIFY(x)]; if (x == nil) {NSLog(@"Failed to decode: %@", OBJC_STRINGIFY(x)); goto fail;} diff --git a/macosx/HBController.m b/macosx/HBController.m index c2a4716f0..8f45ca51f 100644 --- a/macosx/HBController.m +++ b/macosx/HBController.m @@ -41,7 +41,6 @@ #import "HBPreferencesKeys.h" static void *HBControllerScanCoreContext = &HBControllerScanCoreContext; -static void *HBControllerQueueCoreContext = &HBControllerQueueCoreContext; @interface HBController () <HBPresetsViewControllerDelegate, HBTitleSelectionDelegate, NSDraggingDestination, NSPopoverDelegate> { @@ -279,13 +278,9 @@ static void *HBControllerQueueCoreContext = &HBControllerQueueCoreContext; options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial context:HBControllerScanCoreContext]; - [self.queue.core addObserver:self forKeyPath:@"state" - options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial - context:HBControllerQueueCoreContext]; - - [self.queue addObserver:self forKeyPath:@"pendingItemsCount" - options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial - context:HBControllerQueueCoreContext]; + [NSNotificationCenter.defaultCenter addObserverForName:HBQueueDidChangeStateNotification object:_queue queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note) { + [self updateQueueUI]; + }]; [NSNotificationCenter.defaultCenter addObserverForName:HBQueueDidStartNotification object:_queue queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note) { self.bottomConstrain.animator.constant = 0; @@ -383,24 +378,25 @@ static void *HBControllerQueueCoreContext = &HBControllerQueueCoreContext; [self _touchBar_validateUserInterfaceItems]; } } - else if (context == HBControllerQueueCoreContext) - { - [self updateToolbarButtonsState]; - [self.window.toolbar validateVisibleItems]; - if (@available(macOS 10.12.2, *)) - { - [self _touchBar_updateQueueButtonsState]; - [self _touchBar_validateUserInterfaceItems]; - } - NSUInteger count = self.queue.pendingItemsCount; - self.showQueueToolbarItem.badgeValue = count ? @(count).stringValue : nil; - } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } +- (void)updateQueueUI +{ + [self updateToolbarButtonsState]; + [self.window.toolbar validateVisibleItems]; + if (@available(macOS 10.12.2, *)) + { + [self _touchBar_updateQueueButtonsState]; + [self _touchBar_validateUserInterfaceItems]; + } + NSUInteger count = self.queue.pendingItemsCount; + self.showQueueToolbarItem.badgeValue = count ? @(count).stringValue : nil; +} + - (void)updateToolbarButtonsStateForScanCore:(HBState)state { if (state == HBStateIdle) diff --git a/macosx/HBOutputFileWriter.h b/macosx/HBOutputFileWriter.h index a6e22680c..480f198ca 100644 --- a/macosx/HBOutputFileWriter.h +++ b/macosx/HBOutputFileWriter.h @@ -5,7 +5,7 @@ It may be used under the terms of the GNU General Public License. */ #import <Foundation/Foundation.h> -#import "HBOutputRedirect.h" +#import "HBRedirect.h" NS_ASSUME_NONNULL_BEGIN diff --git a/macosx/HBOutputFileWriter.m b/macosx/HBOutputFileWriter.m index 8534308c9..bbc802492 100644 --- a/macosx/HBOutputFileWriter.m +++ b/macosx/HBOutputFileWriter.m @@ -74,12 +74,7 @@ fflush(f); } -- (void)stdoutRedirect:(NSString *)text -{ - [self write:text]; -} - -- (void)stderrRedirect:(NSString *)text +- (void)redirect:(NSString *)text type:(HBRedirectType)type { [self write:text]; } diff --git a/macosx/HBOutputPanelController.h b/macosx/HBOutputPanelController.h index 32907b02b..2a1b6c282 100644 --- a/macosx/HBOutputPanelController.h +++ b/macosx/HBOutputPanelController.h @@ -1,9 +1,8 @@ -/** - * @file - * @date 18.5.2007 - * - * Interface of class HBOutputPanelController. - */ +/* HBOutputPanelController.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> diff --git a/macosx/HBOutputPanelController.m b/macosx/HBOutputPanelController.m index 3ea4d776f..3cfec6caa 100644 --- a/macosx/HBOutputPanelController.m +++ b/macosx/HBOutputPanelController.m @@ -1,15 +1,13 @@ -/** - * @file - * @date 18.5.2007 - * - * Implementation of class HBOutputPanelController. - */ +/* HBOutputPanelController.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 "HBOutputPanelController.h" #import "HBOutputRedirect.h" #import "HBOutputFileWriter.h" #import "HBUtilities.h" -#import "project.h" /// Maximum amount of characters that can be shown in the view. #define TextStorageUpperSizeLimit 125000 @@ -19,19 +17,17 @@ #define TextStorageLowerSizeLimit 120000 @interface HBOutputPanelController () <HBOutputRedirectListening> -{ - /// Textview that displays debug output. - IBOutlet NSTextView *textView; - /// Text storage for the debug output. - NSTextStorage *outputTextStorage; -} +/// Textview that displays debug output. +@property (nonatomic, unsafe_unretained) IBOutlet NSTextView *textView; + +/// Text storage for the debug output. +@property (nonatomic, readonly) NSTextStorage *outputTextStorage; +@property (nonatomic, readonly) NSDictionary *textAttributes; /// Path to log text file. @property (nonatomic, copy, readonly) HBOutputFileWriter *outputFile; -@property (nonatomic, readonly) NSDictionary *textAttributes; - @end @implementation HBOutputPanelController @@ -43,101 +39,90 @@ { if( (self = [super initWithWindowNibName:@"OutputPanel"]) ) { - /* NSWindowController likes to lazily load its window nib. Since this - * controller tries to touch the outlets before accessing the window, we - * need to force it to load immediately by invoking its accessor. - * - * If/when we switch to using bindings, this can probably go away. - */ - (void)[self window]; + // We initialize the outputTextStorage object for the activity window + _outputTextStorage = [[NSTextStorage alloc] init]; + + // Text attributes + _textAttributes = @{NSForegroundColorAttributeName: NSColor.textColor}; - // Additionally, redirect the output to a file on the disk. - NSURL *outputLogFile = [[HBUtilities appSupportURL] URLByAppendingPathComponent:@"HandBrake-activitylog.txt"]; + // Add ourself as stderr/stdout listener + [HBOutputRedirect.stderrRedirect addListener:self queue:dispatch_get_main_queue()]; + [HBOutputRedirect.stdoutRedirect addListener:self queue:dispatch_get_main_queue()]; + + // Redirect the output to a file on the disk. + NSURL *outputLogFile = [HBUtilities.appSupportURL URLByAppendingPathComponent:@"HandBrake-activitylog.txt"]; _outputFile = [[HBOutputFileWriter alloc] initWithFileURL:outputLogFile]; if (_outputFile) { - [[HBOutputRedirect stderrRedirect] addListener:_outputFile]; - [[HBOutputRedirect stdoutRedirect] addListener:_outputFile]; + [HBOutputRedirect.stderrRedirect addListener:_outputFile queue:dispatch_get_main_queue()]; + [HBOutputRedirect.stdoutRedirect addListener:_outputFile queue:dispatch_get_main_queue()]; } - // We initialize the outputTextStorage object for the activity window - outputTextStorage = [[NSTextStorage alloc] init]; - [[textView layoutManager] replaceTextStorage:outputTextStorage]; - [[textView enclosingScrollView] setLineScroll:10]; - [[textView enclosingScrollView] setPageScroll:20]; - - // Text attributes - _textAttributes = @{NSForegroundColorAttributeName: [NSColor textColor]}; - - // Add ourself as stderr/stdout listener - [[HBOutputRedirect stderrRedirect] addListener:self]; - [[HBOutputRedirect stdoutRedirect] addListener:self]; - - // Lets report the HandBrake version number here to the activity log and text log file - NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; - NSString *versionStringFull = [NSString stringWithFormat:@"Handbrake Version: %@ (%@)", infoDict[@"CFBundleShortVersionString"], infoDict[@"CFBundleVersion"]]; - [HBUtilities writeToActivityLog: "%s", versionStringFull.UTF8String]; - - // Lets also report the hardening status to the activity log, if enabled -#if HB_PROJECT_HOST_HARDEN == 1 - [HBUtilities writeToActivityLog:"Compile-time hardening features are enabled"]; -#endif + [self writeHeader]; } return self; } -/** - * Stops redirection of stderr and releases resources. - */ - (void)dealloc { - [[HBOutputRedirect stderrRedirect] removeListener:self]; - [[HBOutputRedirect stdoutRedirect] removeListener:self]; + [HBOutputRedirect.stderrRedirect removeListener:self]; + [HBOutputRedirect.stdoutRedirect removeListener:self]; +} + +- (void)windowDidLoad +{ + [super windowDidLoad]; + + [_textView.layoutManager replaceTextStorage:_outputTextStorage]; + [_textView.enclosingScrollView setLineScroll:10]; + [_textView.enclosingScrollView setPageScroll:20]; + + [_textView scrollToEndOfDocument:self]; } -/** - * Loads output panel from OutputPanel.nib and shows it. - */ - (IBAction)showWindow:(id)sender { - [textView scrollToEndOfDocument:self]; + [_textView scrollToEndOfDocument:self]; [super showWindow:sender]; } +- (void)writeHeader +{ + // Lets report the HandBrake version number here to the activity log and text log file + NSDictionary *infoDict = NSBundle.mainBundle.infoDictionary; + NSString *versionStringFull = [NSString stringWithFormat:@"Handbrake Version: %@ (%@)", infoDict[@"CFBundleShortVersionString"], infoDict[@"CFBundleVersion"]]; + [HBUtilities writeToActivityLog:"%s", versionStringFull.UTF8String]; +} + /** * Displays text received from HBOutputRedirect in the text view - * and write it to the log files. */ -- (void)stderrRedirect:(NSString *)text +- (void)redirect:(NSString *)text type:(HBRedirectType)type { NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:text attributes:_textAttributes]; - /* Actually write the libhb output to the text view (outputTextStorage) */ - [outputTextStorage appendAttributedString:attributedString]; + // Actually write the libhb output to the text view (outputTextStorage) + [_outputTextStorage appendAttributedString:attributedString]; - /* remove text from outputTextStorage as defined by TextStorageUpperSizeLimit and TextStorageLowerSizeLimit */ - if (outputTextStorage.length > TextStorageUpperSizeLimit) + // remove text from outputTextStorage as defined by TextStorageUpperSizeLimit and TextStorageLowerSizeLimit */ + if (_outputTextStorage.length > TextStorageUpperSizeLimit) { - [outputTextStorage deleteCharactersInRange:NSMakeRange(0, [outputTextStorage length] - TextStorageLowerSizeLimit)]; + [_outputTextStorage deleteCharactersInRange:NSMakeRange(0, _outputTextStorage.length - TextStorageLowerSizeLimit)]; } - if (self.window.isVisible) + if (self.windowLoaded && self.window.isVisible) { - [textView scrollToEndOfDocument:self]; + [_textView scrollToEndOfDocument:self]; } } -- (void)stdoutRedirect:(NSString *)text { [self stderrRedirect:text]; } /** * Clears the output window. */ - (IBAction)clearOutput:(id)sender { - [outputTextStorage deleteCharactersInRange:NSMakeRange(0, [outputTextStorage length])]; - /* We want to rewrite the app version info to the top of the activity window so it is always present */ - time_t _now = time( NULL ); - struct tm * now = localtime( &_now ); - fprintf(stderr, "[%02d:%02d:%02d] macgui: %s\n", now->tm_hour, now->tm_min, now->tm_sec, [[HBUtilities handBrakeVersion] UTF8String]); + [_outputTextStorage deleteCharactersInRange:NSMakeRange(0, _outputTextStorage.length)]; + [self writeHeader]; } /** @@ -145,9 +130,9 @@ */ - (IBAction)copyAllOutputToPasteboard:(id)sender { - NSPasteboard *pboard = [NSPasteboard generalPasteboard]; + NSPasteboard *pboard = NSPasteboard.generalPasteboard; [pboard declareTypes:@[NSPasteboardTypeString] owner:nil]; - [pboard setString:[outputTextStorage string] forType:NSPasteboardTypeString]; + [pboard setString:_outputTextStorage.string forType:NSPasteboardTypeString]; } /** @@ -155,8 +140,8 @@ */ - (IBAction)openActivityLogFile:(id)sender { - /* Opens the activity window log file in the users default text editor */ - [[NSWorkspace sharedWorkspace] openURL:self.outputFile.url]; + // Opens the activity window log file in the users default text editor + [NSWorkspace.sharedWorkspace openURL:self.outputFile.url]; } /** @@ -164,16 +149,16 @@ */ - (IBAction)openEncodeLogDirectory:(id)sender { - /* Opens the activity window log file in the users default text editor */ - NSURL *encodeLogDirectory = [[HBUtilities appSupportURL] URLByAppendingPathComponent:@"EncodeLogs"]; - if( ![[NSFileManager defaultManager] fileExistsAtPath:encodeLogDirectory.path] ) + // Opens the activity window log file in the users default text editor + NSURL *encodeLogDirectory = [HBUtilities.appSupportURL URLByAppendingPathComponent:@"EncodeLogs"]; + if (![NSFileManager.defaultManager fileExistsAtPath:encodeLogDirectory.path]) { - [[NSFileManager defaultManager] createDirectoryAtPath:encodeLogDirectory.path - withIntermediateDirectories:NO - attributes:nil - error:nil]; + [NSFileManager.defaultManager createDirectoryAtPath:encodeLogDirectory.path + withIntermediateDirectories:NO + attributes:nil + error:nil]; } - [[NSWorkspace sharedWorkspace] openURL:encodeLogDirectory]; + [NSWorkspace.sharedWorkspace openURL:encodeLogDirectory]; } - (IBAction)clearActivityLogFile:(id)sender diff --git a/macosx/HBOutputRedirect.h b/macosx/HBOutputRedirect.h index 6c1fc718c..8a429f9ff 100644 --- a/macosx/HBOutputRedirect.h +++ b/macosx/HBOutputRedirect.h @@ -6,16 +6,10 @@ */ #import <Foundation/Foundation.h> +#import "HBRedirect.h" NS_ASSUME_NONNULL_BEGIN -@protocol HBOutputRedirectListening <NSObject> - -- (void)stdoutRedirect:(NSString *)text; -- (void)stderrRedirect:(NSString *)text; - -@end - /** * This class is used to redirect @c stdout and @c stderr outputs. It is never * created directly; @c stdoutRedirect and @c stderrRedirect class methods @@ -27,13 +21,7 @@ NS_ASSUME_NONNULL_BEGIN * universal redirecting is needed, it can be done at file descriptor * level. */ -@interface HBOutputRedirect : NSObject - -+ (instancetype)stdoutRedirect; -+ (instancetype)stderrRedirect; - -- (void)addListener:(id <HBOutputRedirectListening>)aListener; -- (void)removeListener:(id <HBOutputRedirectListening>)aListener; +@interface HBOutputRedirect : HBRedirect @end diff --git a/macosx/HBOutputRedirect.m b/macosx/HBOutputRedirect.m index 9aff9eb31..6e94c3747 100644 --- a/macosx/HBOutputRedirect.m +++ b/macosx/HBOutputRedirect.m @@ -17,28 +17,13 @@ static int stdoutwrite(void *inFD, const char *buffer, int size); static int stderrwrite(void *inFD, const char *buffer, int size); @interface HBOutputRedirect () -{ - /// Set that contains all registered listeners for this output. - NSMutableSet *listeners; - - /// Selector that is called on listeners to forward the output. - SEL forwardingSelector; - - /// Output stream (@c stdout or @c stderr) redirected by this object. - FILE *stream; - - /// Pointer to old write function for the stream. - int (*oldWriteFunc)(void *, const char *, int); -} -@end +/// Output stream (@c stdout or @c stderr) redirected by this object. +@property (nonatomic, readonly) FILE *stream; +/// Pointer to old write function for the stream. +@property (nonatomic, readonly) int (*oldWriteFunc)(void *, const char *, int); -@interface HBOutputRedirect (Private) -- (instancetype)initWithStream:(FILE *)aStream selector:(SEL)aSelector; -- (void)startRedirect; -- (void)stopRedirect; -- (void)forwardOutput:(NSData *)data; @end /** @@ -48,8 +33,11 @@ int stdoutwrite(void *inFD, const char *buffer, int size) { @autoreleasepool { - NSData *data = [[NSData alloc] initWithBytes:buffer length:size]; - [g_stdoutRedirect performSelectorOnMainThread:@selector(forwardOutput:) withObject:data waitUntilDone:NO]; + NSString *string = [[NSString alloc] initWithBytes:buffer length:size encoding:NSUTF8StringEncoding]; + if (string) + { + [g_stdoutRedirect forwardOutput:string]; + } } return size; } @@ -58,8 +46,11 @@ int stderrwrite(void *inFD, const char *buffer, int size) { @autoreleasepool { - NSData *data = [[NSData alloc] initWithBytes:buffer length:size]; - [g_stderrRedirect performSelectorOnMainThread:@selector(forwardOutput:) withObject:data waitUntilDone:NO]; + NSString *string = [[NSString alloc] initWithBytes:buffer length:size encoding:NSUTF8StringEncoding]; + if (string) + { + [g_stderrRedirect forwardOutput:string]; + } } return size; } @@ -72,8 +63,9 @@ int stderrwrite(void *inFD, const char *buffer, int size) + (instancetype)stdoutRedirect { if (!g_stdoutRedirect) - g_stdoutRedirect = [[HBOutputRedirect alloc] initWithStream:stdout selector:@selector(stdoutRedirect:)]; - + { + g_stdoutRedirect = [[HBOutputRedirect alloc] initWithStream:stdout type:HBRedirectTypeOutput]; + } return g_stdoutRedirect; } @@ -83,73 +75,27 @@ int stderrwrite(void *inFD, const char *buffer, int size) + (instancetype)stderrRedirect { if (!g_stderrRedirect) - g_stderrRedirect = [[HBOutputRedirect alloc] initWithStream:stderr selector:@selector(stderrRedirect:)]; - + { + g_stderrRedirect = [[HBOutputRedirect alloc] initWithStream:stderr type:HBRedirectTypeError]; + } return g_stderrRedirect; } /** - * Adds specified object as listener for this output. Method @c stdoutRedirect: - * or @c stderrRedirect: of the listener is called to redirect the output. - */ -- (void)addListener:(id <HBOutputRedirectListening>)aListener -{ - NSAssert2([aListener respondsToSelector:forwardingSelector], @"Object %@ doesn't respond to selector \"%@\"", aListener, NSStringFromSelector(forwardingSelector)); - - if (![listeners containsObject:aListener]) - { - [listeners addObject:aListener]; - } - - if ([listeners count] > 0) - [self startRedirect]; -} - -/** - * Stops forwarding for this output to the specified listener object. - */ -- (void)removeListener:(id <HBOutputRedirectListening>)aListener -{ - if ([listeners containsObject:aListener]) - { - [listeners removeObject:aListener]; - } - - // If last listener is removed, stop redirecting output and autorelease - // self. Remember to set proper global pointer to NULL so the object is - // recreated again when needed. - if ([listeners count] == 0) - { - [self stopRedirect]; - - if (self == g_stdoutRedirect) - g_stdoutRedirect = nil; - else if (self == g_stderrRedirect) - g_stderrRedirect = nil; - } -} - -@end - -@implementation HBOutputRedirect (Private) - -/** * Private constructor which should not be called from outside. This is used to * initialize the class at @c stdoutRedirect and @c stderrRedirect. * - * @param aStream Stream that will be redirected (stdout or stderr). - * @param aSelector Selector that will be called in listeners to redirect the stream. + * @param stream Stream that will be redirected (stdout or stderr). + * @param type Type that will be called in listeners to redirect the stream. * * @return New HBOutputRedirect object. */ -- (instancetype)initWithStream:(FILE *)aStream selector:(SEL)aSelector +- (instancetype)initWithStream:(FILE *)stream type:(HBRedirectType)type { - if (self = [super init]) + if (self = [self initWithType:type]) { - listeners = [[NSMutableSet alloc] init]; - forwardingSelector = aSelector; - stream = aStream; - oldWriteFunc = NULL; + _stream = stream; + _oldWriteFunc = NULL; } return self; } @@ -161,10 +107,10 @@ int stderrwrite(void *inFD, const char *buffer, int size) */ - (void)startRedirect { - if (!oldWriteFunc) + if (!_oldWriteFunc) { - oldWriteFunc = stream->_write; - stream->_write = stream == stdout ? stdoutwrite : stderrwrite; + _oldWriteFunc = _stream->_write; + _stream->_write = _stream == stdout ? stdoutwrite : stderrwrite; } } @@ -174,24 +120,11 @@ int stderrwrite(void *inFD, const char *buffer, int size) */ - (void)stopRedirect { - if (oldWriteFunc) + if (_oldWriteFunc) { - stream->_write = oldWriteFunc; - oldWriteFunc = NULL; + _stream->_write = _oldWriteFunc; + _oldWriteFunc = NULL; } } -/** - * Called from @c stdoutwrite() and @c stderrwrite() to forward the output to - * listeners. - */ -- (void)forwardOutput:(NSData *)data -{ - NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - if (string) - { - [listeners makeObjectsPerformSelector:forwardingSelector withObject:string]; - } -} - @end diff --git a/macosx/HBQueue.h b/macosx/HBQueue.h index d1205b6fe..036df8d27 100644 --- a/macosx/HBQueue.h +++ b/macosx/HBQueue.h @@ -6,13 +6,15 @@ #import <Foundation/Foundation.h> -#import "HBCore.h" #import "HBDistributedArray.h" #import "HBQueueItem.h" #import "HBJobOutputFileWriter.h" NS_ASSUME_NONNULL_BEGIN +extern NSString * const HBQueueDidChangeStateNotification; +extern NSString * const HBQueueNotificationStateKey; // HBState + extern NSString * const HBQueueDidAddItemNotification; extern NSString * const HBQueueDidRemoveItemNotification; extern NSString * const HBQueueDidChangeItemNotification; @@ -45,11 +47,9 @@ extern NSString * const HBQueueItemNotificationItemKey; // HBQueueI - (instancetype)init NS_UNAVAILABLE; - (instancetype)initWithURL:(NSURL *)queueURL; -@property (nonatomic, readonly) HBCore *core; @property (nonatomic, readonly) HBDistributedArray<HBQueueItem *> *items; @property (nonatomic, nullable) HBQueueItem *currentItem; -@property (nonatomic, nullable) HBJobOutputFileWriter *currentLog; @property (nonatomic) NSUInteger pendingItemsCount; @property (nonatomic) NSUInteger failedItemsCount; diff --git a/macosx/HBQueue.m b/macosx/HBQueue.m index 498905f17..7e285c185 100644 --- a/macosx/HBQueue.m +++ b/macosx/HBQueue.m @@ -5,8 +5,15 @@ It may be used under the terms of the GNU General Public License. */ #import "HBQueue.h" -#import "NSArray+HBAdditions.h" +#import "HBRemoteCore.h" + #import "HBPreferencesKeys.h" +#import "NSArray+HBAdditions.h" + +static void *HBQueueContext = &HBQueueContext; + +NSString * const HBQueueDidChangeStateNotification = @"HBQueueDidChangeStateNotification"; +NSString * const HBQueueNotificationStateKey = @"HBQueueNotificationStateKey"; NSString * const HBQueueDidAddItemNotification = @"HBQueueDidAddItemNotification"; NSString * const HBQueueDidRemoveItemNotification = @"HBQueueDidRemoveItemNotification"; @@ -38,8 +45,11 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK @interface HBQueue () +@property (nonatomic, readonly) HBRemoteCore *core; @property (nonatomic) BOOL stop; +@property (nonatomic, nullable) HBJobOutputFileWriter *currentLog; + @end @implementation HBQueue @@ -52,7 +62,7 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK NSInteger loggingLevel = [NSUserDefaults.standardUserDefaults integerForKey:HBLoggingLevel]; // Init a separate instance of libhb for the queue - _core = [[HBCore alloc] initWithLogLevel:loggingLevel name:@"QueueCore"]; + _core = [[HBRemoteCore alloc] initWithLogLevel:loggingLevel name:@"QueueCore"]; _core.automaticallyPreventSleep = NO; _items = [[HBDistributedArray alloc] initWithURL:queueURL class:[HBQueueItem class]]; @@ -62,10 +72,28 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadQueue) name:HBDistributedArrayChanged object:_items]; [self updateStats]; + + // Set up observers + [self.core addObserver:self forKeyPath:@"state" + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial + context:HBQueueContext]; + } return self; } +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if (context == HBQueueContext) + { + [NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidChangeStateNotification object:self userInfo:@{HBQueueNotificationStateKey: @(self.core.state)}]; + } + else + { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + #pragma mark - Public methods - (void)addJob:(HBJob *)item @@ -466,6 +494,8 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK self.pendingItemsCount = pendingCount; self.failedItemsCount = failedCount; self.completedItemsCount = completedCount; + + [NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidChangeStateNotification object:self userInfo:@{HBQueueNotificationStateKey: @(self.core.state)}]; } - (BOOL)isDiskSpaceLowAtURL:(NSURL *)url @@ -563,8 +593,9 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK self.currentLog = [[HBJobOutputFileWriter alloc] initWithJob:nextItem.job]; if (self.currentLog) { - [[HBOutputRedirect stderrRedirect] addListener:self.currentLog]; - [[HBOutputRedirect stdoutRedirect] addListener:self.currentLog]; + dispatch_queue_t mainQueue = dispatch_get_main_queue(); + [self.core.stderrRedirect addListener:self.currentLog queue:mainQueue]; + [self.core.stdoutRedirect addListener:self.currentLog queue:mainQueue]; } self.currentItem = nextItem; @@ -601,8 +632,8 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK // Since we are done with this encode, tell output to stop writing to the // individual encode log. - [[HBOutputRedirect stderrRedirect] removeListener:self.currentLog]; - [[HBOutputRedirect stdoutRedirect] removeListener:self.currentLog]; + [self.core.stderrRedirect removeListener:self.currentLog]; + [self.core.stdoutRedirect removeListener:self.currentLog]; self.currentLog = nil; @@ -693,14 +724,11 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK HBJob *job = item.job; - // Reset the title in the job. - job.title = self.core.titles.firstObject; - NSParameterAssert(job); HBStateFormatter *formatter = [[HBStateFormatter alloc] init]; formatter.twoLines = NO; - self.core.stateFormatter = formatter; + //self.core.stateFormatter = formatter; // Progress handler void (^progressHandler)(HBState state, HBProgress progress, NSString *info) = ^(HBState state, HBProgress progress, NSString *info) @@ -739,9 +767,6 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK // We should be all setup so let 'er rip [self.core encodeJob:job progressHandler:progressHandler completionHandler:completionHandler]; - - // We are done using the title, remove it from the job - job.title = nil; } /** diff --git a/macosx/HBQueueController.m b/macosx/HBQueueController.m index 196495a7d..4de78e300 100644 --- a/macosx/HBQueueController.m +++ b/macosx/HBQueueController.m @@ -20,8 +20,6 @@ @import HandBrakeKit; -static void *HBControllerQueueCoreContext = &HBControllerQueueCoreContext; - @interface HBQueueController () <NSUserNotificationCenterDelegate, HBQueueTableViewControllerDelegate, HBQueueDetailsViewControllerDelegate> @property (weak) IBOutlet NSSplitView *splitView; @@ -154,51 +152,41 @@ static void *HBControllerQueueCoreContext = &HBControllerQueueCoreContext; [self.window setFrameFromString:@"HBQueueWindowFrameAutosave"]; // Set up observers - [self.queue.core addObserver:self forKeyPath:@"state" - options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial - context:HBControllerQueueCoreContext]; - [self.queue addObserver:self forKeyPath:@"pendingItemsCount" - options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial - context:HBControllerQueueCoreContext]; + [NSNotificationCenter.defaultCenter addObserverForName:HBQueueDidChangeStateNotification object:_queue queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note) { + [self updateUI]; + }]; [self tableViewDidSelectItemsAtIndexes:[NSIndexSet indexSet]]; } -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +- (void)updateUI { - if (context == HBControllerQueueCoreContext) - { - [self updateToolbarButtonsState]; - [self.window.toolbar validateVisibleItems]; + [self updateToolbarButtonsState]; + [self.window.toolbar validateVisibleItems]; - if (@available(macOS 10.12.2, *)) - { - [self _touchBar_updateButtonsState]; - [self _touchBar_validateUserInterfaceItems]; - } + if (@available(macOS 10.12.2, *)) + { + [self _touchBar_updateButtonsState]; + [self _touchBar_validateUserInterfaceItems]; + } - NSString *string; - if (self.queue.pendingItemsCount == 0) + NSString *string; + if (self.queue.pendingItemsCount == 0) + { + self.window.title = NSLocalizedString(@"Queue", @"Queue window title"); + } + else + { + if (self.queue.pendingItemsCount == 1) { - self.window.title = NSLocalizedString(@"Queue", @"Queue window title"); + string = [NSString stringWithFormat: NSLocalizedString(@"%d encode pending", @"Queue status"), self.queue.pendingItemsCount]; } else { - if (self.queue.pendingItemsCount == 1) - { - string = [NSString stringWithFormat: NSLocalizedString(@"%d encode pending", @"Queue status"), self.queue.pendingItemsCount]; - } - else - { - string = [NSString stringWithFormat: NSLocalizedString(@"%d encodes pending", @"Queue status"), self.queue.pendingItemsCount]; - } - - self.window.title = [NSString stringWithFormat: NSLocalizedString(@"Queue (%@)", @"Queue window title"), string]; + string = [NSString stringWithFormat: NSLocalizedString(@"%d encodes pending", @"Queue status"), self.queue.pendingItemsCount]; } - } - else - { - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + + self.window.title = [NSString stringWithFormat: NSLocalizedString(@"Queue (%@)", @"Queue window title"), string]; } } diff --git a/macosx/HBRedirect.h b/macosx/HBRedirect.h new file mode 100644 index 000000000..3e15df73d --- /dev/null +++ b/macosx/HBRedirect.h @@ -0,0 +1,37 @@ +/* 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> + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSUInteger, HBRedirectType) { + HBRedirectTypeOutput, + HBRedirectTypeError +}; + +@protocol HBOutputRedirectListening <NSObject> + +- (void)redirect:(NSString *)text type:(HBRedirectType)type; + +@end + +@interface HBRedirect : NSObject + ++ (instancetype)stdoutRedirect; ++ (instancetype)stderrRedirect; + +- (void)addListener:(id <HBOutputRedirectListening>)aListener queue:(dispatch_queue_t)queue; +- (void)removeListener:(id <HBOutputRedirectListening>)aListener; + +// Methods to subclass + +- (instancetype)initWithType:(HBRedirectType)type; +- (void)forwardOutput:(NSString *)text; +- (void)startRedirect; +- (void)stopRedirect; + +@end + +NS_ASSUME_NONNULL_END diff --git a/macosx/HBRedirect.m b/macosx/HBRedirect.m new file mode 100644 index 000000000..1b3529bda --- /dev/null +++ b/macosx/HBRedirect.m @@ -0,0 +1,146 @@ +/* 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 "HBRedirect.h" + +@interface HBOutputRedirectListenerEntry : NSObject +{ +@public + id<HBOutputRedirectListening> listener; + dispatch_queue_t queue; +} + +- (instancetype)initWithListener:(id<HBOutputRedirectListening>)listener queue:(dispatch_queue_t)queue; + +@end + +@implementation HBOutputRedirectListenerEntry + +- (instancetype)initWithListener:(id<HBOutputRedirectListening>)entryListener queue:(dispatch_queue_t)entryQueue +{ + self = [super init]; + if (self) + { + self->listener = entryListener; + self->queue = entryQueue; + } + return self; +} + +@end + +@interface HBRedirect () + +/// Set that contains all registered listeners for this output. +@property (nonatomic, readonly) NSMutableSet<HBOutputRedirectListenerEntry *> *listenerEntries; + +/// Selector that is called on listeners to forward the output. +@property (nonatomic, readonly) HBRedirectType type; + +@end + +@implementation HBRedirect + +/** + * Returns HBOutputRedirect object used to redirect stdout. + */ ++ (instancetype)stdoutRedirect +{ + return [[HBRedirect alloc] initWithType:HBRedirectTypeOutput]; +} + +/** + * Returns HBOutputRedirect object used to redirect stderr. + */ ++ (instancetype)stderrRedirect +{ + return [[HBRedirect alloc] initWithType:HBRedirectTypeError]; +} + +- (HBOutputRedirectListenerEntry *)entryForListener:(id <HBOutputRedirectListening>)listener +{ + for (HBOutputRedirectListenerEntry *entry in _listenerEntries) + { + if (entry->listener == listener) + { + return entry; + } + } + return nil; +} + +- (BOOL)containsListener:(id <HBOutputRedirectListening>)listener +{ + HBOutputRedirectListenerEntry *entry = [self entryForListener:listener]; + return entry && [_listenerEntries containsObject:listener]; +} + +/** + * Adds specified object as listener for this output. Method @c stdoutRedirect: + * or @c stderrRedirect: of the listener is called to redirect the output. + */ +- (void)addListener:(id <HBOutputRedirectListening>)listener queue:(dispatch_queue_t)queue +{ + NSAssert2([listener respondsToSelector:@selector(redirect:type:)], @"Object %@ doesn't respond to selector \"%@\"", listener, NSStringFromSelector(@selector(redirect:type:))); + + if (![self containsListener:listener]) + { + HBOutputRedirectListenerEntry *entry = [[HBOutputRedirectListenerEntry alloc] initWithListener:listener queue:queue]; + [_listenerEntries addObject:entry]; + } + + if (_listenerEntries.count > 0) + { + [self startRedirect]; + } +} + +/** + * Stops forwarding for this output to the specified listener object. + */ +- (void)removeListener:(id <HBOutputRedirectListening>)listener +{ + HBOutputRedirectListenerEntry *entry = [self entryForListener:listener]; + if (entry) + { + [_listenerEntries removeObject:entry]; + } + + // If last listener is removed, stop redirecting output and autorelease + // self. Remember to set proper global pointer to NULL so the object is + // recreated again when needed. + if (_listenerEntries.count == 0) + { + [self stopRedirect]; + } +} + +- (instancetype)initWithType:(HBRedirectType)type +{ + if (self = [super init]) + { + _listenerEntries = [[NSMutableSet alloc] init]; + _type = type; + } + return self; +} + +- (void)startRedirect {} +- (void)stopRedirect {} + +/** + * Called from @c stdoutwrite() and @c stderrwrite() to forward the output to + * listeners. + */ +- (void)forwardOutput:(NSString *)string +{ + for (HBOutputRedirectListenerEntry *entry in _listenerEntries) + { + dispatch_async(entry->queue, ^{ + [entry->listener redirect:string type:self->_type]; + }); + } +} + +@end diff --git a/macosx/HBRemoteCore.h b/macosx/HBRemoteCore.h new file mode 100644 index 000000000..6bd43c141 --- /dev/null +++ b/macosx/HBRemoteCore.h @@ -0,0 +1,40 @@ +/* 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 "HBRedirect.h" + +@import HandBrakeKit; + +NS_ASSUME_NONNULL_BEGIN + +@interface HBRemoteCore : NSObject + +- (instancetype)initWithLogLevel:(NSInteger)level name:(NSString *)name; + +@property (nonatomic, readonly) HBState state; + +@property (nonatomic, readonly) HBRedirect *stdoutRedirect; +@property (nonatomic, readonly) HBRedirect *stderrRedirect; + +@property (nonatomic, readwrite) BOOL automaticallyPreventSleep; + +- (void)preventSleep; +- (void)allowSleep; + +- (void)scanURL:(NSURL *)url titleIndex:(NSUInteger)index previews:(NSUInteger)previewsNum minDuration:(NSUInteger)seconds progressHandler:(HBCoreProgressHandler)progressHandler completionHandler:(HBCoreCompletionHandler)completionHandler; + +- (void)cancelScan; + +- (void)encodeJob:(HBJob *)job progressHandler:(HBCoreProgressHandler)progressHandler completionHandler:(HBCoreCompletionHandler)completionHandler; + +- (void)cancelEncode; + +- (void)pause; + +- (void)resume; + +@end + +NS_ASSUME_NONNULL_END diff --git a/macosx/HBRemoteCore.m b/macosx/HBRemoteCore.m new file mode 100644 index 000000000..b3db5b37b --- /dev/null +++ b/macosx/HBRemoteCore.m @@ -0,0 +1,167 @@ +/* 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 "HBRemoteCore.h" +#import "HBRemoteCoreProtocol.h" + +@import HandBrakeKit; + +@interface HBRemoteCore () <HBRemoteProgressProtocol> + +@property (nonatomic, readonly) NSXPCConnection *connection; + +@property (nonatomic, readonly) id<HBRemoteCoreProtocol> proxy; + +@property (nonatomic, readwrite) HBState state; + +@property (nonatomic, readwrite, copy) HBCoreProgressHandler progressHandler; +@property (nonatomic, readwrite, copy) HBCoreCompletionHandler completionHandler; + +@end + +@implementation HBRemoteCore + +- (instancetype)init +{ + self = [super init]; + if (self) + { + _state = HBStateIdle; + _stdoutRedirect = HBRedirect.stdoutRedirect; + _stderrRedirect = HBRedirect.stderrRedirect; + + [self connect]; + } + return self; +} + +- (void)connect +{ + _connection = [[NSXPCConnection alloc] initWithServiceName:@"fr.handbrake.HandBrakeXPCService"]; + _connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(HBRemoteCoreProtocol)]; + + _connection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(HBRemoteProgressProtocol)]; + _connection.exportedObject = self; + + _proxy = [_connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { + + }]; + + [_connection resume]; +} + +- (instancetype)initWithLogLevel:(NSInteger)level name:(NSString *)name +{ + self = [self init]; + if (self) + { + [_proxy setUpWithLogLevel:level name:name]; + } + return self; +} + +- (void)dealloc +{ + [_connection.remoteObjectProxy tearDown]; + [_connection invalidate]; +} + +- (void)updateState:(HBState)state { + dispatch_sync(dispatch_get_main_queue(), ^{ + self.state = state; + }); +} + +- (void)setAutomaticallyPreventSleep:(BOOL)automaticallyPreventSleep +{ + [_proxy setAutomaticallyPreventSleep:automaticallyPreventSleep]; +} + +- (void)allowSleep +{ + [_proxy allowSleep]; +} + +- (void)preventSleep +{ + [_proxy preventSleep]; +} + +- (void)scanURL:(NSURL *)url titleIndex:(NSUInteger)index previews:(NSUInteger)previewsNum minDuration:(NSUInteger)seconds progressHandler:(nonnull HBCoreProgressHandler)progressHandler completionHandler:(nonnull HBCoreCompletionHandler)completionHandler +{ + self.progressHandler = progressHandler; + self.completionHandler = completionHandler; + + NSData *bookmark = [url bookmarkDataWithOptions:0 includingResourceValuesForKeys:nil relativeToURL:nil error:NULL]; + [_connection.remoteObjectProxy provideResourceAccessWithBookmarks:@[bookmark]]; + + self.state = HBStateScanning; + + [_connection.remoteObjectProxy scanURL:url titleIndex:index previews:previewsNum minDuration:seconds withReply:^(HBCoreResult result) { + dispatch_sync(dispatch_get_main_queue(), ^{ + self.progressHandler = nil; + self.completionHandler(result); + }); + }]; +} + +- (void)cancelScan +{ + [_proxy cancelScan]; +} + +- (void)encodeJob:(HBJob *)job progressHandler:(HBCoreProgressHandler)progressHandler completionHandler:(HBCoreCompletionHandler)completionHandler +{ + NSData *bookmark = [job.outputURL bookmarkDataWithOptions:0 includingResourceValuesForKeys:nil relativeToURL:nil error:NULL]; + [_connection.remoteObjectProxy provideResourceAccessWithBookmarks:@[bookmark]]; + + self.progressHandler = progressHandler; + self.completionHandler = completionHandler; + + self.state = HBStateWorking; + + [_connection.remoteObjectProxy encodeJob:job withReply:^(HBCoreResult result) { + dispatch_sync(dispatch_get_main_queue(), ^{ + self.progressHandler = nil; + self.completionHandler(result); + }); + }]; +} + +- (void)cancelEncode +{ + [_proxy cancelEncode]; +} + +- (void)updateProgress:(double)currentProgress hours:(int)hours minutes:(int)minutes seconds:(int)seconds state:(HBState)state info:(NSString *)info { + dispatch_sync(dispatch_get_main_queue(), ^{ + HBProgress progress = {currentProgress , hours, minutes, seconds}; + self.state = state; + self.progressHandler(state, progress, info); + }); +} + +- (void)forwardOutput:(NSString *)text +{ + [_stdoutRedirect forwardOutput:text]; + [HBUtilities writeToActivityLogWithNoHeader:text]; +} + +- (void)forwardError:(NSString *)text +{ + [_stdoutRedirect forwardOutput:text]; + [HBUtilities writeToActivityLogWithNoHeader:text]; +} + +- (void)pause +{ + [_proxy pauseEncode]; +} + +- (void)resume +{ + [_proxy resumeEncode]; +} + +@end diff --git a/macosx/HBStateFormatter.m b/macosx/HBStateFormatter.m index 90919e84f..7993aaa32 100644 --- a/macosx/HBStateFormatter.m +++ b/macosx/HBStateFormatter.m @@ -145,7 +145,10 @@ case HB_STATE_WORKING: case HB_STATE_PAUSED: #define p s.param.working - progress = (p.progress + p.pass - 1) / p.pass_count; + if (p.pass_count > 0) + { + progress = (p.progress + p.pass - 1) / p.pass_count; + } #undef p break; diff --git a/macosx/HBSubtitles.m b/macosx/HBSubtitles.m index dd1d7f981..c31ed233c 100644 --- a/macosx/HBSubtitles.m +++ b/macosx/HBSubtitles.m @@ -488,7 +488,7 @@ extern NSString *keySubTrackExternalFileURLBookmark; _tokens = [NSMutableArray array]; decodeInt(_container); if (_container != HB_MUX_MP4 && _container != HB_MUX_MKV && _container != HB_MUX_WEBM) { goto fail; } - decodeCollectionOfObjects3(_sourceTracks, NSArray, NSDictionary, NSURL, NSData); + decodeCollectionOfObjects5(_sourceTracks, NSArray, NSDictionary, NSURL, NSData, NSString, NSNumber); #ifdef __SANDBOX_ENABLED__ for (NSDictionary *sourceTrack in _sourceTracks) diff --git a/macosx/HBSubtitlesDefaults.m b/macosx/HBSubtitlesDefaults.m index 891f5e6e9..bfbe824c0 100644 --- a/macosx/HBSubtitlesDefaults.m +++ b/macosx/HBSubtitlesDefaults.m @@ -230,7 +230,7 @@ { goto fail; } - decodeObjectOrFail(_trackSelectionLanguages, NSMutableArray); + decodeCollectionOfObjects(_trackSelectionLanguages, NSMutableArray, NSString); decodeBool(_addForeignAudioSearch); decodeBool(_addForeignAudioSubtitle); diff --git a/macosx/HBUtilities.h b/macosx/HBUtilities.h index f2d1aa0c8..18f294a01 100644 --- a/macosx/HBUtilities.h +++ b/macosx/HBUtilities.h @@ -32,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN * @param format a standard c format string with varargs. */ + (void)writeToActivityLog:(const char *)format, ...; ++ (void)writeToActivityLogWithNoHeader:(NSString *)text; + (nullable NSURL *)URLFromBookmark:(NSData *)bookmark; + (nullable NSData *)bookmarkFromURL:(NSURL *)url; diff --git a/macosx/HBUtilities.m b/macosx/HBUtilities.m index 9099af552..733226e89 100644 --- a/macosx/HBUtilities.m +++ b/macosx/HBUtilities.m @@ -54,6 +54,11 @@ va_end(args); } ++ (void)writeToActivityLogWithNoHeader:(NSString *)text +{ + fprintf(stderr, "%s", text.UTF8String); +} + + (nullable NSURL *)URLFromBookmark:(NSData *)bookmark { NSParameterAssert(bookmark); diff --git a/macosx/HandBrake.xcodeproj/project.pbxproj b/macosx/HandBrake.xcodeproj/project.pbxproj index ff0986a70..9e37b17e7 100644 --- a/macosx/HandBrake.xcodeproj/project.pbxproj +++ b/macosx/HandBrake.xcodeproj/project.pbxproj @@ -179,7 +179,7 @@ A91CE2FC1C7DB99D0068F46F /* HBPreset.h in Headers */ = {isa = PBXBuildFile; fileRef = A9CF25F21990D64E0023F727 /* HBPreset.h */; settings = {ATTRIBUTES = (Public, ); }; }; A91CE2FD1C7DB99D0068F46F /* HBMutablePreset.h in Headers */ = {isa = PBXBuildFile; fileRef = A96CD1741BCC5F9100F372F1 /* HBMutablePreset.h */; settings = {ATTRIBUTES = (Public, ); }; }; A91CE2FE1C7DB99D0068F46F /* HBTreeNode.h in Headers */ = {isa = PBXBuildFile; fileRef = A9D488A31996270300E9B1BA /* HBTreeNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A91D54871E378ABD006D0997 /* HBSecurityAccessToken.h in Headers */ = {isa = PBXBuildFile; fileRef = A91D54851E378ABD006D0997 /* HBSecurityAccessToken.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A91D54871E378ABD006D0997 /* HBSecurityAccessToken.h in Headers */ = {isa = PBXBuildFile; fileRef = A91D54851E378ABD006D0997 /* HBSecurityAccessToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; A91D54881E378ABD006D0997 /* HBSecurityAccessToken.m in Sources */ = {isa = PBXBuildFile; fileRef = A91D54861E378ABD006D0997 /* HBSecurityAccessToken.m */; }; A91F97351D7B2A4E00D82DCE /* HBAudioTransformers.h in Headers */ = {isa = PBXBuildFile; fileRef = A91F97331D7B2A4E00D82DCE /* HBAudioTransformers.h */; settings = {ATTRIBUTES = (Public, ); }; }; A91F97361D7B2A4E00D82DCE /* HBAudioTransformers.m in Sources */ = {isa = PBXBuildFile; fileRef = A91F97341D7B2A4E00D82DCE /* HBAudioTransformers.m */; }; @@ -200,6 +200,8 @@ 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 */; }; + A954010022FF240E00F83A5F /* HBOutputRedirect.m in Sources */ = {isa = PBXBuildFile; fileRef = 273F209E14ADBE670021BE6D /* HBOutputRedirect.m */; }; + A954010322FF397000F83A5F /* HBRedirect.m in Sources */ = {isa = PBXBuildFile; fileRef = A954010222FF397000F83A5F /* HBRedirect.m */; }; A955128B1A320B02001BFC6F /* libjansson.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A95512881A320A12001BFC6F /* libjansson.a */; }; A957EBCD218DBE5900007988 /* HBAutoNamer.m in Sources */ = {isa = PBXBuildFile; fileRef = A957EBCC218DBE5900007988 /* HBAutoNamer.m */; }; A958EAC222E24D6400D83AF4 /* HBQueueTableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = A958EAC422E24D6400D83AF4 /* HBQueueTableViewController.xib */; }; @@ -210,6 +212,10 @@ A95BC1E81CD2548A008D6A33 /* volLowTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = A95BC1E61CD2548A008D6A33 /* volLowTemplate.pdf */; }; A96127DF22E0994E0086E6DC /* HBQueueInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A96127DD22E0994E0086E6DC /* HBQueueInfoViewController.m */; }; A96127E422E09ADD0086E6DC /* HBQueueTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A96127E222E09ADD0086E6DC /* HBQueueTableViewController.m */; }; + A964D39A22FDE8EE00DFCAEA /* HandBrakeXPCService.m in Sources */ = {isa = PBXBuildFile; fileRef = A964D39922FDE8EE00DFCAEA /* HandBrakeXPCService.m */; }; + A964D39C22FDE8EE00DFCAEA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A964D39B22FDE8EE00DFCAEA /* main.m */; }; + A964D3A022FDE8EE00DFCAEA /* HandBrakeXPCService.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = A964D39522FDE8EE00DFCAEA /* HandBrakeXPCService.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + A964D3A822FDE91B00DFCAEA /* HBRemoteCore.m in Sources */ = {isa = PBXBuildFile; fileRef = A964D3A722FDE91B00DFCAEA /* HBRemoteCore.m */; }; A96664B01CCE45BF00DA4A57 /* HBPlayerHUDController.m in Sources */ = {isa = PBXBuildFile; fileRef = A96664AE1CCE45BF00DA4A57 /* HBPlayerHUDController.m */; }; A96664B51CCE48F700DA4A57 /* HBPictureHUDController.m in Sources */ = {isa = PBXBuildFile; fileRef = A96664B31CCE48F700DA4A57 /* HBPictureHUDController.m */; }; A96664BA1CCE493D00DA4A57 /* HBEncodingProgressHUDController.m in Sources */ = {isa = PBXBuildFile; fileRef = A96664B81CCE493D00DA4A57 /* HBEncodingProgressHUDController.m */; }; @@ -232,6 +238,7 @@ A98B8E241C7DD2A200B810C9 /* HBPresetCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = A997D8EB1A4ABB0900E19B6F /* HBPresetCoding.h */; settings = {ATTRIBUTES = (Public, ); }; }; A98C29C41977B10600AF5DED /* HBLanguagesSelection.m in Sources */ = {isa = PBXBuildFile; fileRef = A98C29C31977B10600AF5DED /* HBLanguagesSelection.m */; }; A9906B2C1A710920001D82D5 /* HBQueueController.m in Sources */ = {isa = PBXBuildFile; fileRef = A9906B2B1A710920001D82D5 /* HBQueueController.m */; }; + A990C55322FF4FBA00E07CE2 /* HandBrakeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9736F021C7DA5FE008F1D18 /* HandBrakeKit.framework */; }; A99F40CF1B624E7E00750170 /* HBPictureViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A99F40CD1B624E7E00750170 /* HBPictureViewController.m */; }; A9A0CBE81CCEA3670045B3DF /* HBPlayerTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = A9A0CBE61CCEA1D10045B3DF /* HBPlayerTrack.m */; }; A9A25D9C21182741005A8A0F /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9A25D9B21182741005A8A0F /* CoreMedia.framework */; }; @@ -265,6 +272,7 @@ A9ABD1A91E2A0F8200EC8B65 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9ABD1A81E2A0F8200EC8B65 /* CoreGraphics.framework */; }; A9ABD1AA1E2A0F8F00EC8B65 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9ABD1A81E2A0F8200EC8B65 /* CoreGraphics.framework */; }; A9B3B63922E2EA58001CEB9A /* HBQueueItemWorkingView.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B3B63822E2EA58001CEB9A /* HBQueueItemWorkingView.m */; }; + A9B5568522FFE4870050D582 /* HBRedirect.m in Sources */ = {isa = PBXBuildFile; fileRef = A954010222FF397000F83A5F /* HBRedirect.m */; }; A9B6B9EE217B38D200B957AE /* HBLocalizationUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B6B9ED217B38D200B957AE /* HBLocalizationUtilities.h */; }; A9B6B9F1217B408E00B957AE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A9B6B9EF217B408E00B957AE /* InfoPlist.strings */; }; A9B6B9F4217B408E00B957AE /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = A9B6B9F2217B408E00B957AE /* Localizable.strings */; }; @@ -307,6 +315,13 @@ remoteGlobalIDString = 273F203814ADBC200021BE6D; remoteInfo = HandBrake; }; + A964D39E22FDE8EE00DFCAEA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 273F1FE014AD9DA40021BE6D /* Project object */; + proxyType = 1; + remoteGlobalIDString = A964D39422FDE8EE00DFCAEA; + remoteInfo = HandBrakeXPCService; + }; A96A4F85217A4C8900755E35 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 273F1FE014AD9DA40021BE6D /* Project object */; @@ -366,6 +381,7 @@ files = ( A939855622315638001DCAEB /* org.sparkle-project.InstallerConnection.xpc in CopyFiles */, A939855722315638001DCAEB /* org.sparkle-project.InstallerLauncher.xpc in CopyFiles */, + A964D3A022FDE8EE00DFCAEA /* HandBrakeXPCService.xpc in CopyFiles */, A939855822315638001DCAEB /* org.sparkle-project.InstallerStatus.xpc in CopyFiles */, A939855A22315993001DCAEB /* org.sparkle-project.Downloader.xpc in CopyFiles */, ); @@ -410,7 +426,6 @@ 273F209814ADBE670021BE6D /* HBDVDDetector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBDVDDetector.m; sourceTree = "<group>"; }; 273F209B14ADBE670021BE6D /* HBOutputPanelController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBOutputPanelController.h; sourceTree = "<group>"; }; 273F209C14ADBE670021BE6D /* HBOutputPanelController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBOutputPanelController.m; sourceTree = "<group>"; }; - 273F209D14ADBE670021BE6D /* HBOutputRedirect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBOutputRedirect.h; sourceTree = "<group>"; }; 273F209E14ADBE670021BE6D /* HBOutputRedirect.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBOutputRedirect.m; sourceTree = "<group>"; }; 273F209F14ADBE670021BE6D /* HBPreferencesController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBPreferencesController.h; sourceTree = "<group>"; }; 273F20A014ADBE670021BE6D /* HBPreferencesController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBPreferencesController.m; sourceTree = "<group>"; }; @@ -553,6 +568,8 @@ A9537BF71A48AC9000141102 /* HBFilters+UIAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HBFilters+UIAdditions.h"; sourceTree = "<group>"; }; A9537BF81A48AC9000141102 /* HBFilters+UIAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "HBFilters+UIAdditions.m"; sourceTree = "<group>"; }; A953FF3820CAD29300325A51 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/HBSummaryViewController.xib; sourceTree = "<group>"; }; + A954010122FF397000F83A5F /* HBRedirect.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HBRedirect.h; sourceTree = "<group>"; }; + A954010222FF397000F83A5F /* HBRedirect.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HBRedirect.m; sourceTree = "<group>"; }; A95512881A320A12001BFC6F /* libjansson.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libjansson.a; path = external/contrib/lib/libjansson.a; sourceTree = BUILT_PRODUCTS_DIR; }; A957EBCB218DBE5900007988 /* HBAutoNamer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HBAutoNamer.h; sourceTree = "<group>"; }; A957EBCC218DBE5900007988 /* HBAutoNamer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HBAutoNamer.m; sourceTree = "<group>"; }; @@ -597,6 +614,14 @@ A9637DA820F7A252001EAE7C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/HBPictureViewController.strings; sourceTree = "<group>"; }; A9637DA920F7A252001EAE7C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/HBPlayerHUDController.strings; sourceTree = "<group>"; }; A9637DAA20F7A252001EAE7C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/ChaptersTitles.strings; sourceTree = "<group>"; }; + A964D39522FDE8EE00DFCAEA /* HandBrakeXPCService.xpc */ = {isa = PBXFileReference; explicitFileType = "wrapper.xpc-service"; includeInIndex = 0; path = HandBrakeXPCService.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; + A964D39722FDE8EE00DFCAEA /* HBRemoteCoreProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HBRemoteCoreProtocol.h; sourceTree = "<group>"; }; + A964D39822FDE8EE00DFCAEA /* HandBrakeXPCService.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HandBrakeXPCService.h; sourceTree = "<group>"; }; + A964D39922FDE8EE00DFCAEA /* HandBrakeXPCService.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HandBrakeXPCService.m; sourceTree = "<group>"; }; + A964D39B22FDE8EE00DFCAEA /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; + A964D39D22FDE8EE00DFCAEA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; + A964D3A622FDE91A00DFCAEA /* HBRemoteCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBRemoteCore.h; sourceTree = "<group>"; }; + A964D3A722FDE91B00DFCAEA /* HBRemoteCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBRemoteCore.m; sourceTree = "<group>"; }; A96664AD1CCE45BF00DA4A57 /* HBPlayerHUDController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBPlayerHUDController.h; sourceTree = "<group>"; }; A96664AE1CCE45BF00DA4A57 /* HBPlayerHUDController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBPlayerHUDController.m; sourceTree = "<group>"; }; A96664B21CCE48F700DA4A57 /* HBPictureHUDController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBPictureHUDController.h; sourceTree = "<group>"; }; @@ -638,6 +663,7 @@ A98F38041C7DCA7E00E469C8 /* HBStateFormatter+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HBStateFormatter+Private.h"; sourceTree = "<group>"; }; A98FD5941B19C6E400FCC7A5 /* HBTitle+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HBTitle+Private.h"; sourceTree = "<group>"; }; A9906B2B1A710920001D82D5 /* HBQueueController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBQueueController.m; sourceTree = "<group>"; }; + A990C55222FF4EBA00E07CE2 /* HandBrakeXPCService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = HandBrakeXPCService.entitlements; sourceTree = "<group>"; }; A990D9051A64562200139032 /* HBJob+HBJobConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "HBJob+HBJobConversion.h"; sourceTree = "<group>"; }; A990D9061A64562200139032 /* HBJob+HBJobConversion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "HBJob+HBJobConversion.m"; sourceTree = "<group>"; }; A99422DE1B1887B000DDB077 /* NSJSONSerialization+HBAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSJSONSerialization+HBAdditions.h"; sourceTree = "<group>"; }; @@ -685,6 +711,7 @@ A9B34D74197696FE00871B7D /* DiskArbitration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DiskArbitration.framework; path = System/Library/Frameworks/DiskArbitration.framework; sourceTree = SDKROOT; }; A9B3B63722E2EA58001CEB9A /* HBQueueItemWorkingView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HBQueueItemWorkingView.h; sourceTree = "<group>"; }; A9B3B63822E2EA58001CEB9A /* HBQueueItemWorkingView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HBQueueItemWorkingView.m; sourceTree = "<group>"; }; + A9B5568622FFE5370050D582 /* HBOutputRedirect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBOutputRedirect.h; sourceTree = "<group>"; }; A9B6B9ED217B38D200B957AE /* HBLocalizationUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HBLocalizationUtilities.h; sourceTree = "<group>"; }; A9B6B9F0217B408E00B957AE /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; }; A9B6B9F3217B408E00B957AE /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; }; @@ -834,6 +861,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A964D39222FDE8EE00DFCAEA /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A990C55322FF4FBA00E07CE2 /* HandBrakeKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; A9736EFE1C7DA5FE008F1D18 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -942,6 +977,7 @@ 273F200214ADAE950021BE6D /* HandBrakeCLI */, A9736F031C7DA5FE008F1D18 /* HandBrakeKit */, A9736F111C7DA5FE008F1D18 /* HandBrakeKitTests */, + A964D39622FDE8EE00DFCAEA /* HandBrakeXPCService */, 273F200014ADAE950021BE6D /* Products */, 27D6C72314B1013400B785E4 /* Products (external) */, 273F20CD14ADC8E60021BE6D /* Resources */, @@ -958,6 +994,7 @@ 273F203914ADBC210021BE6D /* HandBrake.app */, A9736F021C7DA5FE008F1D18 /* HandBrakeKit.framework */, A9736F0B1C7DA5FE008F1D18 /* HandBrakeKitTests.xctest */, + A964D39522FDE8EE00DFCAEA /* HandBrakeXPCService.xpc */, ); name = Products; sourceTree = "<group>"; @@ -1187,6 +1224,8 @@ children = ( A9706CB21AC1436F00BAEAA8 /* HBApplication.h */, A9706CB31AC1436F00BAEAA8 /* HBApplication.m */, + A964D3A622FDE91A00DFCAEA /* HBRemoteCore.h */, + A964D3A722FDE91B00DFCAEA /* HBRemoteCore.m */, A95BA15F220CA5DB00A2F9F9 /* HBDistributedArray.h */, A95BA160220CA5DB00A2F9F9 /* HBDistributedArray.m */, A9706CB51AC1437800BAEAA8 /* HBExceptionAlertController.h */, @@ -1282,6 +1321,19 @@ name = "UI Bindings Additions"; sourceTree = "<group>"; }; + A964D39622FDE8EE00DFCAEA /* HandBrakeXPCService */ = { + isa = PBXGroup; + children = ( + A990C55222FF4EBA00E07CE2 /* HandBrakeXPCService.entitlements */, + A964D39722FDE8EE00DFCAEA /* HBRemoteCoreProtocol.h */, + A964D39822FDE8EE00DFCAEA /* HandBrakeXPCService.h */, + A964D39922FDE8EE00DFCAEA /* HandBrakeXPCService.m */, + A964D39B22FDE8EE00DFCAEA /* main.m */, + A964D39D22FDE8EE00DFCAEA /* Info.plist */, + ); + path = HandBrakeXPCService; + sourceTree = "<group>"; + }; A9736F031C7DA5FE008F1D18 /* HandBrakeKit */ = { isa = PBXGroup; children = ( @@ -1344,7 +1396,9 @@ A98F00771A972007001C2298 /* Output Redirect */ = { isa = PBXGroup; children = ( - 273F209D14ADBE670021BE6D /* HBOutputRedirect.h */, + A954010122FF397000F83A5F /* HBRedirect.h */, + A954010222FF397000F83A5F /* HBRedirect.m */, + A9B5568622FFE5370050D582 /* HBOutputRedirect.h */, 273F209E14ADBE670021BE6D /* HBOutputRedirect.m */, A91AFD0A1A948827009BECED /* HBOutputFileWriter.h */, A91AFD0B1A948827009BECED /* HBOutputFileWriter.m */, @@ -1530,9 +1584,9 @@ A91F97351D7B2A4E00D82DCE /* HBAudioTransformers.h in Headers */, A98B8E241C7DD2A200B810C9 /* HBPresetCoding.h in Headers */, A9294CC91DC4BBF7004D3415 /* HBJob+Private.h in Headers */, + A91D54871E378ABD006D0997 /* HBSecurityAccessToken.h in Headers */, A91CE2FE1C7DB99D0068F46F /* HBTreeNode.h in Headers */, A9B6B9EE217B38D200B957AE /* HBLocalizationUtilities.h in Headers */, - A91D54871E378ABD006D0997 /* HBSecurityAccessToken.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1588,12 +1642,30 @@ ); dependencies = ( A91CE2EF1C7DB40D0068F46F /* PBXTargetDependency */, + A964D39F22FDE8EE00DFCAEA /* PBXTargetDependency */, ); name = HandBrake; productName = HandBrake; productReference = 273F203914ADBC210021BE6D /* HandBrake.app */; productType = "com.apple.product-type.application"; }; + A964D39422FDE8EE00DFCAEA /* HandBrakeXPCService */ = { + isa = PBXNativeTarget; + buildConfigurationList = A964D3A522FDE8EE00DFCAEA /* Build configuration list for PBXNativeTarget "HandBrakeXPCService" */; + buildPhases = ( + A964D39122FDE8EE00DFCAEA /* Sources */, + A964D39222FDE8EE00DFCAEA /* Frameworks */, + A964D39322FDE8EE00DFCAEA /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = HandBrakeXPCService; + productName = HandBrakeXPCService; + productReference = A964D39522FDE8EE00DFCAEA /* HandBrakeXPCService.xpc */; + productType = "com.apple.product-type.xpc-service"; + }; A9736F011C7DA5FE008F1D18 /* HandBrakeKit */ = { isa = PBXNativeTarget; buildConfigurationList = A9736F1D1C7DA5FE008F1D18 /* Build configuration list for PBXNativeTarget "HandBrakeKit" */; @@ -1656,6 +1728,9 @@ }; }; }; + A964D39422FDE8EE00DFCAEA = { + CreatedOnToolsVersion = 10.3; + }; A96A4F7C217A4C2B00755E35 = { CreatedOnToolsVersion = 10.1; ProvisioningStyle = Automatic; @@ -1691,6 +1766,7 @@ A9736F011C7DA5FE008F1D18 /* HandBrakeKit */, A9736F0A1C7DA5FE008F1D18 /* HandBrakeKitTests */, 273F203814ADBC200021BE6D /* HandBrake */, + A964D39422FDE8EE00DFCAEA /* HandBrakeXPCService */, ); }; /* End PBXProject section */ @@ -1745,6 +1821,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A964D39322FDE8EE00DFCAEA /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; A9736F001C7DA5FE008F1D18 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1802,6 +1885,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + A954010322FF397000F83A5F /* HBRedirect.m in Sources */, A95BA161220CA5DB00A2F9F9 /* HBDistributedArray.m in Sources */, A916C99B1C844A0800C7B560 /* HBTableView.m in Sources */, A916C9991C8449E200C7B560 /* main.mm in Sources */, @@ -1846,6 +1930,7 @@ A9C61F9E22E31CDB00C28E7C /* HBFlippedClipView.m in Sources */, 273F20B414ADBE670021BE6D /* HBOutputRedirect.m in Sources */, A95BA15D220C968500A2F9F9 /* HBQueueItem.m in Sources */, + A964D3A822FDE91B00DFCAEA /* HBRemoteCore.m in Sources */, A9D0FA771C1C284D0003F2A9 /* HBFocusRingView.m in Sources */, A91AFD0C1A948827009BECED /* HBOutputFileWriter.m in Sources */, A9D363512209C08600D8EFEA /* HBQueueItemView.m in Sources */, @@ -1864,6 +1949,17 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + A964D39122FDE8EE00DFCAEA /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A954010022FF240E00F83A5F /* HBOutputRedirect.m in Sources */, + A964D39C22FDE8EE00DFCAEA /* main.m in Sources */, + A964D39A22FDE8EE00DFCAEA /* HandBrakeXPCService.m in Sources */, + A9B5568522FFE4870050D582 /* HBRedirect.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; A9736EFD1C7DA5FE008F1D18 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1928,6 +2024,11 @@ target = 273F203814ADBC200021BE6D /* HandBrake */; targetProxy = A91CE2FF1C7DBA2C0068F46F /* PBXContainerItemProxy */; }; + A964D39F22FDE8EE00DFCAEA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = A964D39422FDE8EE00DFCAEA /* HandBrakeXPCService */; + targetProxy = A964D39E22FDE8EE00DFCAEA /* PBXContainerItemProxy */; + }; A96A4F86217A4C8900755E35 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = A96A4F7C217A4C2B00755E35 /* FakeTarget */; @@ -2503,6 +2604,7 @@ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = ""; + CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -2534,6 +2636,7 @@ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = ""; + CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -2575,6 +2678,254 @@ }; name = release; }; + A964D3A122FDE8EE00DFCAEA /* debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = ""; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = HandBrakeXPCService/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/../../../../Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.handbrake.HandBrakeXPCService; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = debug; + }; + A964D3A222FDE8EE00DFCAEA /* debug-sandbox */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = HandBrakeXPCService/HandBrakeXPCService.entitlements; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = ""; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = HandBrakeXPCService/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/../../../../Frameworks"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.handbrake.HandBrakeXPCService; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = "debug-sandbox"; + }; + A964D3A322FDE8EE00DFCAEA /* release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = HandBrakeXPCService/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/../../../../Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.handbrake.HandBrakeXPCService; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = release; + }; + A964D3A422FDE8EE00DFCAEA /* release-sandbox */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_ENTITLEMENTS = HandBrakeXPCService/HandBrakeXPCService.entitlements; + CODE_SIGN_IDENTITY = "-"; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = HandBrakeXPCService/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/../../../../Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = fr.handbrake.HandBrakeXPCService; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = "release-sandbox"; + }; A96A4F7D217A4C2B00755E35 /* debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -3372,6 +3723,17 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = release; }; + A964D3A522FDE8EE00DFCAEA /* Build configuration list for PBXNativeTarget "HandBrakeXPCService" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A964D3A122FDE8EE00DFCAEA /* debug */, + A964D3A222FDE8EE00DFCAEA /* debug-sandbox */, + A964D3A322FDE8EE00DFCAEA /* release */, + A964D3A422FDE8EE00DFCAEA /* release-sandbox */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = release; + }; A96A4F81217A4C2B00755E35 /* Build configuration list for PBXAggregateTarget "FakeTarget" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/macosx/HandBrake.xcodeproj/xcshareddata/xcschemes/HandBrake-Release-Sandbox.xcscheme b/macosx/HandBrake.xcodeproj/xcshareddata/xcschemes/HandBrake-Release-Sandbox.xcscheme index 1e04e9b67..cd9811d6a 100644 --- a/macosx/HandBrake.xcodeproj/xcshareddata/xcschemes/HandBrake-Release-Sandbox.xcscheme +++ b/macosx/HandBrake.xcodeproj/xcshareddata/xcschemes/HandBrake-Release-Sandbox.xcscheme @@ -83,7 +83,6 @@ buildConfiguration = "release-sandbox" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - disableMainThreadChecker = "YES" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/macosx/HandBrakeKit/HandBrakeKit.h b/macosx/HandBrakeKit/HandBrakeKit.h index 3e388855c..3aed96db5 100644 --- a/macosx/HandBrakeKit/HandBrakeKit.h +++ b/macosx/HandBrakeKit/HandBrakeKit.h @@ -51,3 +51,4 @@ FOUNDATION_EXPORT const unsigned char HandBrakeKitVersionString[]; #import <HandBrakeKit/HBFilters+UIAdditions.h> #import <HandBrakeKit/HBAudioTransformers.h> +#import <HandBrakeKit/HBSecurityAccessToken.h> diff --git a/macosx/HandBrakeXPCService/HBRemoteCoreProtocol.h b/macosx/HandBrakeXPCService/HBRemoteCoreProtocol.h new file mode 100644 index 000000000..5fd0805e0 --- /dev/null +++ b/macosx/HandBrakeXPCService/HBRemoteCoreProtocol.h @@ -0,0 +1,41 @@ +/* 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; + +@protocol HBRemoteCoreProtocol + +- (void)setUpWithLogLevel:(NSInteger)level name:(NSString *)name; +- (void)tearDown; + +- (void)provideResourceAccessWithBookmarks:(NSArray<NSData *> *)bookmarks; + +- (void)setAutomaticallyPreventSleep:(BOOL)automaticallyPreventSleep; + +- (void)preventSleep; +- (void)allowSleep; + +- (void)scanURL:(NSURL *)url titleIndex:(NSUInteger)index previews:(NSUInteger)previewsNum minDuration:(NSUInteger)seconds withReply:(void (^)(HBCoreResult))reply; +- (void)cancelScan; + +- (void)encodeJob:(HBJob *)job withReply:(void (^)(HBCoreResult))reply; +- (void)cancelEncode; + +- (void)pauseEncode; +- (void)resumeEncode; + +@end + +@protocol HBRemoteProgressProtocol + +- (void)updateState:(HBState)state; +- (void)updateProgress:(double)currentProgress hours:(int)hours minutes:(int)minutes seconds:(int)seconds state:(HBState)state info:(NSString *)info; + +- (void)forwardOutput:(NSString *)text; +- (void)forwardError:(NSString *)text; + +@end + diff --git a/macosx/HandBrakeXPCService/HandBrakeXPCService.entitlements b/macosx/HandBrakeXPCService/HandBrakeXPCService.entitlements new file mode 100644 index 000000000..6431476ba --- /dev/null +++ b/macosx/HandBrakeXPCService/HandBrakeXPCService.entitlements @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>com.apple.security.app-sandbox</key> + <true/> + <key>com.apple.security.temporary-exception.apple-events</key> + <array> + <string>com.apple.systemevents</string> + </array> + <key>com.apple.security.temporary-exception.files.absolute-path.read-only</key> + <array> + <string>/usr/local/</string> + </array> + <key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key> + <array> + <string>/.dvdcss/</string> + </array> +</dict> +</plist> diff --git a/macosx/HandBrakeXPCService/HandBrakeXPCService.h b/macosx/HandBrakeXPCService/HandBrakeXPCService.h new file mode 100644 index 000000000..d7a084bd0 --- /dev/null +++ b/macosx/HandBrakeXPCService/HandBrakeXPCService.h @@ -0,0 +1,13 @@ +/* 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 "HBRemoteCoreProtocol.h" + +@interface HandBrakeXPCService : NSObject <HBRemoteCoreProtocol> + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithConnection:(NSXPCConnection *)connection; + +@end diff --git a/macosx/HandBrakeXPCService/HandBrakeXPCService.m b/macosx/HandBrakeXPCService/HandBrakeXPCService.m new file mode 100644 index 000000000..ffd910b55 --- /dev/null +++ b/macosx/HandBrakeXPCService/HandBrakeXPCService.m @@ -0,0 +1,193 @@ +/* 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 "HandBrakeXPCService.h" +#import "HBOutputRedirect.h" + +@import HandBrakeKit; + +static void *HandBrakeXPCServiceContext = &HandBrakeXPCServiceContext; + +@interface HandBrakeXPCService () <HBOutputRedirectListening> + +@property (nonatomic, readonly) HBCore *core; + +@property (nonatomic, readonly, copy) HBCoreProgressHandler progressHandler; +@property (nonatomic, readonly, copy) HBCoreCompletionHandler completionHandler; +@property (nonatomic, readwrite, copy) void (^reply)(HBCoreResult); + +@property (nonatomic, readonly, weak) NSXPCConnection *connection; +@property (nonatomic, readonly) dispatch_queue_t queue; + +@property (nonatomic, readwrite) NSArray<NSURL *> *urls; + +@end + +@implementation HandBrakeXPCService + +- (instancetype)initWithConnection:(NSXPCConnection *)connection +{ + self = [super init]; + if (self) + { + _connection = connection; + + dispatch_queue_attr_t attr; + attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0); + _queue = dispatch_queue_create("fr.handbrake.CoreQueue", attr); + + // Add ourself as stderr/stdout listener + [HBOutputRedirect.stderrRedirect addListener:self queue:_queue]; + [HBOutputRedirect.stdoutRedirect addListener:self queue:_queue]; + } + return self; +} + +- (void)setUpWithLogLevel:(NSInteger)level name:(NSString *)name +{ + [HBCore initGlobal]; + + _core = [[HBCore alloc] initWithLogLevel:level queue:_queue]; + _core.name = name; + + // Completion handler + void (^completionHandler)(HBCoreResult result) = ^(HBCoreResult result) + { + self->_progressHandler = nil; + self.reply(result); + self.reply = nil; + }; + _completionHandler = completionHandler; + + // Set up observers + [self.core addObserver:self forKeyPath:@"state" + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial + context:HandBrakeXPCServiceContext]; +} + +- (void)tearDown +{ + _core = nil; + [HBCore closeGlobal]; +} + +- (void)provideResourceAccessWithBookmarks:(NSArray<NSData *> *)bookmarks +{ + dispatch_sync(_queue, ^{ + for (NSData *bookmark in bookmarks) + { + NSURL *url = [NSURL URLByResolvingBookmarkData:bookmark options:0 relativeToURL:nil bookmarkDataIsStale:NULL error:NULL]; + self.urls = @[url]; + } + }); +} + +- (void)setAutomaticallyPreventSleep:(BOOL)automaticallyPreventSleep +{ + dispatch_sync(_queue, ^{ + self.core.automaticallyPreventSleep = automaticallyPreventSleep; + }); +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if (context == HandBrakeXPCServiceContext) + { + [self.connection.remoteObjectProxy updateState:self.core.state]; + } + else + { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } +} + +- (void)preventSleep +{ + dispatch_sync(_queue, ^{ + [self.core preventSleep]; + }); +} + +- (void)allowSleep +{ + dispatch_sync(_queue, ^{ + [self.core allowSleep]; + }); +} + +- (void)scanURL:(NSURL *)url titleIndex:(NSUInteger)index previews:(NSUInteger)previewsNum minDuration:(NSUInteger)seconds withReply:(void (^)(HBCoreResult))reply +{ + dispatch_sync(_queue, ^{ + void (^progressHandler)(HBState state, HBProgress progress, NSString *info) = ^(HBState state, HBProgress progress, NSString *info) + { + [self.connection.remoteObjectProxy updateProgress:progress.percent hours:progress.hours minutes:progress.minutes seconds:progress.seconds state:state info:info]; + }; + self->_progressHandler = progressHandler; + self.reply = reply; + + [self.core scanURL:url titleIndex:index previews:previewsNum minDuration:seconds + progressHandler:self.progressHandler + completionHandler:self.completionHandler]; + }); +} + +- (void)cancelScan +{ + dispatch_sync(_queue, ^{ + [self.core cancelScan]; + }); +} + + - (void)encodeJob:(HBJob *)job withReply:(void (^)(HBCoreResult))reply; +{ + dispatch_sync(_queue, ^{ + void (^progressHandler)(HBState state, HBProgress progress, NSString *info) = ^(HBState state, HBProgress progress, NSString *info) + { + [self.connection.remoteObjectProxy updateProgress:progress.percent hours:progress.hours minutes:progress.minutes seconds:progress.seconds state:state info:info]; + }; + self->_progressHandler = progressHandler; + self.reply = reply; + + // Reset the title in the job. + job.title = self.core.titles.firstObject; + [self.core encodeJob:job + progressHandler:self.progressHandler + completionHandler:self.completionHandler]; + }); +} + +- (void)cancelEncode +{ + dispatch_sync(_queue, ^{ + [self.core cancelEncode]; + }); +} + +- (void)pauseEncode +{ + dispatch_sync(_queue, ^{ + [self.core pause]; + }); +} + +- (void)resumeEncode +{ + dispatch_sync(_queue, ^{ + [self.core resume]; + }); +} + +- (void)redirect:(nonnull NSString *)text type:(HBRedirectType)type +{ + if (type == HBRedirectTypeOutput) + { + [self.connection.remoteObjectProxy forwardError:text]; + } + else + { + [self.connection.remoteObjectProxy forwardOutput:text]; + } +} + +@end diff --git a/macosx/HandBrakeXPCService/Info.plist b/macosx/HandBrakeXPCService/Info.plist new file mode 100644 index 000000000..78928db23 --- /dev/null +++ b/macosx/HandBrakeXPCService/Info.plist @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleDisplayName</key> + <string>HandBrakeXPCService</string> + <key>CFBundleExecutable</key> + <string>$(EXECUTABLE_NAME)</string> + <key>CFBundleIdentifier</key> + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>$(PRODUCT_NAME)</string> + <key>CFBundlePackageType</key> + <string>XPC!</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleVersion</key> + <string>1</string> + <key>XPCService</key> + <dict> + <key>ServiceType</key> + <string>Application</string> + </dict> +</dict> +</plist> diff --git a/macosx/HandBrakeXPCService/main.m b/macosx/HandBrakeXPCService/main.m new file mode 100644 index 000000000..e127c9a5b --- /dev/null +++ b/macosx/HandBrakeXPCService/main.m @@ -0,0 +1,38 @@ +/* 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 "HandBrakeXPCService.h" + +@interface HBXPCServiceDelegate : NSObject <NSXPCListenerDelegate> +@end + +@implementation HBXPCServiceDelegate + +- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection +{ + newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(HBRemoteCoreProtocol)]; + newConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(HBRemoteProgressProtocol)]; + + HandBrakeXPCService *exportedObject = [[HandBrakeXPCService alloc] initWithConnection:newConnection]; + newConnection.exportedObject = exportedObject; + + [newConnection resume]; + + return YES; +} + +@end + +int main(int argc, const char *argv[]) +{ + HBXPCServiceDelegate *delegate = [HBXPCServiceDelegate new]; + + NSXPCListener *listener = [NSXPCListener serviceListener]; + listener.delegate = delegate; + + [listener resume]; + + return 0; +} |