X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=macosx%2FHBPreviewController.m;h=4b60d7e4ae45989c7ab385b9720c04a8b52d222a;hb=0127c54ac319533945d02788f0a22d02fe699c7a;hp=750a68c4eee327f637748c13f8a1a7f32547a31b;hpb=4c6ed6bcc7a7d8a1fe9384f0e9717b071545660e;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/macosx/HBPreviewController.m b/macosx/HBPreviewController.m index 750a68c4..4b60d7e4 100644 --- a/macosx/HBPreviewController.m +++ b/macosx/HBPreviewController.m @@ -14,6 +14,8 @@ } @end + + @interface PreviewController (Private) - (NSSize)optimalViewSizeForImageSize: (NSSize)imageSize; @@ -44,12 +46,13 @@ int loggingLevel = [[[NSUserDefaults standardUserDefaults] objectForKey:@"LoggingLevel"] intValue]; fPreviewLibhb = hb_init(loggingLevel, 0); + + } return self; } - //------------------------------------------------------------------------------------ // Displays and brings the picture window to the front //------------------------------------------------------------------------------------ @@ -83,7 +86,6 @@ //[self pictureSliderChanged:nil]; [self startReceivingLibhbNotifications]; - isFullScreen = NO; hudTimerSeconds = 0; /* we set the progress indicator to not use threaded animation * as it causes a conflict with the qtmovieview's controllerbar @@ -131,10 +133,11 @@ // Show the picture view [fPictureView setHidden:NO]; [fMovieView pause:nil]; + [fMovieTimer invalidate]; + [fMovieTimer release]; [fMovieView setHidden:YES]; [fMovieView setMovie:nil]; - isFullScreen = NO; hudTimerSeconds = 0; [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"PreviewWindowIsOpen"]; } @@ -159,9 +162,16 @@ [fHudTimer invalidate]; [fHudTimer release]; + [fMovieTimer invalidate]; + [fMovieTimer release]; + [fPicturePreviews release]; [fFullScreenWindow release]; - + + hb_close(&fPreviewLibhb); + + [self removeMovieCallbacks]; + [super dealloc]; } @@ -211,29 +221,33 @@ fPicture = 0; MaxOutputWidth = title->width - job->crop[2] - job->crop[3]; MaxOutputHeight = title->height - job->crop[0] - job->crop[1]; + [self SettingsChanged: nil]; + } // Adjusts the window to draw the current picture (fPicture) adjusting its size as // necessary to display as much of the picture as possible. -- (void) displayPreview +- (void) displayPreview { hb_job_t * job = fTitle->job; /* lets make sure that the still picture view is not hidden and that * the movie preview is */ + aMovie = nil; [fMovieView pause:nil]; [fMovieView setHidden:YES]; [fMovieView setMovie:nil]; [fMovieCreationProgressIndicator stopAnimation: nil]; [fMovieCreationProgressIndicator setHidden: YES]; + [fMoviePlaybackControlBox setHidden: YES]; + [self stopMovieTimer]; + [fPictureControlBox setHidden: NO]; [fPictureView setHidden:NO]; - //[fHBController writeToActivityLog: "displayPreview called"]; - NSImage *fPreviewImage = [self imageForPicture: fPicture]; NSSize imageScaledSize = [fPreviewImage size]; [fPictureView setImage: fPreviewImage]; @@ -276,7 +290,7 @@ @"Source: %dx%d, Output: %dx%d, Anamorphic: %dx%d Custom", fTitle->width, fTitle->height, output_width, output_height, fTitle->job->anamorphic.dar_width, fTitle->job->anamorphic.dar_height]; - displaySize.width = fTitle->job->anamorphic.dar_width + fTitle->job->crop[2] + fTitle->job->crop[3]; + displaySize.width = fTitle->job->anamorphic.dar_width + fTitle->job->crop[2] + fTitle->job->crop[3] ; displaySize.height = fTitle->job->anamorphic.dar_height + fTitle->job->crop[0] + fTitle->job->crop[1]; imageScaledSize.width = (int)fTitle->job->anamorphic.dar_width; imageScaledSize.height = (int)fTitle->job->height; @@ -286,74 +300,118 @@ sizeInfoString = [NSString stringWithFormat: @"Source: %dx%d, Output: %dx%d", fTitle->width, fTitle->height, fTitle->job->width, fTitle->job->height]; - + displaySize.width = fTitle->width; displaySize.height = fTitle->height; imageScaledSize.width = fTitle->job->width; imageScaledSize.height = fTitle->job->height; } + + NSSize viewSize = [self optimalViewSizeForImageSize:displaySize]; + [self resizeSheetForViewSize:viewSize]; + + NSSize windowSize = [[self window] frame].size; - /* Initially set our preview image here */ - /* if (scaleToScreen == YES) { - viewSize.width = viewSize.width - (viewSize.width - imageScaledSize.width); - viewSize.height = viewSize.height - (viewSize.height - imageScaledSize.height); - [fPreviewImage setSize: viewSize]; - //[fPictureView setFrameSize: viewSize]; + /* Note: this should probably become a utility function */ + /* We are in Scale To Screen mode so, we have to get the ratio for height and width against the window + *size so we can scale from there. + */ + CGFloat deltaWidth = imageScaledSize.width / displaySize.width; + CGFloat deltaHeight = imageScaledSize.height /displaySize.height; + NSSize windowSize = [[self window] frame].size; + CGFloat pictureAspectRatio = imageScaledSize.width / imageScaledSize.height; + + /* Set our min size to the storage size */ + NSSize minSize; + minSize.width = fTitle->width; + minSize.height = fTitle->height; + + /* Set delta's based on minimum size */ + if (imageScaledSize.width < minSize.width) + { + deltaWidth = imageScaledSize.width / minSize.width; + } + else + { + deltaWidth = 1.0; + } + + if (imageScaledSize.height < minSize.height) + { + deltaHeight = imageScaledSize.height / minSize.height; + } + else + { + deltaHeight = 1.0; + } + + /* Now apply our deltas to the full screen view */ + if (pictureAspectRatio > 1.0) // we are wider than taller, so expand the width to fill the area and scale the height + { + viewSize.width = windowSize.width * deltaWidth; + viewSize.height = viewSize.width / pictureAspectRatio; + + } + else + { + viewSize.height = windowSize.height * deltaHeight; + viewSize.width = viewSize.height * pictureAspectRatio; + } + } - else { - [fPreviewImage setSize: imageScaledSize]; - [fPictureView setFrameSize: imageScaledSize]; - } - [fPictureView setImage: fPreviewImage]; - // center it vertically and horizontally - NSPoint origin = [fPictureViewArea frame].origin; - origin.y += ([fPictureViewArea frame].size.height - - [fPictureView frame].size.height) / 2.0; - - origin.x += ([fPictureViewArea frame].size.width - - [fPictureView frame].size.width) / 2.0; - [fPictureView setFrameOrigin:origin]; - */ - /* we also need to take into account scaling to full screen to activate switching the view size */ - if( [self viewNeedsToResizeToSize:viewSize]) - { - if (fTitle->job->anamorphic.mode != 2 || (fTitle->job->anamorphic.mode == 2 && fTitle->width == fTitle->job->width)) + viewSize.width = viewSize.width - (viewSize.width - imageScaledSize.width); + viewSize.height = viewSize.height - (viewSize.height - imageScaledSize.height); + + if (fTitle->width > windowSize.width || fTitle->height > windowSize.height) { - [self resizeSheetForViewSize:viewSize]; - //[self setViewSize:viewSize]; - + CGFloat viewSizeAspect = viewSize.width / viewSize.height; + if (viewSizeAspect > 1.0) // we are wider than taller, so expand the width to fill the area and scale the height + { + viewSize.width = viewSize.width * (windowSize.width / fTitle->width) ; + viewSize.height = viewSize.width / viewSizeAspect; + } + else + { + viewSize.height = viewSize.height * (windowSize.height / fTitle->height); + viewSize.width = viewSize.height * viewSizeAspect; + } } - } + + } - viewSize.width = viewSize.width - (viewSize.width - imageScaledSize.width); - viewSize.height = viewSize.height - (viewSize.height - imageScaledSize.height); [self setViewSize:viewSize]; - /* special case for scaleToScreen */ - if (scaleToScreen == YES) - { - [fPreviewImage setSize: viewSize]; - [fPictureView setImage: fPreviewImage]; - } - + /* relocate our hud origins as per setViewSize */ + NSPoint hudControlBoxOrigin = [fPictureControlBox frame].origin; + hudControlBoxOrigin.y = ([[self window] frame].size.height / 2) - (viewSize.height / 2); + hudControlBoxOrigin.x = ([[self window] frame].size.width / 2) - ([fPictureControlBox frame].size.width / 2); + [fPictureControlBox setFrameOrigin:hudControlBoxOrigin]; + [fEncodingControlBox setFrameOrigin:hudControlBoxOrigin]; + [fMoviePlaybackControlBox setFrameOrigin:hudControlBoxOrigin]; + + NSString *scaleString; - - if( imageScaledSize.height > [fPictureView frame].size.height) + CGFloat scale = ( ( CGFloat )[fPictureView frame].size.width) / ( ( CGFloat )imageScaledSize.width); + if (scale * 100.0 != 100) { - CGFloat scale = ( ( CGFloat )[fPictureView frame].size.width) / ( ( CGFloat )imageScaledSize.width); scaleString = [NSString stringWithFormat: - NSLocalizedString( @" (Scaled to %.0f%% actual size)", + NSLocalizedString( @" (%.0f%% actual size)", @"String shown when a preview is scaled" ), scale * 100.0]; } else { - scaleString = @""; + scaleString = @"(Actual size)"; + } + + if (scaleToScreen == YES) + { + scaleString = [scaleString stringByAppendingString:@" Scaled To Screen"]; } /* Set the info fields in the hud controller */ [fInfoField setStringValue: [NSString stringWithFormat: @@ -409,7 +467,6 @@ [self showWindow:sender]; [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"PreviewWindowIsOpen"]; [fPreviewWindow setAcceptsMouseMovedEvents:YES]; - isFullScreen = NO; scaleToScreen = NO; [self pictureSliderChanged:nil]; } @@ -433,19 +490,35 @@ NSPoint mouseLoc = [theEvent locationInWindow]; /* Test for mouse location to show/hide hud controls */ - if( isEncoding == NO ) { + if( isEncoding == NO ) + { + /* Since we are not encoding, verify which control hud to show + * or hide based on aMovie ( aMovie indicates we need movie controls ) + */ + NSBox * hudBoxToShow; + if ( aMovie == nil ) // No movie loaded up + { + hudBoxToShow = fPictureControlBox; + } + else // We have a movie + { + hudBoxToShow = fMoviePlaybackControlBox; + } + if( NSPointInRect( mouseLoc, [fPictureControlBox frame] ) ) { - [[fPictureControlBox animator] setHidden: NO]; + [[hudBoxToShow animator] setHidden: NO]; [self stopHudTimer]; } else if( NSPointInRect( mouseLoc, [fPictureViewArea frame] ) ) { - [[fPictureControlBox animator] setHidden: NO]; + [[hudBoxToShow animator] setHidden: NO]; [self startHudTimer]; } else - [[fPictureControlBox animator] setHidden: YES]; + { + [[hudBoxToShow animator] setHidden: YES]; + } } } @@ -473,25 +546,18 @@ - (void) hudTimerFired: (NSTimer*)theTimer { hudTimerSeconds++; - if( hudTimerSeconds >= 10 ) { + if( hudTimerSeconds >= 10 ) + { + /* Regardless which control box is active, after the timer + * period we want either one to fade to hidden. + */ [[fPictureControlBox animator] setHidden: YES]; + [[fMoviePlaybackControlBox animator] setHidden: YES]; [self stopHudTimer]; } } -#pragma mark Fullscreen Mode -- (IBAction)toggleScreenMode:(id)sender -{ - if (!isFullScreen) - { - [self goFullScreen:nil]; - } - else - { - [self goWindowedScreen:nil]; - } -} - (IBAction)toggleScaleToScreen:(id)sender { @@ -500,116 +566,19 @@ scaleToScreen = NO; /* make sure we are set to a still preview */ [self pictureSliderChanged:nil]; - [fScaleToScreenToggleButton setTitle:@"<->"]; + [fScaleToScreenToggleButton setTitle:@"Scale To Screen"]; } else { scaleToScreen = YES; /* make sure we are set to a still preview */ [self pictureSliderChanged:nil]; - [fScaleToScreenToggleButton setTitle:@">-<"]; + [fScaleToScreenToggleButton setTitle:@"Actual Scale"]; } + } -- (BOOL)fullScreen -{ - return isFullScreen; -} -- (IBAction)goFullScreen:(id)sender -{ - // Get the screen information. - NSScreen* mainScreen = [fPreviewWindow screen]; - NSDictionary* screenInfo = [mainScreen deviceDescription]; - NSNumber* screenID = [screenInfo objectForKey:@"NSScreenNumber"]; - // Capture the screen. - CGDirectDisplayID displayID = (CGDirectDisplayID)[screenID longValue]; - CGDisplayErr err = CGDisplayCapture(displayID); - - if (err == CGDisplayNoErr) - { - - /* make sure we are set to a still preview and not scaled to screen */ - scaleToScreen = NO; - [self pictureSliderChanged:nil]; - - // Create the full-screen window. - //NSRect winRect = [mainScreen frame]; - //fPictureViewArea - NSRect winRect = [fPictureViewArea frame]; - - fFullScreenWindow = [[NSWindow alloc] initWithContentRect:winRect - styleMask:NSBorderlessWindowMask - backing:NSBackingStoreBuffered - defer:NO - screen:mainScreen]; - - // Establish the window attributes. - [fFullScreenWindow setReleasedWhenClosed:NO]; - [fFullScreenWindow setDisplaysWhenScreenProfileChanges:YES]; - [fFullScreenWindow setDelegate:self]; - - /* insert a view into the new window */ - [fFullScreenWindow setContentView:fPictureViewArea]; - [fPictureViewArea setNeedsDisplay:YES]; - - /* Better to center the window using the screen's frame - * and the windows origin. Note that we should take into - * account the auto sizing and alignment that occurs in - * setViewSize each time the preview changes. - * Note: by using [fFullScreenWindow screen] (instead of - * [NSScreen mainScreen]) in referencing the screen - * coordinates, the full screen window will show up on - * whichever display was being used in windowed mode - * on multi-display systems - */ - - NSSize screenSize = [[fFullScreenWindow screen] frame].size; - NSSize windowSize = [fFullScreenWindow frame].size; - NSPoint windowOrigin = [fFullScreenWindow frame].origin; - - /* Adjust our origin y (vertical) based on the screen height */ - windowOrigin.y += (screenSize.height - windowSize.height) / 2.0; - windowOrigin.x += (screenSize.width - windowSize.width) / 2.0; - - [fFullScreenWindow setFrameOrigin:windowOrigin]; - - /* lets kill the timer for now */ - [self stopReceivingLibhbNotifications]; - - /* We need to retain the fPreviewWindow */ - [fPreviewWindow retain]; - - [self setWindow:fFullScreenWindow]; - - // The window has to be above the level of the shield window. - int32_t shieldLevel = CGShieldingWindowLevel(); - - [fFullScreenWindow setLevel:shieldLevel]; - - // Show the window. - [fFullScreenWindow makeKeyAndOrderFront:self]; - - - /* Change the name of fFullScreenToggleButton appropriately */ - [fFullScreenToggleButton setTitle: @"Windowed"]; - - /* Lets fire the timer back up for the hud controls, etc. */ - [self startReceivingLibhbNotifications]; - - isFullScreen = YES; - [fScaleToScreenToggleButton setHidden:NO]; - - /* make sure we are set to a still preview */ - [self pictureSliderChanged:nil]; - - [fFullScreenWindow setAcceptsMouseMovedEvents:YES]; - - - hudTimerSeconds = 0; - [self startHudTimer]; - } -} // Title-less windows normally don't receive key presses, override this - (BOOL)canBecomeKeyWindow @@ -655,14 +624,14 @@ [fPreviewWindow setLevel:NSNormalWindowLevel]; /* Set the isFullScreen flag back to NO */ - isFullScreen = NO; + //isFullScreen = NO; scaleToScreen = NO; /* make sure we are set to a still preview */ [self pictureSliderChanged:nil]; [self showPreviewWindow:nil]; /* Change the name of fFullScreenToggleButton appropriately */ - [fFullScreenToggleButton setTitle: @"Full Screen"]; + //[fFullScreenToggleButton setTitle: @"Full Screen"]; // [fScaleToScreenToggleButton setHidden:YES]; /* set the picture settings pallete back to normal level */ [fHBController picturePanelWindowed]; @@ -992,9 +961,8 @@ [fMovieCreationProgressIndicator stopAnimation: nil]; [fMovieCreationProgressIndicator setHidden: YES]; [fEncodingControlBox setHidden: YES]; + [fPictureControlBox setHidden: YES]; isEncoding = NO; - /* we make sure the picture slider and preview match */ - [self pictureSliderChanged:nil]; // Show the movie view [self showMoviePreview:fPreviewMoviePath]; @@ -1005,6 +973,103 @@ } } +- (IBAction) toggleMoviePreviewPlayPause: (id) sender +{ + /* make sure a movie is even loaded up */ + if (aMovie != nil) + { + /* For some stupid reason there is no "isPlaying" method for a QTMovie + * object, given that, we detect the rate to determine whether the movie + * is playing or not. + */ + if ([aMovie rate] != 0) // we are playing + { + [fMovieView pause:aMovie]; + [fPlayPauseButton setTitle: @">"]; + } + else // we are paused or stopped + { + [fMovieView play:aMovie]; + [fPlayPauseButton setTitle: @"||"]; + } + } + +} + +- (IBAction) moviePlaybackGoToBeginning: (id) sender +{ + /* make sure a movie is even loaded up */ + if (aMovie != nil) + { + [fMovieView gotoBeginning:aMovie]; + } + +} + +- (IBAction) moviePlaybackGoToEnd: (id) sender +{ + /* make sure a movie is even loaded up */ + if (aMovie != nil) + { + [fMovieView gotoEnd:aMovie]; + } + +} + +- (IBAction) moviePlaybackGoBackwardOneFrame: (id) sender +{ + /* make sure a movie is even loaded up */ + if (aMovie != nil) + { + [fMovieView pause:aMovie]; // Pause the movie + [fMovieView stepBackward:aMovie]; + } + +} + +- (IBAction) moviePlaybackGoForwardOneFrame: (id) sender +{ + /* make sure a movie is even loaded up */ + if (aMovie != nil) + { + [fMovieView pause:aMovie]; // Pause the movie + [fMovieView stepForward:aMovie]; + } + +} + + +- (void) startMovieTimer +{ + if( fMovieTimer ) { + [fMovieTimer invalidate]; + [fMovieTimer release]; + } + fMovieTimer = [NSTimer scheduledTimerWithTimeInterval:0.10 target:self selector:@selector(movieTimerFired:) userInfo:nil repeats:YES]; + [fMovieTimer retain]; +} + +- (void) stopMovieTimer +{ + if( fMovieTimer ) + { + [fMovieTimer invalidate]; + [fMovieTimer release]; + fMovieTimer = nil; + } +} + +- (void) movieTimerFired: (NSTimer*)theTimer +{ + if (aMovie != nil) + { + [self adjustPreviewScrubberForCurrentMovieTime]; + [fMovieInfoField setStringValue: [NSString stringWithFormat:NSLocalizedString( @"%@", @"" ),[self calculatePlaybackSMTPETimecodeForDisplay]]]; + } +} + + + - (IBAction) showMoviePreview: (NSString *) path { /* Since the gray background for the still images is part of @@ -1013,10 +1078,11 @@ * we retain the gray cropping border we have already established * with the still previews */ - + /* Load the new movie into fMovieView */ - if (path) { - QTMovie * aMovie; + if (path) + { + //QTMovie * aMovie; NSError *outError; NSURL *movieUrl = [NSURL fileURLWithPath:path]; NSDictionary *movieAttributes = [NSDictionary dictionaryWithObjectsAndKeys: @@ -1025,87 +1091,252 @@ [NSNumber numberWithBool:YES], @"QTMovieOpenForPlaybackAttribute", [NSNumber numberWithBool:NO], @"QTMovieOpenAsyncRequiredAttribute", [NSNumber numberWithBool:NO], @"QTMovieOpenAsyncOKAttribute", + [NSNumber numberWithBool:YES], @"QTMovieIsSteppableAttribute", QTMovieApertureModeClean, QTMovieApertureModeAttribute, nil]; - + aMovie = [[[QTMovie alloc] initWithAttributes:movieAttributes error:&outError] autorelease]; - - if (!aMovie) { + + + if (!aMovie) + { NSLog(@"Unable to open movie"); } - else { + else + { NSRect movieBounds; /* we get some size information from the preview movie */ NSSize movieSize= [[aMovie attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]; movieBounds = [fMovieView movieBounds]; movieBounds.size.height = movieSize.height; - - if ([fMovieView isControllerVisible]) { + /* We also get our view size to use for scaling fMovieView's size */ + NSSize scaledMovieViewSize = [fPictureView frame].size; + [fMovieView setControllerVisible:FALSE]; + if ([fMovieView isControllerVisible]) + { CGFloat controllerBarHeight = [fMovieView controllerBarHeight]; if ( controllerBarHeight != 0 ) //Check if QTKit return a real value or not. + { movieBounds.size.height += controllerBarHeight; + scaledMovieViewSize.height += controllerBarHeight; + } else + { movieBounds.size.height += 15; + scaledMovieViewSize.height += 15; + } } movieBounds.size.width = movieSize.width; - /* We need to find out if the preview movie needs to be scaled down so - * that it doesn't overflow our available viewing container (just like for image - * in -displayPreview) for HD sources, etc. [fPictureViewArea frame].size.height*/ - if( (movieBounds.size.height) > [fPictureViewArea frame].size.height || scaleToScreen == YES ) + /* we need to account for an issue where the scaledMovieViewSize > the window size */ + if (scaledMovieViewSize.height > [[self window] frame].size.height) { - /* The preview movie would be larger than the available viewing area - * in the preview movie, so we go ahead and scale it down to the same size - * as the still preview or we readjust our window to allow for the added height if need be - */ - NSSize displaySize = NSMakeSize( ( CGFloat ) movieBounds.size.width, ( CGFloat ) movieBounds.size.height ); - NSSize viewSize = [self optimalViewSizeForImageSize:displaySize]; - if( [self viewNeedsToResizeToSize:viewSize] ) { - [self resizeSheetForViewSize:viewSize]; - [self setViewSize:viewSize]; - } - [fMovieView setFrameSize:viewSize]; - } - else - { - /* Since the preview movie is smaller than the available viewing area - * we can go ahead and use the preview movies native size */ - [fMovieView setFrameSize:movieBounds.size]; + [fHBController writeToActivityLog: "showMoviePreview: Our window is not tall enough to show the controller bar ..."]; } - //lets reposition the movie if need be - NSPoint origin = [fPictureViewArea frame].origin; - origin.x += trunc( ( [fPictureViewArea frame].size.width - + + /* Scale the fMovieView to scaledMovieViewSize */ + [fMovieView setFrameSize:scaledMovieViewSize]; + + /*set our origin try using fPictureViewArea or fPictureView */ + NSPoint origin = [fPictureView frame].origin; + origin.x += trunc( ( [fPictureView frame].size.width - [fMovieView frame].size.width ) / 2.0 ); - /* We need to detect whether or not we are currently less than the available height.*/ - if( movieBounds.size.height < [fPictureView frame].size.height ) - { - /* If we are, we are adding 15 to the height to allow for the controller bar so - * we need to subtract half of that for the origin.y to get the controller bar - * below the movie to it lines up vertically with where our still preview was - */ - origin.y += trunc( ( ( [fPictureViewArea frame].size.height - + origin.y += trunc( ( ( [fPictureView frame].size.height - [fMovieView frame].size.height ) / 2.0 ) - 7.5 ); - } - else - { - /* if we are >= to the height of the picture view area, the controller bar - * gets taken care of with picture resizing, so we do not want to offset the height - */ - origin.y += trunc( ( [fPictureViewArea frame].size.height - - [fMovieView frame].size.height ) / 2.0 ); - } + [fMovieView setFrameOrigin:origin]; [fMovieView setMovie:aMovie]; [fMovieView setHidden:NO]; + [fMoviePlaybackControlBox setHidden: NO]; + [fPictureControlBox setHidden: YES]; + // to actually play the movie + + [self initPreviewScrubberForMovie]; + [self startMovieTimer]; + /* Install amovie notifications */ + [aMovie setDelegate:self]; + [self installMovieCallbacks]; [fMovieView play:aMovie]; + } } isEncoding = NO; } +#pragma mark *** Movie Playback Scrubber and time code methods *** + +/* Since MacOSX Leopard QTKit has taken over some responsibility for assessing movie playback + * information from the old QuickTime carbon api ( time code information as well as fps, etc.). + * However, the QTKit devs at apple were not really big on documentation and further ... + * QuickTimes ability to playback HB's largely variable framerate output makes perfectly frame + * accurate information at best convoluted. Still, for the purpose of a custom hud based custom + * playback scrubber slider this has so far proven to be as accurate as I have found. To say it + * could use some better accuracy is not understating it enough probably. + * Most of this was gleaned from this obscure Apple Mail list thread: + * http://www.mailinglistarchive.com/quicktime-api@lists.apple.com/msg05642.html + * Now as we currently do not show a QTKit control bar with scrubber for display sizes > container + * size, this seems to facilitate playback control from the HB custom HUD controller fairly close + * to the built in controller bar. + * Further work needs to be done to try to get accurate frame by frame playback display if we want it. + * Note that the keyboard commands for frame by frame step through etc. work as always. + */ + +// Returns a human readable string from the currentTime of movie playback +- (NSString*) calculatePlaybackSMTPETimecodeForDisplay +{ + QTTime time = [aMovie currentTime]; + + NSString *smtpeTimeCodeString; + int days, hour, minute, second, frame; + long long result; + + result = time.timeValue / time.timeScale; // second + frame = (time.timeValue % time.timeScale) / 100; + + second = result % 60; + + result = result / 60; // minute + minute = result % 60; + + result = result / 60; // hour + hour = result % 24; + days = result; + + smtpeTimeCodeString = [NSString stringWithFormat:@"Time: %02d:%02d:%02d", hour, minute, second]; // hh:mm:ss + return smtpeTimeCodeString; + +} + + +// Initialize the preview scrubber min/max to appropriate values for the current movie +-(void) initPreviewScrubberForMovie +{ + if (aMovie) + { + + QTTime duration = [aMovie duration]; + float result = duration.timeValue / duration.timeScale; + + [fMovieScrubberSlider setMinValue:0.0]; + [fMovieScrubberSlider setMaxValue: (float)result]; + [fMovieScrubberSlider setFloatValue: 0.0]; + } +} + + +-(void) adjustPreviewScrubberForCurrentMovieTime +{ + if (aMovie) + { + QTTime time = [aMovie currentTime]; + + float result = (float)time.timeValue / (float)time.timeScale;; + [fMovieScrubberSlider setFloatValue:result]; + } +} + +- (IBAction) previewScrubberChanged: (id) sender +{ + if (aMovie) + { + [fMovieView pause:aMovie]; // Pause the movie + QTTime time = [aMovie currentTime]; + [self setTime: time.timeScale * [fMovieScrubberSlider floatValue]]; + [self calculatePlaybackSMTPETimecodeForDisplay]; + } +} +#pragma mark *** Movie Notifications *** + +- (void) installMovieCallbacks +{ + + +/*Notification for any time the movie rate changes */ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(movieRateDidChange:) + name:@"QTMovieRateDidChangeNotification" + object:aMovie]; + /*Notification for when the movie ends */ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(movieDidEnd:) + name:@"QTMovieDidEndNotification" + object:aMovie]; +} + +- (void)removeMovieCallbacks +{ + if (aMovie) + { + /*Notification for any time the movie rate changes */ + [[NSNotificationCenter defaultCenter] removeObserver:self + name:@"QTMovieRateDidChangeNotification" + object:aMovie]; + /*Notification for when the movie ends */ + [[NSNotificationCenter defaultCenter] removeObserver:self + name:@"QTMovieDidEndNotification" + object:aMovie]; + } +} + +- (void)movieRateDidChange:(NSNotification *)notification +{ + if (aMovie != nil) + { + /* For some stupid reason there is no "isPlaying" method for a QTMovie + * object, given that, we detect the rate to determine whether the movie + * is playing or not. + */ + //[self adjustPreviewScrubberForCurrentMovieTime]; + if ([aMovie rate] != 0) // we are playing + { + [fPlayPauseButton setTitle: @"||"]; + } + else // we are paused or stopped + { + [fPlayPauseButton setTitle: @">"]; + } + } +} +/* This notification is not currently used. However we should keep it "just in case" as + * live preview playback is enhanced. + */ +- (void)movieDidEnd:(NSNotification *)notification +{ + + //[fHBController writeToActivityLog: "Movie DidEnd Notification Received"]; +} + + +#pragma mark *** QTTime Utilities *** + + // convert a time value (long) to a QTTime structure +-(void)timeToQTTime:(long)timeValue resultTime:(QTTime *)aQTTime +{ + NSNumber *timeScaleObj; + long timeScaleValue; + + timeScaleObj = [aMovie attributeForKey:QTMovieTimeScaleAttribute]; + timeScaleValue = [timeScaleObj longValue]; + + *aQTTime = QTMakeTime(timeValue, timeScaleValue); +} + + // set the movie's current time +-(void)setTime:(int)timeValue +{ + QTTime movieQTTime; + NSValue *valueForQTTime; + + [self timeToQTTime:timeValue resultTime:&movieQTTime]; + + valueForQTTime = [NSValue valueWithQTTime:movieQTTime]; + + [aMovie setAttribute:valueForQTTime forKey:QTMovieCurrentTimeAttribute]; +} + @end @@ -1119,31 +1350,37 @@ // - (NSSize)optimalViewSizeForImageSize: (NSSize)imageSize { - // The min size is 320x240 + // The min size is 480x360 CGFloat minWidth = 480.0; CGFloat minHeight = 360.0; - NSSize screenSize = [[NSScreen mainScreen] frame].size; + NSSize screenSize = [[[self window] screen] visibleFrame].size; NSSize sheetSize = [[self window] frame].size; NSSize viewAreaSize = [fPictureViewArea frame].size; - CGFloat paddingX = sheetSize.width - viewAreaSize.width; - CGFloat paddingY = sheetSize.height - viewAreaSize.height; - CGFloat maxWidth; - CGFloat maxHeight; + CGFloat paddingX = 0.00; + CGFloat paddingY = 0.00; - if (isFullScreen) + if (fTitle->width > screenSize.width || fTitle->height > screenSize.height) { - /* We are in full screen mode so lets use the full screen if we need to */ - maxWidth = screenSize.width - paddingX; - maxHeight = screenSize.height - paddingY; - } - else - { - // The max size of the view is when the sheet is taking up 85% of the screen. - maxWidth = (0.85 * screenSize.width) - paddingX; - maxHeight = (0.85 * screenSize.height) - paddingY; + if (scaleToScreen == YES) + { + paddingX = screenSize.width - imageSize.width; + paddingY = screenSize.height - imageSize.height; + } + + else + { + paddingX = sheetSize.width - viewAreaSize.width; + paddingY = sheetSize.height - viewAreaSize.height; + } + } + CGFloat maxWidth; + CGFloat maxHeight; + maxWidth = screenSize.width - paddingX; + maxHeight = screenSize.height - paddingY; + NSSize resultSize = imageSize; CGFloat resultPar = resultSize.width / resultSize.height; @@ -1151,7 +1388,7 @@ CGFloat screenAspect = screenSize.width / screenSize.height; // Note, a standard dvd will use 720 x 480 which is a 1.5 CGFloat viewAreaAspect = viewAreaSize.width / viewAreaSize.height; - + if (scaleToScreen == YES) { @@ -1193,8 +1430,8 @@ { resultSize.height = minHeight; } - - return resultSize; + + return resultSize; } @@ -1213,8 +1450,19 @@ // Now resize the whole panel by those same deltas, but don't exceed the min NSRect frame = [[self window] frame]; - NSSize maxSize = [[self window] maxSize]; - NSSize minSize = [[self window] minSize]; + NSSize maxSize = [[[self window] screen] visibleFrame].size; + /* if we are not Scale To Screen, put an 85% of visible screen on the window */ + if (scaleToScreen == NO ) + { + maxSize.width = maxSize.width * 0.85; + maxSize.height = maxSize.height * 0.85; + } + + /* Set our min size to the storage size */ + NSSize minSize; + minSize.width = fTitle->width; + minSize.height = fTitle->height; + frame.size.width += deltaX; frame.size.height += deltaY; if( frame.size.width < minSize.width ) @@ -1226,37 +1474,46 @@ { frame.size.height = minSize.height; } + /* 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; + } + + + // But now the sheet is off-center, so also shift the origin to center it and // keep the top aligned. if( frame.size.width != [[self window] frame].size.width ) frame.origin.x -= (deltaX / 2.0); - if (isFullScreen) - { - if( frame.size.height != [[self window] frame].size.height ) - { - frame.origin.y -= (deltaY / 2.0); - } - else - { - if( frame.size.height != [[self window] frame].size.height ) - frame.origin.y -= deltaY; - } - [[self window] setFrame:frame display:YES animate:NO]; - } - else - { /* 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 = [[[self window] screen] frame].size; + NSSize screenSize = [[[self window] screen] visibleFrame].size; NSPoint screenOrigin = [[[self window] screen] frame].origin; + if (screenSize.height < frame.size.height) + { + frame.size.height = screenSize.height; + } + if (screenSize.width < frame.size.width) + { + frame.size.width = screenSize.width; + } + + /* our origin is off the screen to the left*/ if (frame.origin.x < screenOrigin.x) { @@ -1270,7 +1527,7 @@ } [[self window] setFrame:frame display:YES animate:YES]; - } + } @@ -1282,12 +1539,16 @@ // - (void)setViewSize: (NSSize)viewSize { + /* special case for scaleToScreen */ - if (scaleToScreen == YES) + NSSize screenSize = [[[self window] screen] visibleFrame].size; + NSSize areaSize = [fPictureViewArea frame].size; + NSSize pictureSize = [fPictureView frame].size; + CGFloat viewSizeAspect = viewSize.width / viewSize.height; + + if (viewSize.width > areaSize.width || viewSize.height > areaSize.height) { - /* for scaleToScreen, we expand the fPictureView to fit the entire screen */ - NSSize areaSize = [fPictureViewArea frame].size; - CGFloat viewSizeAspect = viewSize.width / viewSize.height; + if (viewSizeAspect > 1.0) // we are wider than taller, so expand the width to fill the area and scale the height { viewSize.width = areaSize.width; @@ -1300,9 +1561,11 @@ } } - + [fPictureView setFrameSize:viewSize]; - + NSSize newAreaSize = [fPictureViewArea frame].size; + + // center it vertically and horizontally NSPoint origin = [fPictureViewArea frame].origin; origin.y += ([fPictureViewArea frame].size.height - @@ -1315,6 +1578,7 @@ origin.y = floor( origin.y ); [fPictureView setFrameOrigin:origin]; + }