X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=macosx%2FHBPreviewController.m;h=a4d8b8455319d9c4eafcb4d4235225fbe938bc15;hb=4b72a63eb61a01275493c4bfb51ba02152d1c5e1;hp=71634fcfea6114eddca2064784f41412240abc00;hpb=0867bf7e602765fb0b9dcdc96a29da3928681a32;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/macosx/HBPreviewController.m b/macosx/HBPreviewController.m index 71634fcf..a4d8b845 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]; @@ -147,7 +152,7 @@ hb_stop(fPreviewLibhb); if (fPreviewMoviePath) { - [[NSFileManager defaultManager] removeFileAtPath:fPreviewMoviePath handler:nil]; + [[NSFileManager defaultManager] removeItemAtPath:fPreviewMoviePath error:nil]; [fPreviewMoviePath release]; } @@ -157,9 +162,16 @@ [fHudTimer invalidate]; [fHudTimer release]; + [fMovieTimer invalidate]; + [fMovieTimer release]; + [fPicturePreviews release]; [fFullScreenWindow release]; - + + hb_close(&fPreviewLibhb); + + [self removeMovieCallbacks]; + [super dealloc]; } @@ -209,6 +221,7 @@ fPicture = 0; MaxOutputWidth = title->width - job->crop[2] - job->crop[3]; MaxOutputHeight = title->height - job->crop[0] - job->crop[1]; + [self SettingsChanged: nil]; } @@ -217,17 +230,24 @@ // 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]; + if( fMovieTimer ) + { + [self stopMovieTimer]; + } + [fPictureControlBox setHidden: NO]; [fPictureView setHidden:NO]; @@ -273,7 +293,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; @@ -283,48 +303,106 @@ 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) + { + deltaWidth = imageScaledSize.width / minSize.width; + } + else + { + deltaWidth = 1.0; + } + + if (imageScaledSize.height < minSize.height) { - [self resizeSheetForViewSize:viewSize]; - [self setViewSize:viewSize]; + 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]; @@ -333,6 +411,11 @@ { 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]]; @@ -404,25 +487,63 @@ } #pragma mark Hud Control Overlay +/* enableHudControls and disableHudControls are used to sync enableUI + * in HBController so that during a scan we do not attempt to access source + * images, etc. which can cause a crash. In general this ui behavior will mirror + * the main window ui's enableUI method and in fact is called from there */ +- (void) enableHudControls +{ + [fPictureSlider setEnabled:YES]; + [fScaleToScreenToggleButton setEnabled:YES]; + [fCreatePreviewMovieButton setEnabled:YES]; + [fGoToStillPreviewButton setEnabled:YES]; + [fHBController writeToActivityLog: "Preview: Enabling HUD Controls"]; +} + +- (void) disableHudControls +{ + [fPictureSlider setEnabled:NO]; + [fScaleToScreenToggleButton setEnabled:NO]; + [fCreatePreviewMovieButton setEnabled:NO]; + [fGoToStillPreviewButton setEnabled:NO]; + [fHBController writeToActivityLog: "Preview: Disabling HUD Controls"]; +} + - (void) mouseMoved:(NSEvent *)theEvent { [super mouseMoved:theEvent]; 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]; + } } } @@ -450,8 +571,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]; } } @@ -644,6 +770,30 @@ #pragma mark Movie Preview + +- (IBAction) cancelCreateMoviePreview: (id) sender +{ + + hb_state_t s; + hb_get_state2( fPreviewLibhb, &s ); + + if(isEncoding && (s.state == HB_STATE_WORKING || s.state == HB_STATE_PAUSED)) + { + hb_stop( fPreviewLibhb ); + [fPictureView setHidden:NO]; + [fMovieView pause:nil]; + [fMovieView setHidden:YES]; + [fMovieView setMovie:nil]; + [fPictureSlider setHidden:NO]; + isEncoding = NO; + + [self pictureSliderChanged:nil]; + + return; + } + +} + - (IBAction) createMoviePreview: (id) sender { @@ -657,7 +807,7 @@ hb_get_state2( fPreviewLibhb, &s ); if(sender == fCancelPreviewMovieButton && (s.state == HB_STATE_WORKING || s.state == HB_STATE_PAUSED)) - { + { hb_stop( fPreviewLibhb ); [fPictureView setHidden:NO]; [fMovieView pause:nil]; @@ -682,24 +832,26 @@ [fHBController prepareJobForPreview]; + /* Make sure we have a Preview sub directory with our pidnum attached */ + NSString *PreviewDirectory = [NSString stringWithFormat:@"~/Library/Application Support/HandBrake/Previews/%d", [fHBController getPidnum]]; + PreviewDirectory = [PreviewDirectory stringByExpandingTildeInPath]; + if( ![[NSFileManager defaultManager] fileExistsAtPath:PreviewDirectory] ) + { + [[NSFileManager defaultManager] createDirectoryAtPath:PreviewDirectory + withIntermediateDirectories:NO + attributes:nil + error:nil]; + } /* Destination file. We set this to our preview directory * changing the extension appropriately.*/ if (fTitle->job->mux == HB_MUX_MP4) // MP4 file { /* we use .m4v for our mp4 files so that ac3 and chapters in mp4 will play properly */ - fPreviewMoviePath = @"~/Library/Application Support/HandBrake/Previews/preview_temp.m4v"; + fPreviewMoviePath = [PreviewDirectory stringByAppendingString:@"/preview_temp.m4v"]; } else if (fTitle->job->mux == HB_MUX_MKV) // MKV file { - fPreviewMoviePath = @"~/Library/Application Support/HandBrake/Previews/preview_temp.mkv"; - } - else if (fTitle->job->mux == HB_MUX_AVI) // AVI file - { - fPreviewMoviePath = @"~/Library/Application Support/HandBrake/Previews/preview_temp.avi"; - } - else if (fTitle->job->mux == HB_MUX_OGM) // OGM file - { - fPreviewMoviePath = @"~/Library/Application Support/HandBrake/Previews/preview_temp.ogm"; + fPreviewMoviePath = [PreviewDirectory stringByAppendingString:@"/preview_temp.mkv"]; } fPreviewMoviePath = [[fPreviewMoviePath stringByExpandingTildeInPath]retain]; @@ -707,8 +859,7 @@ /* See if there is an existing preview file, if so, delete it */ if( ![[NSFileManager defaultManager] fileExistsAtPath:fPreviewMoviePath] ) { - [[NSFileManager defaultManager] removeFileAtPath:fPreviewMoviePath - handler:nil]; + [[NSFileManager defaultManager] removeItemAtPath:fPreviewMoviePath error:nil]; } /* We now direct our preview encode to fPreviewMoviePath */ @@ -860,9 +1011,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]; @@ -873,6 +1023,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 @@ -885,7 +1132,7 @@ /* Load the new movie into fMovieView */ if (path) { - QTMovie * aMovie; + //QTMovie * aMovie; NSError *outError; NSURL *movieUrl = [NSURL fileURLWithPath:path]; NSDictionary *movieAttributes = [NSDictionary dictionaryWithObjectsAndKeys: @@ -894,11 +1141,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"); @@ -910,75 +1159,234 @@ NSSize movieSize= [[aMovie attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]; movieBounds = [fMovieView movieBounds]; 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]; 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 @@ -992,18 +1400,34 @@ // - (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; @@ -1014,7 +1438,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) { @@ -1056,8 +1480,8 @@ { resultSize.height = minHeight; } - - return resultSize; + + return resultSize; } @@ -1077,7 +1501,17 @@ // Now resize the whole panel by those same deltas, but don't exceed the min NSRect frame = [[self window] frame]; 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; @@ -1091,6 +1525,7 @@ frame.size.height = minSize.height; } /* compare frame to max size of screen */ + if( frame.size.width > maxSize.width ) { frame.size.width = maxSize.width; @@ -1102,6 +1537,7 @@ } + // But now the sheet is off-center, so also shift the origin to center it and @@ -1153,13 +1589,16 @@ // - (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; @@ -1173,9 +1612,10 @@ } - [fPictureView setFrameSize:viewSize]; - + NSSize newAreaSize = [fPictureViewArea frame].size; + + // center it vertically and horizontally NSPoint origin = [fPictureViewArea frame].origin; origin.y += ([fPictureViewArea frame].size.height - @@ -1189,11 +1629,6 @@ [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]; }