diff options
Diffstat (limited to 'macosx/HBPreviewController.m')
-rw-r--r-- | macosx/HBPreviewController.m | 777 |
1 files changed, 215 insertions, 562 deletions
diff --git a/macosx/HBPreviewController.m b/macosx/HBPreviewController.m index 4e7d259e2..1db48cdcd 100644 --- a/macosx/HBPreviewController.m +++ b/macosx/HBPreviewController.m @@ -1,4 +1,4 @@ -/* $Id: HBPreviewController.mm,v 1.11 2005/08/01 15:10:44 titer Exp $ +/* $Id: HBPreviewController.m $ This file is part of the HandBrake source code. Homepage: <http://handbrake.fr/>. @@ -8,65 +8,42 @@ #import "HBPreviewGenerator.h" #import "HBPictureController.h" +#import "HBController.h" #import "HBPreviewView.h" -#import "HBController.h" +#import "HBPlayer.h" +#import "HBQTKitPlayer.h" +#import "HBAVPlayer.h" -#import <QTKit/QTKit.h> -#import "QTKit+HBQTMovieExtensions.h" +#import "HBPictureHUDController.h" +#import "HBEncodingProgressHUDController.h" +#import "HBPlayerHUDController.h" + +#import "NSWindow+HBAdditions.h" #define ANIMATION_DUR 0.15 +#define HUD_FADEOUT_TIME 4.0 -// make min width and height of preview window large enough for hud +// Make min width and height of preview window large enough for hud. #define MIN_WIDTH 480.0 #define MIN_HEIGHT 360.0 -typedef enum ViewMode : NSUInteger { - ViewModePicturePreview, - ViewModeEncoding, - ViewModeMoviePreview -} ViewMode; +@interface HBPreviewController () <HBPreviewGeneratorDelegate, HBPictureHUDControllerDelegate, HBEncodingProgressHUDControllerDelegate, HBPlayerHUDControllerDelegate> -@interface HBPreviewController () <HBPreviewGeneratorDelegate> -{ - /* HUD boxes */ - IBOutlet NSView * fPictureControlBox; - IBOutlet NSView * fEncodingControlBox; - IBOutlet NSView * fMoviePlaybackControlBox; +@property (nonatomic, readonly) HBPictureHUDController *pictureHUD; +@property (nonatomic, readonly) HBEncodingProgressHUDController *encodingHUD; +@property (nonatomic, readonly) HBPlayerHUDController *playerHUD; - IBOutlet NSSlider * fPictureSlider; - IBOutlet NSTextField * fInfoField; - IBOutlet NSTextField * fscaleInfoField; +@property (nonatomic, readwrite) NSViewController<HBHUD> *currentHUD; - /* Full Screen Mode Toggle */ - IBOutlet NSButton * fScaleToScreenToggleButton; +@property (nonatomic) NSTimer *hudTimer; +@property (nonatomic) BOOL mouseInWindow; - /* Movie Previews */ - IBOutlet QTMovieView * fMovieView; - /* Playback Panel Controls */ - IBOutlet NSButton * fPlayPauseButton; - IBOutlet NSSlider * fMovieScrubberSlider; - IBOutlet NSTextField * fMovieInfoField; - - IBOutlet NSProgressIndicator * fMovieCreationProgressIndicator; - IBOutlet NSTextField * fPreviewMovieStatusField; - - /* Popup of choices for length of preview in seconds */ - IBOutlet NSPopUpButton * fPreviewMovieLengthPopUp; -} +@property (nonatomic) id<HBPlayer> player; -@property (nonatomic, readwrite) HBPictureController *pictureSettingsWindow; +@property (nonatomic) HBPictureController *pictureSettingsWindow; -@property (nonatomic) ViewMode currentViewMode; @property (nonatomic) NSPoint windowCenterPoint; - -@property (nonatomic, strong) NSTimer *hudTimer; - -@property (nonatomic) NSUInteger pictureIndex; - -@property (nonatomic, strong) QTMovie *movie; -@property (nonatomic, strong) NSTimer *movieTimer; - @property (weak) IBOutlet HBPreviewView *previewView; @end @@ -92,51 +69,48 @@ typedef enum ViewMode : NSUInteger { { NSPoint center = NSPointFromString(centerString); self.windowCenterPoint = center; - [self resizeWindowForViewSize:NSMakeSize(MIN_WIDTH, MIN_HEIGHT) animate:NO]; + [self.window HB_resizeToBestSizeForViewSize:NSMakeSize(MIN_WIDTH, MIN_HEIGHT) center:self.windowCenterPoint animate:NO]; } else { - self.windowCenterPoint = [self centerPoint]; + self.windowCenterPoint = [self.window HB_centerPoint]; } self.window.excludedFromWindowsMenu = YES; self.window.acceptsMouseMovedEvents = YES; - // we set the preview length popup in seconds - [fPreviewMovieLengthPopUp removeAllItems]; - [fPreviewMovieLengthPopUp addItemsWithTitles:@[@"15", @"30", @"45", @"60", @"90", - @"120", @"150", @"180", @"210", @"240"]]; + _pictureHUD = [[HBPictureHUDController alloc] init]; + self.pictureHUD.delegate = self; + _encodingHUD = [[HBEncodingProgressHUDController alloc] init]; + self.encodingHUD.delegate = self; + _playerHUD = [[HBPlayerHUDController alloc] init]; + self.playerHUD.delegate = self; - if ([[NSUserDefaults standardUserDefaults] objectForKey:@"PreviewLength"]) - { - [fPreviewMovieLengthPopUp selectItemWithTitle:[[NSUserDefaults standardUserDefaults] - objectForKey:@"PreviewLength"]]; - } - if (!fPreviewMovieLengthPopUp.selectedItem) - { - // currently hard set default to 15 seconds - [fPreviewMovieLengthPopUp selectItemAtIndex: 0]; - } + [self.window.contentView addSubview:self.pictureHUD.view]; + [self.window.contentView addSubview:self.encodingHUD.view]; + [self.window.contentView addSubview:self.playerHUD.view]; // Relocate our hud origins. - NSPoint hudControlBoxOrigin = fMoviePlaybackControlBox.frame.origin; - fPictureControlBox.frameOrigin = hudControlBoxOrigin; - fEncodingControlBox.frameOrigin = hudControlBoxOrigin; - fMoviePlaybackControlBox.frameOrigin = hudControlBoxOrigin; + CGPoint origin = CGPointMake(floor((MIN_WIDTH - _pictureHUD.view.bounds.size.width) / 2), MIN_HEIGHT / 10); + + [self.pictureHUD.view setFrameOrigin:origin]; + [self.encodingHUD.view setFrameOrigin:origin]; + [self.playerHUD.view setFrameOrigin:origin]; - [self hideHud]; + self.currentHUD = self.pictureHUD; + self.currentHUD.view.hidden = YES; - fMovieView.hidden = YES; - fMovieView.delegate = self; - [fMovieView setControllerVisible:NO]; + NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:self.window.contentView.frame + options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways + owner:self + userInfo:nil]; + [self.window.contentView addTrackingArea:trackingArea]; } - (void)dealloc { - [self removeMovieObservers]; - [_hudTimer invalidate]; - [_movieTimer invalidate]; + _generator.delegate = nil; [_generator cancel]; } @@ -188,21 +162,13 @@ typedef enum ViewMode : NSUInteger { generator.delegate = self; // adjust the preview slider length - [fPictureSlider setMaxValue: generator.imagesCount - 1.0]; - [fPictureSlider setNumberOfTickMarks: generator.imagesCount]; - - if (self.pictureIndex > generator.imagesCount) - { - self.pictureIndex = generator.imagesCount - 1; - } - - [self switchViewToMode:ViewModePicturePreview]; - [self displayPreviewAtIndex:self.pictureIndex]; + self.pictureHUD.pictureCount = generator.imagesCount; + [self switchStateToHUD:self.pictureHUD]; } else { self.previewView.image = nil; - [self hideHud]; + self.currentHUD.view.hidden = YES; self.window.title = NSLocalizedString(@"Preview", nil); } } @@ -212,8 +178,7 @@ typedef enum ViewMode : NSUInteger { if (self.generator) { [self.generator cancel]; - [self switchViewToMode:ViewModePicturePreview]; - [self displayPreviewAtIndex:self.pictureIndex]; + [self switchStateToHUD:self.pictureHUD]; } } @@ -221,11 +186,7 @@ typedef enum ViewMode : NSUInteger { { [super showWindow:sender]; - if (self.currentViewMode == ViewModeMoviePreview) - { - [self startMovieTimer]; - } - else if (self.currentViewMode == ViewModePicturePreview) + if (self.currentHUD == self.pictureHUD) { [self reloadPreviews]; } @@ -233,14 +194,13 @@ typedef enum ViewMode : NSUInteger { - (void)windowWillClose:(NSNotification *)aNotification { - if (self.currentViewMode == ViewModeEncoding) + if (self.currentHUD == self.encodingHUD) { - [self cancelCreateMoviePreview:self]; + [self cancelEncoding]; } - else if (self.currentViewMode == ViewModeMoviePreview) + else if (self.currentHUD == self.playerHUD) { - [fMovieView pause:self]; - [self stopMovieTimer]; + [self.player pause]; } [self.pictureSettingsWindow close]; @@ -249,11 +209,10 @@ typedef enum ViewMode : NSUInteger { - (void)windowDidChangeBackingProperties:(NSNotification *)notification { - NSWindow *theWindow = (NSWindow *)[notification object]; + NSWindow *theWindow = (NSWindow *)notification.object; - CGFloat newBackingScaleFactor = [theWindow backingScaleFactor]; - CGFloat oldBackingScaleFactor = [[notification userInfo][@"NSBackingPropertyOldScaleFactorKey"] - doubleValue]; + CGFloat newBackingScaleFactor = theWindow.backingScaleFactor; + CGFloat oldBackingScaleFactor = [notification.userInfo[@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; if (newBackingScaleFactor != oldBackingScaleFactor) { @@ -268,20 +227,11 @@ typedef enum ViewMode : NSUInteger { #pragma mark - Window sizing -/** - * Calculates and returns the center point of the window - */ -- (NSPoint)centerPoint { - NSPoint center = NSMakePoint(floor(self.window.frame.origin.x + self.window.frame.size.width / 2), - floor(self.window.frame.origin.y + self.window.frame.size.height / 2)); - return center; -} - - (void)windowDidMove:(NSNotification *)notification { if (self.previewView.fitToView == NO) { - self.windowCenterPoint = [self centerPoint]; + self.windowCenterPoint = [self.window HB_centerPoint]; [[NSUserDefaults standardUserDefaults] setObject:NSStringFromPoint(self.windowCenterPoint) forKey:@"HBPreviewWindowCenter"]; } } @@ -291,68 +241,6 @@ typedef enum ViewMode : NSUInteger { [self updateSizeLabels]; } -/** - * Resizes the entire window to accomodate a view of a particular size. - */ -- (void)resizeWindowForViewSize:(NSSize)viewSize animate:(BOOL)performAnimation -{ - NSWindow *window = self.window; - NSSize currentSize = [window.contentView frame].size; - NSRect frame = window.frame; - - // Calculate border around content region of the frame - int borderX = (int)(frame.size.width - currentSize.width); - int borderY = (int)(frame.size.height - currentSize.height); - - // Make sure the frame is smaller than the screen - NSSize maxSize = window.screen.visibleFrame.size; - - // if we are not Scale To Screen, put an 10% of visible screen on the window - maxSize.width = maxSize.width * 0.90; - maxSize.height = maxSize.height * 0.90; - - // Set the new frame size - // Add the border to the new frame size so that the content region - // of the frame is large enough to accomodate the preview image - frame.size.width = viewSize.width + borderX; - frame.size.height = viewSize.height + borderY; - - // compare frame to max size of screen - if (frame.size.width > maxSize.width) - { - frame.size.width = maxSize.width; - } - if (frame.size.height > maxSize.height) - { - frame.size.height = maxSize.height; - } - - // Since upon launch we can open up the preview window if it was open - // the last time we quit (and at the size it was) we want to make - // sure that upon resize we do not have the window off the screen - // So check the origin against the screen origin and adjust if - // necessary. - NSSize screenSize = window.screen.visibleFrame.size; - NSPoint screenOrigin = window.screen.visibleFrame.origin; - - frame.origin.x = self.windowCenterPoint.x - floor(frame.size.width / 2); - frame.origin.y = self.windowCenterPoint.y - floor(frame.size.height / 2); - - // our origin is off the screen to the left - if (frame.origin.x < screenOrigin.x) - { - // so shift our origin to the right - frame.origin.x = screenOrigin.x; - } - else if ((frame.origin.x + frame.size.width) > (screenOrigin.x + screenSize.width)) - { - // the right side of the preview is off the screen, so shift to the left - frame.origin.x = (screenOrigin.x + screenSize.width) - frame.size.width; - } - - [window setFrame:frame display:YES animate:performAnimation]; -} - - (void)updateSizeLabels { if (self.generator) @@ -375,8 +263,8 @@ typedef enum ViewMode : NSUInteger { } // Set the info fields in the hud controller - fInfoField.stringValue = self.generator.info; - fscaleInfoField.stringValue = scaleString; + self.pictureHUD.info = self.generator.info; + self.pictureHUD.scale = scaleString; // Set the info field in the window title bar self.window.title = [NSString stringWithFormat:NSLocalizedString(@"Preview - %@ %@", nil), @@ -384,138 +272,86 @@ typedef enum ViewMode : NSUInteger { } } -#pragma mark - Hud mode +#pragma mark - Hud State /** - * Enable/Disable an arbitrary number of UI elements. - * @param boxes an array of UI elements - * @param indexes a set of indexes of the elements in boxes to be enabled - */ -- (void) toggleBoxes: (NSArray *) boxes usingIndexes: (NSIndexSet *) indexes -{ - [NSAnimationContext beginGrouping]; - [[NSAnimationContext currentContext] setDuration:ANIMATION_DUR]; - - [boxes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - BOOL hide = [indexes containsIndex:idx] ? NO : YES; - if (hide) - { - [self hideHudWithAnimation:obj]; - } - else - { - [self showHudWithAnimation:obj]; - } - }]; - - [NSAnimationContext endGrouping]; -} - -/** - * Switch the preview controller to one of his view mode: - * ViewModePicturePreview, ViewModeEncoding, ViewModeMoviePreview + * Switch the preview controller to one of his hud mode: * This methods is the only way to change the mode, do not try otherwise. - * @param mode ViewMode mode + * @param hud NSViewController<HBHUD> the hud to show */ -- (void) switchViewToMode: (ViewMode) mode +- (void)switchStateToHUD:(NSViewController<HBHUD> *)hud { - switch (mode) { - case ViewModePicturePreview: - { - if (self.currentViewMode == ViewModeEncoding) - { - [self toggleBoxes:@[fPictureControlBox, fEncodingControlBox] - usingIndexes:[NSIndexSet indexSetWithIndex:0]]; - [fMovieCreationProgressIndicator stopAnimation:self]; - } - else if (self.currentViewMode == ViewModeMoviePreview) - { - // Stop playback and remove the observers - [fMovieView pause:self]; - [self stopMovieTimer]; - [self removeMovieObservers]; - - [self toggleBoxes:@[fPictureControlBox, fMoviePlaybackControlBox, fMovieView] - usingIndexes:[NSIndexSet indexSetWithIndex:0]]; - - /* Release the movie */ - [fMovieView setMovie:nil]; - self.movie = nil; - } - - break; - } + if (self.currentHUD == self.playerHUD) + { + [self exitPlayerState]; + } - case ViewModeEncoding: - { - [fMovieCreationProgressIndicator setDoubleValue:0]; - [fMovieCreationProgressIndicator startAnimation:self]; - [self toggleBoxes:@[fEncodingControlBox, fPictureControlBox, fMoviePlaybackControlBox] - usingIndexes:[NSIndexSet indexSetWithIndex:0]]; + if (hud == self.pictureHUD) + { + [self enterPictureState]; + } + else if (hud == self.encodingHUD) + { + [self enterEncodingState]; + } + else if (hud == self.playerHUD) + { + [self enterPlayerState]; + } - break; - } + // Show the current hud + NSMutableArray *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; - case ViewModeMoviePreview: - { - [self toggleBoxes:@[fMovieView, fMoviePlaybackControlBox, fEncodingControlBox, fPictureControlBox] - usingIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)]]; + [self.window makeFirstResponder:hud.view]; + [self startHudTimer]; + self.currentHUD = hud; +} - [fMovieCreationProgressIndicator stopAnimation:self]; - [self initPreviewScrubberForMovie]; - [self startMovieTimer]; +#pragma mark - HUD Control Overlay - // Install movie notifications - [self addMovieObservers]; - } - break; +- (void)mouseEntered:(NSEvent *)theEvent +{ + if (self.generator) + { + NSView *hud = self.currentHUD.view; - default: - break; + [self showHudWithAnimation:hud]; + [self startHudTimer]; } - - self.currentViewMode = mode; + self.mouseInWindow = YES; } -#pragma mark - -#pragma mark Hud Control Overlay +- (void)mouseExited:(NSEvent *)theEvent +{ + [self hudTimerFired:nil]; + self.mouseInWindow = NO; +} - (void)mouseMoved:(NSEvent *)theEvent { [super mouseMoved:theEvent]; - NSPoint mouseLoc = [theEvent locationInWindow]; - /* Test for mouse location to show/hide hud controls */ - if (self.currentViewMode != ViewModeEncoding && self.generator) + // Test for mouse location to show/hide hud controls + if (self.generator && self.mouseInWindow) { - /* Since we are not encoding, verify which control hud to show - * or hide based on aMovie ( aMovie indicates we need movie controls ) - */ - NSView *hud; - if (self.currentViewMode == !ViewModeMoviePreview) // No movie loaded up - { - hud = fPictureControlBox; - } - else // We have a movie - { - hud = fMoviePlaybackControlBox; - } + NSView *hud = self.currentHUD.view; + NSPoint mouseLoc = theEvent.locationInWindow; - if (NSPointInRect(mouseLoc, [hud frame])) + if (NSPointInRect(mouseLoc, hud.frame)) { - [self showHudWithAnimation:hud]; [self stopHudTimer]; } - else if (NSPointInRect(mouseLoc, [[[self window] contentView] frame])) + else { [self showHudWithAnimation:hud]; [self startHudTimer]; } - else - { - [self hideHudWithAnimation:hud]; - [self stopHudTimer]; - } } } @@ -524,13 +360,13 @@ typedef enum ViewMode : NSUInteger { // The standard view animator doesn't play // nicely with the Yosemite visual effects yet. // So let's do the fade ourself. - if (hud.layer.opacity == 0 || [hud isHidden]) + if (hud.layer.opacity == 0 || hud.isHidden) { [hud setHidden:NO]; [CATransaction begin]; CABasicAnimation *fadeInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; - fadeInAnimation.fromValue = @(0.0); + fadeInAnimation.fromValue = @([hud.layer.presentationLayer opacity]); fadeInAnimation.toValue = @(1.0); fadeInAnimation.beginTime = 0.0; fadeInAnimation.duration = ANIMATION_DUR; @@ -547,41 +383,28 @@ typedef enum ViewMode : NSUInteger { if (hud.layer.opacity != 0) { [CATransaction begin]; - [CATransaction setCompletionBlock:^{ - if (hud.layer.opacity == 0) - { - [hud setHidden:YES]; - } - }]; - CABasicAnimation *fadeInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; - fadeInAnimation.fromValue = @([hud.layer.presentationLayer opacity]); - fadeInAnimation.toValue = @(0.0); - fadeInAnimation.beginTime = 0.0; - fadeInAnimation.duration = ANIMATION_DUR; + CABasicAnimation *fadeOutAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; + fadeOutAnimation.fromValue = @([hud.layer.presentationLayer opacity]); + fadeOutAnimation.toValue = @(0.0); + fadeOutAnimation.beginTime = 0.0; + fadeOutAnimation.duration = ANIMATION_DUR; - [hud.layer addAnimation:fadeInAnimation forKey:nil]; + [hud.layer addAnimation:fadeOutAnimation forKey:nil]; [hud.layer setOpacity:0]; [CATransaction commit]; } } -- (void)hideHud -{ - [fPictureControlBox setHidden:YES]; - [fMoviePlaybackControlBox setHidden:YES]; - [fEncodingControlBox setHidden:YES]; -} - - (void)startHudTimer { if (self.hudTimer) { - [self.hudTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:8.0]]; + [self.hudTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:HUD_FADEOUT_TIME]]; } else { - self.hudTimer = [NSTimer scheduledTimerWithTimeInterval:8.0 target:self selector:@selector(hudTimerFired:) + self.hudTimer = [NSTimer scheduledTimerWithTimeInterval:HUD_FADEOUT_TIME target:self selector:@selector(hudTimerFired:) userInfo:nil repeats:YES]; } } @@ -592,18 +415,21 @@ typedef enum ViewMode : NSUInteger { self.hudTimer = nil; } -- (void)hudTimerFired: (NSTimer *)theTimer +- (void)hudTimerFired:(NSTimer *)theTimer { - // Regardless which control box is active, after the timer - // period we want either one to fade to hidden. - [self hideHudWithAnimation:fPictureControlBox]; - [self hideHudWithAnimation:fMoviePlaybackControlBox]; - + if (self.currentHUD.canBeHidden) + { + [self hideHudWithAnimation:self.currentHUD.view]; + } [self stopHudTimer]; } -#pragma mark - -#pragma mark Still previews mode +#pragma mark - Still previews mode + +- (void)enterPictureState +{ + [self displayPreviewAtIndex:self.pictureHUD.selectedIndex]; +} /** * Adjusts the window to draw the current picture (fPicture) adjusting its size as @@ -611,6 +437,11 @@ typedef enum ViewMode : NSUInteger { */ - (void)displayPreviewAtIndex:(NSUInteger)idx { + if (!self.generator) + { + return; + } + if (self.window.isVisible) { CGImageRef fPreviewImage = [self.generator copyImageAtIndex:idx shouldCache:YES]; @@ -625,33 +456,18 @@ typedef enum ViewMode : NSUInteger { // Scale the window to the image size NSSize windowSize = [self.previewView optimalViewSizeForImageSize:imageScaledSize minSize:NSMakeSize(MIN_WIDTH, MIN_HEIGHT)]; - [self resizeWindowForViewSize:windowSize animate:self.window.isVisible]; + [self.window HB_resizeToBestSizeForViewSize:windowSize center:self.windowCenterPoint animate:self.window.isVisible]; } [self updateSizeLabels]; } -- (IBAction)previewDurationPopUpChanged:(id)sender -{ - [[NSUserDefaults standardUserDefaults] setObject:[fPreviewMovieLengthPopUp titleOfSelectedItem] forKey:@"PreviewLength"]; -} - -- (IBAction)pictureSliderChanged:(id)sender -{ - if ((self.pictureIndex != [fPictureSlider intValue] || !sender) && self.generator) { - self.pictureIndex = [fPictureSlider intValue]; - [self displayPreviewAtIndex:self.pictureIndex]; - } -} - -- (IBAction)toggleScaleToScreen:(id)sender +- (void)toggleScaleToScreen { if (self.previewView.fitToView == YES) { self.previewView.fitToView = NO; - fScaleToScreenToggleButton.title = NSLocalizedString(@"Scale To Screen", nil); - - [self displayPreviewAtIndex:self.pictureIndex]; + [self displayPreviewAtIndex:self.pictureHUD.selectedIndex]; } else { @@ -660,11 +476,10 @@ typedef enum ViewMode : NSUInteger { { [self.window setFrame:self.window.screen.visibleFrame display:YES animate:YES]; } - fScaleToScreenToggleButton.title = NSLocalizedString(@"Actual Scale", nil); } } -- (IBAction) showPictureSettings: (id) sender +- (void)showPictureSettings { if (self.pictureSettingsWindow == nil) { @@ -676,299 +491,137 @@ typedef enum ViewMode : NSUInteger { [self.pictureSettingsWindow showWindow:self]; } -#pragma mark - -#pragma mark Movie preview mode - -- (void) updateProgress: (double) progress info: (NSString *) progressInfo { - [fPreviewMovieStatusField setStringValue: progressInfo]; +#pragma mark - Encoding mode - [fMovieCreationProgressIndicator setIndeterminate: NO]; - [fMovieCreationProgressIndicator setDoubleValue: progress]; -} - -- (void)didCancelMovieCreation -{ - [self switchViewToMode:ViewModePicturePreview]; -} - -- (void) didCreateMovieAtURL: (NSURL *) fileURL +- (void)enterEncodingState { - /* Load the new movie into fMovieView */ - if (fileURL) - { - NSError *outError; - NSDictionary *movieAttributes = @{QTMovieURLAttribute: fileURL, - QTMovieAskUnresolvedDataRefsAttribute: @NO, - @"QTMovieOpenForPlaybackAttribute": @YES, - @"QTMovieOpenAsyncRequiredAttribute": @NO, - @"QTMovieOpenAsyncOKAttribute": @NO, - @"QTMovieIsSteppableAttribute": @YES, - QTMovieApertureModeAttribute: QTMovieApertureModeClean}; - - QTMovie *movie = [[QTMovie alloc] initWithAttributes:movieAttributes error:&outError]; - - if (!movie) - { - NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"HandBrake can't open the preview.", nil) - defaultButton:NSLocalizedString(@"Open in external player", nil) - alternateButton:NSLocalizedString(@"Cancel", nil) - otherButton:nil - informativeTextWithFormat:NSLocalizedString(@"HandBrake can't playback this combination of video/audio/container format. Do you want to open it in an external player?", nil)]; - [alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) { - if (returnCode == NSModalResponseOK) - { - [[NSWorkspace sharedWorkspace] openURL:fileURL]; - } - }]; - [self switchViewToMode:ViewModePicturePreview]; - } - else - { - // Scale the fMovieView to the picture player size - [fMovieView setFrame:self.previewView.pictureFrame]; - - [fMovieView setMovie:movie]; - [movie setDelegate:self]; - - // get and enable subtitles - NSArray *subtitlesArray = [movie tracksOfMediaType:QTMediaTypeSubtitle]; - if (subtitlesArray.count) - { - // enable the first tx3g subtitle track - [subtitlesArray[0] setEnabled:YES]; - } - else - { - // Perian subtitles - subtitlesArray = [movie tracksOfMediaType: QTMediaTypeVideo]; - if (subtitlesArray.count >= 2) - { - // track 0 should be video, other video tracks should - // be subtitles; force-enable the first subs track - [subtitlesArray[1] setEnabled:YES]; - } - } - - // to actually play the movie - self.movie = movie; - - [self switchViewToMode:ViewModeMoviePreview]; - - [fMovieView play:movie]; - } - } + self.encodingHUD.progress = 0; } -- (IBAction) cancelCreateMoviePreview: (id) sender +- (void)cancelEncoding { [self.generator cancel]; } -- (IBAction) createMoviePreview: (id) sender +- (void)createMoviePreviewWithPictureIndex:(NSUInteger)index duration:(NSUInteger)duration { - if (!self.generator) - return; - - if ([self.generator createMovieAsyncWithImageAtIndex:self.pictureIndex - duration:[[fPreviewMovieLengthPopUp titleOfSelectedItem] intValue]]) + if ([self.generator createMovieAsyncWithImageAtIndex:index duration:duration]) { - [self switchViewToMode:ViewModeEncoding]; + [self switchStateToHUD:self.encodingHUD]; } } -- (IBAction) toggleMoviePreviewPlayPause: (id) sender +- (void)updateProgress:(double)progress info:(NSString *)progressInfo { - // make sure a movie is even loaded up - if (self.movie) - { - if ([self.movie isPlaying]) // we are playing - { - [fMovieView pause:self.movie]; - [fPlayPauseButton setState: NSOnState]; - } - else // we are paused or stopped - { - [fMovieView play:self.movie]; - [fPlayPauseButton setState: NSOffState]; - } - } + self.encodingHUD.progress = progress; + self.encodingHUD.info = progressInfo; } -- (IBAction) moviePlaybackGoToBeginning: (id) sender +- (void)didCancelMovieCreation { - [fMovieView gotoBeginning:self.movie]; + [self switchStateToHUD:self.pictureHUD]; } -- (IBAction) moviePlaybackGoToEnd: (id) sender +- (void)showAlert:(NSURL *)fileURL; { - [fMovieView gotoEnd:self.movie]; + NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"HandBrake can't open the preview.", nil) + defaultButton:NSLocalizedString(@"Open in external player", nil) + alternateButton:NSLocalizedString(@"Cancel", nil) + otherButton:nil + informativeTextWithFormat:NSLocalizedString(@"HandBrake can't playback this combination of video/audio/container format. Do you want to open it in an external player?", nil)]; + + [alert beginSheetModalForWindow:self.window modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:(void *)CFBridgingRetain(fileURL)]; } -- (void) startMovieTimer +- (void)alertDidEnd:(NSAlert *)alert + returnCode:(NSInteger)returnCode + contextInfo:(void *)contextInfo { - if (!self.movieTimer) + NSURL *fileURL = CFBridgingRelease(contextInfo); + if (returnCode == NSModalResponseOK) { - self.movieTimer = [NSTimer scheduledTimerWithTimeInterval:0.09 target:self - selector:@selector(movieTimerFired:) - userInfo:nil repeats:YES]; + [[NSWorkspace sharedWorkspace] openURL:fileURL]; } } -- (void) stopMovieTimer -{ - [self.movieTimer invalidate]; - self.movieTimer = nil; -} - -- (void) movieTimerFired: (NSTimer *)theTimer +- (void)setUpPlaybackOfURL:(NSURL *)fileURL; { - if (self.movie != nil) + if (self.player.isPlayable && self.currentHUD == self.encodingHUD) { - [self adjustPreviewScrubberForCurrentMovieTime]; - [fMovieInfoField setStringValue: [self.movie timecode]]; + [self switchStateToHUD:self.playerHUD]; + } + else + { + [self showAlert:fileURL]; + [self switchStateToHUD:self.pictureHUD]; } } -- (IBAction) showPicturesPreview: (id) sender +- (void)didCreateMovieAtURL:(NSURL *)fileURL { - [self switchViewToMode:ViewModePicturePreview]; -} + if (fileURL) + { + self.player = [[HBAVPlayer alloc] initWithURL:fileURL]; -#pragma mark - -#pragma mark Movie Playback Scrubber + if (self.player) + { + [self.player loadPlayableValueAsynchronouslyWithCompletionHandler:^{ -// Initialize the preview scrubber min/max to appropriate values for the current movie -- (void) initPreviewScrubberForMovie -{ - QTTime duration = [self.movie duration]; - CGFloat result = duration.timeValue / duration.timeScale; + dispatch_async(dispatch_get_main_queue(), ^{ + [self setUpPlaybackOfURL:fileURL]; + }); - [fMovieScrubberSlider setMinValue:0.0]; - [fMovieScrubberSlider setMaxValue: result]; - [fMovieScrubberSlider setDoubleValue: 0.0]; + }]; + } + else + { + [self showAlert:fileURL]; + [self switchStateToHUD:self.pictureHUD]; + } + } } -- (void) adjustPreviewScrubberForCurrentMovieTime -{ - QTTime time = [self.movie currentTime]; - - CGFloat result = (CGFloat)time.timeValue / (CGFloat)time.timeScale;; - [fMovieScrubberSlider setDoubleValue:result]; -} +#pragma mark - Player mode -- (IBAction) previewScrubberChanged: (id) sender +- (void)enterPlayerState { - [fMovieView pause:self.movie]; - [self.movie setCurrentTimeDouble:[fMovieScrubberSlider doubleValue]]; - [fMovieInfoField setStringValue: [self.movie timecode]]; -} + // Scale the layer to the picture player size + CALayer *playerLayer = self.player.layer; + playerLayer.frame = self.previewView.pictureFrame; -#pragma mark - -#pragma mark Movie Notifications + [self.window.contentView.layer insertSublayer:playerLayer atIndex:1]; -- (void) addMovieObservers -{ - // Notification for any time the movie rate changes - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(movieRateDidChange:) - name:@"QTMovieRateDidChangeNotification" - object:self.movie]; + self.playerHUD.player = self.player; } -- (void) removeMovieObservers +- (void)exitPlayerState { - // Notification for any time the movie rate changes - [[NSNotificationCenter defaultCenter] removeObserver:self - name:@"QTMovieRateDidChangeNotification" - object:self.movie]; + self.playerHUD.player = nil; + [self.player pause]; + [self.player.layer removeFromSuperlayer]; + self.player = nil; } -- (void) movieRateDidChange: (NSNotification *) notification +- (void)stopPlayer { - if (self.movie.isPlaying) - [fPlayPauseButton setState: NSOnState]; - else - [fPlayPauseButton setState: NSOffState]; + [self switchStateToHUD:self.pictureHUD]; } -#pragma mark - -#pragma mark Keyboard and mouse wheel control +#pragma mark - Scroll -/* fMovieView Keyboard controls */ -- (void) keyDown: (NSEvent *) event +- (void)keyDown:(NSEvent *)event { - unichar key = [[event charactersIgnoringModifiers] characterAtIndex:0]; - QTMovie *movie = self.movie; - - if (movie) - { - if (key == 32) - { - if ([movie isPlaying]) - [fMovieView pause:movie]; - else - [fMovieView play:movie]; - } - else if (key == 'k') - [fMovieView pause:movie]; - else if (key == 'l') - { - float rate = [movie rate]; - rate += 1.0f; - [fMovieView play:movie]; - [movie setRate:rate]; - } - else if (key == 'j') - { - float rate = [movie rate]; - rate -= 1.0f; - [fMovieView play:movie]; - [movie setRate:rate]; - } - else if ([event modifierFlags] & NSAlternateKeyMask && key == NSLeftArrowFunctionKey) - [fMovieView gotoBeginning:self]; - else if ([event modifierFlags] & NSAlternateKeyMask && key == NSRightArrowFunctionKey) - [fMovieView gotoEnd:self]; - else if (key == NSLeftArrowFunctionKey) - [fMovieView stepBackward:self]; - else if (key == NSRightArrowFunctionKey) - [fMovieView stepForward:self]; - else - [super keyDown:event]; - } - else if (self.currentViewMode != ViewModeEncoding) + if ([self.currentHUD HB_keyDown:event] == NO) { - if (key == NSLeftArrowFunctionKey) - { - [fPictureSlider setIntegerValue:self.pictureIndex > [fPictureSlider minValue] ? self.pictureIndex - 1 : self.pictureIndex]; - [self pictureSliderChanged:self]; - } - else if (key == NSRightArrowFunctionKey) - { - [fPictureSlider setIntegerValue:self.pictureIndex < [fPictureSlider maxValue] ? self.pictureIndex + 1 : self.pictureIndex]; - [self pictureSliderChanged:self]; - } - else - [super keyDown:event]; - } - else [super keyDown:event]; + } } -- (void)scrollWheel:(NSEvent *)theEvent +- (void)scrollWheel:(NSEvent *)event { - if (self.currentViewMode != ViewModeEncoding) + if ([self.currentHUD HB_scrollWheel:event] == NO) { - if (theEvent.deltaY < 0) - { - [fPictureSlider setIntegerValue:self.pictureIndex < [fPictureSlider maxValue] ? self.pictureIndex + 1 : self.pictureIndex]; - [self pictureSliderChanged:self]; - } - else if (theEvent.deltaY > 0) - { - [fPictureSlider setIntegerValue:self.pictureIndex > [fPictureSlider minValue] ? self.pictureIndex - 1 : self.pictureIndex]; - [self pictureSliderChanged:self]; - } + [super scrollWheel:event]; } } |