MacGui: remove distributed queue.

This commit is contained in:
Damiano Galassi 2020-01-31 17:55:52 +01:00
parent b0a2c68ee6
commit c4202b8c37
No known key found for this signature in database
GPG Key ID: 5452E231DFDBCA11
11 changed files with 89 additions and 568 deletions

View File

@ -103,29 +103,14 @@
presetsManager:self.presetsManager];
[self.presetsMenuBuilder build];
// Get the number of HandBrake instances currently running
NSUInteger instances = [NSRunningApplication runningApplicationsWithBundleIdentifier:NSBundle.mainBundle.bundleIdentifier].count;
// Open debug output window now if it was visible when HB was closed
if ([ud boolForKey:@"OutputPanelIsOpen"])
{
[self showOutputPanel:nil];
}
// On Screen Notification
// We check to see if there is already another instance of hb running.
if (instances > 1)
{
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:NSLocalizedString(@"There is already an instance of HandBrake running.", @"Queue -> Multiple instances alert message")];
[alert setInformativeText:NSLocalizedString(@"The queue will be shared between the instances.", @"Queue -> Multiple instances alert informative text")];
[alert runModal];
}
else
{
[self.queue setEncodingJobsAsPending];
[self.queue removeCompletedAndCancelledItems];
}
[self.queue setEncodingJobsAsPending];
[self.queue removeCompletedAndCancelledItems];
// Now we re-check the queue array to see if there are
// any remaining encodes to be done
@ -153,15 +138,7 @@
[self cleanEncodeLogs];
}
// If we are a single instance it is safe to clean up the previews if there are any
// left over. This is a bit of a kludge but will prevent a build up of old instance
// live preview cruft. No danger of removing an active preview directory since they
// are created later in HBPreviewController if they don't exist at the moment a live
// preview encode is initiated.
if (instances == 1)
{
[self cleanPreviews];
}
[self cleanPreviews];
});
}

View File

@ -1,53 +0,0 @@
/* HBDistributedArray.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>
extern NSString *HBDistributedArrayChanged;
/**
* Objects in HBDistributedArray
* must implement this protocol.
*/
@protocol HBUniqueObject <NSObject>
@property (nonatomic, readonly) NSString *uuid;
@end
typedef NS_ENUM(NSUInteger, HBDistributedArrayContent) {
HBDistributedArrayContentAcquired,
HBDistributedArrayContentReload,
};
/**
* HBDistributedArray
* a mutable array that share its content between processes.
* post a HBDistributedArrayChanged when the content is changed
* by another process.
*
* Use beginTransaction and commit to wrap atomic changes to the array.
*
* It is safe to keep a reference to an array object.
*/
@interface HBDistributedArray<ObjectType> : NSMutableArray
- (instancetype)initWithURL:(NSURL *)fileURL class:(Class)objectClass;
/**
* Begins a transaction on the array
*
* @return whether the array content changes or not after beginning the transaction.
*/
- (HBDistributedArrayContent)beginTransaction;
/**
* Commit the changes and notify
* the observers about the changes.
*/
- (void)commit;
@end

View File

@ -1,356 +0,0 @@
/* HBDistributedArray.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 "HBDistributedArray.h"
#import "HBUtilities.h"
#include <semaphore.h>
/**
* HBProxyArrayObject wraps an object inside a proxy
* to make it possible to keep a reference to an array
* object even if the underlying has been swapped
*/
@interface HBProxyArrayObject : NSProxy
- (instancetype)initWithObject:(id)object;
@property (nonatomic, strong) id representedObject;
@property (unsafe_unretained, nonatomic, readonly) NSString *uuid;
@end
@implementation HBProxyArrayObject
- (instancetype)initWithObject:(id)object
{
_representedObject = object;
return self;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
return [self.representedObject methodSignatureForSelector:selector];
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
[invocation invokeWithTarget:self.representedObject];
}
- (NSString *)uuid
{
return [self.representedObject uuid];
}
@end
NSString *HBDistributedArrayChanged = @"HBDistributedArrayChanged";
NSString *HBDistributedArraWrittenToDisk = @"HBDistributedArraWrittenToDisk";
@interface HBDistributedArray<ObjectType> ()
@property (nonatomic, readonly) NSMutableArray<ObjectType> *array;
@property (nonatomic, readonly) NSURL *fileURL;
@property (nonatomic, readwrite) NSTimeInterval modifiedTime;
@property (nonatomic, readonly) NSSet *objectClasses;
@property (nonatomic, readonly) sem_t *mutex;
@property (nonatomic, readwrite) uint32_t mutexCount;
@property (nonatomic, readwrite) BOOL multipleInstances;
@end
@implementation HBDistributedArray
- (instancetype)initWithURL:(NSURL *)fileURL class:(Class)objectClass
{
self = [super init];
if (self)
{
_fileURL = [fileURL copy];
_array = [[NSMutableArray alloc] init];
_objectClasses = [NSSet setWithObjects:[NSMutableArray class], objectClass, nil];
NSString *identifier = [[NSBundle mainBundle] bundleIdentifier];
NSArray *runningInstances = [NSRunningApplication runningApplicationsWithBundleIdentifier:identifier];
const char *name = [NSString stringWithFormat:@"%@/%@", identifier, _fileURL.lastPathComponent.stringByDeletingPathExtension].UTF8String;
// Unlink the semaphore if we are the only
// instance running, this fixes the case where
// HB crashed while the sem is locked.
if (runningInstances.count == 1)
{
sem_unlink(name);
}
// Use a named semaphore as a mutex for now
// it can cause a deadlock if an instance
// crashed while it has the lock on the semaphore.
_mutex = sem_open(name, O_CREAT, 0777, 1);
if (_mutex == SEM_FAILED)
{
[HBUtilities writeToActivityLog:"%s: %d", "Error in creating semaphore: ", errno];
}
[self lock];
NSUInteger instances = [NSRunningApplication runningApplicationsWithBundleIdentifier:NSBundle.mainBundle.bundleIdentifier].count;
_multipleInstances = instances > 1;
[self unlock];
[NSDistributedNotificationCenter.defaultCenter addObserver:self selector:@selector(handleNotification:) name:HBDistributedArraWrittenToDisk object:nil];
if ([NSFileManager.defaultManager fileExistsAtPath:_fileURL.path])
{
// Load the array from disk
[self lock];
[self reload];
[self unlock];
}
}
return self;
}
- (void)dealloc
{
[NSDistributedNotificationCenter.defaultCenter removeObserver:self];
[self lock];
[self synchronize];
[self unlock];
sem_close(_mutex);
}
- (uint32_t)lock
{
if (self.mutexCount == 0)
{
sem_wait(self.mutex);
}
self.mutexCount++;
return self.mutexCount;
}
- (void)unlock
{
if (self.mutexCount == 1)
{
sem_post(self.mutex);
}
self.mutexCount--;
}
- (HBDistributedArrayContent)beginTransaction
{
BOOL alreadyLocked = [self lock] > 1;
// We got the lock, need to check if
// someone else modified the file
// while we were locked, because we
// could have not received the notification yet
if (alreadyLocked == false && self.multipleInstances)
{
NSDate *date = nil;
[self.fileURL getResourceValue:&date forKey:NSURLAttributeModificationDateKey error:nil];
if (date.timeIntervalSinceReferenceDate > self.modifiedTime)
{
// File was modified while we waited on the lock
// reload it
[self reload];
return HBDistributedArrayContentReload;
}
}
return HBDistributedArrayContentAcquired;
}
- (void)commit
{
// Save changes to disk
// and unlock
[self synchronizeIfNeeded];
[self unlock];
}
- (void)postNotification
{
[[NSNotificationCenter defaultCenter] postNotificationName:HBDistributedArrayChanged object:self];
}
/**
* Handle the distributed notification
*/
- (void)handleNotification:(NSNotification *)notification
{
if (!([notification.object integerValue] == getpid()))
{
self.multipleInstances = YES;
[self lock];
[self reload];
[self unlock];
}
}
/**
* Reload the array from disk
*/
- (void)reload
{
NSMutableArray<HBUniqueObject> *jobsArray;
NSError *error;
NSData *queue = [NSData dataWithContentsOfURL:self.fileURL];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:queue];
unarchiver.requiresSecureCoding = YES;
jobsArray = [unarchiver decodeTopLevelObjectOfClasses:self.objectClasses forKey:NSKeyedArchiveRootObjectKey error:&error];
if (error)
{
[HBUtilities writeErrorToActivityLog:error];
}
[unarchiver finishDecoding];
// Swap the proxy objects representation with the new
// one read from disk
NSMutableArray *proxyArray = [NSMutableArray array];
for (id<HBUniqueObject> anObject in jobsArray)
{
NSString *uuid = anObject.uuid;
HBProxyArrayObject *proxy = nil;
for (HBProxyArrayObject *temp in self.array)
{
if ([temp.uuid isEqualToString:uuid])
{
temp.representedObject = anObject;
proxy = temp;
break;
}
}
if (proxy)
{
[proxyArray addObject:proxy];
}
else
{
[proxyArray addObject:[self wrapObjectIfNeeded:anObject]];
}
}
[self setArray:proxyArray];
[self postNotification];
// Update the time, so we can avoid reloaded the file from disk later.
self.modifiedTime = [NSDate timeIntervalSinceReferenceDate];
}
/**
* Writes the changes to disk only if we aren't exiting a recursive lock
*/
- (void)synchronizeIfNeeded
{
if (self.mutexCount == 1)
{
[self synchronize];
}
}
/**
* Writes the changes to disk
*/
- (void)synchronize
{
NSMutableArray *temp = [NSMutableArray array];
// Unwrap the array objects and save them to disk
for (HBProxyArrayObject *proxy in self)
{
[temp addObject:proxy.representedObject];
}
if (![NSKeyedArchiver archiveRootObject:temp toFile:self.fileURL.path])
{
[HBUtilities writeToActivityLog:"Failed to write the queue to disk"];
}
// Send a distributed notification.
[[NSDistributedNotificationCenter defaultCenter] postNotificationName:HBDistributedArraWrittenToDisk
object:[NSString stringWithFormat:@"%d", getpid()]
userInfo:nil
deliverImmediately:YES];
// Update the time, so we can avoid reloaded the file from disk later.
self.modifiedTime = [NSDate timeIntervalSinceReferenceDate];
}
/**
* Wraps an object inside a HBObjectProxy instance
* if it's not already wrapped.
*
* @param anObject the object to wrap
*
* @return a wrapped object
*/
- (id)wrapObjectIfNeeded:(id)anObject
{
if ([[anObject class] isEqual:[HBProxyArrayObject class]])
{
return anObject;
}
else
{
return [[HBProxyArrayObject alloc] initWithObject:anObject];
}
}
#pragma mark - Methods needed to subclass NSMutableArray
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index
{
[self.array insertObject:[self wrapObjectIfNeeded:anObject] atIndex:index];
}
- (void)removeObjectAtIndex:(NSUInteger)index
{
[self.array removeObjectAtIndex:index];
}
- (void)addObject:(id)anObject
{
[self.array addObject:[self wrapObjectIfNeeded:anObject]];
}
- (void)removeLastObject
{
[self.array removeLastObject];
}
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject
{
(self.array)[index] = [self wrapObjectIfNeeded:anObject];
}
- (NSUInteger)count
{
return [self.array count];
}
- (id)objectAtIndex:(NSUInteger)index
{
return (self.array)[index];
}
@end

View File

@ -6,7 +6,6 @@
#import <Foundation/Foundation.h>
#import "HBDistributedArray.h"
#import "HBQueueItem.h"
NS_ASSUME_NONNULL_BEGIN
@ -43,9 +42,9 @@ extern NSString * const HBQueueItemNotificationItemKey; // HBQueueI
@interface HBQueue : NSObject
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithURL:(NSURL *)queueURL;
- (instancetype)initWithURL:(NSURL *)fileURL;
@property (nonatomic, readonly) HBDistributedArray<HBQueueItem *> *items;
@property (nonatomic, readonly) NSArray<HBQueueItem *> *items;
@property (nonatomic, nullable) HBQueueItem *currentItem;
@ -59,7 +58,6 @@ extern NSString * const HBQueueItemNotificationItemKey; // HBQueueI
- (void)addJobs:(NSArray<HBJob *> *)jobs;
- (void)addItems:(NSArray<HBQueueItem *> *)items atIndexes:(NSIndexSet *)indexes;
- (void)removeItemAtIndex:(NSUInteger)index;
- (void)removeItemsAtIndexes:(NSIndexSet *)indexes;
- (void)moveItems:(NSArray<HBQueueItem *> *)items toIndex:(NSUInteger)index;

View File

@ -51,11 +51,14 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
@property (nonatomic, nullable) HBJobOutputFileWriter *currentLog;
@property (nonatomic, readonly) NSURL *fileURL;
@property (nonatomic, readonly) NSMutableArray<HBQueueItem *> *itemsInternal;
@end
@implementation HBQueue
- (instancetype)initWithURL:(NSURL *)queueURL
- (instancetype)initWithURL:(NSURL *)fileURL
{
self = [super init];
if (self)
@ -66,12 +69,10 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
_core = [[HBRemoteCore alloc] initWithLogLevel:loggingLevel name:@"QueueCore"];
_core.automaticallyPreventSleep = NO;
_items = [[HBDistributedArray alloc] initWithURL:queueURL class:[HBQueueItem class]];
_fileURL = fileURL;
_itemsInternal = [self load];
_undoManager = [[NSUndoManager alloc] init];
// Set up the observers
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadQueue) name:HBDistributedArrayChanged object:_items];
[self updateStats];
// Set up observers
@ -107,8 +108,48 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
[self.core invalidate];
}
#pragma mark - Load and save
- (NSMutableArray *)load
{
NSError *error;
NSData *queue = [NSData dataWithContentsOfURL:self.fileURL];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:queue];
unarchiver.requiresSecureCoding = YES;
NSSet *objectClasses = [NSSet setWithObjects:[NSMutableArray class], [HBQueueItem class], nil];
NSArray *loadedItems = [unarchiver decodeTopLevelObjectOfClasses:objectClasses
forKey:NSKeyedArchiveRootObjectKey
error:&error];
if (error)
{
[HBUtilities writeErrorToActivityLog:error];
}
[unarchiver finishDecoding];
return loadedItems ? [loadedItems mutableCopy] : [NSMutableArray array];
}
- (void)save
{
if (![NSKeyedArchiver archiveRootObject:self.itemsInternal toFile:self.fileURL.path])
{
[HBUtilities writeToActivityLog:"Failed to write the queue to disk"];
}
}
#pragma mark - Public methods
- (NSArray *)items
{
return self.itemsInternal;
}
- (void)addJob:(HBJob *)item
{
NSParameterAssert(item);
@ -127,7 +168,7 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
}
if (itemsToAdd.count)
{
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(self.items.count, itemsToAdd.count)];
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(self.itemsInternal.count, itemsToAdd.count)];
[self addItems:itemsToAdd atIndexes:indexes];
}
}
@ -136,7 +177,7 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
{
NSParameterAssert(url);
for (HBQueueItem *item in self.items)
for (HBQueueItem *item in self.itemsInternal)
{
if ((item.state == HBQueueItemStateReady || item.state == HBQueueItemStateWorking)
&& [item.completeOutputURL isEqualTo:url])
@ -151,14 +192,13 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
{
NSParameterAssert(items);
NSParameterAssert(indexes);
[self.items beginTransaction];
// Forward
NSUInteger currentIndex = indexes.firstIndex;
NSUInteger currentObjectIndex = 0;
while (currentIndex != NSNotFound)
{
[self.items insertObject:items[currentObjectIndex] atIndex:currentIndex];
[self.itemsInternal insertObject:items[currentObjectIndex] atIndex:currentIndex];
currentIndex = [indexes indexGreaterThanIndex:currentIndex];
currentObjectIndex++;
}
@ -181,12 +221,7 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
}
[self updateStats];
[self.items commit];
}
- (void)removeItemAtIndex:(NSUInteger)index
{
[self removeItemsAtIndexes:[NSIndexSet indexSetWithIndex:index]];
[self save];
}
- (void)removeItemsAtIndexes:(NSIndexSet *)indexes
@ -198,13 +233,11 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
return;
}
[self.items beginTransaction];
NSArray<HBQueueItem *> *removeItems = [self.itemsInternal objectsAtIndexes:indexes];
NSArray<HBQueueItem *> *removeItems = [self.items objectsAtIndexes:indexes];
if (self.items.count > indexes.lastIndex)
if (self.itemsInternal.count > indexes.lastIndex)
{
[self.items removeObjectsAtIndexes:indexes];
[self.itemsInternal removeObjectsAtIndexes:indexes];
}
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidRemoveItemNotification object:self userInfo:@{HBQueueItemNotificationIndexesKey: indexes}];
@ -225,27 +258,25 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
}
[self updateStats];
[self.items commit];
[self save];
}
- (void)moveItems:(NSArray<HBQueueItem *> *)items toIndex:(NSUInteger)index
{
[self.items beginTransaction];
NSMutableArray<NSNumber *> *source = [NSMutableArray array];
NSMutableArray<NSNumber *> *dest = [NSMutableArray array];
for (id object in items.reverseObjectEnumerator)
{
NSUInteger sourceIndex = [self.items indexOfObject:object];
[self.items removeObjectAtIndex:sourceIndex];
NSUInteger sourceIndex = [self.itemsInternal indexOfObject:object];
[self.itemsInternal removeObjectAtIndex:sourceIndex];
if (sourceIndex < index)
{
index--;
}
[self.items insertObject:object atIndex:index];
[self.itemsInternal insertObject:object atIndex:index];
[source addObject:@(index)];
[dest addObject:@(sourceIndex)];
@ -271,13 +302,11 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
}
}
[self.items commit];
[self save];
}
- (void)moveQueueItemsAtIndexes:(NSArray *)source toIndexes:(NSArray *)dest
{
[self.items beginTransaction];
NSMutableArray<NSNumber *> *newSource = [NSMutableArray array];
NSMutableArray<NSNumber *> *newDest = [NSMutableArray array];
@ -289,9 +318,9 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
[newSource addObject:@(destIndex)];
[newDest addObject:@(sourceIndex)];
id obj = [self.items objectAtIndex:sourceIndex];
[self.items removeObjectAtIndex:sourceIndex];
[self.items insertObject:obj atIndex:destIndex];
id obj = [self.itemsInternal objectAtIndex:sourceIndex];
[self.itemsInternal removeObjectAtIndex:sourceIndex];
[self.itemsInternal insertObject:obj atIndex:destIndex];
}
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidMoveItemNotification
@ -314,7 +343,7 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
}
}
[self.items commit];
[self save];
}
/**
@ -323,13 +352,12 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
*/
- (void)removeCompletedAndCancelledItems
{
[self.items beginTransaction];
NSIndexSet *indexes = [self.items indexesOfObjectsUsingBlock:^BOOL(HBQueueItem *item) {
NSIndexSet *indexes = [self.itemsInternal indexesOfObjectsUsingBlock:^BOOL(HBQueueItem *item) {
return (item.state == HBQueueItemStateCompleted || item.state == HBQueueItemStateCanceled);
}];
[self removeItemsAtIndexes:indexes];
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidRemoveItemNotification object:self userInfo:@{@"indexes": indexes}];
[self.items commit];
[self save];
}
/**
@ -337,45 +365,33 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
*/
- (void)removeAllItems
{
[self.items beginTransaction];
[self removeItemsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.items.count)]];
[self.items commit];
[self removeItemsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.itemsInternal.count)]];
[self save];
}
- (void)removeNotWorkingItems
{
[self.items beginTransaction];
NSIndexSet *indexes = [self.items indexesOfObjectsUsingBlock:^BOOL(HBQueueItem *item) {
NSIndexSet *indexes = [self.itemsInternal indexesOfObjectsUsingBlock:^BOOL(HBQueueItem *item) {
return (item.state != HBQueueItemStateWorking);
}];
[self removeItemsAtIndexes:indexes];
[self.items commit];
}
- (void)removeCompletedItems
{
[self.items beginTransaction];
NSIndexSet *indexes = [self.items indexesOfObjectsUsingBlock:^BOOL(HBQueueItem *item) {
NSIndexSet *indexes = [self.itemsInternal indexesOfObjectsUsingBlock:^BOOL(HBQueueItem *item) {
return (item.state == HBQueueItemStateCompleted);
}];
[self removeItemsAtIndexes:indexes];
[self.items commit];
}
- (void)resetItemsAtIndexes:(NSIndexSet *)indexes
{
if ([self.items beginTransaction] == HBDistributedArrayContentReload)
{
// Do not execute the action if the array changed.
[self.items commit];
return;
}
NSMutableIndexSet *updatedIndexes = [NSMutableIndexSet indexSet];
NSUInteger currentIndex = indexes.firstIndex;
while (currentIndex != NSNotFound) {
HBQueueItem *item = self.items[currentIndex];
HBQueueItem *item = self.itemsInternal[currentIndex];
if (item.state == HBQueueItemStateCanceled || item.state == HBQueueItemStateCompleted || item.state == HBQueueItemStateFailed)
{
@ -387,27 +403,23 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
[self updateStats];
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidChangeItemNotification object:self userInfo:@{HBQueueItemNotificationIndexesKey: indexes}];
[self.items commit];
[self save];
}
- (void)resetAllItems
{
[self.items beginTransaction];
NSIndexSet *indexes = [self.items indexesOfObjectsUsingBlock:^BOOL(HBQueueItem *item) {
NSIndexSet *indexes = [self.itemsInternal indexesOfObjectsUsingBlock:^BOOL(HBQueueItem *item) {
return (item.state != HBQueueItemStateWorking);
}];
[self resetItemsAtIndexes:indexes];
[self.items commit];
}
- (void)resetFailedItems
{
[self.items beginTransaction];
NSIndexSet *indexes = [self.items indexesOfObjectsUsingBlock:^BOOL(HBQueueItem *item) {
NSIndexSet *indexes = [self.itemsInternal indexesOfObjectsUsingBlock:^BOOL(HBQueueItem *item) {
return (item.state == HBQueueItemStateFailed);
}];
[self resetItemsAtIndexes:indexes];
[self.items commit];
}
/**
@ -416,11 +428,9 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
*/
- (void)setEncodingJobsAsPending
{
[self.items beginTransaction];
NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];
NSUInteger idx = 0;
for (HBQueueItem *item in self.items)
for (HBQueueItem *item in self.itemsInternal)
{
// We want to keep any queue item that is pending or was previously being encoded
if (item.state == HBQueueItemStateWorking)
@ -433,7 +443,8 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
[self updateStats];
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidChangeItemNotification object:self userInfo:@{HBQueueItemNotificationIndexesKey: indexes}];
[self.items commit];
[self save];
}
- (BOOL)canEncode
@ -474,21 +485,11 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
#pragma mark - Private queue editing methods
/**
* Reloads the queue, this is called
* when another HandBrake instance modifies the queue
*/
- (void)reloadQueue
{
[self updateStats];
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueReloadItemsNotification object:self];
}
- (void)updateStats
{
NSUInteger pendingCount = 0, failedCount = 0, completedCount = 0;
for (HBQueueItem *item in self.items)
for (HBQueueItem *item in self.itemsInternal)
{
if (item.state == HBQueueItemStateReady)
{
@ -544,7 +545,7 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
*/
- (HBQueueItem *)getNextPendingQueueItem
{
for (HBQueueItem *item in self.items)
for (HBQueueItem *item in self.itemsInternal)
{
if (item.state == HBQueueItemStateReady)
{
@ -569,8 +570,6 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
*/
- (void)encodeNextQueueItem
{
[self.items beginTransaction];
// since we have completed an encode, we go to the next
if (self.stop)
{
@ -614,7 +613,7 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
}
self.currentItem = nextItem;
NSIndexSet *indexes = [NSIndexSet indexSetWithIndex:[self.items indexOfObject:nextItem]];
NSIndexSet *indexes = [NSIndexSet indexSetWithIndex:[self.itemsInternal indexOfObject:nextItem]];
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidStartItemNotification object:self userInfo:@{HBQueueItemNotificationItemKey: nextItem,
HBQueueItemNotificationIndexesKey: indexes}];
@ -638,13 +637,12 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidChangeStateNotification object:self];
[self.items commit];
[self save];
}
- (void)completedItem:(HBQueueItem *)item result:(HBCoreResult)result
{
NSParameterAssert(item);
[self.items beginTransaction];
item.endedDate = [NSDate date];
@ -687,12 +685,12 @@ NSString * const HBQueueItemNotificationItemKey = @"HBQueueItemNotificationItemK
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueProgressNotification object:self userInfo:@{HBQueueProgressNotificationPercentKey: @1.0,
HBQueueProgressNotificationInfoKey: info}];
NSUInteger index = [self.items indexOfObject:item];
NSUInteger index = [self.itemsInternal indexOfObject:item];
NSIndexSet *indexes = index != NSNotFound ? [NSIndexSet indexSetWithIndex:index] : [NSIndexSet indexSet];
[NSNotificationCenter.defaultCenter postNotificationName:HBQueueDidCompleteItemNotification object:self userInfo:@{HBQueueItemNotificationItemKey: item,
HBQueueItemNotificationIndexesKey: indexes}];
[self.items commit];
[self save];
}
/**

View File

@ -309,13 +309,6 @@
*/
- (void)removeQueueItemsAtIndexes:(NSIndexSet *)indexes
{
if ([self.queue.items beginTransaction] == HBDistributedArrayContentReload)
{
// Do not execture the action if the array changed.
[self.queue.items commit];
return;
}
if (indexes.count)
{
NSMutableIndexSet *mutableIndexes = [indexes mutableCopy];
@ -350,13 +343,9 @@
[alert beginSheetModalForWindow:targetWindow completionHandler:^(NSModalResponse returnCode) {
if (returnCode == NSAlertSecondButtonReturn)
{
[self.queue.items beginTransaction];
NSInteger index = [self.queue.items indexOfObject:self.queue.currentItem];
[self.queue cancelCurrentItemAndContinue];
[self.queue removeItemAtIndex:index];
[self.queue.items commit];
[self.queue removeItemsAtIndexes:[NSIndexSet indexSetWithIndex:index]];
}
}];
}
@ -365,13 +354,11 @@
// remove the non working items immediately
[self.queue removeItemsAtIndexes:mutableIndexes];
}
[self.queue.items commit];
}
- (void)doEditQueueItem:(HBQueueItem *)item
{
NSParameterAssert(item);
[self.queue.items beginTransaction];
if (item == self.queue.currentItem)
{
@ -383,23 +370,19 @@
}
[self.delegate openJob:[item.job copy] completionHandler:^(BOOL result) {
[self.queue.items beginTransaction];
if (result)
{
// Now that source is loaded and settings applied, delete the queue item from the queue
NSInteger index = [self.queue.items indexOfObject:item];
item.state = HBQueueItemStateReady;
[self.queue removeItemAtIndex:index];
[self.queue removeItemsAtIndexes:[NSIndexSet indexSetWithIndex:index]];
}
else
{
item.state = HBQueueItemStateFailed;
NSBeep();
}
[self.queue.items commit];
}];
[self.queue.items commit];
}
/**
@ -407,13 +390,6 @@
*/
- (void)editQueueItem:(HBQueueItem *)item
{
if ([self.queue.items beginTransaction] == HBDistributedArrayContentReload)
{
// Do not execture the action if the array changed.
[self.queue.items commit];
return;
}
// if this is a currently encoding item, we need to be sure to alert the user,
// to let them decide to cancel it first, then if they do, we can come back and
// remove it
@ -442,8 +418,6 @@
{
[self doEditQueueItem:item];
}
[self.queue.items commit];
}
- (void)resetQueueItemsAtIndexes:(NSIndexSet *)indexes

View File

@ -5,7 +5,6 @@
It may be used under the terms of the GNU General Public License. */
#import <Foundation/Foundation.h>
#import "HBDistributedArray.h"
@import HandBrakeKit;
@ -22,7 +21,7 @@ typedef NS_ENUM(NSUInteger, HBQueueItemState) {
HBQueueItemStateFailed
};
@interface HBQueueItem : NSObject<NSSecureCoding, HBUniqueObject>
@interface HBQueueItem : NSObject<NSSecureCoding>
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithJob:(HBJob *)job;

View File

@ -60,15 +60,12 @@ static NSDictionary *shortHeightAttr;
@synthesize job = _job;
@synthesize attributedDescription = _attributedDescription;
@synthesize uuid = _uuid;
- (instancetype)initWithJob:(HBJob *)job
{
self = [super init];
if (self)
{
_job = job;
_uuid = [NSUUID UUID].UUIDString;
}
return self;
}
@ -232,7 +229,6 @@ static NSString *versionKey = @"HBQueueItemVersion";
[coder encodeInt:1 forKey:versionKey];
encodeInteger(_state);
encodeObject(_job);
encodeObject(_uuid);
encodeObject(_activityLogURL);
@ -253,7 +249,6 @@ static NSString *versionKey = @"HBQueueItemVersion";
{
decodeInteger(_state); if (_state < HBQueueItemStateReady || _state > HBQueueItemStateFailed) { goto fail; }
decodeObjectOrFail(_job, HBJob);
decodeObjectOrFail(_uuid, NSString);
decodeObject(_activityLogURL, NSURL);

View File

@ -7,7 +7,6 @@
#import <Cocoa/Cocoa.h>
#import "HBQueue.h"
#import "HBDistributedArray.h"
#import "HBQueueItem.h"
NS_ASSUME_NONNULL_BEGIN

View File

@ -4,10 +4,6 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>fr.handbrake.HandBrake</string>
</array>
<key>com.apple.security.assets.movies.read-write</key>
<true/>
<key>com.apple.security.automation.apple-events</key>

View File

@ -206,7 +206,6 @@
A958EAC222E24D6400D83AF4 /* HBQueueTableViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = A958EAC422E24D6400D83AF4 /* HBQueueTableViewController.xib */; };
A958EAC522E24D6800D83AF4 /* HBQueueInfoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = A958EAC722E24D6800D83AF4 /* HBQueueInfoViewController.xib */; };
A95BA15D220C968500A2F9F9 /* HBQueueItem.m in Sources */ = {isa = PBXBuildFile; fileRef = A95BA15C220C968500A2F9F9 /* HBQueueItem.m */; };
A95BA161220CA5DB00A2F9F9 /* HBDistributedArray.m in Sources */ = {isa = PBXBuildFile; fileRef = A95BA160220CA5DB00A2F9F9 /* HBDistributedArray.m */; };
A95BC1E71CD2548A008D6A33 /* volHighTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = A95BC1E51CD2548A008D6A33 /* volHighTemplate.pdf */; };
A95BC1E81CD2548A008D6A33 /* volLowTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = A95BC1E61CD2548A008D6A33 /* volLowTemplate.pdf */; };
A96127DF22E0994E0086E6DC /* HBQueueInfoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A96127DD22E0994E0086E6DC /* HBQueueInfoViewController.m */; };
@ -587,8 +586,6 @@
A9597A291A49749D00007771 /* HBRange+UIAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "HBRange+UIAdditions.m"; sourceTree = "<group>"; };
A95BA15B220C968500A2F9F9 /* HBQueueItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HBQueueItem.h; sourceTree = "<group>"; };
A95BA15C220C968500A2F9F9 /* HBQueueItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HBQueueItem.m; sourceTree = "<group>"; };
A95BA15F220CA5DB00A2F9F9 /* HBDistributedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBDistributedArray.h; sourceTree = "<group>"; };
A95BA160220CA5DB00A2F9F9 /* HBDistributedArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBDistributedArray.m; sourceTree = "<group>"; };
A95BC1E51CD2548A008D6A33 /* volHighTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = volHighTemplate.pdf; sourceTree = "<group>"; };
A95BC1E61CD2548A008D6A33 /* volLowTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = volLowTemplate.pdf; sourceTree = "<group>"; };
A95CB2FB217B6D07001E9F51 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@ -1285,8 +1282,6 @@
A964D3A722FDE91B00DFCAEA /* HBRemoteCore.m */,
A9C3A4FF23C7A66100269CA3 /* HBFilePromiseProvider.h */,
A9C3A50023C7A66100269CA3 /* HBFilePromiseProvider.m */,
A95BA15F220CA5DB00A2F9F9 /* HBDistributedArray.h */,
A95BA160220CA5DB00A2F9F9 /* HBDistributedArray.m */,
A9706CB51AC1437800BAEAA8 /* HBExceptionAlertController.h */,
A9706CB61AC1437800BAEAA8 /* HBExceptionAlertController.m */,
A9E52CD6218DD52A00E17B86 /* ExceptionAlert.xib */,
@ -1956,7 +1951,6 @@
files = (
A9C3A50123C7A66100269CA3 /* HBFilePromiseProvider.m in Sources */,
A954010322FF397000F83A5F /* HBRedirect.m in Sources */,
A95BA161220CA5DB00A2F9F9 /* HBDistributedArray.m in Sources */,
A916C99B1C844A0800C7B560 /* HBTableView.m in Sources */,
A916C9991C8449E200C7B560 /* main.m in Sources */,
A973E10C216E74E900D498EC /* HBThumbnailItemView.m in Sources */,