2007-09-05 20:01:14 +00:00
/ * HBQueueController
This file is part of the HandBrake source code .
2008-04-15 17:08:31 +00:00
Homepage : < http : // handbrake . fr / > .
2007-09-05 20:01:14 +00:00
It may be used under the terms of the GNU General Public License . * /
2008-08-07 17:26:25 +00:00
# import "HBQueueController.h"
2015-01-19 08:48:18 +00:00
2015-01-22 10:34:46 +00:00
# import "HBController.h"
2015-01-22 10:30:26 +00:00
# import "HBAppDelegate.h"
2014-11-23 12:56:03 +00:00
# import "HBQueueOutlineView.h"
2007-09-11 15:03:01 +00:00
2015-07-22 07:46:07 +00:00
# import "NSArray+HBAdditions.h"
2014-12-27 10:46:04 +00:00
2015-01-19 08:48:18 +00:00
# import "HBDockTile.h"
2014-08-18 06:22:02 +00:00
2015-02-20 07:59:38 +00:00
# import "HBOutputRedirect.h"
# import "HBJobOutputFileWriter.h"
2015-07-22 07:46:07 +00:00
# import "HBPreferencesController.h"
2015-02-20 07:59:38 +00:00
2016-02-26 09:50:16 +01:00
@ import HandBrakeKit ;
2007-09-24 15:22:24 +00:00
// Pasteboard type for or drag operations
2015-01-19 08:48:18 +00:00
# define DragDropSimplePboardType @ "HBQueueCustomOutlineViewPboardType"
2007-09-24 15:22:24 +00:00
2015-01-19 08:48:18 +00:00
// DockTile update freqency in total percent increment
# define dockTileUpdateFrequency 0.1 f
2007-09-24 15:22:24 +00:00
2015-07-22 07:46:07 +00:00
@ interface HBQueueController ( ) < NSOutlineViewDataSource , HBQueueOutlineViewDelegate >
2014-08-18 06:22:02 +00:00
2015-01-19 08:48:18 +00:00
@ property ( nonatomic , readonly ) HBDockTile * dockTile ;
@ property ( nonatomic , readwrite ) double dockIconProgress ;
2014-08-18 06:22:02 +00:00
2015-03-17 13:56:21 +00:00
@ property ( unsafe_unretained ) IBOutlet NSTextField * progressTextField ;
@ property ( unsafe_unretained ) IBOutlet NSTextField * countTextField ;
@ property ( unsafe_unretained ) IBOutlet HBQueueOutlineView * outlineView ;
2014-08-18 06:22:02 +00:00
2015-01-19 08:48:18 +00:00
@ property ( nonatomic , readonly ) NSMutableDictionary * descriptions ;
2014-08-18 06:22:02 +00:00
2015-10-28 08:15:52 +01:00
@ property ( nonatomic , readonly ) HBDistributedArray < HBJob * > * jobs ;
2015-10-19 17:57:49 +02:00
@ property ( nonatomic ) HBJob * currentJob ;
@ property ( nonatomic ) HBJobOutputFileWriter * currentLog ;
2014-08-18 06:22:02 +00:00
2015-01-20 08:37:00 +00:00
@ property ( nonatomic , readwrite ) BOOL stop ;
2015-01-19 08:48:18 +00:00
@ property ( nonatomic , readwrite ) NSUInteger pendingItemsCount ;
2015-07-22 07:46:07 +00:00
@ property ( nonatomic , readwrite ) NSUInteger completedItemsCount ;
2014-12-27 10:46:04 +00:00
2015-10-28 08:15:52 +01:00
@ property ( nonatomic ) NSArray < HBJob * > * dragNodesArray ;
2014-11-23 12:56:03 +00:00
2014-08-18 06:22:02 +00:00
@ end
2008-09-16 20:57:13 +00:00
@ implementation HBQueueController
2007-09-05 20:01:14 +00:00
2015-10-19 17:57:49 +02:00
- ( instancetype ) initWithURL : ( NSURL * ) queueURL ;
2007-09-05 20:01:14 +00:00
{
2015-10-19 17:57:49 +02:00
NSParameterAssert ( queueURL ) ;
2008-09-16 20:57:13 +00:00
if ( self = [ super initWithWindowNibName : @ "Queue" ] )
2008-04-07 20:11:46 +00:00
{
2015-10-19 17:57:49 +02:00
// Cached queue items descriptions
2015-01-19 08:48:18 +00:00
_descriptions = [ [ NSMutableDictionary alloc ] init ] ;
2008-08-07 17:26:25 +00:00
2015-01-19 08:48:18 +00:00
// Load the dockTile and instiante initial text fields
_dockTile = [ [ HBDockTile alloc ] initWithDockTile : [ [ NSApplication sharedApplication ] dockTile ]
2015-05-21 17:00:05 +00:00
image : [ [ NSApplication sharedApplication ] applicationIconImage ] ] ;
2015-01-19 08:48:18 +00:00
int loggingLevel = [ [ [ NSUserDefaults standardUserDefaults ] objectForKey : @ "LoggingLevel" ] intValue ] ;
// Init a separate instance of libhb for the queue
2015-04-09 19:43:33 +00:00
_core = [ [ HBCore alloc ] initWithLogLevel : loggingLevel name : @ "QueueCore" ] ;
2015-01-19 08:48:18 +00:00
2015-10-19 17:57:49 +02:00
// Load the queue from disk .
_jobs = [ [ HBDistributedArray alloc ] initWithURL : queueURL ] ;
[ [ NSNotificationCenter defaultCenter ] addObserver : self selector : @ selector ( reloadQueue ) name : HBDistributedArrayChanged object : _jobs ] ;
2013-10-15 11:36:51 +00:00
}
return self ;
2007-10-09 15:15:16 +00:00
}
2007-09-05 20:01:14 +00:00
2015-01-19 08:48:18 +00:00
- ( void ) dealloc
{
[ [ NSNotificationCenter defaultCenter ] removeObserver : self ] ;
}
- ( void ) windowDidLoad
{
// lets setup our queue list outline view for drag and drop here
[ self . outlineView registerForDraggedTypes : @ [ DragDropSimplePboardType ] ] ;
[ self . outlineView setDraggingSourceOperationMask : NSDragOperationEvery forLocal : YES ] ;
[ self . outlineView setVerticalMotionCanBeginDrag : YES ] ;
2015-10-19 17:57:49 +02:00
[ self updateQueueStats ] ;
2015-01-19 08:48:18 +00:00
}
# pragma mark Toolbar
2015-01-22 10:30:26 +00:00
- ( BOOL ) validateMenuItem : ( NSMenuItem * ) menuItem
{
SEL action = menuItem . action ;
if ( action = = @ selector ( rip : ) )
{
if ( self . core . state = = HBStateIdle )
{
menuItem . title = NSLocalizedString ( @ "Start Encoding" , nil ) ;
return ( self . pendingItemsCount > 0 ) ;
}
else if ( self . core . state ! = HBStateIdle )
{
menuItem . title = NSLocalizedString ( @ "Stop Encoding" , nil ) ;
2015-07-22 07:46:07 +00:00
return YES ;
2015-01-22 10:30:26 +00:00
}
}
if ( action = = @ selector ( pause : ) )
{
if ( self . core . state ! = HBStatePaused )
{
menuItem . title = NSLocalizedString ( @ "Pause Encoding" , nil ) ;
}
else
{
menuItem . title = NSLocalizedString ( @ "Resume Encoding" , nil ) ;
}
return ( self . core . state = = HBStateWorking || self . core . state = = HBStatePaused ) ;
}
2015-02-02 11:12:54 +00:00
if ( action = = @ selector ( editSelectedQueueItem : ) ||
action = = @ selector ( removeSelectedQueueItem : ) ||
2015-07-22 07:46:07 +00:00
action = = @ selector ( revealSelectedQueueItems : ) )
2015-02-02 11:12:54 +00:00
{
return ( self . outlineView . selectedRow ! = -1 || self . outlineView . clickedRow ! = -1 ) ;
}
2015-07-22 07:46:07 +00:00
if ( action = = @ selector ( resetJobState : ) )
{
return self . outlineView . targetedRowIndexes . count > 0 ;
}
if ( action = = @ selector ( clearAll : ) )
{
return self . jobs . count > 0 ;
}
if ( action = = @ selector ( clearCompleted : ) )
{
return self . completedItemsCount > 0 ;
}
2015-01-22 10:30:26 +00:00
return YES ;
}
2015-01-19 08:48:18 +00:00
- ( BOOL ) validateToolbarItem : ( NSToolbarItem * ) theItem
2007-10-09 15:15:16 +00:00
{
2015-01-19 08:48:18 +00:00
SEL action = theItem . action ;
HBState s = self . core . state ;
2014-08-18 06:22:02 +00:00
2015-01-19 08:48:18 +00:00
if ( action = = @ selector ( toggleStartCancel : ) )
{
2015-01-27 11:31:50 +00:00
if ( ( s = = HBStateScanning ) || ( s = = HBStatePaused ) || ( s = = HBStateWorking ) || ( s = = HBStateMuxing ) )
2015-01-19 08:48:18 +00:00
{
theItem . image = [ NSImage imageNamed : @ "stopencode" ] ;
theItem . label = NSLocalizedString ( @ "Stop" , @ "" ) ;
theItem . toolTip = NSLocalizedString ( @ "Stop Encoding" , @ "" ) ;
2015-07-22 07:46:07 +00:00
return YES ;
2015-01-19 08:48:18 +00:00
}
else
{
theItem . image = [ NSImage imageNamed : @ "encode" ] ;
theItem . label = NSLocalizedString ( @ "Start" , @ "" ) ;
theItem . toolTip = NSLocalizedString ( @ "Start Encoding" , @ "" ) ;
return ( self . pendingItemsCount > 0 ) ;
}
}
if ( action = = @ selector ( togglePauseResume : ) )
{
if ( s = = HBStatePaused )
{
theItem . image = [ NSImage imageNamed : @ "encode" ] ;
theItem . label = NSLocalizedString ( @ "Resume" , @ "" ) ;
theItem . toolTip = NSLocalizedString ( @ "Resume Encoding" , @ "" ) ;
return YES ;
}
else
{
theItem . image = [ NSImage imageNamed : @ "pauseencode" ] ;
theItem . label = NSLocalizedString ( @ "Pause" , @ "" ) ;
theItem . toolTip = NSLocalizedString ( @ "Pause Encoding" , @ "" ) ;
return ( s = = HBStateWorking || s = = HBStateMuxing ) ;
}
}
return NO ;
}
2015-10-19 17:57:49 +02:00
# pragma mark - Public methods
2015-01-19 08:48:18 +00:00
2015-10-19 17:57:49 +02:00
- ( void ) addJob : ( HBJob * ) item
2015-01-19 08:48:18 +00:00
{
2015-10-19 17:57:49 +02:00
NSParameterAssert ( item ) ;
[ self addJobsFromArray : @ [ item ] ] ;
2015-01-19 08:48:18 +00:00
}
2015-10-28 08:15:52 +01:00
- ( void ) addJobsFromArray : ( NSArray < HBJob * > * ) items ;
2015-01-19 08:48:18 +00:00
{
2015-10-19 17:57:49 +02:00
NSParameterAssert ( items ) ;
2015-10-28 08:15:52 +01:00
if ( items . count )
{
[ self addQueueItems : items ] ;
}
2015-10-19 17:57:49 +02:00
}
2015-01-19 08:48:18 +00:00
2015-10-19 17:57:49 +02:00
- ( BOOL ) jobExistAtURL : ( NSURL * ) url
{
NSParameterAssert ( url ) ;
2015-01-19 08:48:18 +00:00
2015-10-19 17:57:49 +02:00
for ( HBJob * item in self . jobs )
{
if ( [ item . destURL isEqualTo : url ] )
{
return YES ;
}
}
return NO ;
2015-01-19 08:48:18 +00:00
}
2014-08-18 06:22:02 +00:00
2015-10-19 17:57:49 +02:00
- ( NSUInteger ) count
{
return self . jobs . count ;
}
/ * *
* This method will clear the queue of any encodes that are not still pending
* this includes both successfully completed encodes as well as cancelled encodes
* /
- ( void ) removeCompletedJobs
2015-01-19 08:48:18 +00:00
{
[ self . jobs beginTransaction ] ;
2015-10-19 17:57:49 +02:00
NSIndexSet * indexes = [ self . jobs indexesOfObjectsUsingBlock : ^ BOOL ( HBJob * item ) {
return ( item . state = = HBJobStateCompleted || item . state = = HBJobStateCanceled ) ;
} ] ;
[ self removeQueueItemsAtIndexes : indexes ] ;
2015-01-19 08:48:18 +00:00
[ self . jobs commit ] ;
2015-10-19 17:57:49 +02:00
}
2015-01-19 08:48:18 +00:00
2015-10-19 17:57:49 +02:00
/ * *
* This method will clear the queue of all encodes . effectively creating an empty queue
* /
- ( void ) removeAllJobs
{
[ self . jobs beginTransaction ] ;
[ self removeQueueItemsAtIndexes : [ NSIndexSet indexSetWithIndexesInRange : NSMakeRange ( 0 , self . jobs . count ) ] ] ;
[ self . jobs commit ] ;
2015-01-19 08:48:18 +00:00
}
2015-10-19 17:57:49 +02:00
/ * *
* This method will set any item marked as encoding back to pending
* currently used right after a queue reload
* /
- ( void ) setEncodingJobsAsPending
2015-01-19 08:48:18 +00:00
{
[ self . jobs beginTransaction ] ;
2015-10-19 17:57:49 +02:00
NSMutableIndexSet * indexes = [ NSMutableIndexSet indexSet ] ;
NSUInteger idx = 0 ;
for ( HBJob * job in self . jobs )
{
// We want to keep any queue item that is pending or was previously being encoded
if ( job . state = = HBJobStateWorking )
{
job . state = HBJobStateReady ;
[ indexes addIndex : idx ] ;
}
idx + + ;
}
[ self reloadQueueItemsAtIndexes : indexes ] ;
2015-01-19 08:48:18 +00:00
[ self . jobs commit ] ;
2015-10-19 17:57:49 +02:00
}
# pragma mark - Private queue editing methods
/ * *
* Reloads the queue , this is called
* when another HandBrake instances modifies the queue
* /
- ( void ) reloadQueue
{
[ self updateQueueStats ] ;
[ self . outlineView reloadData ] ;
[ self . window . undoManager removeAllActions ] ;
}
- ( void ) reloadQueueItemAtIndex : ( NSUInteger ) idx
{
[ self reloadQueueItemsAtIndexes : [ NSIndexSet indexSetWithIndex : idx ] ] ;
}
2015-01-19 08:48:18 +00:00
2015-10-19 17:57:49 +02:00
- ( void ) reloadQueueItemsAtIndexes : ( NSIndexSet * ) indexes
{
[ self . outlineView reloadDataForRowIndexes : indexes columnIndexes : [ NSIndexSet indexSetWithIndex : 0 ] ] ;
[ self updateQueueStats ] ;
2015-01-19 08:48:18 +00:00
}
2015-10-19 17:57:49 +02:00
- ( void ) addQueueItems : ( NSArray * ) items
2015-01-19 08:48:18 +00:00
{
2015-10-19 17:57:49 +02:00
NSParameterAssert ( items ) ;
NSIndexSet * indexes = [ NSIndexSet indexSetWithIndexesInRange : NSMakeRange ( self . jobs . count , items . count ) ] ;
[ self addQueueItems : items atIndexes : indexes ] ;
}
- ( void ) addQueueItems : ( NSArray * ) items atIndexes : ( NSIndexSet * ) indexes
{
NSParameterAssert ( items ) ;
NSParameterAssert ( indexes ) ;
[ self . jobs beginTransaction ] ;
[ self . outlineView beginUpdates ] ;
// Forward
NSUInteger currentIndex = indexes . firstIndex ;
NSUInteger currentObjectIndex = 0 ;
while ( currentIndex ! = NSNotFound )
2015-01-19 08:48:18 +00:00
{
2015-10-19 17:57:49 +02:00
[ self . jobs insertObject : items [ currentObjectIndex ] atIndex : currentIndex ] ;
currentIndex = [ indexes indexGreaterThanIndex : currentIndex ] ;
currentObjectIndex + + ;
}
[ self . outlineView insertItemsAtIndexes : indexes
inParent : nil
withAnimation : NSTableViewAnimationSlideDown ] ;
NSUndoManager * undo = self . window . undoManager ;
[ [ undo prepareWithInvocationTarget : self ] removeQueueItemsAtIndexes : indexes ] ;
if ( ! undo . isUndoing )
{
if ( items . count = = 1 )
2015-01-19 08:48:18 +00:00
{
2015-10-19 17:57:49 +02:00
[ undo setActionName : NSLocalizedString ( @ "Add Job To Queue" , nil ) ] ;
}
else
{
[ undo setActionName : NSLocalizedString ( @ "Add Jobs To Queue" , nil ) ] ;
2015-01-19 08:48:18 +00:00
}
}
2015-10-19 17:57:49 +02:00
[ self . outlineView endUpdates ] ;
[ self updateQueueStats ] ;
[ self . jobs commit ] ;
2015-01-19 08:48:18 +00:00
}
- ( void ) removeQueueItemAtIndex : ( NSUInteger ) index
{
2015-07-22 07:46:07 +00:00
[ self removeQueueItemsAtIndexes : [ NSIndexSet indexSetWithIndex : index ] ] ;
}
- ( void ) removeQueueItemsAtIndexes : ( NSIndexSet * ) indexes
{
2015-10-19 17:57:49 +02:00
NSParameterAssert ( indexes ) ;
if ( indexes . count = = 0 )
{
return ;
}
[ self . jobs beginTransaction ] ;
[ self . outlineView beginUpdates ] ;
NSArray * removeJobs = [ self . jobs objectsAtIndexes : indexes ] ;
if ( self . jobs . count > indexes . lastIndex )
2015-01-19 08:48:18 +00:00
{
2015-07-22 07:46:07 +00:00
[ self . jobs removeObjectsAtIndexes : indexes ] ;
2015-01-19 08:48:18 +00:00
}
2015-10-19 17:57:49 +02:00
[ self . outlineView removeItemsAtIndexes : indexes inParent : nil withAnimation : NSTableViewAnimationSlideUp ] ;
[ self . outlineView selectRowIndexes : [ NSIndexSet indexSetWithIndex : indexes . firstIndex ] byExtendingSelection : NO ] ;
NSUndoManager * undo = self . window . undoManager ;
[ [ undo prepareWithInvocationTarget : self ] addQueueItems : removeJobs atIndexes : indexes ] ;
if ( ! undo . isUndoing )
{
if ( indexes . count = = 1 )
{
[ undo setActionName : NSLocalizedString ( @ "Remove Job From Queue" , nil ) ] ;
}
else
{
[ undo setActionName : NSLocalizedString ( @ "Remove Jobs From Queue" , nil ) ] ;
}
}
[ self . outlineView endUpdates ] ;
[ self updateQueueStats ] ;
[ self . jobs commit ] ;
}
- ( void ) moveQueueItems : ( NSArray * ) items toIndex : ( NSUInteger ) index
{
[ self . jobs beginTransaction ] ;
[ self . outlineView beginUpdates ] ;
NSMutableArray * source = [ NSMutableArray array ] ;
NSMutableArray * dest = [ NSMutableArray array ] ;
for ( id object in items . reverseObjectEnumerator )
{
NSUInteger sourceIndex = [ self . jobs indexOfObject : object ] ;
[ self . jobs removeObjectAtIndex : sourceIndex ] ;
if ( sourceIndex < index )
{
index - - ;
}
[ self . jobs insertObject : object atIndex : index ] ;
[ source addObject : @ ( index ) ] ;
[ dest addObject : @ ( sourceIndex ) ] ;
[ self . outlineView moveItemAtIndex : sourceIndex inParent : nil toIndex : index inParent : nil ] ;
}
NSUndoManager * undo = self . window . undoManager ;
[ [ undo prepareWithInvocationTarget : self ] moveQueueItemsAtIndexes : source toIndexes : dest ] ;
if ( ! undo . isUndoing )
{
if ( items . count = = 1 )
{
[ undo setActionName : NSLocalizedString ( @ "Move Job in Queue" , nil ) ] ;
}
else
{
[ undo setActionName : NSLocalizedString ( @ "Move Jobs in Queue" , nil ) ] ;
}
}
[ self . outlineView endUpdates ] ;
[ self . jobs commit ] ;
}
- ( void ) moveQueueItemsAtIndexes : ( NSArray * ) source toIndexes : ( NSArray * ) dest
{
[ self . jobs beginTransaction ] ;
[ self . outlineView beginUpdates ] ;
NSMutableArray * newSource = [ NSMutableArray array ] ;
NSMutableArray * newDest = [ NSMutableArray array ] ;
for ( NSInteger idx = source . count - 1 ; idx >= 0 ; idx - - )
{
NSUInteger sourceIndex = [ source [ idx ] integerValue ] ;
NSUInteger destIndex = [ dest [ idx ] integerValue ] ;
[ newSource addObject : @ ( destIndex ) ] ;
[ newDest addObject : @ ( sourceIndex ) ] ;
id obj = [ self . jobs objectAtIndex : sourceIndex ] ;
[ self . jobs removeObjectAtIndex : sourceIndex ] ;
[ self . jobs insertObject : obj atIndex : destIndex ] ;
[ self . outlineView moveItemAtIndex : sourceIndex inParent : nil toIndex : destIndex inParent : nil ] ;
}
NSUndoManager * undo = self . window . undoManager ;
[ [ undo prepareWithInvocationTarget : self ] moveQueueItemsAtIndexes : newSource toIndexes : newDest ] ;
if ( ! undo . isUndoing )
{
if ( source . count = = 1 )
{
[ undo setActionName : NSLocalizedString ( @ "Move Job in Queue" , nil ) ] ;
}
else
{
[ undo setActionName : NSLocalizedString ( @ "Move Jobs in Queue" , nil ) ] ;
}
}
[ self . outlineView endUpdates ] ;
[ self . jobs commit ] ;
2015-01-19 08:48:18 +00:00
}
/ * *
* Updates the queue status label .
* /
2015-10-19 17:57:49 +02:00
- ( void ) updateQueueStats
2015-01-19 08:48:18 +00:00
{
2014-12-27 10:46:04 +00:00
// lets get the stats on the status of the queue array
2015-01-19 08:48:18 +00:00
NSUInteger pendingCount = 0 ;
2015-07-22 07:46:07 +00:00
NSUInteger completedCount = 0 ;
2015-01-19 08:48:18 +00:00
for ( HBJob * job in self . jobs )
{
2015-07-22 07:46:07 +00:00
if ( job . state = = HBJobStateReady )
2015-01-19 08:48:18 +00:00
{
2015-07-22 07:46:07 +00:00
pendingCount + + ;
2015-01-19 08:48:18 +00:00
}
2015-07-22 07:46:07 +00:00
if ( job . state = = HBJobStateCompleted )
2007-09-11 15:03:01 +00:00
{
2015-07-22 07:46:07 +00:00
completedCount + + ;
2015-01-19 08:48:18 +00:00
}
}
2014-12-27 10:46:04 +00:00
2015-01-19 08:48:18 +00:00
NSString * string ;
if ( pendingCount = = 0 )
2011-03-31 13:41:01 +00:00
{
2015-01-19 08:48:18 +00:00
string = NSLocalizedString ( @ "No encode pending" , @ "" ) ;
2011-03-31 13:41:01 +00:00
}
2015-01-19 08:48:18 +00:00
else if ( pendingCount = = 1 )
2007-10-09 15:15:16 +00:00
{
2015-01-19 08:48:18 +00:00
string = [ NSString stringWithFormat : NSLocalizedString ( @ "%d encode pending" , @ "" ) , pendingCount ] ;
2008-08-07 17:26:25 +00:00
}
2008-09-16 20:57:13 +00:00
else
{
2015-01-19 08:48:18 +00:00
string = [ NSString stringWithFormat : NSLocalizedString ( @ "%d encodes pending" , @ "" ) , pendingCount ] ;
2008-09-16 20:57:13 +00:00
}
2015-01-19 08:48:18 +00:00
self . countTextField . stringValue = string ;
[ self . controller setQueueState : string ] ;
self . pendingItemsCount = pendingCount ;
2015-07-22 07:46:07 +00:00
self . completedItemsCount = completedCount ;
2015-01-19 08:48:18 +00:00
}
2015-10-19 17:57:49 +02:00
# pragma mark -
# pragma mark Queue Job Processing
2010-07-17 19:15:38 +00:00
2015-01-19 08:48:18 +00:00
/ * *
* Used to get the next pending queue item and return it if found
2008-09-22 14:44:13 +00:00
* /
2015-01-19 08:48:18 +00:00
- ( HBJob * ) getNextPendingQueueItem
2008-09-22 14:44:13 +00:00
{
2015-01-19 08:48:18 +00:00
for ( HBJob * job in self . jobs )
{
if ( job . state = = HBJobStateReady )
{
return job ;
}
}
return nil ;
2008-09-22 14:44:13 +00:00
}
2007-09-05 20:01:14 +00:00
2015-01-19 08:48:18 +00:00
/ * *
* Starts the queue
* /
- ( void ) encodeNextQueueItem
2007-10-09 15:15:16 +00:00
{
2015-10-19 17:57:49 +02:00
[ self . jobs beginTransaction ] ;
self . currentJob = nil ;
2015-01-19 08:48:18 +00:00
2015-10-19 17:57:49 +02:00
// since we have completed an encode , we go to the next
if ( self . stop )
2015-01-19 08:48:18 +00:00
{
2015-10-19 17:57:49 +02:00
self . stop = NO ;
2015-01-19 08:48:18 +00:00
}
else
{
2015-10-19 17:57:49 +02:00
// Check to see if there are any more pending items in the queue
HBJob * nextJob = [ self getNextPendingQueueItem ] ;
// If we still have more pending items in our queue , lets go to the next one
if ( nextJob )
{
// now we mark the queue item as working so another instance can not come along and try to scan it while we are scanning
nextJob . state = HBJobStateWorking ;
// Tell HB to output a new activity log file for this encode
self . currentLog = [ [ HBJobOutputFileWriter alloc ] initWithJob : nextJob ] ;
2016-01-16 15:06:39 +01:00
if ( self . currentLog )
{
[ [ HBOutputRedirect stderrRedirect ] addListener : self . currentLog ] ;
[ [ HBOutputRedirect stdoutRedirect ] addListener : self . currentLog ] ;
}
2015-01-19 08:48:18 +00:00
2015-10-19 17:57:49 +02:00
self . currentJob = nextJob ;
[ self reloadQueueItemAtIndex : [ self . jobs indexOfObject : nextJob ] ] ;
2015-01-19 08:48:18 +00:00
2015-10-19 17:57:49 +02:00
// now we can go ahead and scan the new pending queue item
[ self encodeJob : nextJob ] ;
// erase undo manager history
[ self . window . undoManager removeAllActions ] ;
}
else
{
[ HBUtilities writeToActivityLog : "Queue Done, there are no more pending encodes" ] ;
// Since there are no more items to encode , go to queueCompletedAlerts
// for user specified alerts after queue completed
[ self queueCompletedAlerts ] ;
}
2015-01-19 08:48:18 +00:00
}
2015-10-19 17:57:49 +02:00
[ self . jobs commit ] ;
2010-07-19 17:02:43 +00:00
}
2015-10-19 17:57:49 +02:00
- ( void ) completedJob : ( HBJob * ) job result : ( HBCoreResult ) result ;
2010-07-19 17:02:43 +00:00
{
2015-10-19 17:57:49 +02:00
NSParameterAssert ( job ) ;
[ self . jobs beginTransaction ] ;
2015-01-19 08:48:18 +00:00
// Since we are done with this encode , tell output to stop writing to the
// individual encode log .
2015-02-20 07:59:38 +00:00
[ [ HBOutputRedirect stderrRedirect ] removeListener : self . currentLog ] ;
[ [ HBOutputRedirect stdoutRedirect ] removeListener : self . currentLog ] ;
2015-10-19 17:57:49 +02:00
2015-02-20 07:59:38 +00:00
self . currentLog = nil ;
2015-01-19 08:48:18 +00:00
// Check to see if the encode state has not been cancelled
// to determine if we should check for encode done notifications .
2015-10-19 17:57:49 +02:00
if ( result ! = HBCoreResultCancelled )
2015-01-19 08:48:18 +00:00
{
2015-10-19 17:57:49 +02:00
[ self jobCompletedAlerts : job ] ;
2015-01-19 08:48:18 +00:00
// Send to tagger
2015-10-19 17:57:49 +02:00
[ self sendToExternalApp : job . destURL ] ;
2015-01-19 08:48:18 +00:00
}
2015-10-19 17:57:49 +02:00
// Mark the encode just finished
switch ( result ) {
case HBCoreResultDone :
job . state = HBJobStateCompleted ;
break ;
case HBCoreResultCancelled :
job . state = HBJobStateCanceled ;
break ;
default :
job . state = HBJobStateFailed ;
break ;
}
2015-01-19 08:48:18 +00:00
2015-10-19 17:57:49 +02:00
if ( [ self . jobs containsObject : job ] )
2015-01-20 08:37:00 +00:00
{
2015-10-19 17:57:49 +02:00
[ self reloadQueueItemAtIndex : [ self . jobs indexOfObject : job ] ] ;
2015-01-20 08:37:00 +00:00
}
2015-01-19 08:48:18 +00:00
[ self . window . toolbar validateVisibleItems ] ;
2015-10-19 17:57:49 +02:00
[ self . jobs commit ] ;
2007-10-09 15:15:16 +00:00
}
2015-01-19 08:48:18 +00:00
/ * *
* Here we actually tell hb_scan to perform the source scan , using the path to source and title number
* /
2015-10-19 17:57:49 +02:00
- ( void ) encodeJob : ( HBJob * ) job
2015-01-19 08:48:18 +00:00
{
2015-10-19 17:57:49 +02:00
NSParameterAssert ( job ) ;
2015-04-30 16:04:37 +00:00
2015-10-19 17:57:49 +02:00
// Progress handler
2016-02-26 09:50:16 +01:00
void ( ^ progressHandler ) ( HBState state , HBProgress progress , NSString * info ) = ^ ( HBState state , HBProgress progress , NSString * info )
2015-10-19 17:57:49 +02:00
{
2016-02-26 09:50:16 +01:00
NSString * status = info ;
2015-10-19 17:57:49 +02:00
self . progressTextField . stringValue = status ;
[ self . controller setQueueInfo : status progress : 0 hidden : NO ] ;
} ;
// Completion handler
void ( ^ completionHandler ) ( HBCoreResult result ) = ^ ( HBCoreResult result )
{
if ( result = = HBCoreResultDone )
{
[ self realEncodeJob : job ] ;
}
else
{
[ self completedJob : job result : result ] ;
[ self encodeNextQueueItem ] ;
}
} ;
2015-01-19 08:48:18 +00:00
// Only scan 10 previews before an encode - additional previews are
// only useful for autocrop and static previews , which are already taken care of at this point
2015-10-19 17:57:49 +02:00
[ self . core scanURL : job . fileURL
titleIndex : job . titleIdx
2015-01-19 08:48:18 +00:00
previews : 10
minDuration : 0
2015-10-19 17:57:49 +02:00
progressHandler : progressHandler
completionHandler : completionHandler ] ;
2015-01-19 08:48:18 +00:00
}
/ * *
* This assumes that we have re - scanned and loaded up a new queue item to send to libhb
* /
2015-10-19 17:57:49 +02:00
- ( void ) realEncodeJob : ( HBJob * ) job
2007-10-09 15:15:16 +00:00
{
2015-10-19 17:57:49 +02:00
NSParameterAssert ( job ) ;
2015-01-19 08:48:18 +00:00
// Reset the title in the job .
2015-10-19 17:57:49 +02:00
job . title = self . core . titles [ 0 ] ;
2015-01-19 08:48:18 +00:00
2016-02-26 09:50:16 +01:00
HBStateFormatter * formatter = [ [ HBStateFormatter alloc ] init ] ;
formatter . title = job . destURL . lastPathComponent ;
self . core . stateFormatter = formatter ;
2015-10-19 17:57:49 +02:00
// Progress handler
2016-02-26 09:50:16 +01:00
void ( ^ progressHandler ) ( HBState state , HBProgress progress , NSString * info ) = ^ ( HBState state , HBProgress progress , NSString * info )
2015-10-19 17:57:49 +02:00
{
if ( state = = HBStateWorking )
{
// Update dock icon
2016-02-26 09:50:16 +01:00
if ( self . dockIconProgress < 100.0 * progress . percent )
2015-10-19 17:57:49 +02:00
{
2016-02-26 09:50:16 +01:00
[ self . dockTile updateDockIcon : progress . percent hours : progress . hours minutes : progress . minutes seconds : progress . seconds ] ;
2015-10-19 17:57:49 +02:00
self . dockIconProgress + = dockTileUpdateFrequency ;
}
}
else if ( state = = HBStateMuxing )
{
[ self . dockTile updateDockIcon : 1.0 withETA : @ "" ] ;
}
// Update text field
2016-02-26 09:50:16 +01:00
self . progressTextField . stringValue = info ;
[ self . controller setQueueInfo : info progress : progress . percent hidden : NO ] ;
2015-10-19 17:57:49 +02:00
} ;
// Completion handler
void ( ^ completionHandler ) ( HBCoreResult result ) = ^ ( HBCoreResult result )
{
NSString * info = NSLocalizedString ( @ "Encode Finished." , @ "" ) ;
self . progressTextField . stringValue = info ;
[ self . controller setQueueInfo : info progress : 1.0 hidden : YES ] ;
// Restore dock icon
[ self . dockTile updateDockIcon : -1.0 withETA : @ "" ] ;
self . dockIconProgress = 0 ;
[ self completedJob : job result : result ] ;
[ self encodeNextQueueItem ] ;
} ;
2015-04-30 16:04:37 +00:00
2015-01-19 08:48:18 +00:00
// We should be all setup so let ' er rip
2015-10-19 17:57:49 +02:00
[ self . core encodeJob : job progressHandler : progressHandler completionHandler : completionHandler ] ;
2015-01-19 08:48:18 +00:00
// We are done using the title , remove it from the job
2015-10-19 17:57:49 +02:00
job . title = nil ;
2007-10-09 15:15:16 +00:00
}
2015-01-19 08:48:18 +00:00
/ * *
2015-01-20 08:37:00 +00:00
* Cancels the current job
2015-01-19 08:48:18 +00:00
* /
- ( void ) doCancelCurrentJob
2015-01-20 08:37:00 +00:00
{
if ( self . core . state = = HBStateScanning )
{
[ self . core cancelScan ] ;
}
else
{
[ self . core cancelEncode ] ;
}
}
/ * *
* Cancels the current job and starts processing the next in queue .
* /
- ( void ) cancelCurrentJobAndContinue
2007-10-09 15:15:16 +00:00
{
2015-01-20 08:37:00 +00:00
[ self doCancelCurrentJob ] ;
2007-09-14 04:42:46 +00:00
}
2015-01-19 08:48:18 +00:00
/ * *
2015-01-20 08:37:00 +00:00
* Cancels the current job and stops libhb from processing the remaining encodes .
2015-01-19 08:48:18 +00:00
* /
2015-01-20 08:37:00 +00:00
- ( void ) cancelCurrentJobAndStop
2008-01-09 05:45:36 +00:00
{
2015-01-20 08:37:00 +00:00
self . stop = YES ;
[ self doCancelCurrentJob ] ;
2015-10-19 17:57:49 +02:00
}
2015-01-19 08:48:18 +00:00
2015-10-19 17:57:49 +02:00
/ * *
* Finishes the current job and stops libhb from processing the remaining encodes .
* /
- ( void ) finishCurrentAndStop
{
self . stop = YES ;
2008-01-09 05:45:36 +00:00
}
2015-01-19 08:48:18 +00:00
# pragma mark - Encode Done Actions
2007-09-07 13:40:40 +00:00
2015-01-19 08:48:18 +00:00
# define SERVICE_NAME @ "Encode Done"
2007-09-07 13:40:40 +00:00
2015-01-19 08:48:18 +00:00
/ * *
* Register a test notification and make
* it enabled by default
* /
- ( NSDictionary * ) registrationDictionaryForGrowl
{
return @ { GROWL_NOTIFICATIONS _ALL : @ [ SERVICE_NAME ] ,
GROWL_NOTIFICATIONS _DEFAULT : @ [ SERVICE_NAME ] } ;
}
2007-09-07 13:40:40 +00:00
2015-07-22 07:46:07 +00:00
- ( void ) showDoneNotification : ( NSURL * ) fileURL
2015-01-19 08:48:18 +00:00
{
// This end of encode action is called as each encode rolls off of the queue
// Setup the Growl stuff
NSString * growlMssg = [ NSString stringWithFormat : @ "your HandBrake encode %@ is done!" , fileURL . lastPathComponent ] ;
[ GrowlApplicationBridge notifyWithTitle : @ "Put down that cocktail…"
description : growlMssg
notificationName : SERVICE_NAME
iconData : nil
priority : 0
isSticky : 1
clickContext : nil ] ;
}
2007-09-07 13:40:40 +00:00
2015-10-19 17:57:49 +02:00
/ * *
* Sends the URL to the external app
* selected in the preferences .
*
* @ param fileURL the URL of the file to send
* /
2015-01-19 08:48:18 +00:00
- ( void ) sendToExternalApp : ( NSURL * ) fileURL
{
// This end of encode action is called as each encode rolls off of the queue
2015-10-19 19:05:07 +02:00
if ( [ [ NSUserDefaults standardUserDefaults ] boolForKey : @ "HBSendToAppEnabled" ] = = YES )
2007-09-07 13:40:40 +00:00
{
2015-07-04 07:02:19 +00:00
NSWorkspace * workspace = [ NSWorkspace sharedWorkspace ] ;
2015-10-19 19:05:07 +02:00
NSString * app = [ workspace fullPathForApplication : [ [ NSUserDefaults standardUserDefaults ] objectForKey : @ "HBSendToApp" ] ] ;
2015-07-04 07:02:19 +00:00
2015-10-19 19:05:07 +02:00
if ( app )
2015-07-04 07:02:19 +00:00
{
2015-10-19 19:05:07 +02:00
if ( ! [ workspace openFile : fileURL . path withApplication : app ] )
2015-07-04 07:02:19 +00:00
{
2015-10-19 19:05:07 +02:00
[ HBUtilities writeToActivityLog : "Failed to send file to: %s" , app ] ;
2015-07-04 07:02:19 +00:00
}
}
else
2007-09-07 13:40:40 +00:00
{
2015-07-04 07:02:19 +00:00
[ HBUtilities writeToActivityLog : "Send file to: app not found" ] ;
2007-09-07 13:40:40 +00:00
}
2015-01-19 08:48:18 +00:00
}
}
2015-10-19 17:57:49 +02:00
/ * *
* Runs the alert for a single job
* /
- ( void ) jobCompletedAlerts : ( HBJob * ) job
2015-07-22 07:46:07 +00:00
{
// Both the Notification and Sending to tagger can be done as encodes roll off the queue
if ( [ [ NSUserDefaults standardUserDefaults ] integerForKey : @ "HBAlertWhenDone" ] = = HBDoneActionNotification ||
[ [ NSUserDefaults standardUserDefaults ] integerForKey : @ "HBAlertWhenDone" ] = = HBDoneActionAlertAndNotification )
{
// If Play System Alert has been selected in Preferences
if ( [ [ NSUserDefaults standardUserDefaults ] boolForKey : @ "HBAlertWhenDoneSound" ] = = YES )
{
NSBeep ( ) ;
}
2015-10-19 17:57:49 +02:00
[ self showDoneNotification : job . destURL ] ;
2015-07-22 07:46:07 +00:00
}
}
2015-10-19 17:57:49 +02:00
/ * *
* Runs the global queue completed alerts
* /
2015-01-19 08:48:18 +00:00
- ( void ) queueCompletedAlerts
{
// If Play System Alert has been selected in Preferences
2015-07-22 07:46:07 +00:00
if ( [ [ NSUserDefaults standardUserDefaults ] boolForKey : @ "HBAlertWhenDoneSound" ] = = YES )
2015-01-19 08:48:18 +00:00
{
NSBeep ( ) ;
}
2015-07-22 07:46:07 +00:00
// If Alert Window or Window and Notification has been selected
if ( [ [ NSUserDefaults standardUserDefaults ] integerForKey : @ "HBAlertWhenDone" ] = = HBDoneActionAlert ||
[ [ NSUserDefaults standardUserDefaults ] integerForKey : @ "HBAlertWhenDone" ] = = HBDoneActionAlertAndNotification )
2015-01-19 08:48:18 +00:00
{
// On Screen Notification
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert setMessageText : NSLocalizedString ( @ "Put down that cocktail…" , @ "" ) ] ;
[ alert setInformativeText : NSLocalizedString ( @ "Your HandBrake queue is done!" , @ "" ) ] ;
[ NSApp requestUserAttention : NSCriticalRequest ] ;
[ alert runModal ] ;
}
// If sleep has been selected
2015-07-22 07:46:07 +00:00
if ( [ [ NSUserDefaults standardUserDefaults ] integerForKey : @ "HBAlertWhenDone" ] = = HBDoneActionSleep )
2015-01-19 08:48:18 +00:00
{
// Sleep
NSDictionary * errorDict ;
NSAppleScript * scriptObject = [ [ NSAppleScript alloc ] initWithSource :
@ "tell application \" Finder \ " to sleep" ] ;
[ scriptObject executeAndReturnError : & errorDict ] ;
}
// If Shutdown has been selected
2015-07-22 07:46:07 +00:00
if ( [ [ NSUserDefaults standardUserDefaults ] integerForKey : @ "HBAlertWhenDone" ] = = HBDoneActionShutDown )
2015-01-19 08:48:18 +00:00
{
// Shut Down
NSDictionary * errorDict ;
NSAppleScript * scriptObject = [ [ NSAppleScript alloc ] initWithSource : @ "tell application \" Finder \ " to shut down" ] ;
[ scriptObject executeAndReturnError : & errorDict ] ;
}
}
# pragma mark - Queue Item Controls
- ( void ) HB_deleteSelectionFromTableView : ( NSTableView * ) tableView
{
[ self removeSelectedQueueItem : tableView ] ;
}
/ * *
* Delete encodes from the queue window and accompanying array
* Also handling first cancelling the encode if in fact its currently encoding .
* /
- ( IBAction ) removeSelectedQueueItem : ( id ) sender
{
2015-10-19 17:57:49 +02:00
if ( [ self . jobs beginTransaction ] = = HBDistributedArrayContentReload )
{
// Do not execture the action if the array changed .
[ self . jobs commit ] ;
return ;
}
2015-07-22 07:46:07 +00:00
NSMutableIndexSet * targetedRows = [ [ self . outlineView targetedRowIndexes ] mutableCopy ] ;
2015-01-19 08:48:18 +00:00
2015-07-22 07:46:07 +00:00
if ( targetedRows . count )
2015-01-19 08:48:18 +00:00
{
2015-07-22 07:46:07 +00:00
// if this is a currently encoding job , 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
NSIndexSet * workingIndexes = [ self . jobs indexesOfObjectsUsingBlock : ^ BOOL ( HBJob * item ) {
return item . state = = HBJobStateWorking ;
} ] ;
2015-07-22 12:02:56 +00:00
if ( [ targetedRows containsIndexes : workingIndexes ] )
{
[ targetedRows removeIndexes : workingIndexes ] ;
2015-10-28 08:15:52 +01:00
NSArray < HBJob * > * workingJobs = [ self . jobs filteredArrayUsingBlock : ^ BOOL ( HBJob * item ) {
2015-07-22 12:02:56 +00:00
return item . state = = HBJobStateWorking ;
} ] ;
if ( [ workingJobs containsObject : self . currentJob ] )
{
NSString * alertTitle = [ NSString stringWithFormat : NSLocalizedString ( @ "Stop This Encode and Remove It?" , nil ) ] ;
// Which window to attach the sheet to ?
2015-10-19 17:57:49 +02:00
NSWindow * targetWindow = self . window ;
2015-07-22 12:02:56 +00:00
if ( [ sender respondsToSelector : @ selector ( window ) ] )
{
targetWindow = [ sender window ] ;
}
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert setMessageText : alertTitle ] ;
[ alert setInformativeText : NSLocalizedString ( @ "Your movie will be lost if you don't continue encoding." , nil ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Keep Encoding" , nil ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Stop Encoding and Delete" , nil ) ] ;
[ alert setAlertStyle : NSCriticalAlertStyle ] ;
[ alert beginSheetModalForWindow : targetWindow
modalDelegate : self
didEndSelector : @ selector ( didDimissCancelCurrentJob : returnCode : contextInfo : )
contextInfo : NULL ] ;
}
}
2015-07-22 07:46:07 +00:00
// remove the non working items immediately
[ self removeQueueItemsAtIndexes : targetedRows ] ;
2015-01-19 08:48:18 +00:00
}
2015-10-19 17:57:49 +02:00
[ self . jobs commit ] ;
2015-01-19 08:48:18 +00:00
}
- ( void ) didDimissCancelCurrentJob : ( NSAlert * ) alert
returnCode : ( NSInteger ) returnCode
contextInfo : ( void * ) contextInfo
{
if ( returnCode = = NSAlertSecondButtonReturn )
{
2015-10-19 17:57:49 +02:00
[ self . jobs beginTransaction ] ;
2015-01-19 08:48:18 +00:00
NSInteger index = [ self . jobs indexOfObject : self . currentJob ] ;
2015-01-20 08:37:00 +00:00
[ self cancelCurrentJobAndContinue ] ;
2015-07-22 07:46:07 +00:00
2015-01-19 08:48:18 +00:00
[ self removeQueueItemAtIndex : index ] ;
2015-07-22 07:46:07 +00:00
[ self . jobs commit ] ;
2015-01-19 08:48:18 +00:00
}
}
/ * *
* Show the finished encode in the finder
* /
2015-10-19 17:57:49 +02:00
- ( IBAction ) revealSelectedQueueItems : ( id ) sender
2015-01-19 08:48:18 +00:00
{
2015-07-22 07:46:07 +00:00
NSIndexSet * targetedRows = [ self . outlineView targetedRowIndexes ] ;
NSMutableArray * urls = [ [ NSMutableArray alloc ] init ] ;
2015-01-19 08:48:18 +00:00
2015-07-22 07:46:07 +00:00
NSUInteger currentIndex = [ targetedRows firstIndex ] ;
while ( currentIndex ! = NSNotFound ) {
NSURL * url = [ [ self . jobs objectAtIndex : currentIndex ] destURL ] ;
[ urls addObject : url ] ;
currentIndex = [ targetedRows indexGreaterThanIndex : currentIndex ] ;
2007-10-09 15:15:16 +00:00
}
2015-07-22 07:46:07 +00:00
[ [ NSWorkspace sharedWorkspace ] activateFileViewerSelectingURLs : urls ] ;
2015-01-19 08:48:18 +00:00
}
2008-08-07 17:26:25 +00:00
2015-01-19 08:48:18 +00:00
- ( void ) remindUserOfSleepOrShutdown
{
2015-07-22 07:46:07 +00:00
if ( [ [ NSUserDefaults standardUserDefaults ] integerForKey : @ "HBAlertWhenDone" ] = = HBDoneActionSleep )
2007-09-14 04:42:46 +00:00
{
2015-01-19 08:48:18 +00:00
// Warn that computer will sleep after encoding
NSBeep ( ) ;
[ NSApp requestUserAttention : NSCriticalRequest ] ;
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert setMessageText : NSLocalizedString ( @ "The computer will sleep after encoding is done." , @ "" ) ] ;
[ alert setInformativeText : NSLocalizedString ( @ "You have selected to sleep the computer after encoding. To turn off sleeping, go to the HandBrake preferences." , @ "" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , @ "" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Preferences…" , @ "" ) ] ;
2008-08-07 17:26:25 +00:00
2015-01-19 08:48:18 +00:00
NSInteger response = [ alert runModal ] ;
if ( response = = NSAlertSecondButtonReturn )
2007-09-14 04:42:46 +00:00
{
2015-01-22 10:30:26 +00:00
[ self . delegate showPreferencesWindow : nil ] ;
2007-09-14 04:42:46 +00:00
}
2015-01-19 08:48:18 +00:00
}
2015-07-22 07:46:07 +00:00
else if ( [ [ NSUserDefaults standardUserDefaults ] integerForKey : @ "HBAlertWhenDone" ] = = HBDoneActionShutDown )
2015-01-19 08:48:18 +00:00
{
// Warn that computer will shut down after encoding
NSBeep ( ) ;
[ NSApp requestUserAttention : NSCriticalRequest ] ;
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert setMessageText : NSLocalizedString ( @ "The computer will shut down after encoding is done." , @ "" ) ] ;
[ alert setInformativeText : NSLocalizedString ( @ "You have selected to shut down the computer after encoding. To turn off shut down, go to the HandBrake preferences." , @ "" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , @ "" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Preferences…" , @ "" ) ] ;
NSInteger response = [ alert runModal ] ;
if ( response = = NSAlertSecondButtonReturn )
2007-09-14 04:42:46 +00:00
{
2015-01-22 10:30:26 +00:00
[ self . delegate showPreferencesWindow : nil ] ;
2007-09-14 04:42:46 +00:00
}
2007-10-09 15:15:16 +00:00
}
2008-09-16 20:57:13 +00:00
}
2015-01-19 08:48:18 +00:00
/ * *
* Rip : puts up an alert before ultimately calling doRip
* /
- ( IBAction ) rip : ( id ) sender
{
// Rip or Cancel ?
if ( self . core . state = = HBStateWorking || self . core . state = = HBStatePaused )
{
2015-01-20 08:05:16 +00:00
[ self cancelRip : sender ] ;
2015-01-19 08:48:18 +00:00
}
// If there are pending jobs in the queue , then this is a rip the queue
else if ( self . pendingItemsCount > 0 )
{
// We check to see if we need to warn the user that the computer will go to sleep
// or shut down when encoding is finished
[ self remindUserOfSleepOrShutdown ] ;
2008-09-16 20:57:13 +00:00
2015-01-19 08:48:18 +00:00
[ self encodeNextQueueItem ] ;
}
2014-11-23 12:56:03 +00:00
}
2015-01-19 08:48:18 +00:00
/ * *
* Displays an alert asking user if the want to cancel encoding of current job .
* Cancel : returns immediately after posting the alert . Later , when the user
* acknowledges the alert , doCancelCurrentJob is called .
* /
2015-01-20 08:05:16 +00:00
- ( IBAction ) cancelRip : ( id ) sender
2008-09-16 20:57:13 +00:00
{
2015-01-19 08:48:18 +00:00
// Which window to attach the sheet to ?
2015-10-19 17:57:49 +02:00
NSWindow * window = self . window ;
2015-01-19 08:48:18 +00:00
if ( [ sender respondsToSelector : @ selector ( window ) ] )
{
window = [ sender window ] ;
2008-09-18 16:11:12 +00:00
}
2015-01-19 08:48:18 +00:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
2015-07-22 07:46:07 +00:00
[ alert setMessageText : NSLocalizedString ( @ "You are currently encoding. What would you like to do?" , nil ) ] ;
2015-01-19 08:48:18 +00:00
[ alert setInformativeText : NSLocalizedString ( @ "Your encode will be cancelled if you don't continue encoding." , nil ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Continue Encoding" , nil ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Cancel Current and Stop" , nil ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Cancel Current and Continue" , nil ) ] ;
2015-10-19 17:57:49 +02:00
[ alert addButtonWithTitle : NSLocalizedString ( @ "Finish Current and Stop" , nil ) ] ;
2015-01-19 08:48:18 +00:00
[ alert setAlertStyle : NSCriticalAlertStyle ] ;
[ alert beginSheetModalForWindow : window
modalDelegate : self
didEndSelector : @ selector ( didDimissCancel : returnCode : contextInfo : )
contextInfo : nil ] ;
2008-09-18 16:11:12 +00:00
}
2015-01-19 08:48:18 +00:00
- ( void ) didDimissCancel : ( NSAlert * ) alert
returnCode : ( NSInteger ) returnCode
contextInfo : ( void * ) contextInfo
2008-09-18 16:11:12 +00:00
{
2014-08-23 07:48:32 +00:00
if ( returnCode = = NSAlertSecondButtonReturn )
2008-09-18 16:11:12 +00:00
{
2015-01-20 08:37:00 +00:00
[ self cancelCurrentJobAndStop ] ;
2008-09-18 16:11:12 +00:00
}
2015-01-19 08:48:18 +00:00
else if ( returnCode = = NSAlertThirdButtonReturn )
2008-09-16 20:57:13 +00:00
{
2015-01-20 08:37:00 +00:00
[ self cancelCurrentJobAndContinue ] ;
2008-09-16 20:57:13 +00:00
}
2015-10-19 17:57:49 +02:00
else if ( returnCode = = NSAlertThirdButtonReturn + 1 )
{
[ self finishCurrentAndStop ] ;
}
2007-09-07 13:40:40 +00:00
}
2015-01-19 08:48:18 +00:00
/ * *
* Starts or cancels the processing of jobs depending on the current state
* /
- ( IBAction ) toggleStartCancel : ( id ) sender
2007-09-05 20:01:14 +00:00
{
2015-01-19 08:48:18 +00:00
HBState s = self . core . state ;
2014-12-27 10:46:04 +00:00
if ( ( s = = HBStatePaused ) || ( s = = HBStateWorking ) || ( s = = HBStateMuxing ) )
{
2015-01-20 08:05:16 +00:00
[ self cancelRip : self ] ;
2014-12-27 10:46:04 +00:00
}
2015-01-19 08:48:18 +00:00
else if ( self . pendingItemsCount > 0 )
2014-12-27 10:46:04 +00:00
{
2015-01-19 08:48:18 +00:00
[ self rip : self ] ;
2014-12-27 10:46:04 +00:00
}
2008-09-16 20:57:13 +00:00
}
2007-09-24 15:22:24 +00:00
2015-01-19 08:48:18 +00:00
/ * *
* Toggles the pause / resume state of libhb
* /
- ( IBAction ) togglePauseResume : ( id ) sender
2008-09-16 20:57:13 +00:00
{
2015-01-19 08:48:18 +00:00
HBState s = self . core . state ;
2014-12-27 10:46:04 +00:00
if ( s = = HBStatePaused )
2009-02-12 21:08:41 +00:00
{
2015-01-19 08:48:18 +00:00
[ self . core resume ] ;
2009-02-12 21:08:41 +00:00
}
2015-01-19 08:48:18 +00:00
else if ( s = = HBStateWorking || s = = HBStateMuxing )
2009-02-12 21:08:41 +00:00
{
2015-01-19 08:48:18 +00:00
[ self . core pause ] ;
2009-02-12 21:08:41 +00:00
}
2007-09-05 20:01:14 +00:00
}
2015-10-19 17:57:49 +02:00
/ * *
* Resets the job state to ready .
* /
2015-07-22 07:46:07 +00:00
- ( IBAction ) resetJobState : ( id ) sender
{
2015-10-19 17:57:49 +02:00
if ( [ self . jobs beginTransaction ] = = HBDistributedArrayContentReload )
{
// Do not execture the action if the array changed .
[ self . jobs commit ] ;
return ;
}
2015-07-22 07:46:07 +00:00
NSIndexSet * targetedRows = [ self . outlineView targetedRowIndexes ] ;
NSMutableIndexSet * updatedIndexes = [ NSMutableIndexSet indexSet ] ;
NSUInteger currentIndex = [ targetedRows firstIndex ] ;
while ( currentIndex ! = NSNotFound ) {
HBJob * job = self . jobs [ currentIndex ] ;
2015-10-19 17:57:49 +02:00
if ( job . state = = HBJobStateCanceled || job . state = = HBJobStateCompleted || job . state = = HBJobStateFailed )
2015-07-22 07:46:07 +00:00
{
job . state = HBJobStateReady ;
[ updatedIndexes addIndex : currentIndex ] ;
}
currentIndex = [ targetedRows indexGreaterThanIndex : currentIndex ] ;
}
2015-10-19 17:57:49 +02:00
[ self reloadQueueItemsAtIndexes : updatedIndexes ] ;
[ self . jobs commit ] ;
}
- ( void ) editQueueItem : ( HBJob * ) job
{
NSParameterAssert ( job ) ;
[ self . jobs beginTransaction ] ;
NSInteger index = [ self . jobs indexOfObject : job ] ;
// Cancel the encode if it ' s the current item
if ( job = = self . currentJob )
{
[ self cancelCurrentJobAndContinue ] ;
}
if ( [ self . controller openJob : job ] )
{
// Now that source is loaded and settings applied , delete the queue item from the queue
[ self removeQueueItemAtIndex : index ] ;
}
else
{
NSBeep ( ) ;
}
2015-07-22 07:46:07 +00:00
[ self . jobs commit ] ;
}
2015-01-19 08:48:18 +00:00
/ * *
* Send the selected queue item back to the main window for rescan and possible edit .
* /
- ( IBAction ) editSelectedQueueItem : ( id ) sender
2010-01-21 18:58:17 +00:00
{
2015-10-19 17:57:49 +02:00
if ( [ self . jobs beginTransaction ] = = HBDistributedArrayContentReload )
{
// Do not execture the action if the array changed .
[ self . jobs commit ] ;
return ;
}
2015-07-22 07:46:07 +00:00
2015-10-19 17:57:49 +02:00
NSInteger row = self . outlineView . clickedRow ;
2015-07-22 07:46:07 +00:00
if ( row ! = NSNotFound )
2014-11-01 16:09:43 +00:00
{
2015-07-22 07:46:07 +00:00
// if this is a currently encoding job , 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
HBJob * job = self . jobs [ row ] ;
if ( job = = self . currentJob )
{
NSString * alertTitle = [ NSString stringWithFormat : NSLocalizedString ( @ "Stop This Encode and Edit It?" , nil ) ] ;
// Which window to attach the sheet to ?
2015-10-19 17:57:49 +02:00
NSWindow * docWindow = self . window ;
2015-07-22 07:46:07 +00:00
if ( [ sender respondsToSelector : @ selector ( window ) ] )
{
docWindow = [ sender window ] ;
}
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert setMessageText : alertTitle ] ;
[ alert setInformativeText : NSLocalizedString ( @ "Your movie will be lost if you don't continue encoding." , nil ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Keep Encoding" , nil ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Stop Encoding and Edit" , nil ) ] ;
[ alert setAlertStyle : NSCriticalAlertStyle ] ;
[ alert beginSheetModalForWindow : docWindow
modalDelegate : self
didEndSelector : @ selector ( didDimissEditCurrentJob : returnCode : contextInfo : )
contextInfo : ( __bridge void * ) ( job ) ] ;
}
2015-07-22 11:38:23 +00:00
else if ( job . state ! = HBJobStateWorking )
2015-07-22 07:46:07 +00:00
{
2015-10-19 17:57:49 +02:00
[ self editQueueItem : job ] ;
2015-07-22 07:46:07 +00:00
}
2014-11-01 16:09:43 +00:00
}
2015-07-22 07:46:07 +00:00
[ self . jobs commit ] ;
}
- ( void ) didDimissEditCurrentJob : ( NSAlert * ) alert
returnCode : ( NSInteger ) returnCode
contextInfo : ( void * ) contextInfo
{
if ( returnCode = = NSAlertSecondButtonReturn )
2010-01-21 18:58:17 +00:00
{
2015-07-22 07:46:07 +00:00
HBJob * job = ( __bridge HBJob * ) contextInfo ;
2015-10-19 17:57:49 +02:00
[ self editQueueItem : job ] ;
2007-10-09 15:15:16 +00:00
}
2007-09-26 12:25:59 +00:00
}
2015-02-02 11:12:54 +00:00
- ( IBAction ) clearAll : ( id ) sender
{
[ self . jobs beginTransaction ] ;
2015-10-19 17:57:49 +02:00
NSIndexSet * indexes = [ self . jobs indexesOfObjectsUsingBlock : ^ BOOL ( HBJob * item ) {
2015-02-02 11:12:54 +00:00
return ( item . state ! = HBJobStateWorking ) ;
} ] ;
2015-10-19 17:57:49 +02:00
[ self removeQueueItemsAtIndexes : indexes ] ;
2015-02-02 11:12:54 +00:00
[ self . jobs commit ] ;
}
- ( IBAction ) clearCompleted : ( id ) sender
{
[ self . jobs beginTransaction ] ;
2015-10-19 17:57:49 +02:00
NSIndexSet * indexes = [ self . jobs indexesOfObjectsUsingBlock : ^ BOOL ( HBJob * item ) {
2015-02-02 11:12:54 +00:00
return ( item . state = = HBJobStateCompleted ) ;
} ] ;
2015-10-19 17:57:49 +02:00
[ self removeQueueItemsAtIndexes : indexes ] ;
2015-02-02 11:12:54 +00:00
[ self . jobs commit ] ;
}
2007-09-07 13:40:40 +00:00
# pragma mark -
2015-07-22 07:46:07 +00:00
# pragma mark NSOutlineView data source
2007-09-05 20:01:14 +00:00
2008-09-16 20:57:13 +00:00
- ( id ) outlineView : ( NSOutlineView * ) fOutlineView child : ( NSInteger ) index ofItem : ( id ) item
2007-09-05 20:01:14 +00:00
{
2007-09-24 15:22:24 +00:00
if ( item = = nil )
2015-01-19 08:48:18 +00:00
{
return self . jobs [ index ] ;
}
2008-08-07 17:26:25 +00:00
2007-09-24 15:22:24 +00:00
// We are only one level deep , so we can ' t be asked about children
2015-07-22 07:46:07 +00:00
NSAssert ( NO , @ "HBQueueController outlineView:child:ofItem: can't handle nested items." ) ;
2007-09-24 15:22:24 +00:00
return nil ;
2007-09-11 15:03:01 +00:00
}
2008-09-16 20:57:13 +00:00
- ( BOOL ) outlineView : ( NSOutlineView * ) fOutlineView isItemExpandable : ( id ) item
2007-09-11 15:03:01 +00:00
{
2007-09-24 15:22:24 +00:00
// Our outline view has no levels , but we can still expand every item . Doing so
// just makes the row taller . See heightOfRowByItem below .
2007-09-11 15:03:01 +00:00
return YES ;
}
2008-09-26 18:57:38 +00:00
- ( BOOL ) outlineView : ( NSOutlineView * ) outlineView shouldExpandItem : ( id ) item
2007-10-09 15:15:16 +00:00
{
// Our outline view has no levels , but we can still expand every item . Doing so
// just makes the row taller . See heightOfRowByItem below .
2014-08-18 06:22:02 +00:00
return ! [ ( HBQueueOutlineView * ) outlineView isDragging ] ;
2007-10-09 15:15:16 +00:00
}
2008-09-16 20:57:13 +00:00
- ( NSInteger ) outlineView : ( NSOutlineView * ) fOutlineView numberOfChildrenOfItem : ( id ) item
2007-09-11 15:03:01 +00:00
{
2007-09-24 15:22:24 +00:00
// Our outline view has no levels , so number of children will be zero for all
// top - level items .
2007-09-11 15:03:01 +00:00
if ( item = = nil )
2015-01-19 08:48:18 +00:00
{
2015-10-19 17:57:49 +02:00
return self . jobs . count ;
2015-01-19 08:48:18 +00:00
}
2007-09-11 15:03:01 +00:00
else
2015-01-19 08:48:18 +00:00
{
2007-09-24 15:22:24 +00:00
return 0 ;
2015-01-19 08:48:18 +00:00
}
2007-09-11 15:03:01 +00:00
}
2015-07-22 07:46:07 +00:00
# pragma mark NSOutlineView delegate
2007-09-24 15:22:24 +00:00
- ( void ) outlineViewItemDidCollapse : ( NSNotification * ) notification
2007-09-11 15:03:01 +00:00
{
2015-07-22 07:46:07 +00:00
id item = notification . userInfo [ @ "NSObject" ] ;
2015-01-19 08:48:18 +00:00
NSInteger row = [ self . outlineView rowForItem : item ] ;
[ self . outlineView noteHeightOfRowsWithIndexesChanged : [ NSIndexSet indexSetWithIndexesInRange : NSMakeRange ( row , 1 ) ] ] ;
2007-09-11 15:03:01 +00:00
}
2007-09-24 15:22:24 +00:00
- ( void ) outlineViewItemDidExpand : ( NSNotification * ) notification
2007-09-11 15:03:01 +00:00
{
2015-07-22 07:46:07 +00:00
id item = notification . userInfo [ @ "NSObject" ] ;
2015-01-19 08:48:18 +00:00
NSInteger row = [ self . outlineView rowForItem : item ] ;
[ self . outlineView noteHeightOfRowsWithIndexesChanged : [ NSIndexSet indexSetWithIndexesInRange : NSMakeRange ( row , 1 ) ] ] ;
2007-09-11 15:03:01 +00:00
}
2015-10-19 17:57:49 +02:00
# define HB_ROW _HEIGHT _TITLE _ONLY 17.0
# define HB_ROW _HEIGHT _PADDING 6.0
2008-04-08 11:54:55 +00:00
- ( CGFloat ) outlineView : ( NSOutlineView * ) outlineView heightOfRowByItem : ( id ) item
2007-09-11 15:03:01 +00:00
{
2015-07-22 07:46:07 +00:00
if ( [ outlineView isItemExpanded : item ] )
2007-09-14 04:42:46 +00:00
{
2013-08-18 06:57:35 +00:00
// It is important to use a constant value when calculating the height . Querying the tableColumn width will not work , since it dynamically changes as the user resizes - - however , we don ' t get a notification that the user "did resize" it until after the mouse is let go . We use the latter as a hook for telling the table that the heights changed . We must return the same height from this method every time , until we tell the table the heights have changed . Not doing so will quicly cause drawing problems .
2014-08-18 06:22:02 +00:00
NSTableColumn * tableColumnToWrap = ( NSTableColumn * ) [ outlineView tableColumns ] [ 1 ] ;
2013-08-18 06:57:35 +00:00
NSInteger columnToWrap = [ outlineView . tableColumns indexOfObject : tableColumnToWrap ] ;
2009-06-23 16:07:04 +00:00
2013-08-18 06:57:35 +00:00
// Grab the fully prepared cell with our content filled in . Note that in IB the cell ' s Layout is set to Wraps .
NSCell * cell = [ outlineView preparedCellAtColumn : columnToWrap row : [ outlineView rowForItem : item ] ] ;
2009-06-23 16:07:04 +00:00
2013-08-18 06:57:35 +00:00
// See how tall it naturally would want to be if given a restricted with , but unbound height
2015-10-19 17:57:49 +02:00
NSRect constrainedBounds = NSMakeRect ( 0 , 0 , tableColumnToWrap . width , CGFLOAT_MAX ) ;
2013-08-18 06:57:35 +00:00
NSSize naturalSize = [ cell cellSizeForBounds : constrainedBounds ] ;
2009-06-23 16:07:04 +00:00
2013-08-18 06:57:35 +00:00
// Make sure we have a minimum height - - use the table ' s set height as the minimum .
2015-10-19 17:57:49 +02:00
if ( naturalSize . height > outlineView . rowHeight )
return naturalSize . height + HB_ROW _HEIGHT _PADDING ;
2013-08-18 06:57:35 +00:00
else
2015-10-19 17:57:49 +02:00
return outlineView . rowHeight ;
2007-09-14 04:42:46 +00:00
}
else
2009-06-23 16:07:04 +00:00
{
2007-09-24 15:22:24 +00:00
return HB_ROW _HEIGHT _TITLE _ONLY ;
2009-06-23 16:07:04 +00:00
}
2007-09-11 15:03:01 +00:00
}
2008-09-16 20:57:13 +00:00
- ( id ) outlineView : ( NSOutlineView * ) fOutlineView objectValueForTableColumn : ( NSTableColumn * ) tableColumn byItem : ( id ) item
2007-09-11 15:03:01 +00:00
{
2015-01-19 08:48:18 +00:00
if ( [ tableColumn . identifier isEqualToString : @ "desc" ] )
2008-09-16 20:57:13 +00:00
{
2014-12-30 07:13:07 +00:00
HBJob * job = item ;
2015-10-19 17:57:49 +02:00
NSAttributedString * description = self . descriptions [ @ ( job . hash ) ] ;
2014-12-30 07:13:07 +00:00
2015-10-19 17:57:49 +02:00
if ( description = = nil )
2009-06-13 19:50:12 +00:00
{
2015-10-19 17:57:49 +02:00
description = job . attributedDescription ;
self . descriptions [ @ ( job . hash ) ] = description ;
2013-10-15 11:36:51 +00:00
}
2015-10-19 17:57:49 +02:00
return description ;
2008-09-16 20:57:13 +00:00
}
2015-01-19 08:48:18 +00:00
else if ( [ tableColumn . identifier isEqualToString : @ "icon" ] )
2007-10-09 15:15:16 +00:00
{
2014-12-27 10:46:04 +00:00
HBJob * job = item ;
if ( job . state = = HBJobStateCompleted )
2008-09-16 20:57:13 +00:00
{
return [ NSImage imageNamed : @ "EncodeComplete" ] ;
}
2014-12-27 10:46:04 +00:00
else if ( job . state = = HBJobStateWorking )
2007-10-09 15:15:16 +00:00
{
2015-01-19 08:48:18 +00:00
return [ NSImage imageNamed : @ "EncodeWorking0" ] ;
2007-10-09 15:15:16 +00:00
}
2014-12-27 10:46:04 +00:00
else if ( job . state = = HBJobStateCanceled )
2008-09-16 20:57:13 +00:00
{
return [ NSImage imageNamed : @ "EncodeCanceled" ] ;
}
2015-10-19 17:57:49 +02:00
else if ( job . state = = HBJobStateFailed )
{
return [ NSImage imageNamed : @ "EncodeFailed" ] ;
}
2008-09-16 20:57:13 +00:00
else
{
return [ NSImage imageNamed : @ "JobSmall" ] ;
}
2007-10-09 15:15:16 +00:00
}
2007-09-11 15:03:01 +00:00
else
2008-09-16 20:57:13 +00:00
{
2007-09-24 15:22:24 +00:00
return @ "" ;
2008-09-16 20:57:13 +00:00
}
2007-09-11 15:03:01 +00:00
}
2015-01-19 08:48:18 +00:00
/ * *
* This method inserts the proper action icons into the far right of the queue window
* /
2007-09-11 15:03:01 +00:00
- ( void ) outlineView : ( NSOutlineView * ) outlineView willDisplayCell : ( id ) cell forTableColumn : ( NSTableColumn * ) tableColumn item : ( id ) item
{
2015-07-22 07:46:07 +00:00
if ( [ tableColumn . identifier isEqualToString : @ "action" ] )
2007-09-11 15:03:01 +00:00
{
2007-09-24 15:22:24 +00:00
[ cell setEnabled : YES ] ;
BOOL highlighted = [ outlineView isRowSelected : [ outlineView rowForItem : item ] ] && [ [ outlineView window ] isKeyWindow ] && ( [ [ outlineView window ] firstResponder ] = = outlineView ) ;
2014-12-27 10:46:04 +00:00
HBJob * job = item ;
2014-12-27 12:26:17 +00:00
if ( job . state = = HBJobStateCompleted )
2007-09-11 15:03:01 +00:00
{
2015-07-22 07:46:07 +00:00
[ cell setAction : @ selector ( revealSelectedQueueItems : ) ] ;
2007-10-09 15:15:16 +00:00
if ( highlighted )
{
[ cell setImage : [ NSImage imageNamed : @ "RevealHighlight" ] ] ;
[ cell setAlternateImage : [ NSImage imageNamed : @ "RevealHighlightPressed" ] ] ;
}
else
2015-10-19 17:57:49 +02:00
{
2007-10-09 15:15:16 +00:00
[ cell setImage : [ NSImage imageNamed : @ "Reveal" ] ] ;
2015-10-19 17:57:49 +02:00
}
2007-09-11 15:03:01 +00:00
}
else
2007-10-09 15:15:16 +00:00
{
2014-12-27 12:26:17 +00:00
[ cell setAction : @ selector ( removeSelectedQueueItem : ) ] ;
if ( highlighted )
{
[ cell setImage : [ NSImage imageNamed : @ "DeleteHighlight" ] ] ;
[ cell setAlternateImage : [ NSImage imageNamed : @ "DeleteHighlightPressed" ] ] ;
}
else
2015-10-19 17:57:49 +02:00
{
2014-12-27 12:26:17 +00:00
[ cell setImage : [ NSImage imageNamed : @ "Delete" ] ] ;
2015-10-19 17:57:49 +02:00
}
2007-10-09 15:15:16 +00:00
}
2007-09-11 15:03:01 +00:00
}
}
2007-09-17 14:46:36 +00:00
- ( void ) outlineView : ( NSOutlineView * ) outlineView willDisplayOutlineCell : ( id ) cell forTableColumn : ( NSTableColumn * ) tableColumn item : ( id ) item
{
2010-07-17 19:15:38 +00:00
// By default , the disclosure image gets centered vertically in the cell . We want
2007-09-17 14:46:36 +00:00
// always at the top .
2015-01-19 08:48:18 +00:00
if ( [ outlineView isItemExpanded : item ] )
{
2007-09-17 14:46:36 +00:00
[ cell setImagePosition : NSImageAbove ] ;
2015-01-19 08:48:18 +00:00
}
2007-09-17 14:46:36 +00:00
else
2015-01-19 08:48:18 +00:00
{
2007-09-17 14:46:36 +00:00
[ cell setImagePosition : NSImageOnly ] ;
2015-01-19 08:48:18 +00:00
}
2007-09-17 14:46:36 +00:00
}
2015-10-19 17:57:49 +02:00
# pragma mark NSOutlineView drag & drop
2007-09-24 15:22:24 +00:00
- ( BOOL ) outlineView : ( NSOutlineView * ) outlineView writeItems : ( NSArray * ) items toPasteboard : ( NSPasteboard * ) pboard
{
2008-08-07 17:26:25 +00:00
// Dragging is only allowed of the pending items .
2015-01-19 08:48:18 +00:00
if ( [ items [ 0 ] state ] ! = HBJobStateReady )
2008-08-07 17:26:25 +00:00
{
2008-09-16 20:57:13 +00:00
return NO ;
2008-08-07 17:26:25 +00:00
}
2015-01-19 08:48:18 +00:00
self . dragNodesArray = items ;
2007-09-24 15:22:24 +00:00
// Provide data for our custom type , and simple NSStrings .
2014-08-18 06:22:02 +00:00
[ pboard declareTypes : @ [ DragDropSimplePboardType ] owner : self ] ;
2015-01-19 08:48:18 +00:00
2007-09-24 15:22:24 +00:00
// the actual data doesn ' t matter since DragDropSimplePboardType drags aren ' t recognized by anyone but us ! .
2008-09-16 20:57:13 +00:00
[ pboard setData : [ NSData data ] forType : DragDropSimplePboardType ] ;
2015-01-19 08:48:18 +00:00
2007-09-24 15:22:24 +00:00
return YES ;
}
2008-04-08 11:54:55 +00:00
- ( NSDragOperation ) outlineView : ( NSOutlineView * ) outlineView validateDrop : ( id < NSDraggingInfo > ) info proposedItem : ( id ) item proposedChildIndex : ( NSInteger ) index
2007-09-24 15:22:24 +00:00
{
2008-08-07 17:26:25 +00:00
// Don ' t allow dropping ONTO an item since they can ' t really contain any children .
2007-10-09 15:15:16 +00:00
BOOL isOnDropTypeProposal = index = = NSOutlineViewDropOnItemIndex ;
2007-09-24 15:22:24 +00:00
if ( isOnDropTypeProposal )
2008-09-26 18:57:38 +00:00
{
2007-09-24 15:22:24 +00:00
return NSDragOperationNone ;
2008-09-26 18:57:38 +00:00
}
2008-08-07 17:26:25 +00:00
// Don ' t allow dropping INTO an item since they can ' t really contain any children .
if ( item ! = nil )
{
2015-10-19 17:57:49 +02:00
index = [ self . outlineView rowForItem : item ] + 1 ;
2008-08-07 17:26:25 +00:00
item = nil ;
}
2015-01-19 08:48:18 +00:00
2008-09-16 20:57:13 +00:00
// We do not let the user drop a pending job before or * above *
// already finished or currently encoding jobs .
2015-01-19 08:48:18 +00:00
NSInteger encodingIndex = [ self . jobs indexOfObject : self . currentJob ] ;
2015-02-23 07:40:50 +00:00
if ( encodingIndex ! = NSNotFound && index <= encodingIndex )
2008-09-16 20:57:13 +00:00
{
return NSDragOperationNone ;
2015-10-19 17:57:49 +02:00
index = MAX ( index , encodingIndex ) ;
2008-09-16 20:57:13 +00:00
}
2015-01-19 08:48:18 +00:00
2008-08-07 17:26:25 +00:00
[ outlineView setDropItem : item dropChildIndex : index ] ;
2007-09-24 15:22:24 +00:00
return NSDragOperationGeneric ;
}
2008-04-08 11:54:55 +00:00
- ( BOOL ) outlineView : ( NSOutlineView * ) outlineView acceptDrop : ( id < NSDraggingInfo > ) info item : ( id ) item childIndex : ( NSInteger ) index
2007-09-24 15:22:24 +00:00
{
2015-10-19 17:57:49 +02:00
[ self moveQueueItems : self . dragNodesArray toIndex : index ] ;
2007-09-24 15:22:24 +00:00
return YES ;
}
2007-09-11 15:03:01 +00:00
2007-09-05 20:01:14 +00:00
@ end