From 0affb4285a52f5e9d87de1c2836075ec34db5289 Mon Sep 17 00:00:00 2001 From: dynaflash Date: Tue, 18 May 2010 16:22:00 +0000 Subject: [PATCH] MacGui: Live Preview HUD Overlay playback controller initial implementation - Fixes current issue where a live preview with the display res larger than storage res would not show the built in QTKit control bar. - Replaces the stock QTKit movie controller. - Adds playback time code information to HUD display. - Allows frame by frame scrubbing via keyboard arrow keys. -- Methods exist for frame by frame step through but buttons are not on the HUD overlay yet. Known Bugs: - If movie is playing, first click on the scrubber bar can cause the movie to jump to beginning or end unless scrubber is held and dragged. - Probably some others I haven't seen yet. To Do (not that it ever will get done): - Replace the current crappy stock buttons with some decent ones. - Display accurate frame number hopefully though QTKit offers little documentation to get that exact info. - Add a volume slider and remember the volume setting in the prefs. - Add a subtitle control widget hopefully so that users can see what the subtitles would look like. Other small changes include adding some tooltips to the hud overlay controller widgets to hopefully make it a bit more intuitive. git-svn-id: svn://localhost/HandBrake/trunk@3300 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- macosx/English.lproj/PicturePreview.xib | 566 +++++++++++++++++++++++++++++++- macosx/HBPreviewController.h | 36 +- macosx/HBPreviewController.m | 351 ++++++++++++++++++-- 3 files changed, 914 insertions(+), 39 deletions(-) diff --git a/macosx/English.lproj/PicturePreview.xib b/macosx/English.lproj/PicturePreview.xib index 906930dd..a068db4a 100644 --- a/macosx/English.lproj/PicturePreview.xib +++ b/macosx/English.lproj/PicturePreview.xib @@ -2,10 +2,10 @@ 1050 - 10C540 + 10D573 740 - 1038.25 - 458.00 + 1038.29 + 460.00 YES @@ -16,12 +16,12 @@ YES 740 - 1591.3 + 1729 YES - + YES @@ -435,7 +435,7 @@ - {{21, 91}, {440, 99}} + {{21, 121}, {440, 99}} {0, 0} @@ -476,6 +476,198 @@ MCAwIDAgMC42AA + + + -2147483611 + + YES + + + 256 + + YES + + + 290 + {{18, 27}, {407, 21}} + + + YES + + + 0.70196080207824707 + 0.70196080207824707 + 0.70196080207824707 + 1 + + + YES + + + YES + + 67501824 + 0 + + + 100 + 0.0 + 0.0 + 0.0 + 0 + 1 + NO + NO + + + + + 268 + {{200, 53}, {39, 25}} + + YES + + 67239424 + 134217728 + + + LucidaGrande + 13 + 1044 + + + -2038169345 + 163 + + + 200 + 25 + + + + + 268 + {{171, 53}, {30, 25}} + + YES + + 67239424 + 134217728 + |< + + + -2038169345 + 163 + + + 200 + 25 + + + + + 268 + {{238, 53}, {32, 25}} + + YES + + 67239424 + 134217728 + >| + + + -2038169345 + 163 + + + 200 + 25 + + + + + 292 + {{335, 53}, {77, 25}} + + + YES + + + 0.70196080207824707 + 0.70196080207824707 + 0.70196080207824707 + 1 + + + YES + + + YES + + 67239424 + 134479872 + Still Previews + + + -2038284033 + 163 + + + 200 + 25 + + + + + 290 + {{18, 10}, {399, 12}} + + YES + + 67239424 + 4456448 + + + + YES + + + + + + {{1, 1}, {438, 97}} + + + + {{21, 16}, {440, 99}} + + {0, 0} + + 67239424 + 0 + Playback Controls + + + + 3 + MCAwLjgwMDAwMDAxAA + + + + 1 + 4 + 0 + NO + 12 + + 1 + MSAxIDEgMC41AA + + + 1 + MCAwIDAgMC42AA + + -2147483611 @@ -512,7 +704,7 @@ 265 - {{368, 23}, {46, 25}} + {{368, 21}, {46, 25}} YES @@ -566,7 +758,7 @@ - {{21, 204}, {440, 100}} + {{21, 233}, {440, 100}} {0, 0} @@ -824,6 +1016,102 @@ 282 + + + fMoviePlaybackControlBox + + + + 363 + + + + fPlayPauseButton + + + + 364 + + + + fGoToStillPreviewButton + + + + 368 + + + + pictureSliderChanged: + + + + 369 + + + + toggleMoviePreviewPlayPause: + + + + 370 + + + + fMovieScrubberSlider + + + + 371 + + + + fMovieInfoField + + + + 374 + + + + fGoToBeginningButton + + + + 380 + + + + fGoToEndButton + + + + 381 + + + + moviePlaybackGoToBeginning: + + + + 382 + + + + moviePlaybackGoToEnd: + + + + 383 + + + + previewScrubberChanged: + + + + 384 + @@ -878,8 +1166,9 @@ YES - + + @@ -1104,6 +1393,104 @@ + + 335 + + + YES + + + + + + + + + + + 341 + + + YES + + + + + + 346 + + + + + 361 + + + YES + + + + + + 362 + + + + + 365 + + + YES + + + + + + 366 + + + + + 372 + + + YES + + + + + + 373 + + + + + 375 + + + YES + + + + + + 376 + + + + + 378 + + + YES + + + + + + 379 + + + @@ -1119,6 +1506,7 @@ 209.IBPluginDependency 210.IBPluginDependency 213.IBPluginDependency + 215.IBAttributePlaceholdersKey 215.IBPluginDependency 215.IBViewIntegration.shadowBlurRadius 215.IBViewIntegration.shadowColor @@ -1127,6 +1515,7 @@ 216.IBPluginDependency 223.IBPluginDependency 224.IBPluginDependency + 226.IBAttributePlaceholdersKey 226.IBPluginDependency 226.ImportedFromIB2 227.IBPluginDependency @@ -1152,14 +1541,17 @@ 252.IBViewIntegration.shadowOffsetHeight 252.IBViewIntegration.shadowOffsetWidth 257.IBPluginDependency + 261.IBAttributePlaceholdersKey 261.IBPluginDependency 262.IBPluginDependency + 271.IBAttributePlaceholdersKey 271.IBPluginDependency 271.IBViewIntegration.shadowBlurRadius 271.IBViewIntegration.shadowColor 271.IBViewIntegration.shadowOffsetHeight 271.IBViewIntegration.shadowOffsetWidth 272.IBPluginDependency + 275.IBAttributePlaceholdersKey 275.IBPluginDependency 275.IBViewIntegration.shadowBlurRadius 275.IBViewIntegration.shadowColor @@ -1169,6 +1561,32 @@ 280.IBPluginDependency 280.ImportedFromIB2 281.IBPluginDependency + 335.IBPluginDependency + 335.IBViewIntegration.shadowBlurRadius + 335.IBViewIntegration.shadowColor + 335.IBViewIntegration.shadowOffsetHeight + 335.IBViewIntegration.shadowOffsetWidth + 341.IBPluginDependency + 346.IBPluginDependency + 361.IBAttributePlaceholdersKey + 361.IBPluginDependency + 362.IBPluginDependency + 365.IBAttributePlaceholdersKey + 365.IBPluginDependency + 365.IBViewIntegration.shadowBlurRadius + 365.IBViewIntegration.shadowColor + 365.IBViewIntegration.shadowOffsetHeight + 365.IBViewIntegration.shadowOffsetWidth + 366.IBPluginDependency + 372.IBPluginDependency + 372.ImportedFromIB2 + 373.IBPluginDependency + 375.IBAttributePlaceholdersKey + 375.IBPluginDependency + 376.IBPluginDependency + 378.IBAttributePlaceholdersKey + 378.IBPluginDependency + 379.IBPluginDependency 38.IBPluginDependency 38.ImportedFromIB2 5.IBEditorWindowLastContentRect @@ -1195,6 +1613,14 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Encode And Play Back A Live Preview At Your Current Settings + + com.apple.InterfaceBuilder.CocoaPlugin @@ -1206,6 +1632,14 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Select The Length Of Live Preview to Encode + + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -1231,14 +1665,38 @@ com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Cancel Live Preview Encode + + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Show Picture Settings Inspector + + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Scale Preview To Screen + + com.apple.InterfaceBuilder.CocoaPlugin @@ -1249,11 +1707,65 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Toggle Play/Pause + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Show Still Previews + + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Go To Beginning + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + ToolTip + + ToolTip + + Go To End + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin - {{261, 473}, {480, 360}} + {{262, 474}, {480, 360}} com.apple.InterfaceBuilder.CocoaPlugin - {{261, 473}, {480, 360}} + {{262, 474}, {480, 360}} {{221, 276}, {533, 580}} @@ -1280,7 +1792,7 @@ - 282 + 394 @@ -1318,11 +1830,17 @@ SettingsChanged: createMoviePreview: goWindowedScreen: + moviePlaybackGoBackwardOneFrame: + moviePlaybackGoForwardOneFrame: + moviePlaybackGoToBeginning: + moviePlaybackGoToEnd: pictureSliderChanged: previewDurationPopUpChanged: + previewScrubberChanged: showMoviePreview: showPictureSettings: showPreviewWindow: + toggleMoviePreviewPlayPause: toggleScaleToScreen: @@ -1332,10 +1850,16 @@ id id id + id + id + id + id + id NSString id id id + id @@ -1345,15 +1869,23 @@ fCancelPreviewMovieButton fCreatePreviewMovieButton fEncodingControlBox - fFullScreenToggleButton + fGoBackwardOneFrameButton + fGoForwardOneFrameButton + fGoToBeginningButton + fGoToEndButton + fGoToStillPreviewButton fInfoField fMovieCreationProgressIndicator + fMovieInfoField + fMoviePlaybackControlBox + fMovieScrubberSlider fMovieView fPictureControlBox fPictureSettingsToggleButton fPictureSlider fPictureView fPictureViewArea + fPlayPauseButton fPreviewMovieLengthPopUp fPreviewMovieStatusField fPreviewWindow @@ -1367,14 +1899,22 @@ NSButton NSBox NSButton + NSButton + NSButton + NSButton + NSButton NSTextField NSProgressIndicator + NSTextField + NSBox + NSSlider QTMovieView NSBox NSButton NSSlider NSImageView NSBox + NSButton NSPopUpButton NSTextField NSWindow diff --git a/macosx/HBPreviewController.h b/macosx/HBPreviewController.h index cbfd04c9..c8dc6d02 100644 --- a/macosx/HBPreviewController.h +++ b/macosx/HBPreviewController.h @@ -30,6 +30,7 @@ IBOutlet NSBox * fPictureViewArea; IBOutlet NSBox * fPictureControlBox; IBOutlet NSBox * fEncodingControlBox; + IBOutlet NSBox * fMoviePlaybackControlBox; IBOutlet NSSlider * fPictureSlider; IBOutlet NSTextField * fInfoField; @@ -52,7 +53,22 @@ IBOutlet NSButton * fScaleToScreenToggleButton; IBOutlet NSButton * fPictureSettingsToggleButton; BOOL scaleToScreen; + /* Movie Previews */ + QTMovie * aMovie; + IBOutlet QTMovieView * fMovieView; + /* Playback Panel Controls */ + IBOutlet NSButton * fPlayPauseButton; + IBOutlet NSButton * fGoToBeginningButton; + IBOutlet NSButton * fGoToEndButton; + IBOutlet NSButton * fGoForwardOneFrameButton; + IBOutlet NSButton * fGoBackwardOneFrameButton; + IBOutlet NSSlider * fMovieScrubberSlider; + IBOutlet NSButton * fGoToStillPreviewButton; + IBOutlet NSTextField * fMovieInfoField; + NSTimer * fMovieTimer; + + IBOutlet NSButton * fCreatePreviewMovieButton; IBOutlet NSButton * fCancelPreviewMovieButton; IBOutlet NSButton * fShowPreviewMovieButton; @@ -61,7 +77,6 @@ hb_handle_t * fPreviewLibhb; // private libhb for creating previews NSTimer * fLibhbTimer; // timer for retrieving state from libhb IBOutlet NSTextField * fPreviewMovieStatusField; - IBOutlet QTMovieView * fMovieView; IBOutlet NSPopUpButton * fPreviewMovieLengthPopUp; // popup of choices for length of preview in seconds } - (id)init; @@ -89,9 +104,28 @@ - (void) startReceivingLibhbNotifications; - (void) stopReceivingLibhbNotifications; +- (void) installMovieCallbacks; +- (void)removeMovieCallbacks; + - (IBAction) createMoviePreview: (id) sender; - (void) libhbStateChanged: (hb_state_t ) state; - (IBAction) showMoviePreview: (NSString *) path; +- (IBAction) toggleMoviePreviewPlayPause: (id) sender; +- (IBAction) moviePlaybackGoToBeginning: (id) sender; +- (IBAction) moviePlaybackGoToEnd: (id) sender; +- (IBAction) moviePlaybackGoBackwardOneFrame: (id) sender; +- (IBAction) moviePlaybackGoForwardOneFrame: (id) sender; + +-(void) initPreviewScrubberForMovie; +-(void) adjustPreviewScrubberForCurrentMovieTime; +- (IBAction) previewScrubberChanged: (id) sender; +-(void)setTime:(int)timeValue; +-(void)timeToQTTime:(long)timeValue resultTime:(QTTime *)aQTTime; +- (void) startMovieTimer; +- (void) stopMovieTimer; +- (NSString*) calculatePlaybackSMTPETimecodeForDisplay; + + - (IBAction) previewDurationPopUpChanged: (id) sender; diff --git a/macosx/HBPreviewController.m b/macosx/HBPreviewController.m index 764da459..5ad59761 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 //------------------------------------------------------------------------------------ @@ -130,6 +133,8 @@ // Show the picture view [fPictureView setHidden:NO]; [fMovieView pause:nil]; + [fMovieTimer invalidate]; + [fMovieTimer release]; [fMovieView setHidden:YES]; [fMovieView setMovie:nil]; @@ -157,11 +162,16 @@ [fHudTimer invalidate]; [fHudTimer release]; + [fMovieTimer invalidate]; + [fMovieTimer release]; + [fPicturePreviews release]; [fFullScreenWindow release]; hb_close(&fPreviewLibhb); - + + [self removeMovieCallbacks]; + [super dealloc]; } @@ -219,6 +229,7 @@ hudControlBoxOrigin.y = ([[self window] frame].size.height / 2) - [fPictureControlBox frame].size.height; [fPictureControlBox setFrameOrigin:hudControlBoxOrigin]; [fEncodingControlBox setFrameOrigin:hudControlBoxOrigin]; + [fMoviePlaybackControlBox setFrameOrigin:hudControlBoxOrigin]; } @@ -232,11 +243,15 @@ /* 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]; @@ -473,19 +488,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]; + } } } @@ -513,8 +544,13 @@ - (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]; } } @@ -923,6 +959,7 @@ [fMovieCreationProgressIndicator stopAnimation: nil]; [fMovieCreationProgressIndicator setHidden: YES]; [fEncodingControlBox setHidden: YES]; + [fPictureControlBox setHidden: YES]; isEncoding = NO; // Show the movie view @@ -934,6 +971,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 @@ -946,7 +1080,7 @@ /* Load the new movie into fMovieView */ if (path) { - QTMovie * aMovie; + //QTMovie * aMovie; NSError *outError; NSURL *movieUrl = [NSURL fileURLWithPath:path]; NSDictionary *movieAttributes = [NSDictionary dictionaryWithObjectsAndKeys: @@ -955,11 +1089,13 @@ [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) { NSLog(@"Unable to open movie"); @@ -973,6 +1109,7 @@ movieBounds.size.height = movieSize.height; /* 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]; @@ -994,23 +1131,6 @@ if (scaledMovieViewSize.height > [[self window] frame].size.height) { [fHBController writeToActivityLog: "showMoviePreview: Our window is not tall enough to show the controller bar ..."]; - /*we need to scale the movie down vertically by 15 px to allow for the controller bar - * and scale the width accordingly. - */ - - // FIX ME: currently trying to scale everything to show the controller bar does not work right. - // Commented out til fixed, resulting issue when the movie is the full size of the window is no - // controller bar is visible. Live Preview still plays fine though. - /* - CGFloat pictureAspectRatio = scaledMovieViewSize.width / scaledMovieViewSize.height; - scaledMovieViewSize.height = [[self window] frame].size.height - 15; - scaledMovieViewSize.width = scaledMovieViewSize.height * pictureAspectRatio; - NSRect windowFrame = [[self window] frame]; - windowFrame.size.width = scaledMovieViewSize.width; - windowFrame.size.height = scaledMovieViewSize.height + 15; - [[self window] setFrame:windowFrame display:YES animate:YES]; - [fPictureView setFrameSize:scaledMovieViewSize]; - */ } @@ -1028,12 +1148,193 @@ [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 -- 2.11.0