1 /* $Id: PictureController.mm,v 1.11 2005/08/01 15:10:44 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.fr/>.
5 It may be used under the terms of the GNU General Public License. */
7 #import "PictureController.h"
9 #import "HBPreviewController.h"
10 #import "HBFilterController.h"
13 @implementation PictureController
17 if (self = [super initWithWindowNibName:@"PictureSettings"])
19 // NSWindowController likes to lazily load its window. However since
20 // this controller tries to set all sorts of outlets before the window
21 // is displayed, we need it to load immediately. The correct way to do
22 // this, according to the documentation, is simply to invoke the window
25 // If/when we switch a lot of this stuff to bindings, this can probably
29 fPreviewController = [[PreviewController alloc] init];
30 //fPictureFilterController = [[PictureFilterController alloc] init];
35 //------------------------------------------------------------------------------------
36 // Displays and brings the picture window to the front
37 //------------------------------------------------------------------------------------
38 - (IBAction) showPictureWindow: (id)sender
40 if ([[self window] isVisible])
42 [[self window] close];
46 [self showWindow:sender];
47 [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"PictureSizeWindowIsOpen"];
48 if ([fPreviewController fullScreen] == YES)
50 [self setToFullScreenMode];
54 [self setToWindowedMode];
59 - (BOOL) previewFullScreenMode
61 return [fPreviewController fullScreen];
64 - (IBAction) previewGoWindowed: (id)sender
66 [fPreviewController goWindowedScreen:self];
69 - (IBAction) showPreviewWindow: (id)sender
71 [fPreviewController showWindow:sender];
74 - (IBAction) showFilterWindow: (id)sender
76 [fHBController showFiltersPanel:sender];
80 - (void) setToFullScreenMode
82 int32_t shieldLevel = CGShieldingWindowLevel();
84 [fPictureWindow setLevel:shieldLevel + 1];
86 [fPictureWindow makeKeyAndOrderFront:self];
89 - (void) setToWindowedMode
91 /* Set the window back to regular level */
92 [[self window] setLevel:NSNormalWindowLevel];
95 - (void)setHBController: (HBController *)controller
97 fHBController = controller;
98 //[fPictureFilterController setHBController: controller];
99 [fPreviewController setHBController: controller];
105 [fPictureWindow setDelegate:self];
106 if( ![[self window] setFrameUsingName:@"PictureSizing"] )
107 [[self window] center];
108 [self setWindowFrameAutosaveName:@"PictureSizing"];
109 [[self window] setExcludedFromWindowsMenu:YES];
113 - (void)windowWillClose:(NSNotification *)aNotification
115 [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"PictureSizeWindowIsOpen"];
118 - (BOOL)windowShouldClose:(id)fPictureWindow
125 [fPictureFilterController release];
126 [fPreviewController release];
130 - (void) SetHandle: (hb_handle_t *) handle
134 [fWidthStepper setValueWraps: NO];
135 [fWidthStepper setIncrement: 16];
136 [fWidthStepper setMinValue: 64];
137 [fHeightStepper setValueWraps: NO];
138 [fHeightStepper setIncrement: 16];
139 [fHeightStepper setMinValue: 64];
141 [fCropTopStepper setIncrement: 2];
142 [fCropTopStepper setMinValue: 0];
143 [fCropBottomStepper setIncrement: 2];
144 [fCropBottomStepper setMinValue: 0];
145 [fCropLeftStepper setIncrement: 2];
146 [fCropLeftStepper setMinValue: 0];
147 [fCropRightStepper setIncrement: 2];
148 [fCropRightStepper setMinValue: 0];
150 [fPreviewController SetHandle: fHandle];
151 [fPictureFilterController SetHandle: fHandle];
156 - (void) SetTitle: (hb_title_t *) title
158 hb_job_t * job = title->job;
164 [fWidthStepper setMaxValue: title->width];
165 [fWidthStepper setIntValue: job->width];
166 [fWidthField setIntValue: job->width];
167 [fHeightStepper setMaxValue: title->height];
168 [fHeightStepper setIntValue: job->height];
169 [fHeightField setIntValue: job->height];
170 [fRatioCheck setState: job->keep_ratio ? NSOnState : NSOffState];
171 [fCropTopStepper setMaxValue: title->height/2-2];
172 [fCropBottomStepper setMaxValue: title->height/2-2];
173 [fCropLeftStepper setMaxValue: title->width/2-2];
174 [fCropRightStepper setMaxValue: title->width/2-2];
176 /* Populate the Anamorphic NSPopUp button here */
177 [fAnamorphicPopUp removeAllItems];
178 [fAnamorphicPopUp addItemWithTitle: @"None"];
179 [fAnamorphicPopUp addItemWithTitle: @"Strict"];
180 if (allowLooseAnamorphic)
182 [fAnamorphicPopUp addItemWithTitle: @"Loose"];
184 [fAnamorphicPopUp selectItemAtIndex: job->anamorphic.mode];
186 /* We initially set the previous state of keep ar to on */
187 keepAspectRatioPreviousState = 1;
190 [fCropMatrix selectCellAtRow: 1 column:0];
191 /* If auto, lets set the crop steppers according to current job->crop values */
192 [fCropTopStepper setIntValue: job->crop[0]];
193 [fCropTopField setIntValue: job->crop[0]];
194 [fCropBottomStepper setIntValue: job->crop[1]];
195 [fCropBottomField setIntValue: job->crop[1]];
196 [fCropLeftStepper setIntValue: job->crop[2]];
197 [fCropLeftField setIntValue: job->crop[2]];
198 [fCropRightStepper setIntValue: job->crop[3]];
199 [fCropRightField setIntValue: job->crop[3]];
203 [fCropMatrix selectCellAtRow: 0 column:0];
206 /* Set filters widgets according to the filters struct */
207 /* this has now been movied to the filters controller */
209 [fDetelecineCheck setState:fPictureFilterSettings.detelecine];
210 [fDeinterlacePopUp selectItemAtIndex: fPictureFilterSettings.deinterlace];
211 [fDenoisePopUp selectItemAtIndex: fPictureFilterSettings.denoise];
212 [fDeblockCheck setState: fPictureFilterSettings.deblock];
213 [fDecombCheck setState: fPictureFilterSettings.decomb];
217 MaxOutputWidth = title->width - job->crop[2] - job->crop[3];
218 MaxOutputHeight = title->height - job->crop[0] - job->crop[1];
220 [self SettingsChanged: nil];
225 - (IBAction) SettingsChanged: (id) sender
227 hb_job_t * job = fTitle->job;
229 autoCrop = ( [fCropMatrix selectedRow] == 0 );
230 [fCropTopStepper setEnabled: !autoCrop];
231 [fCropBottomStepper setEnabled: !autoCrop];
232 [fCropLeftStepper setEnabled: !autoCrop];
233 [fCropRightStepper setEnabled: !autoCrop];
237 memcpy( job->crop, fTitle->crop, 4 * sizeof( int ) );
241 job->crop[0] = [fCropTopStepper intValue];
242 job->crop[1] = [fCropBottomStepper intValue];
243 job->crop[2] = [fCropLeftStepper intValue];
244 job->crop[3] = [fCropRightStepper intValue];
247 if( [fAnamorphicPopUp indexOfSelectedItem] > 0 )
249 if ([fAnamorphicPopUp indexOfSelectedItem] == 2) // Loose anamorphic
251 job->anamorphic.mode = 2;
252 [fWidthStepper setEnabled: YES];
253 [fWidthField setEnabled: YES];
254 /* We set job->width and call hb_set_anamorphic_size in libhb to do a "dry run" to get
255 * the values to be used by libhb for loose anamorphic
257 /* if the sender is the anamorphic popup, then we know that loose anamorphic has just
258 * been turned on, so snap the width to full width for the source.
260 if (sender == fAnamorphicPopUp)
262 [fWidthStepper setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
263 [fWidthField setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
265 job->width = [fWidthStepper intValue];
266 hb_set_anamorphic_size(job, &output_width, &output_height, &output_par_width, &output_par_height);
267 [fHeightStepper setIntValue: output_height];
268 [fHeightField setIntValue: output_height];
269 job->height = [fHeightStepper intValue];
272 else // must be "1" or strict anamorphic
274 [fWidthStepper setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
275 [fWidthField setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
277 /* This will show correct anamorphic height values, but
278 show distorted preview picture ratio */
279 [fHeightStepper setIntValue: fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]];
280 [fHeightField setIntValue: fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]];
281 job->width = [fWidthStepper intValue];
282 job->height = [fHeightStepper intValue];
284 job->anamorphic.mode = 1;
285 [fWidthStepper setEnabled: NO];
286 [fWidthField setEnabled: NO];
289 /* if the sender is the Anamorphic checkbox, record the state
290 of KeepAspect Ratio so it can be reset if Anamorphic is unchecked again */
291 if (sender == fAnamorphicPopUp)
293 keepAspectRatioPreviousState = [fRatioCheck state];
295 [fRatioCheck setState:NSOffState];
296 [fRatioCheck setEnabled: NO];
299 [fHeightStepper setEnabled: NO];
300 [fHeightField setEnabled: NO];
305 job->width = [fWidthStepper intValue];
306 job->height = [fHeightStepper intValue];
307 job->anamorphic.mode = 0;
308 [fWidthStepper setEnabled: YES];
309 [fWidthField setEnabled: YES];
310 [fHeightStepper setEnabled: YES];
311 [fHeightField setEnabled: YES];
312 [fRatioCheck setEnabled: YES];
313 /* if the sender is the Anamorphic checkbox, we return the
314 keep AR checkbox to its previous state */
315 if (sender == fAnamorphicPopUp)
317 [fRatioCheck setState:keepAspectRatioPreviousState];
322 job->keep_ratio = ( [fRatioCheck state] == NSOnState );
324 if( job->keep_ratio )
326 if( sender == fWidthStepper || sender == fRatioCheck ||
327 sender == fCropTopStepper || sender == fCropBottomStepper )
329 hb_fix_aspect( job, HB_KEEP_WIDTH );
330 if( job->height > fTitle->height )
332 job->height = fTitle->height;
333 hb_fix_aspect( job, HB_KEEP_HEIGHT );
338 hb_fix_aspect( job, HB_KEEP_HEIGHT );
339 if( job->width > fTitle->width )
341 job->width = fTitle->width;
342 hb_fix_aspect( job, HB_KEEP_WIDTH );
345 // hb_get_preview can't handle sizes that are larger than the original title
347 if( job->width > fTitle->width )
348 job->width = fTitle->width;
350 if( job->height > fTitle->height )
351 job->height = fTitle->height;
354 [fWidthStepper setIntValue: job->width];
355 [fWidthField setIntValue: job->width];
356 if( [fAnamorphicPopUp indexOfSelectedItem] < 2 )
358 [fHeightStepper setIntValue: job->height];
359 [fHeightField setIntValue: job->height];
361 [fCropTopStepper setIntValue: job->crop[0]];
362 [fCropTopField setIntValue: job->crop[0]];
363 [fCropBottomStepper setIntValue: job->crop[1]];
364 [fCropBottomField setIntValue: job->crop[1]];
365 [fCropLeftStepper setIntValue: job->crop[2]];
366 [fCropLeftField setIntValue: job->crop[2]];
367 [fCropRightStepper setIntValue: job->crop[3]];
368 [fCropRightField setIntValue: job->crop[3]];
370 [fPreviewController SetTitle:fTitle];
371 /* Sanity Check Here for < 16 px preview to avoid
372 crashing hb_get_preview. In fact, just for kicks
373 lets getting previews at a min limit of 32, since
374 no human can see any meaningful detail below that */
375 if (job->width >= 64 && job->height >= 64)
378 // Purge the existing picture previews so they get recreated the next time
380 [fPreviewController purgeImageCache];
381 /* We actually call displayPreview now from pictureSliderChanged which keeps
382 * our picture preview slider in sync with the previews being shown
385 //[fPreviewController pictureSliderChanged:nil];
386 [self reloadStillPreview];
389 /* we get the sizing info to display from fPreviewController */
390 [fSizeInfoField setStringValue: [fPreviewController pictureSizeInfoString]];
394 [fHBController pictureSettingsDidChange];
399 - (NSString*) getPictureSizeInfoString
401 return [fSizeInfoField stringValue];
404 - (void)reloadStillPreview
406 hb_job_t * job = fTitle->job;
408 [fPreviewController SetTitle:fTitle];
409 /* Sanity Check Here for < 16 px preview to avoid
410 crashing hb_get_preview. In fact, just for kicks
411 lets getting previews at a min limit of 32, since
412 no human can see any meaningful detail below that */
413 if (job->width >= 64 && job->height >= 64)
416 // Purge the existing picture previews so they get recreated the next time
418 [fPreviewController purgeImageCache];
419 /* We actually call displayPreview now from pictureSliderChanged which keeps
420 * our picture preview slider in sync with the previews being shown
423 [fPreviewController pictureSliderChanged:nil];
435 - (void) setAutoCrop: (BOOL) setting
440 - (BOOL) allowLooseAnamorphic
442 return allowLooseAnamorphic;
445 - (void) setAllowLooseAnamorphic: (BOOL) setting
447 allowLooseAnamorphic = setting;
450 - (IBAction)showPreviewPanel: (id)sender forTitle: (hb_title_t *)title
452 [self SetTitle:title];
453 [self showWindow:sender];