mirror of https://github.com/HandBrake/HandBrake
300 lines
8.4 KiB
Objective-C
300 lines
8.4 KiB
Objective-C
/* 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 "HBPreferencesKeys.h"
|
|
|
|
@import HandBrakeKit;
|
|
|
|
@interface HBRemoteCore () <HBRemoteProgressProtocol>
|
|
|
|
@property (nonatomic, readonly) NSXPCConnection *connection;
|
|
@property (nonatomic, readonly) id<HBRemoteCoreProtocol> proxy;
|
|
|
|
@property (nonatomic, readwrite) HBState state;
|
|
|
|
@property (nonatomic, readonly) NSInteger level;
|
|
@property (nonatomic, readonly, copy) NSString *name;
|
|
@property (nonatomic, readonly, copy) NSString *serviceName;
|
|
|
|
@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;
|
|
_automaticallyPreventSleep = NO;
|
|
_level = 1;
|
|
_name = @"HandBrakeXPC";
|
|
_serviceName = @"fr.handbrake.HandBrakeXPCService";
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (instancetype)initWithLogLevel:(NSInteger)level name:(NSString *)name serviceName:(NSString *)serviceName
|
|
{
|
|
self = [self init];
|
|
if (self)
|
|
{
|
|
_level = level;
|
|
_name = [name copy];
|
|
_serviceName = [serviceName copy];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)connect
|
|
{
|
|
_connection = [[NSXPCConnection alloc] initWithServiceName:self.serviceName];
|
|
_connection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(HBRemoteCoreProtocol)];
|
|
|
|
_connection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(HBRemoteProgressProtocol)];
|
|
_connection.exportedObject = self;
|
|
|
|
__weak HBRemoteCore *weakSelf = self;
|
|
|
|
_connection.interruptionHandler = ^{
|
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
[weakSelf handleInterruption];
|
|
});
|
|
};
|
|
|
|
_connection.invalidationHandler = ^{
|
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
[weakSelf forwardError:@"XPC: Service connection was invalidated\n"];
|
|
});
|
|
};
|
|
|
|
_proxy = [_connection remoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {
|
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
[self forwardError:@"XPC: Service did report an error\n"];
|
|
[HBUtilities writeErrorToActivityLog:error];
|
|
});
|
|
}];
|
|
|
|
[_connection resume];
|
|
|
|
[_proxy initGlobal];
|
|
[_proxy setDVDNav:[NSUserDefaults.standardUserDefaults boolForKey:HBUseDvdNav]];
|
|
[_proxy setUpWithLogLevel:self.level name:self.name];
|
|
[_proxy setAutomaticallyPreventSleep:self.automaticallyPreventSleep];
|
|
}
|
|
|
|
- (void)invalidate
|
|
{
|
|
[[_connection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) {}] closeGlobal];
|
|
[_connection invalidate];
|
|
_connection = nil;
|
|
_proxy = nil;
|
|
}
|
|
|
|
- (void)handleInterruption
|
|
{
|
|
[_connection invalidate];
|
|
_connection = nil;
|
|
_proxy = nil;
|
|
|
|
if (self.state == HBStateIdle)
|
|
{
|
|
// XPC was idle and the system closed it
|
|
// to free ram, no need to restart it.
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
HBCoreCompletionHandler handler = self.completionHandler;
|
|
|
|
self.progressHandler = nil;
|
|
self.completionHandler = nil;
|
|
self.state = HBStateIdle;
|
|
|
|
if (handler)
|
|
{
|
|
HBCoreResult result = {0, HBCoreResultCodeUnknown};
|
|
result.code = HBCoreResultCodeUnknown;
|
|
handler(result);
|
|
}
|
|
|
|
[self forwardError:@"XPC: Service did crash\n"];
|
|
}
|
|
}
|
|
|
|
- (void)updateState:(HBState)state
|
|
{
|
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
self.state = state;
|
|
});
|
|
}
|
|
|
|
- (void)setLogLevel:(NSInteger)logLevel
|
|
{
|
|
_logLevel = logLevel;
|
|
[_proxy setLogLevel:logLevel];
|
|
}
|
|
|
|
- (void)setAutomaticallyPreventSleep:(BOOL)automaticallyPreventSleep
|
|
{
|
|
_automaticallyPreventSleep = automaticallyPreventSleep;
|
|
[_proxy setAutomaticallyPreventSleep:automaticallyPreventSleep];
|
|
}
|
|
|
|
- (void)allowSleep
|
|
{
|
|
[_proxy allowSleep];
|
|
}
|
|
|
|
- (void)preventSleep
|
|
{
|
|
[_proxy preventSleep];
|
|
}
|
|
|
|
- (void)scanURL:(NSURL *)url titleIndex:(NSUInteger)index previews:(NSUInteger)previewsNum minDuration:(NSUInteger)minSeconds maxDuration:(NSUInteger)maxSeconds keepPreviews:(BOOL)keepPreviews hardwareDecoder:(BOOL)hardwareDecoder keepDuplicateTitles:(BOOL)keepDuplicateTitles progressHandler:(nonnull HBCoreProgressHandler)progressHandler completionHandler:(nonnull HBCoreCompletionHandler)completionHandler
|
|
{
|
|
if (!_connection)
|
|
{
|
|
[self connect];
|
|
}
|
|
|
|
#ifdef __SANDBOX_ENABLED__
|
|
__block HBSecurityAccessToken *token = [HBSecurityAccessToken tokenWithObject:url];
|
|
|
|
NSData *bookmark = [url bookmarkDataWithOptions:0 includingResourceValuesForKeys:nil relativeToURL:nil error:NULL];
|
|
if (bookmark)
|
|
{
|
|
[_proxy provideResourceAccessWithBookmarks:@[bookmark]];
|
|
}
|
|
#endif
|
|
|
|
self.progressHandler = progressHandler;
|
|
self.completionHandler = completionHandler;
|
|
|
|
self.state = HBStateScanning;
|
|
|
|
__weak HBRemoteCore *weakSelf = self;
|
|
|
|
[_proxy scanURL:url titleIndex:index previews:previewsNum minDuration:minSeconds maxDuration:maxSeconds keepPreviews:keepPreviews hardwareDecoder:(BOOL)hardwareDecoder keepDuplicateTitles:(BOOL)keepDuplicateTitles withReply:^(HBCoreResult result) {
|
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
HBCoreCompletionHandler handler = weakSelf.completionHandler;
|
|
weakSelf.completionHandler = nil;
|
|
weakSelf.progressHandler = nil;
|
|
#ifdef __SANDBOX_ENABLED__
|
|
token = nil;
|
|
#endif
|
|
handler(result);
|
|
});
|
|
}];
|
|
}
|
|
|
|
- (void)cancelScan
|
|
{
|
|
[_proxy cancelScan];
|
|
}
|
|
|
|
- (void)encodeJob:(HBJob *)job progressHandler:(HBCoreProgressHandler)progressHandler completionHandler:(HBCoreCompletionHandler)completionHandler
|
|
{
|
|
#ifdef __SANDBOX_ENABLED__
|
|
__block HBSecurityAccessToken *token = [HBSecurityAccessToken tokenWithObject:job];
|
|
|
|
NSMutableArray<NSData *> *bookmarks = [NSMutableArray array];
|
|
|
|
for (HBSubtitlesTrack *track in job.subtitles.tracks)
|
|
{
|
|
if (track.fileURL)
|
|
{
|
|
NSData *subtitlesBookmark = [track.fileURL bookmarkDataWithOptions:0 includingResourceValuesForKeys:nil relativeToURL:nil error:NULL];
|
|
if (subtitlesBookmark)
|
|
{
|
|
[bookmarks addObject:subtitlesBookmark];
|
|
}
|
|
}
|
|
}
|
|
|
|
NSData *destinationBookmark = [job.destinationFolderURL bookmarkDataWithOptions:0 includingResourceValuesForKeys:nil relativeToURL:nil error:NULL];
|
|
if (destinationBookmark)
|
|
{
|
|
[bookmarks addObject:destinationBookmark];
|
|
}
|
|
|
|
NSData *sourceBookmark = [job.fileURL bookmarkDataWithOptions:0 includingResourceValuesForKeys:nil relativeToURL:nil error:NULL];
|
|
if (sourceBookmark)
|
|
{
|
|
[bookmarks addObject:sourceBookmark];
|
|
}
|
|
|
|
[_proxy provideResourceAccessWithBookmarks:bookmarks];
|
|
|
|
#endif
|
|
|
|
self.progressHandler = progressHandler;
|
|
self.completionHandler = completionHandler;
|
|
|
|
self.state = HBStateWorking;
|
|
|
|
__weak HBRemoteCore *weakSelf = self;
|
|
|
|
[_proxy encodeJob:job withReply:^(HBCoreResult result) {
|
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
HBCoreCompletionHandler handler = weakSelf.completionHandler;
|
|
weakSelf.completionHandler = nil;
|
|
weakSelf.progressHandler = nil;
|
|
#ifdef __SANDBOX_ENABLED__
|
|
token = nil;
|
|
#endif
|
|
handler(result);
|
|
});
|
|
}];
|
|
}
|
|
|
|
- (void)cancelEncode
|
|
{
|
|
[_proxy cancelEncode];
|
|
}
|
|
|
|
- (void)updateProgress:(double)currentProgress hours:(int)hours minutes:(int)minutes seconds:(int)seconds state:(HBState)state info:(NSString *)info
|
|
{
|
|
__weak HBRemoteCore *weakSelf = self;
|
|
|
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
if (weakSelf.progressHandler)
|
|
{
|
|
HBProgress progress = {currentProgress , hours, minutes, seconds};
|
|
weakSelf.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
|