From fdabd6ab9d2a8b8d7d1460b3b351a5b452abc963 Mon Sep 17 00:00:00 2001 From: dynaflash Date: Mon, 24 Nov 2008 10:01:06 +0000 Subject: [PATCH] MacGui: Live Preview Initial Implementation - Uses a separate instance of libhb called fPreviewLibhb to do the preview encode. Bypasses the queueing system so you can encode a live preview on one source while encoding another. - All facets of the encode are replicated (including but not limited to audio tracks, subtitles and picture filters) *except* 2 pass. For speed's sake we only do one pass which should be more than sufficient for a 6 to 60 second preview. - Live Preview clips are stored in "~/Library/Application Support/HandBrake/Previews/" and remain until a new preview is called for of the same format in which case the old version of "mymovie.mkv" would be replaced with a current version called "mymovie.mkv". - Uses QTMovieView and QTMovieKit to show 5 - 60 seconds in 5 second increments (determined by a user set NSPopUpButton) of a live preview from the starting point of any of the existing 10 still previews. - Preview window is now non-modal so can be kept open to see the effect of changing presets, etc. - Next and Previous buttons replaced with a 10 position slider - Live Preview is shown same as users QuickTime implementation would show it. ie. without Perian installed, mkv's will not play back, etc. - Uses QT's stock controller bar with volume, scrubber and single frame advance buttons. - Known Issues: Movie alignment against the still preview considering the additional height of the movie controller bar. Particularly using loose anamorphic. I am sure there are others. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1951 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- macosx/Controller.h | 2 +- macosx/Controller.mm | 338 ++++++++++- macosx/English.lproj/PictureSettings.xib | 624 +++++++++++++++------ macosx/HandBrake.xcodeproj/project.pbxproj | 14 + macosx/PictureController.h | 34 +- macosx/PictureController.mm | 409 +++++++++++++- 6 files changed, 1210 insertions(+), 211 deletions(-) diff --git a/macosx/Controller.h b/macosx/Controller.h index 3625efd3d..453b48017 100644 --- a/macosx/Controller.h +++ b/macosx/Controller.h @@ -391,7 +391,7 @@ BOOL fIsDragging; - (IBAction)showDebugOutputPanel:(id)sender; - (void)setupToolbar; - +- (void) prepareJobForPreview; - (void) remindUserOfSleepOrShutdown; - (void)moveObjectsInPresetsArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(unsigned)insertIndex; diff --git a/macosx/Controller.mm b/macosx/Controller.mm index a1ab827e4..aba746109 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -34,7 +34,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It { return nil; } - + [HBPreferencesController registerUserDefaults]; fHandle = NULL; fQueueEncodeLibhb = NULL; @@ -42,24 +42,30 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It * outputPanel needs it right away, as may other future methods */ NSString *libraryDir = [NSSearchPathForDirectoriesInDomains( NSLibraryDirectory, - NSUserDomainMask, - YES ) objectAtIndex:0]; + NSUserDomainMask, + YES ) objectAtIndex:0]; AppSupportDirectory = [[libraryDir stringByAppendingPathComponent:@"Application Support"] - stringByAppendingPathComponent:@"HandBrake"]; + stringByAppendingPathComponent:@"HandBrake"]; if( ![[NSFileManager defaultManager] fileExistsAtPath:AppSupportDirectory] ) { [[NSFileManager defaultManager] createDirectoryAtPath:AppSupportDirectory attributes:nil]; } - + /* Check for and create the App Support Preview directory if necessary */ + NSString *PreviewDirectory = [AppSupportDirectory stringByAppendingPathComponent:@"Previews"]; + if( ![[NSFileManager defaultManager] fileExistsAtPath:PreviewDirectory] ) + { + [[NSFileManager defaultManager] createDirectoryAtPath:PreviewDirectory + attributes:nil]; + } outputPanel = [[HBOutputPanelController alloc] init]; fPictureController = [[PictureController alloc] initWithDelegate:self]; fQueueController = [[HBQueueController alloc] init]; fAdvancedOptions = [[HBAdvancedController alloc] init]; /* we init the HBPresets class which currently is only used - * for updating built in presets, may move more functionality - * there in the future - */ + * for updating built in presets, may move more functionality + * there in the future + */ fPresetsBuiltin = [[HBPresets alloc] init]; fPreferencesController = [[HBPreferencesController alloc] init]; /* Lets report the HandBrake version number here to the activity log and text log file */ @@ -2529,6 +2535,297 @@ fWorkingCount = 0; [self doRip]; } +#pragma mark - +#pragma mark Live Preview +/* Note,this is much like prepareJob, but directly sets the job vars so Picture Preview + * can encode to its temp preview directory and playback. This is *not* used for any actual user + * encodes + */ +- (void) prepareJobForPreview +{ + hb_list_t * list = hb_get_titles( fHandle ); + hb_title_t * title = (hb_title_t *) hb_list_item( list, + [fSrcTitlePopUp indexOfSelectedItem] ); + hb_job_t * job = title->job; + hb_audio_config_t * audio; + + /* Chapter selection */ + job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1; + job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1; + + /* Format (Muxer) and Video Encoder */ + job->mux = [[fDstFormatPopUp selectedItem] tag]; + job->vcodec = [[fVidEncoderPopUp selectedItem] tag]; + + + /* If mpeg-4, then set mpeg-4 specific options like chapters and > 4gb file sizes */ + if( [fDstFormatPopUp indexOfSelectedItem] == 0 ) + { + /* We set the largeFileSize (64 bit formatting) variable here to allow for > 4gb files based on the format being + mpeg4 and the checkbox being checked + *Note: this will break compatibility with some target devices like iPod, etc.!!!!*/ + if( [fDstMp4LargeFileCheck state] == NSOnState ) + { + job->largeFileSize = 1; + } + else + { + job->largeFileSize = 0; + } + /* We set http optimized mp4 here */ + if( [fDstMp4HttpOptFileCheck state] == NSOnState && [fDstMp4HttpOptFileCheck isEnabled] ) + { + job->mp4_optimize = 1; + } + else + { + job->mp4_optimize = 0; + } + } + if( [fDstFormatPopUp indexOfSelectedItem] == 0 || [fDstFormatPopUp indexOfSelectedItem] == 1 ) + { + /* We set the chapter marker extraction here based on the format being + mpeg4 or mkv and the checkbox being checked */ + if ([fCreateChapterMarkers state] == NSOnState) + { + job->chapter_markers = 1; + } + else + { + job->chapter_markers = 0; + } + } + + if( job->vcodec & HB_VCODEC_X264 ) + { + if ([fDstMp4iPodFileCheck state] == NSOnState) + { + job->ipod_atom = 1; + } + else + { + job->ipod_atom = 0; + } + + /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake + Currently only used with Constant Quality setting*/ + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2) + { + job->crf = 1; + } + + /* Below Sends x264 options to the core library if x264 is selected*/ + /* Lets use this as per Nyx, Thanks Nyx!*/ + job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ + /* For previews we ignore the turbo option for the first pass of two since we only use 1 pass */ + strcpy(job->x264opts, [[fAdvancedOptions optionsString] UTF8String]); + + + } + + /* Video settings */ + /* Set vfr to 0 as it's only on if using same as source in the framerate popup + * and detelecine is on, so we handle that in the logic below + */ + job->vfr = 0; + if( [fVidRatePopUp indexOfSelectedItem] > 0 ) + { + /* a specific framerate has been chosen */ + job->vrate = 27000000; + job->vrate_base = hb_video_rates[[fVidRatePopUp indexOfSelectedItem]-1].rate; + /* We are not same as source so we set job->cfr to 1 + * to enable constant frame rate since user has specified + * a specific framerate*/ + job->cfr = 1; + } + else + { + /* We are same as source (variable) */ + job->vrate = title->rate; + job->vrate_base = title->rate_base; + /* We are same as source so we set job->cfr to 0 + * to enable true same as source framerate */ + job->cfr = 0; + /* If we are same as source and we have detelecine on, we need to turn on + * job->vfr + */ + if ([fPictureController detelecine] == 1) + { + job->vfr = 1; + } + } + + switch( [fVidQualityMatrix selectedRow] ) + { + case 0: + /* Target size. + Bitrate should already have been calculated and displayed + in fVidBitrateField, so let's just use it */ + case 1: + job->vquality = -1.0; + job->vbitrate = [fVidBitrateField intValue]; + break; + case 2: + job->vquality = [fVidQualitySlider floatValue]; + job->vbitrate = 0; + break; + } + + job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState ); + + /* Subtitle settings */ + job->subtitle = [fSubPopUp indexOfSelectedItem] - 2; + + /* Audio tracks and mixdowns */ + /* Lets make sure there arent any erroneous audio tracks in the job list, so lets make sure its empty*/ + int audiotrack_count = hb_list_count(job->list_audio); + for( int i = 0; i < audiotrack_count;i++) + { + hb_audio_t * temp_audio = (hb_audio_t*) hb_list_item( job->list_audio, 0 ); + hb_list_rem(job->list_audio, temp_audio); + } + /* Now lets add our new tracks to the audio list here */ + if ([fAudLang1PopUp indexOfSelectedItem] > 0) + { + audio = (hb_audio_config_t *) calloc(1, sizeof(*audio)); + hb_audio_config_init(audio); + audio->in.track = [fAudLang1PopUp indexOfSelectedItem] - 1; + /* We go ahead and assign values to our audio->out. */ + audio->out.track = [fAudLang1PopUp indexOfSelectedItem] - 1; + audio->out.codec = [[fAudTrack1CodecPopUp selectedItem] tag]; + audio->out.mixdown = [[fAudTrack1MixPopUp selectedItem] tag]; + audio->out.bitrate = [[fAudTrack1BitratePopUp selectedItem] tag]; + audio->out.samplerate = [[fAudTrack1RatePopUp selectedItem] tag]; + audio->out.dynamic_range_compression = [fAudTrack1DrcField floatValue]; + + hb_audio_add( job, audio ); + free(audio); + } + if ([fAudLang2PopUp indexOfSelectedItem] > 0) + { + audio = (hb_audio_config_t *) calloc(1, sizeof(*audio)); + hb_audio_config_init(audio); + audio->in.track = [fAudLang2PopUp indexOfSelectedItem] - 1; + /* We go ahead and assign values to our audio->out. */ + audio->out.track = [fAudLang2PopUp indexOfSelectedItem] - 1; + audio->out.codec = [[fAudTrack2CodecPopUp selectedItem] tag]; + audio->out.mixdown = [[fAudTrack2MixPopUp selectedItem] tag]; + audio->out.bitrate = [[fAudTrack2BitratePopUp selectedItem] tag]; + audio->out.samplerate = [[fAudTrack2RatePopUp selectedItem] tag]; + audio->out.dynamic_range_compression = [fAudTrack2DrcField floatValue]; + + hb_audio_add( job, audio ); + free(audio); + + } + + if ([fAudLang3PopUp indexOfSelectedItem] > 0) + { + audio = (hb_audio_config_t *) calloc(1, sizeof(*audio)); + hb_audio_config_init(audio); + audio->in.track = [fAudLang3PopUp indexOfSelectedItem] - 1; + /* We go ahead and assign values to our audio->out. */ + audio->out.track = [fAudLang3PopUp indexOfSelectedItem] - 1; + audio->out.codec = [[fAudTrack3CodecPopUp selectedItem] tag]; + audio->out.mixdown = [[fAudTrack3MixPopUp selectedItem] tag]; + audio->out.bitrate = [[fAudTrack3BitratePopUp selectedItem] tag]; + audio->out.samplerate = [[fAudTrack3RatePopUp selectedItem] tag]; + audio->out.dynamic_range_compression = [fAudTrack3DrcField floatValue]; + + hb_audio_add( job, audio ); + free(audio); + + } + + if ([fAudLang4PopUp indexOfSelectedItem] > 0) + { + audio = (hb_audio_config_t *) calloc(1, sizeof(*audio)); + hb_audio_config_init(audio); + audio->in.track = [fAudLang4PopUp indexOfSelectedItem] - 1; + /* We go ahead and assign values to our audio->out. */ + audio->out.track = [fAudLang4PopUp indexOfSelectedItem] - 1; + audio->out.codec = [[fAudTrack4CodecPopUp selectedItem] tag]; + audio->out.mixdown = [[fAudTrack4MixPopUp selectedItem] tag]; + audio->out.bitrate = [[fAudTrack4BitratePopUp selectedItem] tag]; + audio->out.samplerate = [[fAudTrack4RatePopUp selectedItem] tag]; + audio->out.dynamic_range_compression = [fAudTrack4DrcField floatValue]; + + hb_audio_add( job, audio ); + free(audio); + + } + + + + /* Filters */ + job->filters = hb_list_init(); + + /* Now lets call the filters if applicable. + * The order of the filters is critical + */ + + /* Detelecine */ + if ([fPictureController detelecine]) + { + hb_list_add( job->filters, &hb_filter_detelecine ); + } + + /* Decomb */ + if ([fPictureController decomb] > 0) + { + /* Run old deinterlacer fd by default */ + //fPicSettingDecomb + hb_filter_decomb.settings = (char *) [[fPicSettingDecomb stringValue] UTF8String]; + //hb_filter_decomb.settings = "4:10:15:9:10:35:9"; // <-- jbrjakes recommended parameters as of 5/23/08 + hb_list_add( job->filters, &hb_filter_decomb ); + } + + + /* Deinterlace */ + if ([fPictureController deinterlace] == 1) + { + /* Run old deinterlacer fd by default */ + hb_filter_deinterlace.settings = "-1"; + hb_list_add( job->filters, &hb_filter_deinterlace ); + } + else if ([fPictureController deinterlace] == 2) + { + /* Yadif mode 0 (without spatial deinterlacing.) */ + hb_filter_deinterlace.settings = "2"; + hb_list_add( job->filters, &hb_filter_deinterlace ); + } + else if ([fPictureController deinterlace] == 3) + { + /* Yadif (with spatial deinterlacing) */ + hb_filter_deinterlace.settings = "0"; + hb_list_add( job->filters, &hb_filter_deinterlace ); + } + + /* Denoise */ + if ([fPictureController denoise] == 1) // Weak in popup + { + hb_filter_denoise.settings = "2:1:2:3"; + hb_list_add( job->filters, &hb_filter_denoise ); + } + else if ([fPictureController denoise] == 2) // Medium in popup + { + hb_filter_denoise.settings = "3:2:2:3"; + hb_list_add( job->filters, &hb_filter_denoise ); + } + else if ([fPictureController denoise] == 3) // Strong in popup + { + hb_filter_denoise.settings = "7:7:5:5"; + hb_list_add( job->filters, &hb_filter_denoise ); + } + + /* Deblock (uses pp7 default) */ + if ([fPictureController deblock]) + { + hb_list_add( job->filters, &hb_filter_deblock ); + } + +} + #pragma mark - #pragma mark Job Handling @@ -2611,10 +2908,6 @@ fWorkingCount = 0; job->chapter_markers = 0; } - - - - if( job->vcodec & HB_VCODEC_X264 ) { if ([[queueToApply objectForKey:@"Mp4iPodCompatible"] intValue] == 1) @@ -2700,6 +2993,7 @@ fWorkingCount = 0; job->vfr = 1; } } + if ( [[queueToApply objectForKey:@"VideoQualityType"] intValue] != 2 ) { /* Target size. @@ -3210,11 +3504,14 @@ fWorkingCount = 0; /* Start Get and set the initial pic size for display */ hb_job_t * job = title->job; fTitle = title; - + + /* Reset the new title in fPictureController */ + [fPictureController SetTitle:title]; + /*Set Source Size Field Here */ [fPicSettingsSrc setStringValue: [NSString stringWithFormat: @"%d x %d", fTitle->width, fTitle->height]]; - /* Set Auto Crop to on upon selecting a new title */ + /* Set Auto Crop to on upon selecting a new title */ [fPictureController setAutoCrop:YES]; /* We get the originial output picture width and height and put them @@ -3869,9 +4166,13 @@ the user is using "Custom" settings by determining the sender*/ else { [fPicSettingAutoCrop setStringValue: @"Auto"]; - } - - + } + +//[self showPicturePanel:self]; +hb_list_t * list = hb_get_titles( fHandle ); + hb_title_t * title = (hb_title_t *) hb_list_item( list, + [fSrcTitlePopUp indexOfSelectedItem] ); + [fPictureController SetTitle:title]; } @@ -4782,7 +5083,8 @@ the user is using "Custom" settings by determining the sender*/ hb_list_t * list = hb_get_titles( fHandle ); hb_title_t * title = (hb_title_t *) hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] ); - [fPictureController showPanelInWindow:fWindow forTitle:title]; + //[fPictureController SetTitle:title]; + [fPictureController showPreviewPanel:sender forTitle:title]; } #pragma mark - diff --git a/macosx/English.lproj/PictureSettings.xib b/macosx/English.lproj/PictureSettings.xib index aa3cd14a1..b5e0cea8f 100644 --- a/macosx/English.lproj/PictureSettings.xib +++ b/macosx/English.lproj/PictureSettings.xib @@ -8,10 +8,11 @@ 352.00 YES - + YES + com.apple.QTKitIBPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -26,9 +27,9 @@ NSApplication - 1 + 7 2 - {{482, 298}, {453, 558}} + {{482, 299}, {484, 557}} 1886912512 Picture Settings NSPanel @@ -42,64 +43,10 @@ 256 YES - - - 289 - {{346, 58}, {92, 28}} - - YES - - 67239424 - 134348800 - Next - - LucidaGrande - 1.100000e+01 - 3100 - - - -2038284033 - 1 - - LucidaGrande - 1.100000e+01 - 16 - - - - - - 200 - 25 - - - - - 289 - {{241, 59}, {101, 28}} - - YES - - 67239424 - 134348800 - Previous - - - -2038284033 - 1 - - - - - - 200 - 25 - - 290 - {{20, 58}, {413, 5}} + {{20, 57}, {413, 5}} {0, 0} @@ -133,14 +80,18 @@ 290 - {{17, 22}, {320, 17}} + {{16, 19}, {215, 14}} YES 67239424 - 4194304 + 4325376 - + + LucidaGrande + 1.100000e+01 + 3100 + 6 @@ -164,19 +115,27 @@ - 289 - {{339, 12}, {100, 32}} + -2147483359 + {{276, 66}, {59, 16}} YES 67239424 - 134217728 + 134479872 Close - + + LucidaGrande + 9.000000e+00 + 3614 + -2038284033 1 - + + LucidaGrande + 9.000000e+00 + 16 + DQ 200 @@ -284,7 +243,7 @@ YES YES - + TU0AKgAABRgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAMAAAADAAAAAwAAAAAAAAAA @@ -503,7 +462,7 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA - {{243, 235}, {193, 163}} + {{272, 234}, {193, 163}} {0, 0} @@ -665,11 +624,7 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA -2076049856 264192 - - LucidaGrande - 9.000000e+00 - 3614 - + 109199615 1 @@ -752,7 +707,7 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA - {{245, 402}, {193, 136}} + {{274, 401}, {193, 136}} {0, 0} @@ -795,11 +750,7 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA 109199615 1 - - LucidaGrande - 9.000000e+00 - 16 - + @@ -1124,7 +1075,7 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA - {{243, 87}, {193, 144}} + {{272, 86}, {193, 144}} {0, 0} @@ -1156,7 +1107,7 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA - {{20, 75}, {208, 451}} + {{20, 74}, {208, 451}} {0, 0} @@ -1191,7 +1142,7 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA NeXT TIFF v4.0 pasteboard type - {{20, 66}, {208, 460}} + {{20, 74}, {208, 451}} YES @@ -1204,8 +1155,184 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA YES + + + 268 + + YES + + YES + Apple URL pasteboard type + CorePasteboardFlavorType 0x6D6F6F76 + NSFilenamesPboardType + QTMoviePasteboardType + + + {{20, 74}, {208, 451}} + + + 1 + MC44MDAwMDAwMSAwLjgwMDAwMDAxIDAuODAwMDAwMDEAA + + + + + + + + + 290 + {{18, 37}, {210, 16}} + + YES + + -2079981824 + 262144 + + + + 9.000000e+00 + 0.000000e+00 + 0.000000e+00 + 0.000000e+00 + 10 + 1 + YES + NO + + + + + -2147482334 + + {{19, 36}, {210, 12}} + + 16650 + 2.000000e+01 + 1.000000e+02 + + + + 289 + {{235, 18}, {85, 16}} + + YES + + 67239424 + 134479872 + Live Preview + + + -2038284033 + 129 + + + 200 + 25 + + + + + -2147483358 + {{17, 61}, {214, 12}} + + YES + + 68288064 + 4457472 + + + + + 2 + MC45MDE5NjA4NSAwLjkwMTk2MDg1IDAuOTAxOTYwODUAA + + + + + + + 289 + {{417, 19}, {48, 15}} + + YES + + -2076049856 + 264192 + + + 109199615 + 1 + + + 400 + 75 + + + Item 1 + + 1048576 + 2147483647 + 1 + + + _popUpItemAction: + + + YES + + OtherViews + + YES + + + + Item 2 + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + Item 3 + + 1048576 + 2147483647 + + + _popUpItemAction: + + + + + 1 + YES + YES + 2 + + + + + 289 + {{324, 21}, {89, 11}} + + YES + + 68288064 + 71566336 + Duration (seconds): + + + + + + - {453, 558} + {484, 557} {{0, 0}, {1440, 878}} @@ -1344,22 +1471,6 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA 69 - - - fNextButton - - - - 71 - - - - fPrevButton - - - - 72 - fInfoField @@ -1392,22 +1503,6 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA 77 - - - NextPicture: - - - - 78 - - - - PreviousPicture: - - - - 79 - SettingsChanged: @@ -1568,6 +1663,78 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA 206 + + + fMovieView + + + + 208 + + + + fPictureSlider + + + + 211 + + + + pictureSliderChanged: + + + + 212 + + + + fMovieCreationProgressIndicator + + + + 214 + + + + fCreatePreviewMovieButton + + + + 217 + + + + createMoviePreview: + + + + 218 + + + + fPreviewMovieStatusField + + + + 225 + + + + fPreviewMovieLengthPopUp + + + + 232 + + + + previewDurationPopUpChanged: + + + + 233 + @@ -1617,12 +1784,17 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA - - + + + + + - + + + @@ -1705,15 +1877,6 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA - - 49 - - - YES - - - - 50 @@ -1723,15 +1886,6 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA - - 52 - - - YES - - - - 92 @@ -1745,21 +1899,11 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA - - 175 - - - 176 - - 177 - - - 12 @@ -2298,6 +2442,116 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA + + 207 + + + + + 209 + + + YES + + + + + + 210 + + + + + 213 + + + + + 215 + + + YES + + + + + + 216 + + + + + 223 + + + YES + + + + + + 224 + + + + + 226 + + + YES + + + + + + 227 + + + YES + + + + + + 228 + + + YES + + + + + + + + 229 + + + + + 230 + + + + + 231 + + + + + 234 + + + YES + + + + + + 235 + + + @@ -2360,12 +2614,33 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA 197.ImportedFromIB2 204.IBPluginDependency 204.ImportedFromIB2 + 207.IBPluginDependency + 209.IBPluginDependency 21.IBPluginDependency 21.ImportedFromIB2 + 210.IBPluginDependency + 213.IBPluginDependency + 215.IBPluginDependency + 216.IBPluginDependency 22.IBPluginDependency 22.ImportedFromIB2 + 223.IBPluginDependency + 224.IBPluginDependency + 226.IBPluginDependency + 226.ImportedFromIB2 + 228.IBEditorWindowLastContentRect + 228.IBPluginDependency + 228.ImportedFromIB2 + 229.IBPluginDependency + 229.ImportedFromIB2 23.IBPluginDependency 23.ImportedFromIB2 + 230.IBPluginDependency + 230.ImportedFromIB2 + 231.IBPluginDependency + 231.ImportedFromIB2 + 234.IBPluginDependency + 235.IBPluginDependency 25.IBPluginDependency 25.ImportedFromIB2 26.IBPluginDependency @@ -2410,8 +2685,6 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA 46.ImportedFromIB2 47.IBPluginDependency 47.ImportedFromIB2 - 49.IBPluginDependency - 49.ImportedFromIB2 5.IBEditorWindowLastContentRect 5.IBPluginDependency 5.IBViewEditorWindowController.showingLayoutRectangles @@ -2424,8 +2697,6 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA 5.windowTemplate.minSize 50.IBPluginDependency 50.ImportedFromIB2 - 52.IBPluginDependency - 52.ImportedFromIB2 6.IBPluginDependency 6.ImportedFromIB2 7.IBPluginDependency @@ -2493,6 +2764,23 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA com.apple.InterfaceBuilder.CocoaPlugin + com.apple.QTKitIBPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + {{656, 304}, {87, 48}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2502,6 +2790,8 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -2545,10 +2835,10 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA com.apple.InterfaceBuilder.CocoaPlugin - {{462, 298}, {453, 558}} + {{302, 299}, {484, 557}} com.apple.InterfaceBuilder.CocoaPlugin - - {{462, 298}, {453, 558}} + + {{302, 299}, {484, 557}} {{221, 276}, {533, 580}} @@ -2565,8 +2855,6 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - @@ -2589,7 +2877,7 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA - 206 + 235 @@ -2624,10 +2912,12 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA YES ClosePanel: - NextPicture: - PreviousPicture: SettingsChanged: + createMoviePreview: deblockSliderChanged: + pictureSliderChanged: + previewDurationPopUpChanged: + showMoviePreview: YES @@ -2636,6 +2926,8 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA id id id + id + NSString @@ -2644,6 +2936,7 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA YES delegate fAnamorphicPopUp + fCreatePreviewMovieButton fCropBottomField fCropBottomStepper fCropLeftField @@ -2663,11 +2956,15 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA fHeightField fHeightStepper fInfoField - fNextButton + fMovieCreationProgressIndicator + fMovieView + fPictureSlider fPictureView fPictureViewArea - fPrevButton + fPreviewMovieLengthPopUp + fPreviewMovieStatusField fRatioCheck + fShowPreviewMovieButton fWidthField fWidthStepper @@ -2675,6 +2972,7 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA YES id NSPopUpButton + NSButton NSTextField NSStepper NSTextField @@ -2694,9 +2992,13 @@ AAB0ZXh0AAAAAENvcHlyaWdodCBBcHBsZSBDb21wdXRlciwgSW5jLiwgMjAwNQAAAAA NSTextField NSStepper NSTextField - NSButton + NSProgressIndicator + QTMovieView + NSSlider NSImageView NSBox + NSPopUpButton + NSTextField NSButton NSButton NSTextField diff --git a/macosx/HandBrake.xcodeproj/project.pbxproj b/macosx/HandBrake.xcodeproj/project.pbxproj index f864f75a7..6bf957210 100644 --- a/macosx/HandBrake.xcodeproj/project.pbxproj +++ b/macosx/HandBrake.xcodeproj/project.pbxproj @@ -89,6 +89,8 @@ 59CBD2650BBB4D1B004A3BE3 /* ChapterTitles.m in Sources */ = {isa = PBXBuildFile; fileRef = 593034EA0BBA39A100172349 /* ChapterTitles.m */; }; 7497010F0DC281BB009200D8 /* decomb.c in Sources */ = {isa = PBXBuildFile; fileRef = 7497010E0DC281BB009200D8 /* decomb.c */; }; 749701100DC281BB009200D8 /* decomb.c in Sources */ = {isa = PBXBuildFile; fileRef = 7497010E0DC281BB009200D8 /* decomb.c */; }; + A20F46DC0EBB5E7A005B861B /* QuickTime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A20F46DB0EBB5E7A005B861B /* QuickTime.framework */; }; + A20F47010EBB5EC2005B861B /* QTKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A20F47000EBB5EC2005B861B /* QTKit.framework */; }; A22C85EC0D05D35000C10E36 /* HBPresets.h in Headers */ = {isa = PBXBuildFile; fileRef = A22C85EA0D05D35000C10E36 /* HBPresets.h */; }; A22C85ED0D05D35100C10E36 /* HBPresets.m in Sources */ = {isa = PBXBuildFile; fileRef = A22C85EB0D05D35000C10E36 /* HBPresets.m */; }; A25289E60D87A27D00461D5B /* enctheora.c in Sources */ = {isa = PBXBuildFile; fileRef = A25289E50D87A27D00461D5B /* enctheora.c */; }; @@ -251,6 +253,8 @@ 593034EA0BBA39A100172349 /* ChapterTitles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChapterTitles.m; sourceTree = ""; }; 59CBD2360BBB44DA004A3BE3 /* parsecsv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = parsecsv.c; path = ../test/parsecsv.c; sourceTree = SOURCE_ROOT; }; 7497010E0DC281BB009200D8 /* decomb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = decomb.c; path = ../libhb/decomb.c; sourceTree = SOURCE_ROOT; }; + A20F46DB0EBB5E7A005B861B /* QuickTime.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickTime.framework; path = /System/Library/Frameworks/QuickTime.framework; sourceTree = ""; }; + A20F47000EBB5EC2005B861B /* QTKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QTKit.framework; path = /System/Library/Frameworks/QTKit.framework; sourceTree = ""; }; A22C85EA0D05D35000C10E36 /* HBPresets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBPresets.h; sourceTree = ""; }; A22C85EB0D05D35000C10E36 /* HBPresets.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBPresets.m; sourceTree = ""; }; A25289E50D87A27D00461D5B /* enctheora.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = enctheora.c; path = ../libhb/enctheora.c; sourceTree = SOURCE_ROOT; }; @@ -347,6 +351,8 @@ 4D1125D809D72FD200E0657B /* libz.dylib in Frameworks */, A29E05800BE1283E000533F5 /* Growl.framework in Frameworks */, A2D0A0AB0D3E5929002D57CB /* Sparkle.framework in Frameworks */, + A20F46DC0EBB5E7A005B861B /* QuickTime.framework in Frameworks */, + A20F47010EBB5EC2005B861B /* QTKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -405,6 +411,8 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + A20F47000EBB5EC2005B861B /* QTKit.framework */, + A20F46DB0EBB5E7A005B861B /* QuickTime.framework */, D289A9F20DBBE7AC00CE614B /* CoreServices.framework */, A2D0A0AA0D3E5929002D57CB /* Sparkle.framework */, A29E057F0BE1283E000533F5 /* Growl.framework */, @@ -1141,6 +1149,8 @@ ../libhb, ../contrib/include, ); + IBC_PLUGINS = /System/Library/Frameworks/QTKit.framework/Resources/QTKitIBPlugin.ibplugin; + IBC_PLUGIN_SEARCH_PATHS = /System/Library/Frameworks/QTKit.framework/Resources; INFOPLIST_FILE = HandBrake.plist; LIBRARY_SEARCH_PATHS = ""; MACOSX_DEPLOYMENT_TARGET = 10.5; @@ -1411,6 +1421,8 @@ ../libhb, ../contrib/include, ); + IBC_PLUGINS = /System/Library/Frameworks/QTKit.framework/Resources/QTKitIBPlugin.ibplugin; + IBC_PLUGIN_SEARCH_PATHS = /System/Library/Frameworks/QTKit.framework/Resources; INFOPLIST_FILE = HandBrake.plist; INFOPLIST_PREPROCESS = NO; LIBRARY_SEARCH_PATHS = ""; @@ -1474,6 +1486,8 @@ ../libhb, ../contrib/include, ); + IBC_PLUGINS = /System/Library/Frameworks/QTKit.framework/Resources/QTKitIBPlugin.ibplugin; + IBC_PLUGIN_SEARCH_PATHS = /System/Library/Frameworks/QTKit.framework/Resources; INFOPLIST_FILE = HandBrake.plist; LIBRARY_SEARCH_PATHS = ""; MACOSX_DEPLOYMENT_TARGET = 10.5; diff --git a/macosx/PictureController.h b/macosx/PictureController.h index 24631c386..d2a3bc8f0 100644 --- a/macosx/PictureController.h +++ b/macosx/PictureController.h @@ -7,6 +7,8 @@ #import #include "hb.h" +/* Needed for Quicktime movie previews */ +#import #define HB_NUM_HBLIB_PICTURES 10 // hbilb generates 10 preview pictures @@ -42,8 +44,7 @@ IBOutlet NSSlider * fDeblockSlider; IBOutlet NSPopUpButton * fDenoisePopUp; IBOutlet NSPopUpButton * fAnamorphicPopUp; - IBOutlet NSButton * fPrevButton; - IBOutlet NSButton * fNextButton; + IBOutlet NSSlider * fPictureSlider; IBOutlet NSTextField * fInfoField; int MaxOutputWidth; @@ -67,6 +68,18 @@ } fPictureFilterSettings; id delegate; + + /* Movie Previews */ + IBOutlet NSButton * fCreatePreviewMovieButton; + IBOutlet NSButton * fShowPreviewMovieButton; + NSString * fPreviewMoviePath; + IBOutlet NSProgressIndicator * fMovieCreationProgressIndicator; + hb_handle_t * fPreviewLibhb; // private libhb for creating previews + NSTimer * fLibhbTimer; // timer for retrieving state from libhb + IBOutlet NSTextField * fPreviewMovieStatusField; + BOOL play_movie; // flag used to determine whether or not to automatically play the movie when done. + IBOutlet QTMovieView * fMovieView; + IBOutlet NSPopUpButton * fPreviewMovieLengthPopUp; // popup of choices for length of preview in seconds } - (id)initWithDelegate:(id)del; @@ -76,8 +89,18 @@ - (void) displayPreview; - (IBAction) SettingsChanged: (id) sender; -- (IBAction) PreviousPicture: (id) sender; -- (IBAction) NextPicture: (id) sender; +- (IBAction) pictureSliderChanged: (id) sender; + +/* Movie Previews */ +- (void) startReceivingLibhbNotifications; +- (void) stopReceivingLibhbNotifications; + +- (IBAction) createMoviePreview: (id) sender; +- (void) libhbStateChanged: (hb_state_t &) state; +- (IBAction) showMoviePreview: (NSString *) path; +- (IBAction) previewDurationPopUpChanged: (id) sender; + + - (IBAction) ClosePanel: (id) sender; - (BOOL) autoCrop; @@ -97,7 +120,7 @@ - (int) deblock; - (void) setDeblock: (int) setting; -- (void)showPanelInWindow: (NSWindow *)fWindow forTitle: (hb_title_t *)title; +- (IBAction)showPreviewPanel: (id)sender forTitle: (hb_title_t *)title; + (NSImage *) makeImageForPicture: (int)pictureIndex libhb:(hb_handle_t*)handle @@ -109,4 +132,5 @@ @interface NSObject (PictureControllertDelegateMethod) - (void)pictureSettingsDidChange; +- (void)prepareJobForPreview; @end diff --git a/macosx/PictureController.mm b/macosx/PictureController.mm index d63107496..940bdb2fe 100644 --- a/macosx/PictureController.mm +++ b/macosx/PictureController.mm @@ -30,15 +30,28 @@ // If/when we switch a lot of this stuff to bindings, this can probably // go away. [self window]; - + delegate = del; fPicturePreviews = [[NSMutableDictionary dictionaryWithCapacity: HB_NUM_HBLIB_PICTURES] retain]; + /* Init libhb with check for updates libhb style set to "0" so its ignored and lets sparkle take care of it */ + int loggingLevel = [[[NSUserDefaults standardUserDefaults] objectForKey:@"LoggingLevel"] intValue]; + fPreviewLibhb = hb_init(loggingLevel, 0); } return self; } - (void) dealloc { + hb_stop(fPreviewLibhb); + if (fPreviewMoviePath) + { + [[NSFileManager defaultManager] removeFileAtPath:fPreviewMoviePath handler:nil]; + [fPreviewMoviePath release]; + } + + [fLibhbTimer invalidate]; + [fLibhbTimer release]; + [fPicturePreviews release]; [super dealloc]; } @@ -46,14 +59,14 @@ - (void) SetHandle: (hb_handle_t *) handle { fHandle = handle; - + [fWidthStepper setValueWraps: NO]; [fWidthStepper setIncrement: 16]; [fWidthStepper setMinValue: 64]; [fHeightStepper setValueWraps: NO]; [fHeightStepper setIncrement: 16]; [fHeightStepper setMinValue: 64]; - + [fCropTopStepper setIncrement: 2]; [fCropTopStepper setMinValue: 0]; [fCropBottomStepper setIncrement: 2]; @@ -62,6 +75,31 @@ [fCropLeftStepper setMinValue: 0]; [fCropRightStepper setIncrement: 2]; [fCropRightStepper setMinValue: 0]; + + /* we set the preview length popup in seconds */ + [fPreviewMovieLengthPopUp removeAllItems]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"5"]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"10"]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"15"]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"20"]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"25"]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"30"]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"35"]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"40"]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"45"]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"50"]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"55"]; + [fPreviewMovieLengthPopUp addItemWithTitle: @"60"]; + + if ([[NSUserDefaults standardUserDefaults] objectForKey:@"PreviewLength"]) + { + [fPreviewMovieLengthPopUp selectItemWithTitle:[[NSUserDefaults standardUserDefaults] objectForKey:@"PreviewLength"]]; + } + else + { + /* currently hard set default to 10 seconds */ + [fPreviewMovieLengthPopUp selectItemAtIndex: 1]; + } } - (void) SetTitle: (hb_title_t *) title @@ -161,6 +199,17 @@ are maintained across different sources */ // necessary to display as much of the picture as possible. - (void) displayPreview { + + /* lets make sure that the still picture view is not hidden and that + * the movie preview is + */ + [fMovieView pause:nil]; + [fMovieView setHidden:YES]; + [fMovieCreationProgressIndicator stopAnimation: nil]; + [fMovieCreationProgressIndicator setHidden: YES]; + + [fPictureView setHidden:NO]; + [fPictureView setImage: [self imageForPicture: fPicture]]; NSSize displaySize = NSMakeSize( ( CGFloat )fTitle->width, ( CGFloat )fTitle->height ); @@ -213,11 +262,17 @@ are maintained across different sources */ scale * 100.0]; [fInfoField setStringValue: [[fInfoField stringValue] stringByAppendingString:scaleString]]; } - - [fPrevButton setEnabled: ( fPicture > 0 )]; - [fNextButton setEnabled: ( fPicture < 9 )]; } +- (IBAction) previewDurationPopUpChanged: (id) sender +{ + +[[NSUserDefaults standardUserDefaults] setObject:[fPreviewMovieLengthPopUp titleOfSelectedItem] forKey:@"PreviewLength"]; + +} + + + - (IBAction) deblockSliderChanged: (id) sender { if ([fDeblockSlider floatValue] == 4.0) @@ -411,30 +466,330 @@ are maintained across different sources */ // Purge the existing picture previews so they get recreated the next time // they are needed. [self purgeImageCache]; - [self displayPreview]; + /* We actually call displayPreview now from pictureSliderChanged which keeps + * our picture preview slider in sync with the previews being shown + */ + //[self displayPreview]; + [self pictureSliderChanged:nil]; + } + + } -- (IBAction) PreviousPicture: (id) sender -{ - if( fPicture <= 0 ) +- (IBAction) pictureSliderChanged: (id) sender +{ + // Show the picture view + [fCreatePreviewMovieButton setTitle: @"Live Preview"]; + [fPictureView setHidden:NO]; + [fMovieView pause:nil]; + [fMovieView setHidden:YES]; + [fPreviewMovieStatusField setHidden: YES]; + + int newPicture = [fPictureSlider intValue]; + if (newPicture != fPicture) { - return; + fPicture = newPicture; } - fPicture--; [self displayPreview]; + } -- (IBAction) NextPicture: (id) sender +#pragma mark Movie Preview +- (IBAction) createMoviePreview: (id) sender { - if( fPicture >= 9 ) - { + /* Lets make sure the still picture previews are showing in case + * there is currently a movie showing */ + [self pictureSliderChanged:nil]; + + /* Rip or Cancel ? */ + hb_state_t s; + hb_get_state2( fPreviewLibhb, &s ); + + if(s.state == HB_STATE_WORKING || s.state == HB_STATE_PAUSED) + { + + play_movie = NO; + hb_stop( fPreviewLibhb ); + [fPictureView setHidden:NO]; + [fMovieView pause:nil]; + [fMovieView setHidden:YES]; + [fPictureSlider setHidden:NO]; + [fCreatePreviewMovieButton setTitle: @"Live Preview"]; return; } - fPicture++; - [self displayPreview]; + + /* we use controller.mm's prepareJobForPreview to go ahead and set all of our settings + * however, we want to use a temporary destination field of course + * so that we do not put our temp preview in the users chosen + * directory */ + + hb_job_t * job = fTitle->job; + /* We run our current setting through prepeareJob in Controller.mm + * just as if it were a regular encode */ + if ([delegate respondsToSelector:@selector(prepareJobForPreview)]) + { + [delegate prepareJobForPreview]; + } + + /* 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"; + } + 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 = [[fPreviewMoviePath stringByExpandingTildeInPath]retain]; + + /* See if there is an existing preview file, if so, delete it */ + if( ![[NSFileManager defaultManager] fileExistsAtPath:fPreviewMoviePath] ) + { + [[NSFileManager defaultManager] removeFileAtPath:fPreviewMoviePath + handler:nil]; + } + + /* We now direct our preview encode to fPreviewMoviePath */ + fTitle->job->file = [fPreviewMoviePath UTF8String]; + + job->start_at_preview = fPicture + 1; + + /* we use the preview duration popup to get the specified + * number of seconds for the preview encode. + */ + + job->pts_to_stop = [[fPreviewMovieLengthPopUp titleOfSelectedItem] intValue] * 90000LL; + + /* lets go ahead and send it off to libhb + * Note: unlike a full encode, we only send 1 pass regardless if the final encode calls for 2 passes. + * this should suffice for a fairly accurate short preview and cuts our preview generation time in half. + */ + hb_add( fPreviewLibhb, job ); + + [fPictureSlider setHidden:YES]; + [fMovieCreationProgressIndicator setHidden: NO]; + [fPreviewMovieStatusField setHidden: NO]; + [self startReceivingLibhbNotifications]; + + + [fCreatePreviewMovieButton setTitle: @"Cancel Preview"]; + + play_movie = YES; + + /* Let fPreviewLibhb do the job */ + hb_start( fPreviewLibhb ); + } +- (void) startReceivingLibhbNotifications +{ + if (!fLibhbTimer) + { + fLibhbTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(libhbTimerFired:) userInfo:nil repeats:YES]; + [fLibhbTimer retain]; + } +} + +- (void) stopReceivingLibhbNotifications +{ + if (fLibhbTimer) + { + [fLibhbTimer invalidate]; + [fLibhbTimer release]; + fLibhbTimer = nil; + } +} +- (void) libhbTimerFired: (NSTimer*)theTimer +{ + hb_state_t s; + hb_get_state( fPreviewLibhb, &s ); + [self libhbStateChanged: s]; +} +- (void) libhbStateChanged: (hb_state_t &)state +{ + switch( state.state ) + { + case HB_STATE_IDLE: + case HB_STATE_SCANNING: + case HB_STATE_SCANDONE: + break; + + case HB_STATE_WORKING: + { +#define p state.param.working + + NSMutableString * string; + /* Update text field */ + string = [NSMutableString stringWithFormat: NSLocalizedString( @"Encoding %d seconds of preview %d: %.2f %%", @"" ), [[fPreviewMovieLengthPopUp titleOfSelectedItem] intValue], fPicture + 1, 100.0 * p.progress]; + + if( p.seconds > -1 ) + { + [string appendFormat: + NSLocalizedString( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)", @"" ), + p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds]; + } + [fPreviewMovieStatusField setStringValue: string]; + + [fMovieCreationProgressIndicator setIndeterminate: NO]; + /* Update slider */ + [fMovieCreationProgressIndicator setDoubleValue: 100.0 * p.progress]; + + [fCreatePreviewMovieButton setTitle: @"Cancel Preview"]; + + break; + + } +#undef p + +#define p state.param.muxing + case HB_STATE_MUXING: + { + // Update fMovieCreationProgressIndicator + [fMovieCreationProgressIndicator setIndeterminate: YES]; + [fMovieCreationProgressIndicator startAnimation: nil]; + [fPreviewMovieStatusField setStringValue: [NSString stringWithFormat: + NSLocalizedString( @"Muxing Preview ...", @"" )]]; + break; + } +#undef p + case HB_STATE_PAUSED: + [fMovieCreationProgressIndicator stopAnimation: nil]; + break; + + case HB_STATE_WORKDONE: + { + // Delete all remaining jobs since libhb doesn't do this on its own. + hb_job_t * job; + while( ( job = hb_job(fPreviewLibhb, 0) ) ) + hb_rem( fHandle, job ); + + [self stopReceivingLibhbNotifications]; + [fPreviewMovieStatusField setStringValue: @""]; + [fPreviewMovieStatusField setHidden: YES]; + + [fMovieCreationProgressIndicator stopAnimation: nil]; + [fMovieCreationProgressIndicator setHidden: YES]; + /* we make sure the picture slider and preview match */ + [self pictureSliderChanged:nil]; + [fPictureSlider setHidden:NO]; + + // Show the movie view + if (play_movie) + { + [self showMoviePreview:fPreviewMoviePath]; + } + + [fCreatePreviewMovieButton setTitle: @"Live Preview"]; + + + break; + } + } + +} + +- (IBAction) showMoviePreview: (NSString *) path +{ + /* Since the gray background for the still images is part of + * fPictureView, lets leave the picture view visible and postion + * the fMovieView over the image portion of fPictureView so + * we retain the gray cropping border we have already established + * with the still previews + */ + [fMovieView setHidden:NO]; + + /* Load the new movie into fMovieView */ + QTMovie * aMovie; + NSRect movieBounds; + if (path) + { + [fMovieView setControllerVisible: YES]; + /* let's make sure there is no movie currently set */ + [fMovieView setMovie:nil]; + + aMovie = [QTMovie movieWithFile:path error:nil]; + + /* we get some size information from the preview movie */ + Rect movieBox; + GetMovieBox ([aMovie quickTimeMovie], &movieBox); + movieBounds = [fMovieView movieBounds]; + movieBounds.size.height = movieBox.bottom - movieBox.top; + + if ([fMovieView isControllerVisible]) + movieBounds.size.height += [fMovieView controllerBarHeight]; + /* since for whatever the reason I cannot seem to get the [fMovieView controllerBarHeight] + * For now just use 15 for additional height as it seems to line up well + */ + movieBounds.size.height += 15; + + movieBounds.size.width = movieBox.right - movieBox.left; + + /* 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( ((int)movieBounds.size.height) > [fPictureView 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( (float)movieBounds.size.width, (float)movieBounds.size.height ); + //NSSize displaySize = NSMakeSize( (float)fTitle->width, (float)fTitle->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]; + } + + // lets reposition the movie if need be + NSPoint origin = [fPictureViewArea frame].origin; + origin.x += trunc(([fPictureViewArea frame].size.width - + [fMovieView frame].size.width) / 2.0); + /* Since we are adding 15 to the height to allow for the controller bar + * 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 - + [fMovieView frame].size.height) / 2.0) - 7.5); + [fMovieView setFrameOrigin:origin]; + + [fMovieView setMovie:aMovie]; + /// to actually play the movie + [fMovieView play:aMovie]; + } + else + { + aMovie = nil; + } + +} + +#pragma mark - + - (IBAction) ClosePanel: (id) sender { if ([delegate respondsToSelector:@selector(pictureSettingsDidChange)]) @@ -509,15 +864,11 @@ are maintained across different sources */ fPictureFilterSettings.deblock = setting; } -- (void)showPanelInWindow: (NSWindow *)fWindow forTitle: (hb_title_t *)title +- (IBAction)showPreviewPanel: (id)sender forTitle: (hb_title_t *)title { [self SetTitle:title]; + [self showWindow:sender]; - [NSApp beginSheet:[self window] - modalForWindow:fWindow - modalDelegate:nil - didEndSelector:nil - contextInfo:NULL]; } @@ -707,14 +1058,20 @@ are maintained across different sources */ CGFloat minWidth = 320.0; CGFloat minHeight = 240.0; - // The max size of the view is when the sheet is taking up 85% of the screen. NSSize screenSize = [[NSScreen mainScreen] frame].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 = (0.85 * screenSize.width) - paddingX; - CGFloat maxHeight = (0.85 * screenSize.height) - paddingY; + /* Since we are now non-modal, lets go ahead and allow the mac size to + * go up to the full screen height or width below. Am leaving the original + * code here that blindjimmy setup for 85% in case we don't like it. + */ + // The max size of the view is when the sheet is taking up 85% of the screen. + //CGFloat maxWidth = (0.85 * screenSize.width) - paddingX; + //CGFloat maxHeight = (0.85 * screenSize.height) - paddingY; + CGFloat maxWidth = screenSize.width - paddingX; + CGFloat maxHeight = screenSize.height - paddingY; NSSize resultSize = imageSize; -- 2.40.0