}
@end
+
+
@interface PreviewController (Private)
- (NSSize)optimalViewSizeForImageSize: (NSSize)imageSize;
int loggingLevel = [[[NSUserDefaults standardUserDefaults] objectForKey:@"LoggingLevel"] intValue];
fPreviewLibhb = hb_init(loggingLevel, 0);
+
+
}
return self;
}
-
//------------------------------------------------------------------------------------
// Displays and brings the picture window to the front
//------------------------------------------------------------------------------------
//[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
// 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"];
}
[fHudTimer invalidate];
[fHudTimer release];
+ [fMovieTimer invalidate];
+ [fMovieTimer release];
+
[fPicturePreviews release];
[fFullScreenWindow release];
-
+
+ hb_close(&fPreviewLibhb);
+
+ [self removeMovieCallbacks];
+
[super dealloc];
}
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];
@"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;
sizeInfoString = [NSString stringWithFormat:
@"Source: %dx%d, Output: %dx%d", fTitle->width, fTitle->height,
fTitle->job->width, fTitle->job->height];
- /* original
+
displaySize.width = fTitle->width;
displaySize.height = fTitle->height;
imageScaledSize.width = fTitle->job->width;
imageScaledSize.height = fTitle->job->height;
- */
- /* Test ... */
- displaySize.width = fTitle->width;
- displaySize.height = fTitle->height;
- imageScaledSize.width = fTitle->job->width + fTitle->job->crop[2] + fTitle->job->crop[3];
- imageScaledSize.height = fTitle->job->height + fTitle->job->crop[0] - fTitle->job->crop[1];
}
+
+
NSSize viewSize = [self optimalViewSizeForImageSize:displaySize];
+ [self resizeSheetForViewSize:viewSize];
+
+ NSSize windowSize = [[self window] frame].size;
- /* we also need to take into account scaling to full screen to activate switching the view size */
- if( [self viewNeedsToResizeToSize:viewSize])
+ if (scaleToScreen == YES)
{
- if (fTitle->job->anamorphic.mode != 2 || (fTitle->job->anamorphic.mode == 2 && fTitle->width == fTitle->job->width))
+ /* 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)
{
- [self resizeSheetForViewSize:viewSize];
- [self setViewSize:viewSize];
+ 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;
}
- }
-
- 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)
+ else
+ {
+ viewSize.height = windowSize.height * deltaHeight;
+ viewSize.width = viewSize.height * pictureAspectRatio;
+ }
+
+ }
+ else
{
- [fPreviewImage setSize: viewSize];
- [fPictureView setImage: fPreviewImage];
+ 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)
+ {
+ 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;
+ }
+ }
+
}
+ [self setViewSize:viewSize];
+
+ /* 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;
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( @" (%.0f%% actual size)",
@"String shown when a preview is scaled" ), scale * 100.0];
{
scaleString = @"(Actual size)";
}
+
+ if (scaleToScreen == YES)
+ {
+ scaleString = [scaleString stringByAppendingString:@" Scaled To Screen"];
+ }
/* Set the info fields in the hud controller */
[fInfoField setStringValue: [NSString stringWithFormat:
@"%@", sizeInfoString]];
[self showWindow:sender];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"PreviewWindowIsOpen"];
[fPreviewWindow setAcceptsMouseMovedEvents:YES];
- isFullScreen = NO;
scaleToScreen = NO;
[self pictureSliderChanged:nil];
}
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];
+ }
}
}
- (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
{
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
[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];
[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];
}
}
+- (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
* 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:
[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
//
- (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] visibleFrame].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 paddingX = 0.00;
+ CGFloat paddingY = 0.00;
+
+ if (fTitle->width > screenSize.width || fTitle->height > screenSize.height)
+ {
+ 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;
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)
{
{
resultSize.height = minHeight;
}
-
- return resultSize;
+
+ return resultSize;
}
// Now resize the whole panel by those same deltas, but don't exceed the min
NSRect frame = [[self window] frame];
- NSSize screenSize = [[[self window] screen] frame].size;
- //NSSize maxSize = [[self window] maxSize];
NSSize maxSize = [[[self window] screen] visibleFrame].size;
- NSSize minSize = [[self window] minSize];
+ /* 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;
frame.size.height = minSize.height;
}
/* compare frame to max size of screen */
+
if( frame.size.width > maxSize.width )
{
frame.size.width = maxSize.width;
}
+
// But now the sheet is off-center, so also shift the origin to center it and
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
}
[[self window] setFrame:frame display:YES animate:YES];
- }
+
}
//
- (void)setViewSize: (NSSize)viewSize
{
+
/* special case for scaleToScreen */
NSSize screenSize = [[[self window] screen] visibleFrame].size;
NSSize areaSize = [fPictureViewArea frame].size;
- if (scaleToScreen == YES || viewSize.width > areaSize.width || viewSize.height > areaSize.height)
+ 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 */
- 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;
}
-
[fPictureView setFrameSize:viewSize];
-
+ NSSize newAreaSize = [fPictureViewArea frame].size;
+
+
// center it vertically and horizontally
NSPoint origin = [fPictureViewArea frame].origin;
origin.y += ([fPictureViewArea frame].size.height -
[fPictureView setFrameOrigin:origin];
- /* set the top of the hud controller boxes centered vertically with the origin of our window */
- NSPoint hudControlBoxOrigin = [fPictureControlBox frame].origin;
- hudControlBoxOrigin.y = ([[self window] frame].size.height / 2) - [fPictureControlBox frame].size.height;
- [fPictureControlBox setFrameOrigin:hudControlBoxOrigin];
- [fEncodingControlBox setFrameOrigin:hudControlBoxOrigin];
}