2016-05-03 18:47:14 +02:00
/ * $ Id : HBPreviewController . m $
2009-01-12 00:07:38 +00:00
2013-11-04 07:09:50 +00:00
This file is part of the HandBrake source code .
Homepage : < http : // handbrake . fr / > .
It may be used under the terms of the GNU General Public License . * /
2009-01-12 00:07:38 +00:00
# import "HBPreviewController.h"
2013-11-04 07:09:50 +00:00
# import "HBPreviewGenerator.h"
2020-10-05 17:45:47 +02:00
# import "HBCroppingController.h"
2015-07-27 08:51:30 +00:00
2016-05-03 18:47:14 +02:00
# import "HBController.h"
2015-10-06 19:52:42 +02:00
# import "HBPreviewView.h"
2013-11-04 07:09:50 +00:00
2016-05-03 18:47:14 +02:00
# import "HBPlayer.h"
# import "HBAVPlayer.h"
2016-01-15 19:44:27 +01:00
2016-05-03 18:47:14 +02:00
# import "HBPictureHUDController.h"
# import "HBEncodingProgressHUDController.h"
# import "HBPlayerHUDController.h"
# import "NSWindow+HBAdditions.h"
2013-11-04 07:09:50 +00:00
2015-10-06 19:52:42 +02:00
# define ANIMATION_DUR 0.15
2016-05-03 18:47:14 +02:00
# define HUD_FADEOUT _TIME 4.0
2009-08-21 12:25:51 +00:00
2016-05-03 18:47:14 +02:00
// Make min width and height of preview window large enough for hud .
2014-08-22 17:59:21 +00:00
# define MIN_WIDTH 480.0
# define MIN_HEIGHT 360.0
2013-11-04 07:09:50 +00:00
2020-10-05 13:26:25 +02:00
@ interface HBPreviewController ( ) < NSMenuItemValidation , HBPreviewGeneratorDelegate , HBPictureHUDControllerDelegate , HBEncodingProgressHUDControllerDelegate , HBPlayerHUDControllerDelegate >
2013-11-04 07:09:50 +00:00
2016-05-03 18:47:14 +02:00
@ property ( nonatomic , readonly ) HBPictureHUDController * pictureHUD ;
@ property ( nonatomic , readonly ) HBEncodingProgressHUDController * encodingHUD ;
@ property ( nonatomic , readonly ) HBPlayerHUDController * playerHUD ;
2013-11-04 07:09:50 +00:00
2016-05-03 18:47:14 +02:00
@ property ( nonatomic , readwrite ) NSViewController < HBHUD > * currentHUD ;
2013-11-04 07:09:50 +00:00
2016-05-03 18:47:14 +02:00
@ property ( nonatomic ) NSTimer * hudTimer ;
@ property ( nonatomic ) BOOL mouseInWindow ;
2013-11-04 07:09:50 +00:00
2016-05-03 18:47:14 +02:00
@ property ( nonatomic ) id < HBPlayer > player ;
2013-11-04 07:09:50 +00:00
2020-10-05 17:45:47 +02:00
@ property ( nonatomic ) NSPopover * croppingPopover ;
2015-07-27 08:51:30 +00:00
2015-10-06 19:52:42 +02:00
@ property ( nonatomic ) NSPoint windowCenterPoint ;
2024-12-05 09:34:58 +01:00
2019-08-12 10:19:00 +02:00
@ property ( nonatomic , weak ) IBOutlet HBPreviewView * previewView ;
2024-12-05 09:34:58 +01:00
@ property ( nonatomic ) BOOL wantsDisplayLayer ;
2009-01-12 00:07:38 +00:00
@ end
2013-11-04 07:09:50 +00:00
@ implementation HBPreviewController
2009-01-12 00:07:38 +00:00
2015-04-07 16:14:30 +00:00
- ( instancetype ) init
2009-01-12 00:07:38 +00:00
{
2015-04-07 16:14:30 +00:00
self = [ super initWithWindowNibName : @ "PicturePreview" ] ;
2013-11-04 07:09:50 +00:00
return self ;
2009-01-12 00:07:38 +00:00
}
2015-03-17 13:56:21 +00:00
- ( void ) windowDidLoad
2009-01-12 00:07:38 +00:00
{
2022-01-04 08:46:11 +01:00
self . window . tabbingMode = NSWindowTabbingModeDisallowed ;
self . window . excludedFromWindowsMenu = YES ;
self . window . acceptsMouseMovedEvents = YES ;
self . window . contentView . wantsLayer = YES ;
2024-12-05 09:34:58 +01:00
self . wantsDisplayLayer = NO ;
2013-11-04 07:09:50 +00:00
2015-10-09 20:20:50 +02:00
// Read the window center position
// We need the center and we can ' t use the
// standard NSWindow autosave because we change
// the window size at startup .
2019-10-05 19:00:30 +02:00
NSString * centerString = [ NSUserDefaults . standardUserDefaults stringForKey : @ "HBPreviewWindowCenter" ] ;
2015-10-09 20:20:50 +02:00
if ( centerString . length )
{
NSPoint center = NSPointFromString ( centerString ) ;
self . windowCenterPoint = center ;
2019-10-05 19:00:30 +02:00
[ self . window HB_resizeToBestSizeForViewSize : NSMakeSize ( MIN_WIDTH , MIN_HEIGHT ) keepInScreenRect : YES centerPoint : center animate : NO ] ;
2015-10-09 20:20:50 +02:00
}
else
{
2016-05-03 18:47:14 +02:00
self . windowCenterPoint = [ self . window HB_centerPoint ] ;
2015-10-09 20:20:50 +02:00
}
2009-08-21 12:25:51 +00:00
2016-05-03 18:47:14 +02:00
_pictureHUD = [ [ HBPictureHUDController alloc ] init ] ;
self . pictureHUD . delegate = self ;
_encodingHUD = [ [ HBEncodingProgressHUDController alloc ] init ] ;
self . encodingHUD . delegate = self ;
_playerHUD = [ [ HBPlayerHUDController alloc ] init ] ;
self . playerHUD . delegate = self ;
2013-11-04 07:09:50 +00:00
2016-05-03 18:47:14 +02:00
[ self . window . contentView addSubview : self . pictureHUD . view ] ;
[ self . window . contentView addSubview : self . encodingHUD . view ] ;
[ self . window . contentView addSubview : self . playerHUD . view ] ;
2009-08-21 12:25:51 +00:00
2015-10-06 19:52:42 +02:00
// Relocate our hud origins .
2016-12-24 09:02:43 +01:00
CGPoint origin = CGPointMake ( floor ( ( self . window . frame . size . width - _pictureHUD . view . bounds . size . width ) / 2 ) , MIN_HEIGHT / 10 ) ;
2016-05-03 18:47:14 +02:00
[ self . pictureHUD . view setFrameOrigin : origin ] ;
[ self . encodingHUD . view setFrameOrigin : origin ] ;
[ self . playerHUD . view setFrameOrigin : origin ] ;
2013-02-01 16:58:48 +00:00
2016-05-03 18:47:14 +02:00
self . currentHUD = self . pictureHUD ;
self . currentHUD . view . hidden = YES ;
2013-02-01 16:58:48 +00:00
2016-05-03 18:47:14 +02:00
NSTrackingArea * trackingArea = [ [ NSTrackingArea alloc ] initWithRect : self . window . contentView . frame
options : NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways
owner : self
userInfo : nil ] ;
[ self . window . contentView addTrackingArea : trackingArea ] ;
2015-10-06 19:52:42 +02:00
}
2013-11-04 07:09:50 +00:00
2015-10-06 19:52:42 +02:00
- ( void ) dealloc
{
[ _hudTimer invalidate ] ;
2016-05-03 18:47:14 +02:00
_generator . delegate = nil ;
2015-10-06 19:52:42 +02:00
[ _generator cancel ] ;
2009-01-12 00:07:38 +00:00
}
2013-01-30 18:48:23 +00:00
2016-01-15 19:44:27 +01:00
- ( BOOL ) validateMenuItem : ( NSMenuItem * ) menuItem
{
SEL action = menuItem . action ;
if ( action = = @ selector ( selectPresetFromMenu : ) )
{
return [ self . documentController validateMenuItem : menuItem ] ;
}
return YES ;
}
- ( IBAction ) selectDefaultPreset : ( id ) sender
{
[ self . documentController selectDefaultPreset : sender ] ;
}
- ( NSUndoManager * ) windowWillReturnUndoManager : ( NSWindow * ) window
{
return self . documentController . window . undoManager ;
}
- ( IBAction ) selectPresetFromMenu : ( id ) sender
{
[ self . documentController selectPresetFromMenu : sender ] ;
}
2015-10-10 08:24:54 +02:00
- ( void ) setPicture : ( HBPicture * ) picture
{
_picture = picture ;
2020-10-05 17:45:47 +02:00
[ self . croppingPopover close ] ;
self . croppingPopover = nil ;
2015-10-10 08:24:54 +02:00
}
2015-02-04 11:18:25 +00:00
- ( void ) setGenerator : ( HBPreviewGenerator * ) generator
2009-01-12 00:07:38 +00:00
{
2015-02-04 11:18:25 +00:00
if ( _generator )
{
_generator . delegate = nil ;
[ _generator cancel ] ;
}
2013-11-04 07:09:50 +00:00
2015-03-17 13:56:21 +00:00
_generator = generator ;
2013-11-04 07:09:50 +00:00
2015-02-04 11:18:25 +00:00
if ( generator )
2013-11-04 07:09:50 +00:00
{
2015-02-04 11:18:25 +00:00
generator . delegate = self ;
2018-10-10 19:58:21 +02:00
self . pictureHUD . generator = generator ;
2013-11-04 07:09:50 +00:00
}
2015-04-07 16:14:30 +00:00
else
{
2015-10-10 08:24:54 +02:00
self . previewView . image = nil ;
2018-06-09 10:06:52 +02:00
self . window . title = NSLocalizedString ( @ "Preview" , @ "Preview -> window title" ) ;
2018-10-10 19:58:21 +02:00
self . pictureHUD . generator = nil ;
2015-04-07 16:14:30 +00:00
}
2019-10-05 19:00:30 +02:00
2016-05-19 13:44:52 +02:00
[ self switchStateToHUD : self . pictureHUD ] ;
2019-11-01 21:34:54 +01:00
2019-10-05 19:00:30 +02:00
if ( generator )
{
2024-04-12 16:33:54 +02:00
[ self resizeIfNeeded : NO ] ;
2019-10-05 19:00:30 +02:00
}
2009-01-12 00:07:38 +00:00
}
2015-10-06 19:52:42 +02:00
- ( void ) reloadPreviews
2009-01-12 00:07:38 +00:00
{
2015-02-04 11:18:25 +00:00
if ( self . generator )
2013-11-04 07:09:50 +00:00
{
2016-04-22 13:25:20 +02:00
[ self . generator cancel ] ;
2016-05-03 18:47:14 +02:00
[ self switchStateToHUD : self . pictureHUD ] ;
2024-04-12 16:33:54 +02:00
[ self resizeIfNeeded : NO ] ;
2013-11-04 07:09:50 +00:00
}
}
2013-02-01 16:58:48 +00:00
2015-10-06 19:52:42 +02:00
- ( void ) showWindow : ( id ) sender
2013-11-04 07:09:50 +00:00
{
2014-12-20 18:56:10 +00:00
[ super showWindow : sender ] ;
2016-05-03 18:47:14 +02:00
if ( self . currentHUD = = self . pictureHUD )
2014-12-20 18:56:10 +00:00
{
[ self reloadPreviews ] ;
}
2024-04-12 18:24:16 +02:00
2024-04-17 07:51:48 +02:00
if ( self . generator )
{
[ self showHud : self . currentHUD ] ;
}
2013-11-04 07:09:50 +00:00
}
2015-10-06 19:52:42 +02:00
- ( void ) windowWillClose : ( NSNotification * ) aNotification
2013-11-04 07:09:50 +00:00
{
2016-05-03 18:47:14 +02:00
if ( self . currentHUD = = self . encodingHUD )
2011-08-18 22:11:49 +00:00
{
2016-05-03 18:47:14 +02:00
[ self cancelEncoding ] ;
2013-11-04 07:09:50 +00:00
}
2016-05-03 18:47:14 +02:00
else if ( self . currentHUD = = self . playerHUD )
2013-11-04 07:09:50 +00:00
{
2016-05-03 18:47:14 +02:00
[ self . player pause ] ;
2011-08-18 22:11:49 +00:00
}
2013-02-01 16:58:48 +00:00
2013-12-03 17:01:56 +00:00
[ self . generator purgeImageCache ] ;
2009-01-12 00:07:38 +00:00
}
2019-10-05 19:00:30 +02:00
# pragma mark - Window sizing
2024-04-12 16:33:54 +02:00
- ( void ) resizeIfNeeded : ( BOOL ) forceResize
2019-10-05 19:00:30 +02:00
{
if ( ! ( self . window . styleMask & NSWindowStyleMaskFullScreen ) )
{
if ( self . previewView . fitToView )
{
[ self . window setFrame : self . window . screen . visibleFrame display : YES animate : YES ] ;
}
else
{
// Get the optimal view size for the image
NSSize windowSize = [ self . previewView optimalViewSizeForImageSize : self . generator . imageSize
minSize : NSMakeSize ( MIN_WIDTH , MIN_HEIGHT )
scaleFactor : self . window . backingScaleFactor ] ;
2024-04-12 16:33:54 +02:00
if ( forceResize ||
windowSize . width > self . window . contentView . frame . size . width ||
windowSize . height > self . window . contentView . frame . size . height )
{
// Scale the window to the image size
[ self . window HB_resizeToBestSizeForViewSize : windowSize keepInScreenRect : YES centerPoint : NSZeroPoint animate : self . window . isVisible ] ;
}
2019-10-05 19:00:30 +02:00
}
}
[ self updateSizeLabels ] ;
}
2015-10-06 19:52:42 +02:00
- ( void ) windowDidChangeBackingProperties : ( NSNotification * ) notification
2009-01-12 00:07:38 +00:00
{
2016-05-03 18:47:14 +02:00
NSWindow * theWindow = ( NSWindow * ) notification . object ;
2013-11-04 07:09:50 +00:00
2016-05-03 18:47:14 +02:00
CGFloat newBackingScaleFactor = theWindow . backingScaleFactor ;
2019-10-05 19:00:30 +02:00
CGFloat oldBackingScaleFactor = [ notification . userInfo [ NSBackingPropertyOldScaleFactorKey ] doubleValue ] ;
2013-11-04 07:09:50 +00:00
if ( newBackingScaleFactor ! = oldBackingScaleFactor )
2009-01-12 00:07:38 +00:00
{
2019-10-05 19:00:30 +02:00
// Scale factor changed , resize the preview window
2015-02-04 11:18:25 +00:00
if ( self . generator )
2015-10-06 19:52:42 +02:00
{
2024-04-12 16:33:54 +02:00
[ self resizeIfNeeded : NO ] ;
2015-10-06 19:52:42 +02:00
}
2013-02-01 16:58:48 +00:00
}
2009-01-12 00:07:38 +00:00
}
2015-10-06 19:52:42 +02:00
# pragma mark - Window sizing
- ( void ) windowDidMove : ( NSNotification * ) notification
{
if ( self . previewView . fitToView = = NO )
2009-01-12 00:07:38 +00:00
{
2016-05-03 18:47:14 +02:00
self . windowCenterPoint = [ self . window HB_centerPoint ] ;
2019-10-05 19:00:30 +02:00
[ NSUserDefaults . standardUserDefaults setObject : NSStringFromPoint ( self . windowCenterPoint ) forKey : @ "HBPreviewWindowCenter" ] ;
2009-01-12 00:07:38 +00:00
}
2015-10-06 19:52:42 +02:00
}
2013-11-04 07:09:50 +00:00
2015-10-06 19:52:42 +02:00
- ( void ) windowDidResize : ( NSNotification * ) notification
{
[ self updateSizeLabels ] ;
2019-10-05 19:00:30 +02:00
if ( self . currentHUD = = self . playerHUD )
{
[ CATransaction begin ] ;
CATransaction . disableActions = YES ;
self . player . layer . frame = self . previewView . pictureFrame ;
[ CATransaction commit ] ;
}
2013-11-04 07:09:50 +00:00
}
2015-10-06 19:52:42 +02:00
- ( void ) updateSizeLabels
{
if ( self . generator )
2013-11-04 07:09:50 +00:00
{
2015-10-06 19:52:42 +02:00
CGFloat scale = self . previewView . scale ;
NSMutableString * scaleString = [ NSMutableString string ] ;
if ( scale * 100.0 ! = 100 )
2013-11-04 07:09:50 +00:00
{
2019-10-05 19:00:30 +02:00
[ scaleString appendFormat : NSLocalizedString ( @ "(%.0f%% actual size)" , @ "Preview -> size info label" ) , floor ( scale * 100.0 ) ] ;
2013-11-04 07:09:50 +00:00
}
2015-10-06 19:52:42 +02:00
else
2013-11-04 07:09:50 +00:00
{
2018-06-09 10:06:52 +02:00
[ scaleString appendString : NSLocalizedString ( @ "(Actual size)" , @ "Preview -> size info label" ) ] ;
2015-10-06 19:52:42 +02:00
}
if ( self . previewView . fitToView = = YES )
{
2018-06-09 10:06:52 +02:00
[ scaleString appendString : NSLocalizedString ( @ " Scaled To Screen" , @ "Preview -> size info label" ) ] ;
2013-11-04 07:09:50 +00:00
}
2015-10-06 19:52:42 +02:00
// Set the info fields in the hud controller
2016-05-03 18:47:14 +02:00
self . pictureHUD . info = self . generator . info ;
self . pictureHUD . scale = scaleString ;
2015-10-06 19:52:42 +02:00
// Set the info field in the window title bar
2018-06-09 10:06:52 +02:00
self . window . title = [ NSString stringWithFormat : NSLocalizedString ( @ "Preview - %@ %@" , @ "Preview -> window title format" ) ,
2015-10-06 19:52:42 +02:00
self . generator . info , scaleString ] ;
}
2009-01-12 00:07:38 +00:00
}
2024-11-15 10:03:19 +01:00
- ( void ) setScaleToScreen : ( BOOL ) scaleToScreen
2019-10-05 19:00:30 +02:00
{
2024-11-15 10:03:19 +01:00
self . previewView . fitToView = scaleToScreen ;
2024-04-12 16:33:54 +02:00
[ self resizeIfNeeded : YES ] ;
2019-10-05 19:00:30 +02:00
}
2016-05-03 18:47:14 +02:00
# pragma mark - Hud State
2015-10-06 19:52:42 +02:00
2013-11-04 07:09:50 +00:00
/ * *
2016-05-03 18:47:14 +02:00
* Switch the preview controller to one of his hud mode :
2013-11-04 07:09:50 +00:00
* This methods is the only way to change the mode , do not try otherwise .
2016-05-03 18:47:14 +02:00
* @ param hud NSViewController < HBHUD > the hud to show
2013-11-04 07:09:50 +00:00
* /
2016-05-03 18:47:14 +02:00
- ( void ) switchStateToHUD : ( NSViewController < HBHUD > * ) hud
2013-11-04 07:09:50 +00:00
{
2016-05-03 18:47:14 +02:00
if ( self . currentHUD = = self . playerHUD )
{
[ self exitPlayerState ] ;
}
2013-11-04 07:09:50 +00:00
2016-05-03 18:47:14 +02:00
if ( hud = = self . pictureHUD )
{
[ self enterPictureState ] ;
}
else if ( hud = = self . encodingHUD )
{
[ self enterEncodingState ] ;
}
else if ( hud = = self . playerHUD )
{
[ self enterPlayerState ] ;
}
2013-11-04 07:09:50 +00:00
2024-04-12 18:24:16 +02:00
if ( self . generator && self . currentHUD ! = hud )
2019-10-05 19:00:30 +02:00
{
2024-04-12 18:24:16 +02:00
[ self showHud : hud ] ;
2016-05-03 18:47:14 +02:00
}
2019-11-01 21:34:54 +01:00
2016-05-03 18:47:14 +02:00
self . currentHUD = hud ;
}
2013-11-04 07:09:50 +00:00
2016-05-03 18:47:14 +02:00
# pragma mark - HUD Control Overlay
2013-11-04 07:09:50 +00:00
2016-05-03 18:47:14 +02:00
- ( void ) mouseEntered : ( NSEvent * ) theEvent
{
if ( self . generator )
{
2024-04-12 18:24:16 +02:00
[ self showHudWithAnimation : self . currentHUD ] ;
2016-05-03 18:47:14 +02:00
[ self startHudTimer ] ;
2013-11-04 07:09:50 +00:00
}
2016-05-03 18:47:14 +02:00
self . mouseInWindow = YES ;
2013-11-04 07:09:50 +00:00
}
2016-05-03 18:47:14 +02:00
- ( void ) mouseExited : ( NSEvent * ) theEvent
{
[ self hudTimerFired : nil ] ;
self . mouseInWindow = NO ;
}
2013-11-04 07:09:50 +00:00
2015-10-06 19:52:42 +02:00
- ( void ) mouseMoved : ( NSEvent * ) theEvent
2013-11-04 07:09:50 +00:00
{
[ super mouseMoved : theEvent ] ;
2016-05-03 18:47:14 +02:00
// Test for mouse location to show / hide hud controls
if ( self . generator && self . mouseInWindow )
2013-01-30 18:48:23 +00:00
{
2016-05-03 18:47:14 +02:00
NSPoint mouseLoc = theEvent . locationInWindow ;
2013-11-04 07:09:50 +00:00
2024-04-12 18:24:16 +02:00
if ( NSPointInRect ( mouseLoc , self . currentHUD . view . frame ) )
2013-11-04 07:09:50 +00:00
{
[ self stopHudTimer ] ;
}
2016-05-03 18:47:14 +02:00
else
2013-11-04 07:09:50 +00:00
{
2024-04-12 18:24:16 +02:00
[ self showHudWithAnimation : self . currentHUD ] ;
2013-11-04 07:09:50 +00:00
[ self startHudTimer ] ;
}
}
}
2024-04-12 18:24:16 +02:00
- ( void ) showHud : ( NSViewController < HBHUD > * ) HUD
{
NSMutableArray < NSViewController < HBHUD > * > * HUDs = [ @ [ self . pictureHUD , self . encodingHUD , self . playerHUD ] mutableCopy ] ;
[ HUDs removeObject : HUD ] ;
for ( NSViewController * controller in HUDs )
{
controller . view . hidden = YES ;
}
HUD . view . hidden = NO ;
HUD . view . layer . opacity = 1.0 ;
[ self . window makeFirstResponder : HUD . view ] ;
[ self startHudTimer ] ;
}
- ( void ) showHudWithAnimation : ( NSViewController < HBHUD > * ) HUD
2014-08-22 17:59:21 +00:00
{
// The standard view animator doesn ' t play
// nicely with the Yosemite visual effects yet .
// So let ' s do the fade ourself .
2024-04-12 18:24:16 +02:00
NSView * view = HUD . view ;
CALayer * layer = view . layer ;
if ( layer . opacity = = 0 || view . isHidden )
2014-08-22 17:59:21 +00:00
{
2024-04-12 18:24:16 +02:00
view . hidden = NO ;
2014-08-22 17:59:21 +00:00
[ CATransaction begin ] ;
CABasicAnimation * fadeInAnimation = [ CABasicAnimation animationWithKeyPath : @ "opacity" ] ;
2024-04-12 18:24:16 +02:00
fadeInAnimation . fromValue = @ ( [ layer . presentationLayer opacity ] ) ;
2021-01-16 12:34:33 +01:00
fadeInAnimation . toValue = @ 1.0 ;
2014-08-22 17:59:21 +00:00
fadeInAnimation . beginTime = 0.0 ;
fadeInAnimation . duration = ANIMATION_DUR ;
2024-04-12 18:24:16 +02:00
[ layer addAnimation : fadeInAnimation forKey : nil ] ;
[ layer setOpacity : 1 ] ;
2014-08-22 17:59:21 +00:00
[ CATransaction commit ] ;
}
}
- ( void ) hideHudWithAnimation : ( NSView * ) hud
{
if ( hud . layer . opacity ! = 0 )
{
[ CATransaction begin ] ;
2016-05-03 18:47:14 +02:00
CABasicAnimation * fadeOutAnimation = [ CABasicAnimation animationWithKeyPath : @ "opacity" ] ;
fadeOutAnimation . fromValue = @ ( [ hud . layer . presentationLayer opacity ] ) ;
2021-01-16 12:34:33 +01:00
fadeOutAnimation . toValue = @ 0.0 ;
2016-05-03 18:47:14 +02:00
fadeOutAnimation . beginTime = 0.0 ;
fadeOutAnimation . duration = ANIMATION_DUR ;
2014-08-22 17:59:21 +00:00
2016-05-03 18:47:14 +02:00
[ hud . layer addAnimation : fadeOutAnimation forKey : nil ] ;
2014-08-22 17:59:21 +00:00
[ hud . layer setOpacity : 0 ] ;
[ CATransaction commit ] ;
}
}
2015-10-06 19:52:42 +02:00
- ( void ) startHudTimer
2013-11-04 07:09:50 +00:00
{
if ( self . hudTimer )
{
2016-05-03 18:47:14 +02:00
[ self . hudTimer setFireDate : [ NSDate dateWithTimeIntervalSinceNow : HUD_FADEOUT _TIME ] ] ;
2013-11-04 07:09:50 +00:00
}
else
{
2016-05-03 18:47:14 +02:00
self . hudTimer = [ NSTimer scheduledTimerWithTimeInterval : HUD_FADEOUT _TIME target : self selector : @ selector ( hudTimerFired : )
2013-11-04 07:09:50 +00:00
userInfo : nil repeats : YES ] ;
2013-01-30 18:48:23 +00:00
}
}
2009-01-12 00:07:38 +00:00
2015-10-06 19:52:42 +02:00
- ( void ) stopHudTimer
2013-11-04 07:09:50 +00:00
{
[ self . hudTimer invalidate ] ;
self . hudTimer = nil ;
}
2016-05-03 18:47:14 +02:00
- ( void ) hudTimerFired : ( NSTimer * ) theTimer
2013-11-04 07:09:50 +00:00
{
2016-05-03 18:47:14 +02:00
if ( self . currentHUD . canBeHidden )
{
[ self hideHudWithAnimation : self . currentHUD . view ] ;
}
2013-11-04 07:09:50 +00:00
[ self stopHudTimer ] ;
}
2016-05-03 18:47:14 +02:00
# pragma mark - Still previews mode
- ( void ) enterPictureState
{
[ self displayPreviewAtIndex : self . pictureHUD . selectedIndex ] ;
}
2013-11-04 07:09:50 +00:00
2015-10-06 19:52:42 +02:00
- ( void ) displayPreviewAtIndex : ( NSUInteger ) idx
2009-01-12 00:07:38 +00:00
{
2019-10-05 19:00:30 +02:00
if ( self . generator && self . window . isVisible )
2014-12-20 18:56:10 +00:00
{
2024-12-05 09:34:58 +01:00
CFTypeRef image = self . wantsDisplayLayer ?
( CFTypeRef ) [ self . generator copyPixelBufferAtIndex : idx shouldCache : NO ] :
( CFTypeRef ) [ self . generator copyImageAtIndex : idx shouldCache : YES ] ;
2021-04-13 09:17:52 +02:00
if ( image )
{
2024-12-05 09:34:58 +01:00
self . previewView . image = ( __bridge id _Nullable ) ( image ) ;
2021-04-13 09:17:52 +02:00
CFRelease ( image ) ;
}
2009-01-12 00:07:38 +00:00
}
}
2020-10-05 17:45:47 +02:00
- ( void ) showCroppingSettings : ( id ) sender
2009-01-12 00:07:38 +00:00
{
2022-09-30 10:24:55 +02:00
if ( self . croppingPopover )
{
if ( self . croppingPopover . isShown )
{
[ self . croppingPopover close ] ;
}
else
{
[ self . croppingPopover showRelativeToRect : [ sender bounds ] ofView : sender preferredEdge : NSMaxYEdge ] ;
}
}
else
{
HBCroppingController * croppingController = [ [ HBCroppingController alloc ] initWithPicture : self . picture ] ;
self . croppingPopover = [ [ NSPopover alloc ] init ] ;
self . croppingPopover . behavior = NSPopoverBehaviorTransient ;
self . croppingPopover . contentViewController = croppingController ;
self . croppingPopover . appearance = [ NSAppearance appearanceNamed : NSAppearanceNameVibrantDark ] ;
[ self . croppingPopover showRelativeToRect : [ sender bounds ] ofView : sender preferredEdge : NSMaxYEdge ] ;
}
2013-11-04 07:09:50 +00:00
}
2016-05-03 18:47:14 +02:00
# pragma mark - Encoding mode
2013-11-04 07:09:50 +00:00
2016-05-03 18:47:14 +02:00
- ( void ) enterEncodingState
2009-01-12 00:07:38 +00:00
{
2016-05-03 18:47:14 +02:00
self . encodingHUD . progress = 0 ;
2009-01-12 00:07:38 +00:00
}
2016-05-03 18:47:14 +02:00
- ( void ) cancelEncoding
2013-11-04 07:09:50 +00:00
{
2014-09-19 07:32:35 +00:00
[ self . generator cancel ] ;
2013-11-04 07:09:50 +00:00
}
2016-05-03 18:47:14 +02:00
- ( void ) createMoviePreviewWithPictureIndex : ( NSUInteger ) index duration : ( NSUInteger ) duration
2013-11-04 07:09:50 +00:00
{
2016-05-03 18:47:14 +02:00
if ( [ self . generator createMovieAsyncWithImageAtIndex : index duration : duration ] )
2015-01-13 07:37:56 +00:00
{
2016-05-03 18:47:14 +02:00
[ self switchStateToHUD : self . encodingHUD ] ;
2015-01-13 07:37:56 +00:00
}
2013-11-04 07:09:50 +00:00
}
2016-05-03 18:47:14 +02:00
- ( void ) updateProgress : ( double ) progress info : ( NSString * ) progressInfo
2010-05-18 16:22:00 +00:00
{
2016-05-03 18:47:14 +02:00
self . encodingHUD . progress = progress ;
self . encodingHUD . info = progressInfo ;
2010-05-18 16:22:00 +00:00
}
2016-05-03 18:47:14 +02:00
- ( void ) didCancelMovieCreation
2010-05-18 16:22:00 +00:00
{
2016-05-03 18:47:14 +02:00
[ self switchStateToHUD : self . pictureHUD ] ;
2010-05-18 16:22:00 +00:00
}
2019-08-12 10:19:00 +02:00
- ( void ) showAlert : ( NSURL * ) fileURL
2010-05-18 16:22:00 +00:00
{
2018-06-09 10:26:57 +02:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
alert . messageText = NSLocalizedString ( @ "HandBrake can't open the preview." , @ "Preview -> live preview alert message" ) ;
alert . informativeText = NSLocalizedString ( @ "HandBrake can't playback this combination of video/audio/container format. Do you want to open it in an external player?" , @ "Preview -> live preview alert informative text" ) ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Open in external player" , @ "Preview -> live preview alert default button" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Cancel" , @ "Preview -> live preview alert alternate button" ) ] ;
[ alert beginSheetModalForWindow : self . window completionHandler : ^ ( NSModalResponse returnCode )
{
if ( returnCode = = NSAlertFirstButtonReturn )
2018-06-09 10:06:52 +02:00
{
[ [ NSWorkspace sharedWorkspace ] openURL : fileURL ] ;
}
} ] ;
2010-05-18 16:22:00 +00:00
}
2019-08-12 10:19:00 +02:00
- ( void ) setUpPlaybackOfURL : ( NSURL * ) fileURL playerClass : ( Class ) class
2010-05-18 16:22:00 +00:00
{
2016-06-17 12:04:22 +02:00
NSArray < Class > * availablePlayerClasses = @ [ [ HBAVPlayer class ] ] ;
2016-05-19 13:44:52 +02:00
self . player = [ [ class alloc ] initWithURL : fileURL ] ;
if ( self . player )
2010-05-18 16:22:00 +00:00
{
2016-05-19 13:44:52 +02:00
[ self . player loadPlayableValueAsynchronouslyWithCompletionHandler : ^ {
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
if ( self . player . isPlayable && self . currentHUD = = self . encodingHUD )
{
[ self switchStateToHUD : self . playerHUD ] ;
}
else
{
// Try to open the preview with the next player class .
NSUInteger idx = [ availablePlayerClasses indexOfObject : class ] ;
if ( idx ! = NSNotFound && ( idx + 1 ) < availablePlayerClasses . count )
{
Class nextPlayer = availablePlayerClasses [ idx + 1 ] ;
[ self setUpPlaybackOfURL : fileURL playerClass : nextPlayer ] ;
}
else
{
[ self showAlert : fileURL ] ;
[ self switchStateToHUD : self . pictureHUD ] ;
}
}
} ) ;
} ] ;
2016-05-03 18:47:14 +02:00
}
else
{
[ self showAlert : fileURL ] ;
[ self switchStateToHUD : self . pictureHUD ] ;
2010-05-18 16:22:00 +00:00
}
}
2016-05-03 18:47:14 +02:00
- ( void ) didCreateMovieAtURL : ( NSURL * ) fileURL
2013-02-01 16:58:48 +00:00
{
2016-05-19 13:44:52 +02:00
[ self setUpPlaybackOfURL : fileURL playerClass : [ HBAVPlayer class ] ] ;
2010-05-18 16:22:00 +00:00
}
2016-05-03 18:47:14 +02:00
# pragma mark - Player mode
2010-05-18 16:22:00 +00:00
2016-05-03 18:47:14 +02:00
- ( void ) enterPlayerState
2010-05-18 16:22:00 +00:00
{
2016-05-03 18:47:14 +02:00
// Scale the layer to the picture player size
CALayer * playerLayer = self . player . layer ;
playerLayer . frame = self . previewView . pictureFrame ;
2010-05-18 16:22:00 +00:00
2019-10-05 19:00:30 +02:00
[ self . previewView . layer insertSublayer : playerLayer atIndex : 10 ] ;
2016-05-03 18:47:14 +02:00
self . playerHUD . player = self . player ;
2010-05-18 16:22:00 +00:00
}
2016-05-03 18:47:14 +02:00
- ( void ) exitPlayerState
2010-05-18 16:22:00 +00:00
{
2016-05-03 18:47:14 +02:00
self . playerHUD . player = nil ;
[ self . player pause ] ;
[ self . player . layer removeFromSuperlayer ] ;
self . player = nil ;
2010-05-18 16:22:00 +00:00
}
2016-05-03 18:47:14 +02:00
- ( void ) stopPlayer
2010-05-18 16:22:00 +00:00
{
2016-05-03 18:47:14 +02:00
[ self switchStateToHUD : self . pictureHUD ] ;
2010-05-18 16:22:00 +00:00
}
2013-02-01 16:58:48 +00:00
2016-05-03 18:47:14 +02:00
# pragma mark - Scroll
2010-05-18 16:22:00 +00:00
2016-05-03 18:47:14 +02:00
- ( void ) keyDown : ( NSEvent * ) event
2013-02-01 16:58:48 +00:00
{
2019-08-12 10:19:00 +02:00
if ( self . generator && [ self . currentHUD HB_keyDown : event ] = = NO )
2013-02-01 19:48:33 +00:00
{
2013-02-04 19:22:24 +00:00
[ super keyDown : event ] ;
2016-05-03 18:47:14 +02:00
}
2013-02-01 16:58:48 +00:00
}
2010-05-18 16:22:00 +00:00
2016-05-03 18:47:14 +02:00
- ( void ) scrollWheel : ( NSEvent * ) event
2013-08-04 09:12:33 +00:00
{
2019-08-12 10:19:00 +02:00
if ( self . generator && [ self . currentHUD HB_scrollWheel : event ] = = NO )
2013-08-04 09:12:33 +00:00
{
2016-05-03 18:47:14 +02:00
[ super scrollWheel : event ] ;
2013-08-04 09:12:33 +00:00
}
}
2009-01-12 00:07:38 +00:00
@ end