MacGui: remove distributed queue.
This commit is contained in:
parent
b0a2c68ee6
commit
c4202b8c37
@ -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];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -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;
|
||||
|
||||
|
164
macosx/HBQueue.m
164
macosx/HBQueue.m
@ -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];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "HBQueue.h"
|
||||
#import "HBDistributedArray.h"
|
||||
#import "HBQueueItem.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
@ -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>
|
||||
|
@ -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 */,
|
||||
|
Loading…
x
Reference in New Issue
Block a user