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:30:26 +00:00
# import "HBAppDelegate.h"
2014-11-23 12:56:03 +00:00
2019-07-19 21:17:27 +02:00
# import "HBQueue.h"
2020-04-11 12:19:17 +02:00
# import "HBQueueWorker.h"
2019-07-19 21:17:27 +02:00
# import "HBQueueTableViewController.h"
# import "HBQueueDetailsViewController.h"
2019-07-27 13:15:37 +02:00
# import "HBQueueInfoViewController.h"
# import "HBQueueMultiSelectionViewController.h"
2014-12-27 10:46:04 +00:00
2024-03-02 08:47:58 +01:00
# import "HBQueueToolbarDelegate.h"
2019-07-29 07:34:38 +02:00
# import "HBPreferencesKeys.h"
2019-07-19 21:17:27 +02:00
# import "NSArray+HBAdditions.h"
2015-02-20 07:59:38 +00:00
2016-02-26 09:50:16 +01:00
@ import HandBrakeKit ;
2022-01-11 09:22:48 +01:00
@ import QuickLookUI ;
2024-09-14 08:14:29 +02:00
@ import UserNotifications ;
2016-02-26 09:50:16 +01:00
2024-09-14 08:14:29 +02:00
@ interface HBQueueController ( ) < NSToolbarItemValidation , NSMenuItemValidation , NSUserNotificationCenterDelegate , UNUserNotificationCenterDelegate , HBQueueTableViewControllerDelegate , HBQueueDetailsViewControllerDelegate >
2019-07-19 21:17:27 +02:00
@ property ( nonatomic ) NSSplitViewController * splitViewController ;
@ property ( nonatomic ) HBQueueTableViewController * tableViewController ;
2019-07-27 13:15:37 +02:00
@ property ( nonatomic ) NSViewController * containerViewController ;
@ property ( nonatomic ) HBQueueInfoViewController * infoViewController ;
@ property ( nonatomic ) HBQueueMultiSelectionViewController * multiSelectionViewController ;
2014-08-18 06:22:02 +00:00
2024-03-02 08:47:58 +01:00
@ property ( nonatomic ) HBQueueToolbarDelegate * toolbarDelegate ;
2018-10-08 16:27:16 +02:00
@ property ( nonatomic ) IBOutlet NSToolbarItem * ripToolbarItem ;
@ property ( nonatomic ) IBOutlet NSToolbarItem * pauseToolbarItem ;
2020-03-30 14:23:34 +02:00
@ property ( nonatomic , readonly ) dispatch_queue _t sendQueue ;
2014-08-18 06:22:02 +00:00
@ end
2018-10-08 16:27:16 +02:00
@ interface HBQueueController ( TouchBar ) < NSTouchBarProvider , NSTouchBarDelegate >
2019-07-19 21:17:27 +02:00
- ( void ) _touchBar _updateButtonsState ;
2018-10-10 19:58:21 +02:00
- ( void ) _touchBar _validateUserInterfaceItems ;
2019-07-29 07:34:38 +02:00
- ( IBAction ) _touchBar _toggleStartCancel : ( id ) sender ;
2018-10-08 16:27:16 +02:00
@ end
2008-09-16 20:57:13 +00:00
@ implementation HBQueueController
2007-09-05 20:01:14 +00:00
2019-07-19 21:17:27 +02:00
- ( instancetype ) initWithQueue : ( HBQueue * ) queue
2007-09-05 20:01:14 +00:00
{
2019-07-19 21:17:27 +02:00
NSParameterAssert ( queue ) ;
2015-10-19 17:57:49 +02:00
2008-09-16 20:57:13 +00:00
if ( self = [ super initWithWindowNibName : @ "Queue" ] )
2008-04-07 20:11:46 +00:00
{
2019-07-29 07:34:38 +02:00
_queue = queue ;
2025-01-24 08:25:14 +01:00
_sendQueue = dispatch_queue _create ( "fr.handbrake.SendToQueue" ,
dispatch_queue _attr _make _with _autorelease _frequency ( DISPATCH_QUEUE _SERIAL ,
DISPATCH_AUTORELEASE _FREQUENCY _WORK _ITEM ) ) ;
2019-09-17 07:36:43 +02:00
2025-03-11 08:03:00 +01:00
if ( @ available ( macOS 10.15 , * ) )
{
UNUserNotificationCenter * center = UNUserNotificationCenter . currentNotificationCenter ;
center . delegate = self ;
UNNotificationAction * action = [ UNNotificationAction actionWithIdentifier : HBQueueItemNotificationShowAction
title : NSLocalizedString ( @ "Show" , @ "Notification -> Show in Finder" )
options : UNNotificationActionOptionForeground ] ;
UNNotificationCategory * category = [ UNNotificationCategory categoryWithIdentifier : HBQueueItemNotificationShowCategory
actions : @ [ action ]
intentIdentifiers : @ [ ]
options : 0 ] ;
[ center setNotificationCategories : [ NSSet setWithObject : category ] ] ;
[ center requestAuthorizationWithOptions : UNAuthorizationOptionSound | UNAuthorizationOptionAlert
completionHandler : ^ ( BOOL granted , NSError * _Nullable error ) { } ] ;
}
else
{
NSUserNotificationCenter . defaultUserNotificationCenter . delegate = self ;
}
2019-07-25 08:10:15 +02:00
[ NSNotificationCenter . defaultCenter addObserverForName : HBQueueLowSpaceAlertNotification object : _queue queue : NSOperationQueue . mainQueue usingBlock : ^ ( NSNotification * _Nonnull note ) {
[ self queueLowDiskSpaceAlert ] ;
} ] ;
[ NSNotificationCenter . defaultCenter addObserverForName : HBQueueDidCompleteNotification object : _queue queue : NSOperationQueue . mainQueue usingBlock : ^ ( NSNotification * _Nonnull note ) {
[ self queueCompletedAlerts ] ;
} ] ;
[ NSNotificationCenter . defaultCenter addObserverForName : HBQueueDidCompleteItemNotification object : _queue queue : NSOperationQueue . mainQueue usingBlock : ^ ( NSNotification * _Nonnull note ) {
// Run the per item notification and actions
2020-09-11 18:02:23 +02:00
HBQueueJobItem * item = note . userInfo [ HBQueueItemNotificationItemKey ] ;
2019-07-25 08:10:15 +02:00
if ( item . state = = HBQueueItemStateCompleted )
{
[ self sendToExternalApp : item ] ;
}
if ( item . state = = HBQueueItemStateCompleted || item . state = = HBQueueItemStateFailed )
{
[ self itemCompletedAlerts : item ] ;
}
} ] ;
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
2019-07-25 08:10:15 +02:00
- ( NSUndoManager * ) windowWillReturnUndoManager : ( NSWindow * ) window
{
return _queue . undoManager ;
}
2015-01-19 08:48:18 +00:00
- ( void ) windowDidLoad
{
2021-10-15 18:41:40 +02:00
self . window . tabbingMode = NSWindowTabbingModeDisallowed ;
2019-02-15 09:25:26 +01:00
2020-08-03 16:33:02 +02:00
if ( @ available ( macOS 11 , * ) )
2020-06-27 14:13:12 +02:00
{
2020-08-03 16:33:02 +02:00
self . window . toolbarStyle = NSWindowToolbarStyleUnified ;
2020-09-12 12:09:07 +02:00
self . window . titlebarSeparatorStyle = NSTitlebarSeparatorStyleLine ;
2020-06-27 14:13:12 +02:00
}
2024-03-02 08:47:58 +01:00
// Set up toolbar
2025-03-10 11:24:44 +01:00
self . toolbarDelegate = [ [ HBQueueToolbarDelegate alloc ] initWithTarget : self ] ;
2024-03-02 08:47:58 +01:00
NSToolbar * toolbar = [ [ NSToolbar alloc ] initWithIdentifier : @ "HBQueueWindowToolbar2" ] ;
toolbar . delegate = self . toolbarDelegate ;
toolbar . allowsUserCustomization = YES ;
toolbar . autosavesConfiguration = YES ;
toolbar . displayMode = NSToolbarDisplayModeIconAndLabel ;
self . window . toolbar = toolbar ;
2019-07-19 21:17:27 +02:00
// Set up the child view controllers
_splitViewController = [ [ NSSplitViewController alloc ] init ] ;
_splitViewController . view . wantsLayer = YES ;
2019-08-13 10:35:05 +02:00
[ _splitViewController . view setFrameSize : NSMakeSize ( 780 , 500 ) ] ;
2019-07-19 21:17:27 +02:00
_splitViewController . splitView . vertical = YES ;
_tableViewController = [ [ HBQueueTableViewController alloc ] initWithQueue : self . queue delegate : self ] ;
2019-07-27 13:15:37 +02:00
_containerViewController = [ [ HBQueueDetailsViewController alloc ] init ] ;
_infoViewController = [ [ HBQueueInfoViewController alloc ] initWithDelegate : self ] ;
_multiSelectionViewController = [ [ HBQueueMultiSelectionViewController alloc ] init ] ;
2015-01-19 08:48:18 +00:00
2019-07-19 21:17:27 +02:00
NSSplitViewItem * tableItem = [ NSSplitViewItem splitViewItemWithViewController : _tableViewController ] ;
tableItem . minimumThickness = 160 ;
2018-10-08 16:27:16 +02:00
2019-07-19 21:17:27 +02:00
[ _splitViewController addSplitViewItem : tableItem ] ;
2019-07-27 13:15:37 +02:00
NSSplitViewItem * detailsItem = [ NSSplitViewItem splitViewItemWithViewController : _containerViewController ] ;
2019-07-19 21:17:27 +02:00
detailsItem . canCollapse = YES ;
detailsItem . minimumThickness = 240 ;
[ _splitViewController addSplitViewItem : detailsItem ] ;
2019-07-20 09:08:25 +02:00
_splitViewController . splitView . autosaveName = @ "HBQueueSplitViewAutosave" ;
_splitViewController . splitView . identifier = @ "HBQueueSplitViewIdentifier" ;
2019-07-19 21:17:27 +02:00
self . window . contentViewController = _splitViewController ;
self . window . frameAutosaveName = @ "HBQueueWindowFrameAutosave" ;
2019-07-25 08:10:15 +02:00
[ self . window setFrameFromString : @ "HBQueueWindowFrameAutosave" ] ;
2019-07-19 21:17:27 +02:00
// Set up observers
2019-08-11 09:07:20 +02:00
[ NSNotificationCenter . defaultCenter addObserverForName : HBQueueDidChangeStateNotification object : _queue queue : NSOperationQueue . mainQueue usingBlock : ^ ( NSNotification * _Nonnull note ) {
[ self updateUI ] ;
} ] ;
2019-07-27 13:15:37 +02:00
2020-04-11 12:19:17 +02:00
[ self updateUI ] ;
2019-07-27 13:15:37 +02:00
[ self tableViewDidSelectItemsAtIndexes : [ NSIndexSet indexSet ] ] ;
2018-10-08 16:27:16 +02:00
}
2019-08-11 09:07:20 +02:00
- ( void ) updateUI
2018-10-08 16:27:16 +02:00
{
2024-03-02 08:47:58 +01:00
[ self . toolbarDelegate updateToolbarButtonsState : self . queue toolbar : self . window . toolbar ] ;
2019-08-11 09:07:20 +02:00
[ self . window . toolbar validateVisibleItems ] ;
2019-07-19 21:17:27 +02:00
2021-10-15 18:41:40 +02:00
[ self _touchBar _updateButtonsState ] ;
[ self _touchBar _validateUserInterfaceItems ] ;
2019-07-19 21:17:27 +02:00
2020-08-03 16:33:02 +02:00
NSString * subtitle ;
2019-08-11 09:07:20 +02:00
if ( self . queue . pendingItemsCount = = 0 )
{
self . window . title = NSLocalizedString ( @ "Queue" , @ "Queue window title" ) ;
2020-08-03 16:33:02 +02:00
subtitle = NSLocalizedString ( @ "No encode pending" , @ "Queue status" ) ;
2019-08-11 09:07:20 +02:00
}
else
{
if ( self . queue . pendingItemsCount = = 1 )
2019-07-19 21:17:27 +02:00
{
2020-08-03 16:33:02 +02:00
subtitle = [ NSString stringWithFormat : NSLocalizedString ( @ "%lu encode pending" , @ "Queue status" ) , ( unsigned long ) self . queue . pendingItemsCount ] ;
2019-07-19 21:17:27 +02:00
}
else
{
2020-08-03 16:33:02 +02:00
subtitle = [ NSString stringWithFormat : NSLocalizedString ( @ "%lu encodes pending" , @ "Queue status" ) , ( unsigned long ) self . queue . pendingItemsCount ] ;
2019-07-27 13:15:37 +02:00
}
2019-08-11 09:07:20 +02:00
2020-08-03 16:33:02 +02:00
if ( @ available ( macOS 11 , * ) ) { } else
{
self . window . title = [ NSString stringWithFormat : NSLocalizedString ( @ "Queue (%@)" , @ "Queue window title" ) , subtitle ] ;
}
}
if ( @ available ( macOS 11 , * ) )
{
self . window . subtitle = subtitle ;
2018-10-08 16:27:16 +02:00
}
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 ;
2019-07-19 21:17:27 +02:00
if ( action = = @ selector ( toggleStartCancel : ) )
2015-01-22 10:30:26 +00:00
{
2019-07-19 21:17:27 +02:00
if ( self . queue . isEncoding )
2015-01-22 10:30:26 +00:00
{
2018-06-09 10:06:52 +02:00
menuItem . title = NSLocalizedString ( @ "Stop Encoding" , @ "Queue -> start/stop menu" ) ;
2015-07-22 07:46:07 +00:00
return YES ;
2015-01-22 10:30:26 +00:00
}
2019-07-19 21:17:27 +02:00
else
{
menuItem . title = NSLocalizedString ( @ "Start Encoding" , @ "Queue -> start/stop menu" ) ;
return self . queue . canEncode ;
}
2015-01-22 10:30:26 +00:00
}
2025-06-07 09:26:10 +02:00
else if ( action = = @ selector ( togglePauseResume : ) )
2015-01-22 10:30:26 +00:00
{
2019-07-19 21:17:27 +02:00
if ( self . queue . canPause )
2015-01-22 10:30:26 +00:00
{
2018-06-09 10:06:52 +02:00
menuItem . title = NSLocalizedString ( @ "Pause Encoding" , @ "Queue -> pause/resume menu" ) ;
2015-01-22 10:30:26 +00:00
}
else
{
2018-06-09 10:06:52 +02:00
menuItem . title = NSLocalizedString ( @ "Resume Encoding" , @ "Queue -> pause/resume men" ) ;
2015-01-22 10:30:26 +00:00
}
2019-07-19 21:17:27 +02:00
return self . queue . canPause || self . queue . canResume ;
2015-07-22 07:46:07 +00:00
}
2025-06-07 09:26:10 +02:00
else if ( action = = @ selector ( toggleDetails : ) )
{
NSSplitViewItem * detailsItem = self . splitViewController . splitViewItems [ 1 ] ;
if ( detailsItem . isCollapsed )
{
menuItem . title = NSLocalizedString ( @ "Show Sidebar" , @ "Queue -> sidebar menu" ) ;
}
else
{
menuItem . title = NSLocalizedString ( @ "Hide Sidebar" , @ "Queue -> sidebar menu" ) ;
}
return YES ;
}
else if ( action = = @ selector ( removeAll : ) || action = = @ selector ( resetAll : ) )
2019-07-20 10:15:19 +02:00
{
return self . queue . items . count > 0 ;
}
2025-06-07 09:26:10 +02:00
else if ( action = = @ selector ( resetFailed : ) )
2019-07-20 10:15:19 +02:00
{
return self . queue . failedItemsCount > 0 ;
}
2025-06-07 09:26:10 +02:00
else if ( action = = @ selector ( removeCompleted : ) )
2019-07-20 10:15:19 +02:00
{
return self . queue . completedItemsCount > 0 ;
}
2015-01-22 10:30:26 +00:00
return YES ;
}
2018-10-08 16:27:16 +02:00
- ( BOOL ) validateUserIterfaceItemForAction : ( SEL ) action
2007-10-09 15:15:16 +00:00
{
2019-07-29 07:34:38 +02:00
if ( action = = @ selector ( toggleStartCancel : ) || action = = @ selector ( _touchBar _toggleStartCancel : ) )
2015-01-19 08:48:18 +00:00
{
2019-07-19 21:17:27 +02:00
return self . queue . isEncoding || self . queue . canEncode ;
2015-01-19 08:48:18 +00:00
}
2025-06-07 09:26:10 +02:00
else if ( action = = @ selector ( togglePauseResume : ) )
2015-01-19 08:48:18 +00:00
{
2019-07-19 21:17:27 +02:00
return self . queue . canPause || self . queue . canResume ;
2015-01-19 08:48:18 +00:00
}
2025-06-07 09:26:10 +02:00
else if ( action = = @ selector ( toggleDetails : ) ||
2024-03-02 08:47:58 +01:00
action = = @ selector ( toggleQuickLook : ) )
{
return YES ;
}
2015-01-19 08:48:18 +00:00
return NO ;
}
2018-10-08 16:27:16 +02:00
- ( BOOL ) validateToolbarItem : ( NSToolbarItem * ) theItem
{
2024-03-02 08:47:58 +01:00
return [ self validateUserIterfaceItemForAction : theItem . action ] ;
2018-10-08 16:27:16 +02:00
}
2015-10-19 17:57:49 +02:00
# pragma mark - Private queue editing methods
/ * *
2019-07-19 21:17:27 +02:00
* Delete encodes from the queue window and accompanying array
* Also handling first cancelling the encode if in fact its currently encoding .
2015-10-19 17:57:49 +02:00
* /
2015-07-22 07:46:07 +00:00
- ( void ) removeQueueItemsAtIndexes : ( NSIndexSet * ) indexes
{
2019-07-19 21:17:27 +02:00
if ( indexes . count )
2015-10-19 17:57:49 +02:00
{
2019-07-19 21:17:27 +02:00
NSMutableIndexSet * mutableIndexes = [ indexes mutableCopy ] ;
// 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
2020-09-12 11:27:19 +02:00
NSIndexSet * workingIndexes = [ self . queue . items HB_indexesOfObjectsUsingBlock : ^ BOOL ( HBQueueJobItem * item ) {
2019-07-19 21:17:27 +02:00
return item . state = = HBQueueItemStateWorking ;
} ] ;
2017-05-31 11:53:59 +02:00
2020-09-12 11:27:19 +02:00
NSIndexSet * workingSelectedIndexes = [ workingIndexes HB_intersectionWith : indexes ] ;
2020-04-11 12:19:17 +02:00
[ mutableIndexes removeIndexes : workingSelectedIndexes ] ;
if ( workingSelectedIndexes . count )
2017-05-31 11:53:59 +02:00
{
2020-04-11 12:19:17 +02:00
NSString * alertTitle = [ NSString stringWithFormat : NSLocalizedString ( @ "Stop This Encode and Remove It?" , @ "Queue Stop Alert -> stop and remove message" ) ] ;
2017-05-31 11:53:59 +02:00
2020-04-11 12:19:17 +02:00
// Which window to attach the sheet to ?
NSWindow * targetWindow = self . window ;
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert setMessageText : alertTitle ] ;
[ alert setInformativeText : NSLocalizedString ( @ "Your movie will be lost if you don't continue encoding." , @ "Queue Stop Alert -> stop and remove informative text" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Keep Encoding" , @ "Queue Stop Alert -> stop and remove first button" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Stop Encoding and Delete" , @ "Queue Stop Alert -> stop and remove second button" ) ] ;
2020-08-03 16:33:02 +02:00
if ( @ available ( macOS 11 , * ) )
2020-06-27 14:13:12 +02:00
{
alert . buttons . lastObject . hasDestructiveAction = true ;
}
2020-04-11 12:19:17 +02:00
[ alert setAlertStyle : NSAlertStyleCritical ] ;
[ alert beginSheetModalForWindow : targetWindow completionHandler : ^ ( NSModalResponse returnCode ) {
if ( returnCode = = NSAlertSecondButtonReturn )
{
[ self . queue cancelItemsAtIndexes : workingSelectedIndexes ] ;
[ self . queue removeItemsAtIndexes : workingSelectedIndexes ] ;
}
} ] ;
2015-10-19 17:57:49 +02:00
}
2015-01-19 08:48:18 +00:00
2019-07-19 21:17:27 +02:00
// remove the non working items immediately
2019-07-20 10:15:19 +02:00
[ self . queue removeItemsAtIndexes : mutableIndexes ] ;
2016-07-29 12:42:46 +02:00
}
2007-10-09 15:15:16 +00:00
}
2020-09-11 18:02:23 +02:00
- ( void ) doEditQueueItem : ( HBQueueJobItem * ) item
2015-01-19 08:48:18 +00:00
{
2020-05-08 13:11:47 +02:00
[ self . queue prepareItemForEditingAtIndex : [ self . queue . items indexOfObject : item ] ] ;
2015-01-19 08:48:18 +00:00
2019-07-29 07:34:38 +02:00
[ self . delegate openJob : [ item . job copy ] completionHandler : ^ ( BOOL result ) {
2020-05-08 13:11:47 +02:00
NSInteger index = [ self . queue . items indexOfObject : item ] ;
2021-01-30 21:48:49 +01:00
if ( index ! = NSNotFound )
2019-07-29 07:34:38 +02:00
{
2021-01-30 21:48:49 +01:00
[ self . queue resetItemsAtIndexes : [ NSIndexSet indexSetWithIndex : index ] ] ;
if ( result )
{
// Now that source is loaded and settings applied , delete the queue item from the queue
[ self . queue removeItemsAtIndexes : [ NSIndexSet indexSetWithIndex : index ] ] ;
}
else
{
NSBeep ( ) ;
}
2019-07-29 07:34:38 +02:00
}
else
{
2021-01-30 21:48:49 +01:00
item . state = HBQueueItemStateReady ;
2019-07-29 07:34:38 +02:00
}
} ] ;
2007-10-09 15:15:16 +00:00
}
2015-01-19 08:48:18 +00:00
/ * *
2019-07-19 21:17:27 +02:00
* Send the selected queue item back to the main window for rescan and possible edit .
2015-01-19 08:48:18 +00:00
* /
2020-09-11 18:02:23 +02:00
- ( void ) editQueueItem : ( HBQueueJobItem * ) item
2015-01-20 08:37:00 +00:00
{
2019-07-19 21:17:27 +02:00
// 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
2020-04-11 12:19:17 +02:00
if ( item . state = = HBQueueItemStateWorking )
2015-01-20 08:37:00 +00:00
{
2019-07-19 21:17:27 +02:00
NSString * alertTitle = [ NSString stringWithFormat : NSLocalizedString ( @ "Stop This Encode and Edit It?" , @ "Queue Edit Alert -> stop and edit message" ) ] ;
2015-01-20 08:37:00 +00:00
2019-07-19 21:17:27 +02:00
// Which window to attach the sheet to ?
NSWindow * docWindow = self . window ;
2007-09-14 04:42:46 +00:00
2019-07-19 21:17:27 +02:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert setMessageText : alertTitle ] ;
[ alert setInformativeText : NSLocalizedString ( @ "Your movie will be lost if you don't continue encoding." , @ "Queue Edit Alert -> stop and edit informative text" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Keep Encoding" , @ "Queue Edit Alert -> stop and edit first button" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Stop Encoding and Edit" , @ "Queue Edit Alert -> stop and edit second button" ) ] ;
2020-08-03 16:33:02 +02:00
if ( @ available ( macOS 11 , * ) )
2020-06-27 14:13:12 +02:00
{
alert . buttons . lastObject . hasDestructiveAction = true ;
}
2019-07-19 21:17:27 +02:00
[ alert setAlertStyle : NSAlertStyleCritical ] ;
[ alert beginSheetModalForWindow : docWindow completionHandler : ^ ( NSModalResponse returnCode ) {
if ( returnCode = = NSAlertSecondButtonReturn )
{
[ self doEditQueueItem : item ] ;
}
} ] ;
}
2020-05-08 13:11:47 +02:00
else if ( item . state ! = HBQueueItemStateWorking && item . state ! = HBQueueItemStateRescanning )
2019-07-19 21:17:27 +02:00
{
[ self doEditQueueItem : item ] ;
}
2008-01-09 05:45:36 +00:00
}
2019-07-27 13:15:37 +02:00
- ( void ) resetQueueItemsAtIndexes : ( NSIndexSet * ) indexes
{
[ self . queue resetItemsAtIndexes : indexes ] ;
}
2015-01-19 08:48:18 +00:00
# pragma mark - Encode Done Actions
2007-09-07 13:40:40 +00:00
2019-07-25 08:10:15 +02:00
NSString * const HBQueueItemNotificationPathKey = @ "HBQueueItemNotificationPathKey" ;
2024-09-14 08:14:29 +02:00
NSString * const HBQueueItemNotificationShowAction = @ "HBQueueItemNotificationShowAction" ;
NSString * const HBQueueItemNotificationShowCategory = @ "HBQueueItemNotificationShowCategory" ;
2019-07-25 08:10:15 +02:00
2024-09-14 08:14:29 +02:00
- ( void ) showInFinder : ( NSString * ) path
2016-09-07 12:07:09 +02:00
{
2018-06-08 16:59:25 +02:00
if ( [ path isKindOfClass : [ NSString class ] ] && path . length )
2016-09-07 12:07:09 +02:00
{
2018-06-08 16:59:25 +02:00
NSURL * fileURL = [ NSURL fileURLWithPath : path ] ;
2020-04-06 13:56:00 +02:00
[ NSWorkspace . sharedWorkspace activateFileViewerSelectingURLs : @ [ fileURL ] ] ;
2016-09-07 12:07:09 +02:00
}
2015-01-19 08:48:18 +00:00
}
2007-09-07 13:40:40 +00:00
2024-09-14 08:14:29 +02:00
- ( void ) userNotificationCenter : ( NSUserNotificationCenter * ) center didActivateNotification : ( NSUserNotification * ) notification
2018-06-08 16:59:25 +02:00
{
2024-09-14 08:14:29 +02:00
// Show the file in Finder when a done notification is clicked
NSString * path = notification . userInfo [ HBQueueItemNotificationPathKey ] ;
[ self showInFinder : path ] ;
}
- ( void ) userNotificationCenter : ( UNUserNotificationCenter * ) center didReceiveNotificationResponse : ( UNNotificationResponse * ) response withCompletionHandler : ( void ( ^ ) ( void ) ) completionHandler API_AVAILABLE ( macos ( 10.14 ) )
{
NSString * path = response . notification . request . content . userInfo [ HBQueueItemNotificationPathKey ] ;
[ self showInFinder : path ] ;
completionHandler ( ) ;
}
2024-06-19 11:37:53 +02:00
2024-09-14 08:14:29 +02:00
- ( void ) showNotificationWithTitle : ( NSString * ) title description : ( NSString * ) description url : ( NSURL * ) fileURL playSound : ( BOOL ) playSound
{
2025-03-11 08:03:00 +01:00
if ( @ available ( macOS 10.15 , * ) )
2024-02-07 11:39:21 +01:00
{
2024-09-14 08:14:29 +02:00
UNMutableNotificationContent * notification = [ [ UNMutableNotificationContent alloc ] init ] ;
notification . title = title ;
notification . body = description ;
notification . sound = playSound ? UNNotificationSound . defaultSound : nil ;
if ( fileURL )
{
notification . categoryIdentifier = HBQueueItemNotificationShowCategory ;
notification . userInfo = @ { HBQueueItemNotificationPathKey : fileURL . path } ;
}
UNNotificationRequest * request = [ UNNotificationRequest requestWithIdentifier : [ NSUUID UUID ] . UUIDString
content : notification
trigger : nil ] ;
[ UNUserNotificationCenter . currentNotificationCenter addNotificationRequest : request withCompletionHandler : NULL ] ;
2024-02-07 11:39:21 +01:00
}
2024-06-19 11:37:53 +02:00
else
{
2024-09-14 08:14:29 +02:00
NSUserNotification * notification = [ [ NSUserNotification alloc ] init ] ;
notification . title = title ;
notification . informativeText = description ;
notification . soundName = playSound ? NSUserNotificationDefaultSoundName : nil ;
2019-07-19 21:17:27 +02:00
2024-09-14 08:14:29 +02:00
if ( fileURL )
{
notification . hasActionButton = YES ;
notification . actionButtonTitle = NSLocalizedString ( @ "Show" , @ "Notification -> Show in Finder" ) ;
notification . userInfo = @ { HBQueueItemNotificationPathKey : fileURL . path } ;
}
else
{
notification . hasActionButton = NO ;
}
[ NSUserNotificationCenter . defaultUserNotificationCenter deliverNotification : notification ] ;
}
2018-06-08 16:59:25 +02:00
}
2015-10-19 17:57:49 +02:00
/ * *
* Sends the URL to the external app
* selected in the preferences .
*
2017-01-20 18:52:22 +01:00
* @ param job the job of the file to send
2015-10-19 17:57:49 +02:00
* /
2020-09-11 18:02:23 +02:00
- ( void ) sendToExternalApp : ( HBQueueJobItem * ) item
2015-01-19 08:48:18 +00:00
{
// This end of encode action is called as each encode rolls off of the queue
2019-07-29 07:34:38 +02:00
if ( [ NSUserDefaults . standardUserDefaults boolForKey : HBSendToAppEnabled ] = = YES )
2007-09-07 13:40:40 +00:00
{
2022-01-11 09:18:47 +01:00
NSURL * destinationFolderURL = item . destinationFolderURL ;
2022-01-11 09:36:11 +01:00
NSString * destinationPath = item . destinationURL . path ;
2020-03-30 14:23:34 +02:00
dispatch_async ( _sendQueue , ^ {
2017-01-20 18:52:22 +01:00
# ifdef __SANDBOX _ENABLED __
2022-01-11 09:18:47 +01:00
BOOL accessingSecurityScopedResource = [ destinationFolderURL startAccessingSecurityScopedResource ] ;
2017-01-20 18:52:22 +01:00
# endif
2020-03-30 14:23:34 +02:00
NSWorkspace * workspace = NSWorkspace . sharedWorkspace ;
NSString * app = [ workspace fullPathForApplication : [ NSUserDefaults . standardUserDefaults objectForKey : HBSendToApp ] ] ;
2015-07-04 07:02:19 +00:00
2020-03-30 14:23:34 +02:00
if ( app )
2015-07-04 07:02:19 +00:00
{
2022-01-11 09:36:11 +01:00
if ( ! [ workspace openFile : destinationPath withApplication : app ] )
2020-03-30 14:23:34 +02:00
{
[ HBUtilities writeToActivityLog : "Failed to send file to: %s" , app ] ;
}
}
else
{
[ HBUtilities writeToActivityLog : "Send file to: app not found" ] ;
2015-07-04 07:02:19 +00:00
}
2017-01-20 18:52:22 +01:00
# ifdef __SANDBOX _ENABLED __
2020-03-30 14:23:34 +02:00
if ( accessingSecurityScopedResource )
{
2022-01-11 09:18:47 +01:00
[ destinationFolderURL stopAccessingSecurityScopedResource ] ;
2020-03-30 14:23:34 +02:00
}
2017-01-20 18:52:22 +01:00
# endif
2020-03-30 14:23:34 +02:00
} ) ;
2015-01-19 08:48:18 +00:00
}
}
2015-10-19 17:57:49 +02:00
/ * *
* Runs the alert for a single job
* /
2020-09-11 18:02:23 +02:00
- ( void ) itemCompletedAlerts : ( HBQueueJobItem * ) item
2015-07-22 07:46:07 +00:00
{
2019-07-19 21:17:27 +02:00
NSUserDefaults * ud = NSUserDefaults . standardUserDefaults ;
2024-02-07 11:39:21 +01:00
if ( [ ud boolForKey : HBQueueNotificationWhenJobDone ] )
2015-07-22 07:46:07 +00:00
{
2016-09-07 12:18:03 +02:00
NSString * title ;
NSString * description ;
2019-07-19 21:17:27 +02:00
if ( item . state = = HBQueueItemStateCompleted )
2016-09-07 12:18:03 +02:00
{
2018-06-09 11:12:21 +02:00
title = NSLocalizedString ( @ "Put down that cocktail…" , @ "Queue notification alert message" ) ;
2018-06-09 10:06:52 +02:00
description = [ NSString stringWithFormat : NSLocalizedString ( @ "Your encode %@ is done!" , @ "Queue done notification message" ) ,
2022-01-11 09:18:47 +01:00
item . destinationFileName ] ;
2016-09-07 12:18:03 +02:00
}
else
{
2018-06-09 11:12:21 +02:00
title = NSLocalizedString ( @ "Encode failed" , @ "Queue done notification failed message" ) ;
2018-06-09 10:06:52 +02:00
description = [ NSString stringWithFormat : NSLocalizedString ( @ "Your encode %@ couldn't be completed." , @ "Queue done notification message" ) ,
2022-01-11 09:18:47 +01:00
item . destinationFileName ] ;
2016-09-07 12:18:03 +02:00
}
2024-02-07 11:39:21 +01:00
bool playSound = [ ud boolForKey : HBQueueNotificationPlaySound ] ;
2016-09-07 12:18:03 +02:00
[ self showNotificationWithTitle : title
2016-09-07 12:07:09 +02:00
description : description
2022-01-11 09:18:47 +01:00
url : item . destinationURL
2019-07-29 07:34:38 +02:00
playSound : playSound ] ;
2015-07-22 07:46:07 +00:00
}
2024-04-12 16:33:54 +02:00
if ( [ ud boolForKey : HBQueueAutoClearCompletedItems ] )
{
[ self . queue removeCompletedItems ] ;
}
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
{
2019-07-19 21:17:27 +02:00
NSUserDefaults * ud = NSUserDefaults . standardUserDefaults ;
2015-01-19 08:48:18 +00:00
2024-02-07 11:39:21 +01:00
if ( [ ud boolForKey : HBQueueNotificationWhenDone ] )
2015-01-19 08:48:18 +00:00
{
2024-02-07 11:39:21 +01:00
bool playSound = [ ud boolForKey : HBQueueNotificationPlaySound ] ;
[ self showNotificationWithTitle : NSLocalizedString ( @ "Put down that cocktail…" , @ "Queue notification alert message" )
description : NSLocalizedString ( @ "Your queue is done!" , @ "Queue done notification message" )
url : nil
playSound : playSound ] ;
2015-01-19 08:48:18 +00:00
}
// If sleep has been selected
2024-02-07 11:39:21 +01:00
if ( [ ud integerForKey : HBQueueDoneAction ] = = HBDoneActionSleep )
2015-01-19 08:48:18 +00:00
{
// Sleep
2024-02-07 11:39:21 +01:00
NSAppleScript * scriptObject = [ [ NSAppleScript alloc ] initWithSource : @ "tell application \" System Events \ " to sleep" ] ;
2019-07-29 07:34:38 +02:00
[ scriptObject executeAndReturnError : NULL ] ;
2015-01-19 08:48:18 +00:00
}
2019-07-29 07:34:38 +02:00
2015-01-19 08:48:18 +00:00
// If Shutdown has been selected
2024-02-07 11:39:21 +01:00
if ( [ ud integerForKey : HBQueueDoneAction ] = = HBDoneActionShutDown )
2015-01-19 08:48:18 +00:00
{
// Shut Down
2019-06-08 17:46:01 +02:00
NSAppleScript * scriptObject = [ [ NSAppleScript alloc ] initWithSource : @ "tell application \" System Events \ " to shut down" ] ;
2019-07-29 07:34:38 +02:00
[ scriptObject executeAndReturnError : NULL ] ;
2015-01-19 08:48:18 +00:00
}
2022-03-16 20:06:23 +01:00
// If Quit HB has been selected
2024-02-07 11:39:21 +01:00
if ( [ ud integerForKey : HBQueueDoneAction ] = = HBDoneActionQuit )
2022-03-16 20:06:23 +01:00
{
[ NSApp terminate : self ] ;
}
2015-01-19 08:48:18 +00:00
}
2016-09-07 12:50:54 +02:00
- ( void ) queueLowDiskSpaceAlert
{
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
2018-06-09 10:06:52 +02:00
[ alert setMessageText : NSLocalizedString ( @ "Your destination disk is almost full." , @ "Queue -> disk almost full alert message" ) ] ;
[ alert setInformativeText : NSLocalizedString ( @ "You need to make more space available on your destination disk." , @ "Queue -> disk almost full alert informative text" ) ] ;
2016-09-07 12:50:54 +02:00
[ NSApp requestUserAttention : NSCriticalRequest ] ;
[ alert runModal ] ;
}
2015-01-19 08:48:18 +00:00
- ( void ) remindUserOfSleepOrShutdown
{
2019-07-19 21:17:27 +02:00
NSUserDefaults * ud = NSUserDefaults . standardUserDefaults ;
2024-02-07 11:39:21 +01:00
if ( [ ud integerForKey : HBQueueDoneAction ] = = 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 ] ;
2018-06-09 10:06:52 +02:00
[ alert setMessageText : NSLocalizedString ( @ "The computer will sleep after encoding is done." , @ "Queue Done Alert -> sleep message" ) ] ;
[ alert setInformativeText : NSLocalizedString ( @ "You have selected to sleep the computer after encoding. To turn off sleeping, go to the HandBrake preferences." , @ "Queue Done Alert -> sleep informative text" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , @ "Queue Done Alert -> sleep first button" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Preferences…" , @ "Queue Done Alert -> sleep second button" ) ] ;
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
}
2019-06-08 17:46:01 +02:00
[ self promptForAppleEventAuthorization ] ;
2015-01-19 08:48:18 +00:00
}
2024-02-07 11:39:21 +01:00
else if ( [ ud integerForKey : HBQueueDoneAction ] = = 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 ] ;
2018-06-09 10:06:52 +02:00
[ alert setMessageText : NSLocalizedString ( @ "The computer will shut down after encoding is done." , @ "Queue Done Alert -> shut down message" ) ] ;
[ alert setInformativeText : NSLocalizedString ( @ "You have selected to shut down the computer after encoding. To turn off shut down, go to the HandBrake preferences." , @ "Queue Done Alert -> shut down informative text" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , @ "Queue Done Alert -> shut down first button" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Preferences…" , @ "Queue Done Alert -> shut down second button" ) ] ;
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
}
2019-06-08 17:46:01 +02:00
[ self promptForAppleEventAuthorization ] ;
}
}
- ( void ) promptForAppleEventAuthorization
{
HBPrivacyConsentState result = [ HBUtilities determinePermissionToAutomateTarget : @ "com.apple.systemevents" promptIfNeeded : YES ] ;
if ( result ! = HBPrivacyConsentStateGranted )
{
[ HBUtilities writeToActivityLog : "Failed to get permission to automate system events" ] ;
2007-10-09 15:15:16 +00:00
}
2008-09-16 20:57:13 +00:00
}
2019-07-19 21:17:27 +02:00
# pragma mark - UI Actions
2015-01-19 08:48:18 +00:00
/ * *
* Rip : puts up an alert before ultimately calling doRip
* /
2019-07-19 21:17:27 +02:00
- ( IBAction ) toggleStartCancel : ( id ) sender
2015-01-19 08:48:18 +00:00
{
// Rip or Cancel ?
2019-07-19 21:17:27 +02:00
if ( self . queue . isEncoding )
2015-01-19 08:48:18 +00:00
{
2015-01-20 08:05:16 +00:00
[ self cancelRip : sender ] ;
2015-01-19 08:48:18 +00:00
}
2019-02-07 19:11:51 +01:00
// If there are pending items in the queue , then this is a rip the queue
2019-07-19 21:17:27 +02:00
else if ( self . queue . canEncode )
2015-01-19 08:48:18 +00:00
{
// 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 ] ;
2019-07-19 21:17:27 +02:00
[ self . queue start ] ;
2015-01-19 08:48:18 +00:00
}
2014-11-23 12:56:03 +00:00
}
2015-01-19 08:48:18 +00:00
/ * *
2019-07-19 21:17:27 +02:00
* Starts or cancels the processing of items depending on the current state
2019-02-07 19:11:51 +01:00
* Displays an alert asking user if the want to cancel encoding of current item .
2015-01-19 08:48:18 +00:00
* /
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 ] ;
2018-06-09 10:06:52 +02:00
[ alert setMessageText : NSLocalizedString ( @ "You are currently encoding. What would you like to do?" , @ "Queue Alert -> cancel rip message" ) ] ;
2018-09-04 03:07:51 -04:00
[ alert setInformativeText : NSLocalizedString ( @ "Select Continue Encoding to dismiss this dialog without making changes." , @ "Queue Alert -> cancel rip informative text" ) ] ;
2018-06-09 10:06:52 +02:00
[ alert addButtonWithTitle : NSLocalizedString ( @ "Continue Encoding" , @ "Queue Alert -> cancel rip first button" ) ] ;
2018-09-04 03:07:51 -04:00
[ alert addButtonWithTitle : NSLocalizedString ( @ "Skip Current Job" , @ "Queue Alert -> cancel rip second button" ) ] ;
2020-08-03 16:33:02 +02:00
if ( @ available ( macOS 11 , * ) )
{
2024-03-02 08:47:58 +01:00
alert . buttons . lastObject . hasDestructiveAction = YES ;
2020-08-03 16:33:02 +02:00
}
2018-09-04 03:07:51 -04:00
[ alert addButtonWithTitle : NSLocalizedString ( @ "Stop After Current Job" , @ "Queue Alert -> cancel rip third button" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Stop All" , @ "Queue Alert -> cancel rip fourth button" ) ] ;
2020-08-03 16:33:02 +02:00
if ( @ available ( macOS 11 , * ) )
{
2024-03-02 08:47:58 +01:00
alert . buttons . lastObject . hasDestructiveAction = YES ;
2020-08-03 16:33:02 +02:00
}
2018-06-10 09:12:18 +02:00
[ alert setAlertStyle : NSAlertStyleCritical ] ;
2015-01-19 08:48:18 +00:00
2018-06-08 16:59:25 +02:00
[ alert beginSheetModalForWindow : window completionHandler : ^ ( NSModalResponse returnCode ) {
if ( returnCode = = NSAlertSecondButtonReturn )
{
2020-04-11 12:19:17 +02:00
[ self . queue cancelCurrentAndContinue ] ;
2018-06-08 16:59:25 +02:00
}
else if ( returnCode = = NSAlertThirdButtonReturn )
{
2019-07-19 21:17:27 +02:00
[ self . queue finishCurrentAndStop ] ;
2018-06-08 16:59:25 +02:00
}
else if ( returnCode = = NSAlertThirdButtonReturn + 1 )
{
2020-04-11 12:19:17 +02:00
[ self . queue cancelCurrentAndStop ] ;
2018-06-08 16:59:25 +02:00
}
} ] ;
2007-09-07 13:40:40 +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
{
2019-07-19 21:17:27 +02:00
if ( self . queue . canResume )
2009-02-12 21:08:41 +00:00
{
2019-07-19 21:17:27 +02:00
[ self . queue resume ] ;
2009-02-12 21:08:41 +00:00
}
2019-07-19 21:17:27 +02:00
else if ( self . queue . canPause )
2009-02-12 21:08:41 +00:00
{
2019-07-19 21:17:27 +02:00
[ self . queue pause ] ;
2009-02-12 21:08:41 +00:00
}
2007-09-05 20:01:14 +00:00
}
2019-07-19 21:17:27 +02:00
- ( IBAction ) toggleDetails : ( id ) sender
2015-07-22 07:46:07 +00:00
{
2019-07-19 21:17:27 +02:00
NSSplitViewItem * detailsItem = self . splitViewController . splitViewItems [ 1 ] ;
detailsItem . animator . collapsed = ! detailsItem . isCollapsed ;
2015-10-19 17:57:49 +02:00
}
2022-01-11 09:22:48 +01:00
- ( IBAction ) toggleQuickLook : ( id ) sender
{
if ( QLPreviewPanel . sharedPreviewPanelExists && QLPreviewPanel . sharedPreviewPanel . isVisible )
{
[ QLPreviewPanel . sharedPreviewPanel orderOut : sender ] ;
}
else
{
[ QLPreviewPanel . sharedPreviewPanel makeKeyAndOrderFront : sender ] ;
}
}
2019-07-19 21:17:27 +02:00
# pragma mark - table view controller delegate
2015-07-22 07:46:07 +00:00
2019-07-27 13:15:37 +02:00
- ( void ) tableViewDidSelectItemsAtIndexes : ( NSIndexSet * ) indexes
2010-01-21 18:58:17 +00:00
{
2019-07-27 13:15:37 +02:00
NSUInteger count = indexes . count ;
if ( count ! = 1 )
{
self . multiSelectionViewController . count = count ;
[ self switchToViewController : self . multiSelectionViewController ] ;
}
else
{
2020-09-11 18:02:23 +02:00
NSArray < id < HBQueueItem > > * items = [ self . queue . items objectsAtIndexes : indexes ] ;
2019-07-27 13:15:37 +02:00
self . infoViewController . item = items . firstObject ;
[ self switchToViewController : self . infoViewController ] ;
}
}
- ( void ) switchToViewController : ( NSViewController * ) viewController
{
NSViewController * firstChild = self . containerViewController . childViewControllers . firstObject ;
if ( firstChild ! = viewController )
{
if ( firstChild )
{
[ firstChild . view removeFromSuperviewWithoutNeedingDisplay ] ;
[ firstChild removeFromParentViewController ] ;
}
2019-11-01 21:34:54 +01:00
2019-07-27 13:15:37 +02:00
[ self . containerViewController addChildViewController : viewController ] ;
viewController . view . frame = self . containerViewController . view . bounds ;
viewController . view . autoresizingMask = NSViewWidthSizable | NSViewHeightSizable ;
[ self . containerViewController . view addSubview : viewController . view ] ;
}
2015-07-22 07:46:07 +00:00
}
2020-09-11 18:02:23 +02:00
- ( void ) tableViewEditItem : ( id < HBQueueItem > ) item
2015-02-02 11:12:54 +00:00
{
2020-09-11 18:02:23 +02:00
if ( [ item isKindOfClass : [ HBQueueJobItem class ] ] )
{
[ self editQueueItem : item ] ;
}
2015-02-02 11:12:54 +00:00
}
2019-07-27 13:15:37 +02:00
- ( void ) tableViewRemoveItemsAtIndexes : ( nonnull NSIndexSet * ) indexes
{
2015-10-19 17:57:49 +02:00
[ self removeQueueItemsAtIndexes : indexes ] ;
2007-09-11 15:03:01 +00:00
}
2019-07-27 13:15:37 +02:00
- ( void ) tableViewResetItemsAtIndexes : ( nonnull NSIndexSet * ) indexes {
[ self resetQueueItemsAtIndexes : indexes ] ;
2007-09-17 14:46:36 +00:00
}
2020-09-11 18:02:23 +02:00
- ( void ) detailsViewEditItem : ( nonnull id < HBQueueItem > ) item
2019-07-27 13:15:37 +02:00
{
2020-09-11 18:02:23 +02:00
if ( [ item isKindOfClass : [ HBQueueJobItem class ] ] )
{
[ self editQueueItem : item ] ;
}
2019-02-05 14:03:27 +01:00
}
2007-09-24 15:22:24 +00:00
2020-09-11 18:02:23 +02:00
- ( void ) detailsViewResetItem : ( nonnull id < HBQueueItem > ) item
2019-07-27 13:15:37 +02:00
{
2020-09-11 18:02:23 +02:00
if ( [ item isKindOfClass : [ HBQueueJobItem class ] ] )
{
NSUInteger index = [ self . queue . items indexOfObject : item ] ;
[ self resetQueueItemsAtIndexes : [ NSIndexSet indexSetWithIndex : index ] ] ;
}
2019-07-27 13:15:37 +02:00
}
2019-07-19 21:17:27 +02:00
- ( IBAction ) resetAll : ( id ) sender
2007-09-24 15:22:24 +00:00
{
2019-07-19 21:17:27 +02:00
[ self . queue resetAllItems ] ;
2019-02-05 14:03:27 +01:00
}
2019-07-19 21:17:27 +02:00
- ( IBAction ) resetFailed : ( id ) sender
2019-02-05 14:03:27 +01:00
{
2019-07-19 21:17:27 +02:00
[ self . queue resetFailedItems ] ;
2007-09-24 15:22:24 +00:00
}
2019-07-19 21:17:27 +02:00
- ( IBAction ) removeAll : ( id ) sender
2007-09-24 15:22:24 +00:00
{
2019-07-19 21:17:27 +02:00
[ self . queue removeNotWorkingItems ] ;
2007-09-24 15:22:24 +00:00
}
2019-07-19 21:17:27 +02:00
- ( IBAction ) removeCompleted : ( id ) sender
2007-09-24 15:22:24 +00:00
{
2019-07-19 21:17:27 +02:00
[ self . queue removeCompletedItems ] ;
2007-09-24 15:22:24 +00:00
}
2007-09-11 15:03:01 +00:00
2007-09-05 20:01:14 +00:00
@ end
2018-10-08 16:27:16 +02:00
@ implementation HBQueueController ( TouchBar )
2018-10-10 19:58:21 +02:00
@ dynamic touchBar ;
2018-10-08 16:27:16 +02:00
static NSTouchBarItemIdentifier HBTouchBarMain = @ "fr.handbrake.queueWindowTouchBar" ;
static NSTouchBarItemIdentifier HBTouchBarRip = @ "fr.handbrake.rip" ;
static NSTouchBarItemIdentifier HBTouchBarPause = @ "fr.handbrake.pause" ;
- ( NSTouchBar * ) makeTouchBar
{
NSTouchBar * bar = [ [ NSTouchBar alloc ] init ] ;
bar . delegate = self ;
bar . defaultItemIdentifiers = @ [ HBTouchBarRip , HBTouchBarPause ] ;
bar . customizationIdentifier = HBTouchBarMain ;
bar . customizationAllowedItemIdentifiers = @ [ HBTouchBarRip , HBTouchBarPause ] ;
return bar ;
}
2019-07-29 07:34:38 +02:00
- ( IBAction ) _touchBar _toggleStartCancel : ( id ) sender
{
[ self toggleStartCancel : self ] ;
}
2018-10-08 16:27:16 +02:00
- ( NSTouchBarItem * ) touchBar : ( NSTouchBar * ) touchBar makeItemForIdentifier : ( NSTouchBarItemIdentifier ) identifier
{
if ( [ identifier isEqualTo : HBTouchBarRip ] )
{
NSCustomTouchBarItem * item = [ [ NSCustomTouchBarItem alloc ] initWithIdentifier : identifier ] ;
2018-10-10 19:58:21 +02:00
item . customizationLabel = NSLocalizedString ( @ "Start/Stop Encoding" , @ "Touch bar" ) ;
2018-10-08 16:27:16 +02:00
2019-07-29 07:34:38 +02:00
NSButton * button = [ NSButton buttonWithImage : [ NSImage imageNamed : NSImageNameTouchBarPlayTemplate ] target : self action : @ selector ( _touchBar _toggleStartCancel : ) ] ;
2018-10-08 16:27:16 +02:00
item . view = button ;
return item ;
}
else if ( [ identifier isEqualTo : HBTouchBarPause ] )
{
NSCustomTouchBarItem * item = [ [ NSCustomTouchBarItem alloc ] initWithIdentifier : identifier ] ;
2018-10-10 19:58:21 +02:00
item . customizationLabel = NSLocalizedString ( @ "Pause/Resume Encoding" , @ "Touch bar" ) ;
2018-10-08 16:27:16 +02:00
NSButton * button = [ NSButton buttonWithImage : [ NSImage imageNamed : NSImageNameTouchBarPauseTemplate ] target : self action : @ selector ( togglePauseResume : ) ] ;
item . view = button ;
return item ;
}
return nil ;
}
2019-08-12 10:19:00 +02:00
- ( void ) _touchBar _updateButtonsState
2018-10-08 16:27:16 +02:00
{
NSButton * ripButton = ( NSButton * ) [ [ self . touchBar itemForIdentifier : HBTouchBarRip ] view ] ;
NSButton * pauseButton = ( NSButton * ) [ [ self . touchBar itemForIdentifier : HBTouchBarPause ] view ] ;
2019-07-19 21:17:27 +02:00
if ( self . queue . isEncoding )
2018-10-08 16:27:16 +02:00
{
ripButton . image = [ NSImage imageNamed : NSImageNameTouchBarRecordStopTemplate ] ;
}
2019-07-19 21:17:27 +02:00
else
{
ripButton . image = [ NSImage imageNamed : NSImageNameTouchBarPlayTemplate ] ;
}
if ( self . queue . canResume )
2018-10-08 16:27:16 +02:00
{
pauseButton . image = [ NSImage imageNamed : NSImageNameTouchBarPlayTemplate ] ;
}
2019-07-19 21:17:27 +02:00
else
2018-10-08 16:27:16 +02:00
{
pauseButton . image = [ NSImage imageNamed : NSImageNameTouchBarPauseTemplate ] ;
}
}
2018-10-10 19:58:21 +02:00
- ( void ) _touchBar _validateUserInterfaceItems
2018-10-08 16:27:16 +02:00
{
for ( NSTouchBarItemIdentifier identifier in self . touchBar . itemIdentifiers ) {
NSTouchBarItem * item = [ self . touchBar itemForIdentifier : identifier ] ;
NSView * view = item . view ;
if ( [ view isKindOfClass : [ NSButton class ] ] ) {
NSButton * button = ( NSButton * ) view ;
BOOL enabled = [ self validateUserIterfaceItemForAction : button . action ] ;
button . enabled = enabled ;
}
}
}
@ end