2019-08-11 09:07:20 +02:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2019-08-11 13:16:44 +02:00
|
|
|
- (void)setDVDNav:(BOOL)enabled
|
|
|
|
{
|
|
|
|
dispatch_sync(_queue, ^{
|
|
|
|
[HBCore setDVDNav:enabled];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-08-11 09:07:20 +02:00
|
|
|
- (void)setUpWithLogLevel:(NSInteger)level name:(NSString *)name
|
|
|
|
{
|
|
|
|
_core = [[HBCore alloc] initWithLogLevel:level queue:_queue];
|
|
|
|
_core.name = name;
|
|
|
|
|
2023-06-01 12:23:34 +02:00
|
|
|
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];
|
|
|
|
};
|
|
|
|
_progressHandler = progressHandler;
|
|
|
|
|
2019-08-11 09:07:20 +02:00
|
|
|
void (^completionHandler)(HBCoreResult result) = ^(HBCoreResult result)
|
|
|
|
{
|
2024-05-06 08:32:48 +02:00
|
|
|
[HBCore cleanTemporaryFiles];
|
2023-06-01 12:23:34 +02:00
|
|
|
[self stopAccessingSecurityScopedResources];
|
2019-08-11 09:07:20 +02:00
|
|
|
self.reply(result);
|
|
|
|
self.reply = nil;
|
|
|
|
};
|
|
|
|
_completionHandler = completionHandler;
|
|
|
|
|
|
|
|
// Set up observers
|
|
|
|
[self.core addObserver:self forKeyPath:@"state"
|
|
|
|
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial
|
|
|
|
context:HandBrakeXPCServiceContext];
|
|
|
|
}
|
|
|
|
|
2024-05-06 08:32:48 +02:00
|
|
|
- (void)initGlobal
|
|
|
|
{
|
|
|
|
[HBCore initGlobal];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)closeGlobal
|
2019-08-11 09:07:20 +02:00
|
|
|
{
|
|
|
|
[HBCore closeGlobal];
|
|
|
|
}
|
|
|
|
|
2019-08-14 07:21:48 +02:00
|
|
|
- (void)setLogLevel:(NSInteger)logLevel
|
|
|
|
{
|
|
|
|
dispatch_sync(_queue, ^{
|
|
|
|
self.core.logLevel = logLevel;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-08-11 09:07:20 +02:00
|
|
|
- (void)provideResourceAccessWithBookmarks:(NSArray<NSData *> *)bookmarks
|
|
|
|
{
|
|
|
|
dispatch_sync(_queue, ^{
|
2019-08-13 10:27:05 +02:00
|
|
|
NSMutableArray<NSURL *> *urls = [NSMutableArray array];
|
2019-08-11 09:07:20 +02:00
|
|
|
for (NSData *bookmark in bookmarks)
|
|
|
|
{
|
|
|
|
NSURL *url = [NSURL URLByResolvingBookmarkData:bookmark options:0 relativeToURL:nil bookmarkDataIsStale:NULL error:NULL];
|
2019-08-13 10:27:05 +02:00
|
|
|
if (url)
|
|
|
|
{
|
|
|
|
[urls addObject:url];
|
|
|
|
}
|
2019-08-11 09:07:20 +02:00
|
|
|
}
|
2019-08-13 10:27:05 +02:00
|
|
|
self.urls = urls;
|
2019-08-11 09:07:20 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-06-01 12:23:34 +02:00
|
|
|
- (void)stopAccessingSecurityScopedResources
|
|
|
|
{
|
|
|
|
for (NSURL *url in self.urls)
|
|
|
|
{
|
|
|
|
[url stopAccessingSecurityScopedResource];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-11 12:19:17 +02:00
|
|
|
- (void)setAutomaticallyPreventSleep:(BOOL)automaticallyPreventSleep
|
|
|
|
{
|
|
|
|
dispatch_sync(_queue, ^{
|
|
|
|
self.core.automaticallyPreventSleep = automaticallyPreventSleep;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-08-11 09:07:20 +02:00
|
|
|
- (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];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-11 12:19:17 +02:00
|
|
|
- (void)preventSleep
|
|
|
|
{
|
|
|
|
dispatch_sync(_queue, ^{
|
|
|
|
[self.core preventSleep];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)allowSleep
|
|
|
|
{
|
|
|
|
dispatch_sync(_queue, ^{
|
|
|
|
[self.core allowSleep];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-10-22 13:08:18 +02:00
|
|
|
- (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 withReply:(void (^)(HBCoreResult))reply
|
2019-08-11 09:07:20 +02:00
|
|
|
{
|
|
|
|
dispatch_sync(_queue, ^{
|
|
|
|
self.reply = reply;
|
|
|
|
|
2023-07-10 19:19:45 +01:00
|
|
|
[self.core scanURLs:@[url] titleIndex:index
|
|
|
|
previews:previewsNum
|
2024-10-22 13:08:18 +02:00
|
|
|
minDuration:minSeconds
|
|
|
|
maxDuration:maxSeconds
|
2023-07-10 19:19:45 +01:00
|
|
|
keepPreviews:keepPreviews
|
2023-08-10 10:25:03 +02:00
|
|
|
hardwareDecoder:hardwareDecoder
|
2024-04-21 14:19:22 +01:00
|
|
|
keepDuplicateTitles:keepDuplicateTitles
|
2023-07-10 19:19:45 +01:00
|
|
|
progressHandler:self.progressHandler
|
|
|
|
completionHandler:self.completionHandler];
|
2019-08-11 09:07:20 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)cancelScan
|
|
|
|
{
|
|
|
|
dispatch_sync(_queue, ^{
|
|
|
|
[self.core cancelScan];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-08-12 10:19:00 +02:00
|
|
|
- (void)encodeJob:(HBJob *)job withReply:(void (^)(HBCoreResult))reply
|
2019-08-11 09:07:20 +02:00
|
|
|
{
|
|
|
|
dispatch_sync(_queue, ^{
|
|
|
|
self.reply = reply;
|
|
|
|
|
|
|
|
// Reset the title in the job.
|
|
|
|
job.title = self.core.titles.firstObject;
|
2023-06-01 12:23:34 +02:00
|
|
|
|
2019-08-11 09:07:20 +02:00
|
|
|
[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
|