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"
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];
34 //------------------------------------------------------------------------------------
35 // Displays and brings the picture window to the front
36 //------------------------------------------------------------------------------------
37 - (IBAction) showPictureWindow: (id)sender
39 [self showWindow:sender];
42 - (IBAction) showPreviewWindow: (id)sender
44 [fPreviewController showWindow:sender];
47 - (void) setToFullScreenMode
49 [self showWindow:nil];
50 int32_t shieldLevel = CGShieldingWindowLevel();
52 [fPictureWindow setLevel:shieldLevel];
54 [fPictureWindow makeKeyAndOrderFront:self];
57 - (void) setToWindowedMode
59 /* Set the window back to regular level */
61 [self showWindow:nil];
63 [[self window] setLevel:NSNormalWindowLevel];
66 - (void)setHBController: (HBController *)controller
68 fHBController = controller;
69 [fPreviewController setHBController: controller];
75 [fPictureWindow setDelegate:self];
79 - (void)windowWillClose:(NSNotification *)aNotification
84 - (BOOL)windowShouldClose:(id)fPictureWindow
91 [fPreviewController release];
95 - (void) SetHandle: (hb_handle_t *) handle
99 [fWidthStepper setValueWraps: NO];
100 [fWidthStepper setIncrement: 16];
101 [fWidthStepper setMinValue: 64];
102 [fHeightStepper setValueWraps: NO];
103 [fHeightStepper setIncrement: 16];
104 [fHeightStepper setMinValue: 64];
106 [fCropTopStepper setIncrement: 2];
107 [fCropTopStepper setMinValue: 0];
108 [fCropBottomStepper setIncrement: 2];
109 [fCropBottomStepper setMinValue: 0];
110 [fCropLeftStepper setIncrement: 2];
111 [fCropLeftStepper setMinValue: 0];
112 [fCropRightStepper setIncrement: 2];
113 [fCropRightStepper setMinValue: 0];
115 [fPreviewController SetHandle: fHandle];
120 - (void) SetTitle: (hb_title_t *) title
122 hb_job_t * job = title->job;
128 [fWidthStepper setMaxValue: title->width];
129 [fWidthStepper setIntValue: job->width];
130 [fWidthField setIntValue: job->width];
131 [fHeightStepper setMaxValue: title->height];
132 [fHeightStepper setIntValue: job->height];
133 [fHeightField setIntValue: job->height];
134 [fRatioCheck setState: job->keep_ratio ? NSOnState : NSOffState];
135 [fCropTopStepper setMaxValue: title->height/2-2];
136 [fCropBottomStepper setMaxValue: title->height/2-2];
137 [fCropLeftStepper setMaxValue: title->width/2-2];
138 [fCropRightStepper setMaxValue: title->width/2-2];
140 /* Populate the Anamorphic NSPopUp button here */
141 [fAnamorphicPopUp removeAllItems];
142 [fAnamorphicPopUp addItemWithTitle: @"None"];
143 [fAnamorphicPopUp addItemWithTitle: @"Strict"];
144 if (allowLooseAnamorphic)
146 [fAnamorphicPopUp addItemWithTitle: @"Loose"];
148 [fAnamorphicPopUp selectItemAtIndex: job->pixel_ratio];
150 /* We initially set the previous state of keep ar to on */
151 keepAspectRatioPreviousState = 1;
154 [fCropMatrix selectCellAtRow: 1 column:0];
155 /* If auto, lets set the crop steppers according to current job->crop values */
156 [fCropTopStepper setIntValue: job->crop[0]];
157 [fCropTopField setIntValue: job->crop[0]];
158 [fCropBottomStepper setIntValue: job->crop[1]];
159 [fCropBottomField setIntValue: job->crop[1]];
160 [fCropLeftStepper setIntValue: job->crop[2]];
161 [fCropLeftField setIntValue: job->crop[2]];
162 [fCropRightStepper setIntValue: job->crop[3]];
163 [fCropRightField setIntValue: job->crop[3]];
167 [fCropMatrix selectCellAtRow: 0 column:0];
170 /* Set filters widgets according to the filters struct */
171 [fDetelecineCheck setState:fPictureFilterSettings.detelecine];
172 [fDeinterlacePopUp selectItemAtIndex: fPictureFilterSettings.deinterlace];
173 [fDenoisePopUp selectItemAtIndex: fPictureFilterSettings.denoise];
174 [fDeblockCheck setState: fPictureFilterSettings.deblock];
175 [fDecombCheck setState: fPictureFilterSettings.decomb];
178 MaxOutputWidth = title->width - job->crop[2] - job->crop[3];
179 MaxOutputHeight = title->height - job->crop[0] - job->crop[1];
181 //[fPreviewController SetTitle:fTitle];
183 [self SettingsChanged: nil];
186 /* we use this to setup the initial picture filters upon first launch, after that their states
187 are maintained across different sources */
188 - (void) setInitialPictureFilters
190 /* we use a popup to show the deinterlace settings */
191 [fDeinterlacePopUp removeAllItems];
192 [fDeinterlacePopUp addItemWithTitle: @"None"];
193 [fDeinterlacePopUp addItemWithTitle: @"Fast"];
194 [fDeinterlacePopUp addItemWithTitle: @"Slow"];
195 [fDeinterlacePopUp addItemWithTitle: @"Slower"];
197 /* Set deinterlaces level according to the integer in the main window */
198 [fDeinterlacePopUp selectItemAtIndex: fPictureFilterSettings.deinterlace];
200 /* we use a popup to show the denoise settings */
201 [fDenoisePopUp removeAllItems];
202 [fDenoisePopUp addItemWithTitle: @"None"];
203 [fDenoisePopUp addItemWithTitle: @"Weak"];
204 [fDenoisePopUp addItemWithTitle: @"Medium"];
205 [fDenoisePopUp addItemWithTitle: @"Strong"];
206 /* Set denoises level according to the integer in the main window */
207 [fDenoisePopUp selectItemAtIndex: fPictureFilterSettings.denoise];
215 - (IBAction) deblockSliderChanged: (id) sender
217 if ([fDeblockSlider floatValue] == 4.0)
219 [fDeblockField setStringValue: [NSString stringWithFormat: @"Off"]];
223 [fDeblockField setStringValue: [NSString stringWithFormat: @"%.0f", [fDeblockSlider floatValue]]];
225 [self SettingsChanged: sender];
228 - (IBAction) SettingsChanged: (id) sender
230 hb_job_t * job = fTitle->job;
232 autoCrop = ( [fCropMatrix selectedRow] == 0 );
233 [fCropTopStepper setEnabled: !autoCrop];
234 [fCropBottomStepper setEnabled: !autoCrop];
235 [fCropLeftStepper setEnabled: !autoCrop];
236 [fCropRightStepper setEnabled: !autoCrop];
240 memcpy( job->crop, fTitle->crop, 4 * sizeof( int ) );
244 job->crop[0] = [fCropTopStepper intValue];
245 job->crop[1] = [fCropBottomStepper intValue];
246 job->crop[2] = [fCropLeftStepper intValue];
247 job->crop[3] = [fCropRightStepper intValue];
250 if( [fAnamorphicPopUp indexOfSelectedItem] > 0 )
252 if ([fAnamorphicPopUp indexOfSelectedItem] == 2) // Loose anamorphic
254 job->pixel_ratio = 2;
255 [fWidthStepper setEnabled: YES];
256 [fWidthField setEnabled: YES];
257 /* We set job->width and call hb_set_anamorphic_size in libhb to do a "dry run" to get
258 * the values to be used by libhb for loose anamorphic
260 /* if the sender is the anamorphic popup, then we know that loose anamorphic has just
261 * been turned on, so snap the width to full width for the source.
263 if (sender == fAnamorphicPopUp)
265 [fWidthStepper setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
266 [fWidthField setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
268 job->width = [fWidthStepper intValue];
269 hb_set_anamorphic_size(job, &output_width, &output_height, &output_par_width, &output_par_height);
270 [fHeightStepper setIntValue: output_height];
271 [fHeightField setIntValue: output_height];
272 job->height = [fHeightStepper intValue];
275 else // must be "1" or strict anamorphic
277 [fWidthStepper setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
278 [fWidthField setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
280 /* This will show correct anamorphic height values, but
281 show distorted preview picture ratio */
282 [fHeightStepper setIntValue: fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]];
283 [fHeightField setIntValue: fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]];
284 job->width = [fWidthStepper intValue];
285 job->height = [fHeightStepper intValue];
287 job->pixel_ratio = 1;
288 [fWidthStepper setEnabled: NO];
289 [fWidthField setEnabled: NO];
292 /* if the sender is the Anamorphic checkbox, record the state
293 of KeepAspect Ratio so it can be reset if Anamorphic is unchecked again */
294 if (sender == fAnamorphicPopUp)
296 keepAspectRatioPreviousState = [fRatioCheck state];
298 [fRatioCheck setState:NSOffState];
299 [fRatioCheck setEnabled: NO];
302 [fHeightStepper setEnabled: NO];
303 [fHeightField setEnabled: NO];
308 job->width = [fWidthStepper intValue];
309 job->height = [fHeightStepper intValue];
310 job->pixel_ratio = 0;
311 [fWidthStepper setEnabled: YES];
312 [fWidthField setEnabled: YES];
313 [fHeightStepper setEnabled: YES];
314 [fHeightField setEnabled: YES];
315 [fRatioCheck setEnabled: YES];
316 /* if the sender is the Anamorphic checkbox, we return the
317 keep AR checkbox to its previous state */
318 if (sender == fAnamorphicPopUp)
320 [fRatioCheck setState:keepAspectRatioPreviousState];
325 job->keep_ratio = ( [fRatioCheck state] == NSOnState );
327 fPictureFilterSettings.deinterlace = [fDeinterlacePopUp indexOfSelectedItem];
328 /* if the gui deinterlace settings are fast through slowest, the job->deinterlace
329 value needs to be set to one, for the job as well as the previews showing deinterlacing
330 otherwise set job->deinterlace to 0 or "off" */
331 if (fPictureFilterSettings.deinterlace > 0)
333 job->deinterlace = 1;
337 job->deinterlace = 0;
339 fPictureFilterSettings.denoise = [fDenoisePopUp indexOfSelectedItem];
341 fPictureFilterSettings.detelecine = [fDetelecineCheck state];
343 if ([fDeblockField stringValue] == @"Off")
345 fPictureFilterSettings.deblock = 0;
349 fPictureFilterSettings.deblock = [fDeblockField intValue];
352 fPictureFilterSettings.decomb = [fDecombCheck state];
354 if( job->keep_ratio )
356 if( sender == fWidthStepper || sender == fRatioCheck ||
357 sender == fCropTopStepper || sender == fCropBottomStepper )
359 hb_fix_aspect( job, HB_KEEP_WIDTH );
360 if( job->height > fTitle->height )
362 job->height = fTitle->height;
363 hb_fix_aspect( job, HB_KEEP_HEIGHT );
368 hb_fix_aspect( job, HB_KEEP_HEIGHT );
369 if( job->width > fTitle->width )
371 job->width = fTitle->width;
372 hb_fix_aspect( job, HB_KEEP_WIDTH );
375 // hb_get_preview can't handle sizes that are larger than the original title
377 if( job->width > fTitle->width )
378 job->width = fTitle->width;
380 if( job->height > fTitle->height )
381 job->height = fTitle->height;
384 [fWidthStepper setIntValue: job->width];
385 [fWidthField setIntValue: job->width];
386 if( [fAnamorphicPopUp indexOfSelectedItem] < 2 )
388 [fHeightStepper setIntValue: job->height];
389 [fHeightField setIntValue: job->height];
391 [fCropTopStepper setIntValue: job->crop[0]];
392 [fCropTopField setIntValue: job->crop[0]];
393 [fCropBottomStepper setIntValue: job->crop[1]];
394 [fCropBottomField setIntValue: job->crop[1]];
395 [fCropLeftStepper setIntValue: job->crop[2]];
396 [fCropLeftField setIntValue: job->crop[2]];
397 [fCropRightStepper setIntValue: job->crop[3]];
398 [fCropRightField setIntValue: job->crop[3]];
400 [fPreviewController SetTitle:fTitle];
401 /* Sanity Check Here for < 16 px preview to avoid
402 crashing hb_get_preview. In fact, just for kicks
403 lets getting previews at a min limit of 32, since
404 no human can see any meaningful detail below that */
405 if (job->width >= 64 && job->height >= 64)
408 // Purge the existing picture previews so they get recreated the next time
410 [fPreviewController purgeImageCache];
411 /* We actually call displayPreview now from pictureSliderChanged which keeps
412 * our picture preview slider in sync with the previews being shown
415 [fPreviewController pictureSliderChanged:nil];
421 [fHBController pictureSettingsDidChange];
434 - (void) setAutoCrop: (BOOL) setting
439 - (BOOL) allowLooseAnamorphic
441 return allowLooseAnamorphic;
444 - (void) setAllowLooseAnamorphic: (BOOL) setting
446 allowLooseAnamorphic = setting;
451 return fPictureFilterSettings.detelecine;
454 - (void) setDetelecine: (int) setting
456 fPictureFilterSettings.detelecine = setting;
461 return fPictureFilterSettings.deinterlace;
464 - (void) setDeinterlace: (int) setting {
465 fPictureFilterSettings.deinterlace = setting;
469 return fPictureFilterSettings.decomb;
472 - (void) setDecomb: (int) setting {
473 fPictureFilterSettings.decomb = setting;
477 return fPictureFilterSettings.denoise;
480 - (void) setDenoise: (int) setting
482 fPictureFilterSettings.denoise = setting;
487 return fPictureFilterSettings.deblock;
490 - (void) setDeblock: (int) setting
492 fPictureFilterSettings.deblock = setting;
495 - (IBAction)showPreviewPanel: (id)sender forTitle: (hb_title_t *)title
497 [self SetTitle:title];
498 [self showWindow:sender];