From a3fb08633e62775c251886aa6dff15e5f91f60e4 Mon Sep 17 00:00:00 2001 From: Damiano Galassi Date: Mon, 8 Oct 2018 16:27:16 +0200 Subject: [PATCH] MacGui: add touch bars to main and queue windows. --- macosx/Base.lproj/HBFiltersViewController.xib | 26 +- macosx/Base.lproj/HBPictureViewController.xib | 28 +- macosx/Base.lproj/MainWindow.xib | 73 ++-- macosx/Base.lproj/Queue.xib | 6 +- macosx/Base.lproj/Video.xib | 8 +- macosx/HBAppDelegate.m | 4 + macosx/HBController.m | 369 +++++++++++++----- macosx/HBCore.m | 5 +- macosx/HBQueueController.m | 174 ++++++++- 9 files changed, 517 insertions(+), 176 deletions(-) diff --git a/macosx/Base.lproj/HBFiltersViewController.xib b/macosx/Base.lproj/HBFiltersViewController.xib index 073c58741..aa4f8668d 100644 --- a/macosx/Base.lproj/HBFiltersViewController.xib +++ b/macosx/Base.lproj/HBFiltersViewController.xib @@ -1,8 +1,8 @@ - + - + @@ -71,7 +71,7 @@ - + Custom Detelecine parameters. @@ -213,7 +213,7 @@ Decomb switches between multiple interpolation algorithms for speed and quality. - + Custom Deinterlace parameters. @@ -296,7 +296,7 @@ Bob attempts to better preserve motion for a slight penalty to perceived resolut - + @@ -320,7 +320,7 @@ Bob attempts to better preserve motion for a slight penalty to perceived resolut - + @@ -568,7 +571,7 @@ Blu-ray and DVD sources often have multiple titles, the longest of which is typi - + @@ -595,7 +598,7 @@ Blu-ray and DVD sources often have multiple titles, the longest of which is typi - + @@ -611,7 +614,7 @@ Blu-ray and DVD sources often have multiple titles, the longest of which is typi - + @@ -622,7 +625,7 @@ Blu-ray and DVD sources often have multiple titles, the longest of which is typi - + diff --git a/macosx/Base.lproj/Queue.xib b/macosx/Base.lproj/Queue.xib index 8c1906e35..b850fc152 100644 --- a/macosx/Base.lproj/Queue.xib +++ b/macosx/Base.lproj/Queue.xib @@ -1,8 +1,8 @@ - + - + @@ -10,7 +10,9 @@ + + diff --git a/macosx/Base.lproj/Video.xib b/macosx/Base.lproj/Video.xib index 4fc9f01f5..c2b1c556a 100644 --- a/macosx/Base.lproj/Video.xib +++ b/macosx/Base.lproj/Video.xib @@ -1,8 +1,8 @@ - + - + @@ -38,7 +38,7 @@ - + @@ -592,7 +592,7 @@ This setting is no longer supported and may be removed in a future version. Use - + diff --git a/macosx/HBAppDelegate.m b/macosx/HBAppDelegate.m index 72e3f3656..e4d78e6fb 100644 --- a/macosx/HBAppDelegate.m +++ b/macosx/HBAppDelegate.m @@ -79,6 +79,10 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { + if (@available (macOS 10.12.2, *)) + { + NSApplication.sharedApplication.automaticCustomizeTouchBarMenuItemEnabled = YES; + } self.presetsMenuBuilder = [[HBPresetsMenuBuilder alloc] initWithMenu:self.presetsMenu action:@selector(selectPresetFromMenu:) diff --git a/macosx/HBController.m b/macosx/HBController.m index fd4b054c7..62330608d 100644 --- a/macosx/HBController.m +++ b/macosx/HBController.m @@ -34,6 +34,10 @@ @import HandBrakeKit; +static void *HBControllerContext = &HBControllerContext; +static void *HBControllerScanCoreContext = &HBControllerScanCoreContext; +static void *HBControllerQueueCoreContext = &HBControllerQueueCoreContext; + @interface HBController () { IBOutlet NSTabView *fMainTabView; @@ -69,9 +73,6 @@ // Picture Preview HBPreviewController * fPreviewController; - // Queue panel - HBQueueController * fQueueController; - // Source box IBOutlet NSProgressIndicator * fScanIndicator; IBOutlet NSBox * fScanHorizontalLine; @@ -123,6 +124,9 @@ /// The HBCore used for scanning. @property (nonatomic, strong) HBCore *core; +/// The queue controller. +@property (nonatomic, strong) HBQueueController *queue; + /// Whether the window is visible or occluded, /// useful to avoid updating the UI needlessly @property (nonatomic) BOOL visible; @@ -136,6 +140,16 @@ // Alerts @property (nonatomic) BOOL suppressCopyProtectionWarning; +@property (nonatomic) IBOutlet NSToolbarItem *openSourceToolbarItem; +@property (nonatomic) IBOutlet NSToolbarItem *ripToolbarItem; +@property (nonatomic) IBOutlet NSToolbarItem *pauseToolbarItem; + +@end + +@interface HBController (TouchBar) +- (void)updateButtonsStateForScanCore:(HBState)state; +- (void)updateButtonsStateForQueueCore:(HBState)state; +- (void)validateTouchBarsItems; @end #define WINDOW_HEIGHT_OFFSET_INIT 48 @@ -156,8 +170,8 @@ fPreviewController = [[HBPreviewController alloc] init]; fPreviewController.documentController = self; - fQueueController = queueController; - fQueueController.controller = self; + _queue = queueController; + _queue.controller = self; presetManager = manager; _currentPreset = manager.defaultPreset; @@ -263,8 +277,19 @@ [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.HBShowAdvancedTab" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial - context:NULL]; + context:HBControllerContext]; + + [self.core addObserver:self forKeyPath:@"state" + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial + context:HBControllerScanCoreContext]; + [self.queue.core addObserver:self forKeyPath:@"state" + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial + context:HBControllerQueueCoreContext]; + + [self.queue addObserver:self forKeyPath:@"pendingItemsCount" + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial + context:HBControllerQueueCoreContext]; self.presetsMenuBuilder = [[HBPresetsMenuBuilder alloc] initWithMenu:self.presetsPopup.menu action:@selector(selectPresetFromMenu:) @@ -320,26 +345,89 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - if ([keyPath isEqualToString:@"values.HBShowAdvancedTab"]) + if (context == HBControllerContext && [keyPath isEqualToString:@"values.HBShowAdvancedTab"]) { - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HBShowAdvancedTab"]) + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HBShowAdvancedTab"] && ![[fMainTabView tabViewItems] containsObject:fAdvancedTab]) { - if (![[fMainTabView tabViewItems] containsObject:fAdvancedTab]) - { - [fMainTabView insertTabViewItem:fAdvancedTab atIndex:5]; - } + [fMainTabView insertTabViewItem:fAdvancedTab atIndex:5]; } else { [fMainTabView removeTabViewItem:fAdvancedTab]; } } + else if (context == HBControllerScanCoreContext) + { + HBState state = [change[NSKeyValueChangeNewKey] intValue]; + [self updateToolbarButtonsStateForScanCore:state]; + if (@available(macOS 10.12.2, *)) + { + [self updateButtonsStateForScanCore:state]; + [self validateTouchBarsItems]; + } + } + else if (context == HBControllerQueueCoreContext) + { + HBState state = self.queue.core.state; + [self updateToolbarButtonsStateForQueueCore:state]; + [self.window.toolbar validateVisibleItems]; + if (@available(macOS 10.12.2, *)) + { + [self updateButtonsStateForQueueCore:state]; + [self validateTouchBarsItems]; + } + } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } +- (void)updateToolbarButtonsStateForScanCore:(HBState)state +{ + if (state == HBStateIdle) + { + _openSourceToolbarItem.image = [NSImage imageNamed: @"source"]; + _openSourceToolbarItem.label = NSLocalizedString(@"Open Source", @"Toolbar Open/Cancel Item"); + _openSourceToolbarItem.toolTip = NSLocalizedString(@"Open Source", @"Toolbar Open/Cancel Item"); + } + else + { + _openSourceToolbarItem.image = [NSImage imageNamed: @"stopencode"]; + _openSourceToolbarItem.label = NSLocalizedString(@"Cancel Scan", @"Toolbar Open/Cancel Item"); + _openSourceToolbarItem.toolTip = NSLocalizedString(@"Cancel Scanning Source", @"Toolbar Open/Cancel Item"); + } +} + +- (void)updateToolbarButtonsStateForQueueCore:(HBState)state +{ + if (state == HBStatePaused) + { + _pauseToolbarItem.image = [NSImage imageNamed: @"encode"]; + _pauseToolbarItem.label = NSLocalizedString(@"Resume", @"Toolbar Pause Item"); + _pauseToolbarItem.toolTip = NSLocalizedString(@"Resume Encoding", @"Toolbar Pause Item"); + } + else + { + _pauseToolbarItem.image = [NSImage imageNamed:@"pauseencode"]; + _pauseToolbarItem.label = NSLocalizedString(@"Pause", @"Toolbar Pause Item"); + _pauseToolbarItem.toolTip = NSLocalizedString(@"Pause Encoding", @"Toolbar Pause Item"); + + } + if (state == HBStateScanning || state == HBStateWorking || state == HBStateSearching || state == HBStateMuxing || state == HBStatePaused) + { + _ripToolbarItem.image = [NSImage imageNamed:@"stopencode"]; + _ripToolbarItem.label = NSLocalizedString(@"Stop", @"Toolbar Start/Stop Item"); + _ripToolbarItem.toolTip = NSLocalizedString(@"Stop Encoding", @"Toolbar Start/Stop Item"); + } + else + { + _ripToolbarItem.image = [NSImage imageNamed: @"encode"]; + _ripToolbarItem.label = _queue.pendingItemsCount > 0 ? NSLocalizedString(@"Start Queue", @"Toolbar Start/Stop Item") : NSLocalizedString(@"Start", @"Toolbar Start/Stop Item"); + _pauseToolbarItem.toolTip = NSLocalizedString(@"Start Encoding", @"Toolbar Start/Stop Item"); + } +} + - (void)enableUI:(BOOL)enabled { if (enabled) @@ -364,91 +452,47 @@ #pragma mark - UI Validation -- (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem +- (BOOL)validateUserIterfaceItemForAction:(SEL)action { - SEL action = toolbarItem.action; - if (self.core.state == HBStateScanning) { if (action == @selector(browseSources:)) { - [toolbarItem setImage: [NSImage imageNamed: @"stopencode"]]; - [toolbarItem setLabel: NSLocalizedString(@"Cancel Scan", @"Toolbar Open/Cancel Item")]; - [toolbarItem setPaletteLabel: NSLocalizedString(@"Cancel Scanning", @"Toolbar Open/Cancel Item")]; - [toolbarItem setToolTip: NSLocalizedString(@"Cancel Scanning Source", @"Toolbar Open/Cancel Item")]; return YES; } - if (action == @selector(rip:) || action == @selector(addToQueue:)) + { return NO; + } } - else + else if (action == @selector(browseSources:)) { - if (action == @selector(browseSources:)) - { - [toolbarItem setImage:[NSImage imageNamed:@"source"]]; - [toolbarItem setLabel:NSLocalizedString(@"Open Source", @"Toolbar Open/Cancel Item")]; - [toolbarItem setPaletteLabel:NSLocalizedString(@"Open Source", @"Toolbar Open/Cancel Item")]; - [toolbarItem setToolTip:NSLocalizedString(@"Open Source", @"Toolbar Open/Cancel Item")]; - return YES; - } + return YES; } - HBState queueState = fQueueController.core.state; + HBState queueState = _queue.core.state; - if (queueState == HBStateScanning || queueState == HBStateWorking || queueState == HBStateSearching || queueState == HBStateMuxing) + if (action == @selector(rip:)) { - if (action == @selector(rip:)) + if (queueState == HBStateScanning || queueState == HBStateWorking || queueState == HBStateSearching || + queueState == HBStateMuxing || queueState == HBStatePaused) { - [toolbarItem setImage: [NSImage imageNamed: @"stopencode"]]; - [toolbarItem setLabel: NSLocalizedString(@"Stop", @"Toolbar Start/Stop Item")]; - [toolbarItem setPaletteLabel: NSLocalizedString(@"Stop", @"Toolbar Start/Stop Item")]; - [toolbarItem setToolTip: NSLocalizedString(@"Stop Encoding", @"Toolbar Start/Stop Item")]; return YES; } - if (action == @selector(pause:)) - { - [toolbarItem setImage: [NSImage imageNamed: @"pauseencode"]]; - [toolbarItem setLabel: NSLocalizedString(@"Pause", @"Toolbar Pause Item")]; - [toolbarItem setPaletteLabel: NSLocalizedString(@"Pause Encoding", @"Pause Item")]; - [toolbarItem setToolTip: NSLocalizedString(@"Pause Encoding", @"Toolbar Pause Item")]; - return YES; - } - } - else if (queueState == HBStatePaused) - { - if (action == @selector(pause:)) + else { - [toolbarItem setImage: [NSImage imageNamed: @"encode"]]; - [toolbarItem setLabel: NSLocalizedString(@"Resume", @"Toolbar Pause Item")]; - [toolbarItem setPaletteLabel: NSLocalizedString(@"Resume Encoding", @"Toolbar Pause Item")]; - [toolbarItem setToolTip: NSLocalizedString(@"Resume Encoding", @"Toolbar Pause Item")]; - return YES; + return (self.job != nil || _queue.pendingItemsCount > 0); } - if (action == @selector(rip:)) - return YES; } - else - { - if (action == @selector(rip:)) - { - [toolbarItem setImage: [NSImage imageNamed: @"encode"]]; - if (fQueueController.pendingItemsCount > 0) - [toolbarItem setLabel: NSLocalizedString(@"Start Queue", @"Toolbar Start/Stop Item")]; - else - [toolbarItem setLabel: NSLocalizedString(@"Start", @"Toolbar Start/Stop Item")]; - [toolbarItem setPaletteLabel: NSLocalizedString(@"Start Encoding", @"Toolbar Start/Stop Item")]; - [toolbarItem setToolTip: NSLocalizedString(@"Start Encoding", @"Toolbar Start/Stop Item")]; - } - if (action == @selector(rip:)) + if (action == @selector(pause:)) { + if (queueState == HBStatePaused) { - return (self.job != nil || fQueueController.pendingItemsCount > 0); + return YES; } - - if (action == @selector(pause:)) + else { - return NO; + return (queueState == HBStateWorking || queueState == HBStateMuxing); } } @@ -460,6 +504,11 @@ return YES; } +- (BOOL)validateUserInterfaceItem:(id )anItem +{ + return [self validateUserIterfaceItemForAction:anItem.action]; +} + - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { SEL action = menuItem.action; @@ -475,11 +524,11 @@ } if (action == @selector(pause:)) { - return [fQueueController validateMenuItem:menuItem]; + return [_queue validateMenuItem:menuItem]; } if (action == @selector(rip:)) { - BOOL result = [fQueueController validateMenuItem:menuItem]; + BOOL result = [_queue validateMenuItem:menuItem]; if ([menuItem.title isEqualToString:NSLocalizedString(@"Start Encoding", @"Menu Start/Stop Item")]) { @@ -646,6 +695,10 @@ completionHandler(self.core.titles); [self.window.toolbar validateVisibleItems]; + if (@available(macOS 10.12.2, *)) + { + [self validateTouchBarsItems]; + } }]; } else @@ -1038,9 +1091,6 @@ self.bottomConstrain.animator.constant = -WINDOW_HEIGHT_OFFSET; fRipIndicator.hidden = YES; fRipIndicatorShown = NO; - - // Refresh the toolbar buttons - [self.window.toolbar validateVisibleItems]; } } else @@ -1052,9 +1102,6 @@ self.bottomConstrain.animator.constant = 0; fRipIndicatorShown = YES; fRipIndicator.hidden = NO; - - // Refresh the toolbar buttons - [self.window.toolbar validateVisibleItems]; } } } @@ -1094,7 +1141,7 @@ [alert beginSheetModalForWindow:self.window completionHandler:handler]; } - else if ([fQueueController jobExistAtURL:job.completeOutputURL]) + else if ([_queue jobExistAtURL:job.completeOutputURL]) { NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:NSLocalizedString(@"There is already a queue item for this destination.", @"File already exists in queue alert -> message")]; @@ -1116,7 +1163,7 @@ */ - (void)doAddToQueue { - [fQueueController addJob:[self.job copy]]; + [_queue addJob:[self.job copy]]; } /** @@ -1139,12 +1186,12 @@ { // if there are no jobs in the queue, then add this one to the queue and rip // otherwise, just rip the queue - if (fQueueController.pendingItemsCount == 0) + if (_queue.pendingItemsCount == 0) { [self doAddToQueue]; } - [fQueueController rip:self]; + [_queue rip:self]; } /** @@ -1153,15 +1200,15 @@ - (IBAction)rip:(id)sender { // Rip or Cancel ? - if (fQueueController.core.state == HBStateWorking || fQueueController.core.state == HBStatePaused || fQueueController.core.state == HBStateSearching) + if (_queue.core.state == HBStateWorking || _queue.core.state == HBStatePaused || _queue.core.state == HBStateSearching) { // Displays an alert asking user if the want to cancel encoding of current job. - [fQueueController cancelRip:self]; + [_queue cancelRip:self]; } // If there are pending jobs in the queue, then this is a rip the queue - else if (fQueueController.pendingItemsCount > 0) + else if (_queue.pendingItemsCount > 0) { - [fQueueController rip:self]; + [_queue rip:self]; } else { @@ -1179,7 +1226,7 @@ - (IBAction)pause:(id)sender { - [fQueueController togglePauseResume:sender]; + [_queue togglePauseResume:sender]; } #pragma mark - @@ -1234,7 +1281,7 @@ [destinations addObject:job.completeOutputURL]; } - if ([[NSFileManager defaultManager] fileExistsAtPath:job.completeOutputURL.path] || [fQueueController jobExistAtURL:job.completeOutputURL]) + if ([[NSFileManager defaultManager] fileExistsAtPath:job.completeOutputURL.path] || [_queue jobExistAtURL:job.completeOutputURL]) { fileExists = YES; break; @@ -1269,13 +1316,13 @@ [alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) { if (returnCode == NSAlertSecondButtonReturn) { - [self->fQueueController addJobsFromArray:jobs]; + [self->_queue addJobsFromArray:jobs]; } }]; } else { - [fQueueController addJobsFromArray:jobs]; + [_queue addJobsFromArray:jobs]; } } @@ -1491,3 +1538,141 @@ } @end + +@implementation HBController (TouchBar) + +static NSTouchBarItemIdentifier HBTouchBarMain = @"fr.handbrake.mainWindowTouchBar"; + +static NSTouchBarItemIdentifier HBTouchBarOpen = @"fr.handbrake.openSource"; +static NSTouchBarItemIdentifier HBTouchBarAddToQueue = @"fr.handbrake.addToQueue"; +static NSTouchBarItemIdentifier HBTouchBarRip = @"fr.handbrake.rip"; +static NSTouchBarItemIdentifier HBTouchBarPause = @"fr.handbrake.pause"; +static NSTouchBarItemIdentifier HBTouchBarPreview = @"fr.handbrake.preview"; + +- (NSTouchBar *)makeTouchBar +{ + NSTouchBar *bar = [[NSTouchBar alloc] init]; + bar.delegate = self; + + bar.defaultItemIdentifiers = @[HBTouchBarOpen, NSTouchBarItemIdentifierFixedSpaceSmall, HBTouchBarAddToQueue, NSTouchBarItemIdentifierFixedSpaceLarge, HBTouchBarRip, HBTouchBarPause, NSTouchBarItemIdentifierFixedSpaceLarge, HBTouchBarPreview]; + + bar.customizationIdentifier = HBTouchBarMain; + bar.customizationAllowedItemIdentifiers = @[HBTouchBarOpen, HBTouchBarAddToQueue, HBTouchBarRip, HBTouchBarPause, HBTouchBarPreview]; + + return bar; +} + +- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier +{ + if ([identifier isEqualTo:HBTouchBarOpen]) + { + NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; + item.customizationLabel = NSLocalizedString(@"Open Source", @"Touch bar"); + + NSButton *button = [NSButton buttonWithTitle:NSLocalizedString(@"Open Source", @"Touch bar") target:self action:@selector(browseSources:)]; + + item.view = button; + return item; + } + else if ([identifier isEqualTo:HBTouchBarAddToQueue]) + { + NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; + item.customizationLabel = NSLocalizedString(@"Add to Queue", @"Touch bar"); + + NSButton *button = [NSButton buttonWithTitle:NSLocalizedString(@"Add to Queue", @"Touch bar") target:self action:@selector(addToQueue:)]; + + item.view = button; + return item; + } + else if ([identifier isEqualTo:HBTouchBarRip]) + { + NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; + item.customizationLabel = NSLocalizedString(@"Rip", @"Touch bar"); + + NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarPlayTemplate] target:self action:@selector(rip:)]; + + item.view = button; + return item; + } + else if ([identifier isEqualTo:HBTouchBarPause]) + { + NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; + item.customizationLabel = NSLocalizedString(@"Pause", @"Touch bar"); + + NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarPauseTemplate] target:self action:@selector(pause:)]; + + item.view = button; + return item; + } + else if ([identifier isEqualTo:HBTouchBarPreview]) + { + NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; + item.customizationLabel = NSLocalizedString(@"Show Preview", @"Touch bar"); + + NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarQuickLookTemplate] target:self action:@selector(showPreviewWindow:)]; + + item.view = button; + return item; + } + + return nil; +} + +- (void)updateButtonsStateForScanCore:(HBState)state +{ + NSButton *openButton = (NSButton *)[[self.touchBar itemForIdentifier:HBTouchBarOpen] view]; + + NSButton *addToQueueButton = (NSButton *)[[self.touchBar itemForIdentifier:HBTouchBarAddToQueue] view]; + NSButton *previewButton = (NSButton *)[[self.touchBar itemForIdentifier:HBTouchBarPreview] view]; + + if (state == HBStateIdle) + { + openButton.title = NSLocalizedString(@"Open Source", @"Touch bar"); + addToQueueButton.enabled = NO; + previewButton.enabled = NO; + } + else + { + openButton.title = NSLocalizedString(@"Cancel scan", @"Touch bar"); + addToQueueButton.enabled = YES; + } +} + +- (void)updateButtonsStateForQueueCore:(HBState)state; +{ + NSButton *ripButton = (NSButton *)[[self.touchBar itemForIdentifier:HBTouchBarRip] view]; + NSButton *pauseButton = (NSButton *)[[self.touchBar itemForIdentifier:HBTouchBarPause] view]; + + if (state == HBStateScanning || state == HBStateWorking || state == HBStateSearching || state == HBStateMuxing) + { + ripButton.image = [NSImage imageNamed:NSImageNameTouchBarRecordStopTemplate]; + pauseButton.image = [NSImage imageNamed:NSImageNameTouchBarPauseTemplate]; + } + else if (state == HBStatePaused) + { + ripButton.image = [NSImage imageNamed:NSImageNameTouchBarRecordStopTemplate]; + pauseButton.image = [NSImage imageNamed:NSImageNameTouchBarPlayTemplate]; + } + else if (state == HBStateIdle) + { + ripButton.image = [NSImage imageNamed:NSImageNameTouchBarPlayTemplate]; + pauseButton.image = [NSImage imageNamed:NSImageNameTouchBarPauseTemplate]; + } +} + +- (void)validateTouchBarsItems +{ + 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; + } + } +} + +@dynamic touchBar; + +@end diff --git a/macosx/HBCore.m b/macosx/HBCore.m index b2252183d..de9a26941 100644 --- a/macosx/HBCore.m +++ b/macosx/HBCore.m @@ -546,7 +546,10 @@ typedef void (^HBCoreCleanupHandler)(void); } // Update HBCore state to reflect the current state of libhb - self.state = _hb_state->state; + if (_state != _hb_state->state) + { + self.state = _hb_state->state; + } // Call the handler for the current state if (_hb_state->state == HB_STATE_WORKDONE || _hb_state->state == HB_STATE_SCANDONE) diff --git a/macosx/HBQueueController.m b/macosx/HBQueueController.m index 519aef569..78df3bcb4 100644 --- a/macosx/HBQueueController.m +++ b/macosx/HBQueueController.m @@ -28,6 +28,8 @@ // DockTile update frequency in total percent increment #define dockTileUpdateFrequency 0.1f +static void *HBControllerQueueCoreContext = &HBControllerQueueCoreContext; + @interface HBQueueController () /// Whether the window is visible or occluded, @@ -44,6 +46,9 @@ @property (unsafe_unretained) IBOutlet NSTextField *countTextField; @property (unsafe_unretained) IBOutlet HBQueueOutlineView *outlineView; +@property (nonatomic) IBOutlet NSToolbarItem *ripToolbarItem; +@property (nonatomic) IBOutlet NSToolbarItem *pauseToolbarItem; + @property (nonatomic, readonly) NSMutableDictionary *descriptions; @property (nonatomic, readonly) HBDistributedArray *jobs; @@ -59,6 +64,11 @@ @end +@interface HBQueueController (TouchBar) +- (void)updateButtonsStateForQueueCore:(HBState)state; +- (void)validateTouchBarsItems; +@end + @implementation HBQueueController - (instancetype)initWithURL:(NSURL *)queueURL; @@ -106,10 +116,65 @@ [self.outlineView setVerticalMotionCanBeginDrag:YES]; [self updateQueueStats]; + + [self.core addObserver:self forKeyPath:@"state" + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial + context:HBControllerQueueCoreContext]; + [self addObserver:self forKeyPath:@"pendingItemsCount" + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial + context:HBControllerQueueCoreContext]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if (context == HBControllerQueueCoreContext) + { + HBState state = self.core.state; + [self updateToolbarButtonsStateForQueueCore:state]; + [self.window.toolbar validateVisibleItems]; + if (@available(macOS 10.12.2, *)) + { + [self updateButtonsStateForQueueCore:state]; + [self validateTouchBarsItems]; + } + } + else + { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } } #pragma mark Toolbar +- (void)updateToolbarButtonsStateForQueueCore:(HBState)state +{ + if (state == HBStatePaused) + { + _pauseToolbarItem.image = [NSImage imageNamed: @"encode"]; + _pauseToolbarItem.label = NSLocalizedString(@"Resume", @"Toolbar Pause Item"); + _pauseToolbarItem.toolTip = NSLocalizedString(@"Resume Encoding", @"Toolbar Pause Item"); + } + else + { + _pauseToolbarItem.image = [NSImage imageNamed:@"pauseencode"]; + _pauseToolbarItem.label = NSLocalizedString(@"Pause", @"Toolbar Pause Item"); + _pauseToolbarItem.toolTip = NSLocalizedString(@"Pause Encoding", @"Toolbar Pause Item"); + + } + if (state == HBStateScanning || state == HBStateWorking || state == HBStateSearching || state == HBStateMuxing || state == HBStatePaused) + { + _ripToolbarItem.image = [NSImage imageNamed:@"stopencode"]; + _ripToolbarItem.label = NSLocalizedString(@"Stop", @"Toolbar Start/Stop Item"); + _ripToolbarItem.toolTip = NSLocalizedString(@"Stop Encoding", @"Toolbar Start/Stop Item"); + } + else + { + _ripToolbarItem.image = [NSImage imageNamed: @"encode"]; + _ripToolbarItem.label = NSLocalizedString(@"Start", @"Toolbar Start/Stop Item"); + _pauseToolbarItem.toolTip = NSLocalizedString(@"Start Encoding", @"Toolbar Start/Stop Item"); + } +} + - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { SEL action = menuItem.action; @@ -169,25 +234,18 @@ return YES; } -- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem +- (BOOL)validateUserIterfaceItemForAction:(SEL)action { - SEL action = theItem.action; HBState s = self.core.state; if (action == @selector(toggleStartCancel:)) { if ((s == HBStateScanning) || (s == HBStatePaused) || (s == HBStateWorking) || (s == HBStateMuxing)) { - theItem.image = [NSImage imageNamed:@"stopencode"]; - theItem.label = NSLocalizedString(@"Stop", @"Queue Toolbar -> start/stop item title"); - theItem.toolTip = NSLocalizedString(@"Stop Encoding", @"Queue Toolbar -> start/stop item tooltip"); return YES; } else { - theItem.image = [NSImage imageNamed:@"encode"]; - theItem.label = NSLocalizedString(@"Start", @"Queue Toolbar -> start/stop item title"); - theItem.toolTip = NSLocalizedString(@"Start Encoding", @"Queue Toolbar -> start/stop item tooltip"); return (self.pendingItemsCount > 0); } } @@ -196,16 +254,10 @@ { if (s == HBStatePaused) { - theItem.image = [NSImage imageNamed:@"encode"]; - theItem.label = NSLocalizedString(@"Resume", @"Queue Toolbar -> pause/resume item title"); - theItem.toolTip = NSLocalizedString(@"Resume Encoding", @"Queue Toolbar -> pause/resume item tooltip"); return YES; } else { - theItem.image = [NSImage imageNamed:@"pauseencode"]; - theItem.label = NSLocalizedString(@"Pause", @"Queue Toolbar -> pause/resume item title"); - theItem.toolTip = NSLocalizedString(@"Pause Encoding", @"Queue Toolbar -> pause/resume item tooltip"); return (s == HBStateWorking || s == HBStateMuxing); } } @@ -213,6 +265,12 @@ return NO; } +- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem +{ + SEL action = theItem.action; + return [self validateUserIterfaceItemForAction:action]; +} + #pragma mark - Public methods - (void)addJob:(HBJob *)item @@ -1600,7 +1658,7 @@ #pragma mark NSOutlineView drag & drop -- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard +- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard { // Dragging is only allowed of the pending items. if ([items[0] state] != HBJobStateReady) @@ -1655,3 +1713,89 @@ } @end + +@implementation HBQueueController (TouchBar) + +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; +} + +- (NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier +{ + if ([identifier isEqualTo:HBTouchBarRip]) + { + NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; + item.customizationLabel = NSLocalizedString(@"Rip", @"Touch bar"); + + NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarPlayTemplate] target:self action:@selector(toggleStartCancel:)]; + + item.view = button; + return item; + } + else if ([identifier isEqualTo:HBTouchBarPause]) + { + NSCustomTouchBarItem *item = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; + item.customizationLabel = NSLocalizedString(@"Pause", @"Touch bar"); + + NSButton *button = [NSButton buttonWithImage:[NSImage imageNamed:NSImageNameTouchBarPauseTemplate] target:self action:@selector(togglePauseResume:)]; + + item.view = button; + return item; + } + + return nil; +} + +- (void)updateButtonsStateForQueueCore:(HBState)state; +{ + NSButton *ripButton = (NSButton *)[[self.touchBar itemForIdentifier:HBTouchBarRip] view]; + NSButton *pauseButton = (NSButton *)[[self.touchBar itemForIdentifier:HBTouchBarPause] view]; + + if (state == HBStateScanning || state == HBStateWorking || state == HBStateSearching || state == HBStateMuxing) + { + ripButton.image = [NSImage imageNamed:NSImageNameTouchBarRecordStopTemplate]; + pauseButton.image = [NSImage imageNamed:NSImageNameTouchBarPauseTemplate]; + } + else if (state == HBStatePaused) + { + ripButton.image = [NSImage imageNamed:NSImageNameTouchBarRecordStopTemplate]; + pauseButton.image = [NSImage imageNamed:NSImageNameTouchBarPlayTemplate]; + } + else if (state == HBStateIdle) + { + ripButton.image = [NSImage imageNamed:NSImageNameTouchBarPlayTemplate]; + pauseButton.image = [NSImage imageNamed:NSImageNameTouchBarPauseTemplate]; + } +} + +- (void)validateTouchBarsItems +{ + 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; + } + } +} + +@dynamic touchBar; + +@end + -- 2.40.0