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 - (IBAction) showPreviewWindow: (id)sender
61 [fPreviewController showWindow:sender];
64 - (IBAction) showFilterWindow: (id)sender
66 [fHBController showFiltersPanel:sender];
70 - (void) setToFullScreenMode
72 int32_t shieldLevel = CGShieldingWindowLevel();
74 [fPictureWindow setLevel:shieldLevel + 1];
76 [fPictureWindow makeKeyAndOrderFront:self];
79 - (void) setToWindowedMode
81 /* Set the window back to regular level */
82 [[self window] setLevel:NSNormalWindowLevel];
85 - (void)setHBController: (HBController *)controller
87 fHBController = controller;
88 //[fPictureFilterController setHBController: controller];
89 [fPreviewController setHBController: controller];
95 [fPictureWindow setDelegate:self];
96 if( ![[self window] setFrameUsingName:@"PictureSizing"] )
97 [[self window] center];
98 [self setWindowFrameAutosaveName:@"PictureSizing"];
99 [[self window] setExcludedFromWindowsMenu:YES];
103 - (void)windowWillClose:(NSNotification *)aNotification
105 [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"PictureSizeWindowIsOpen"];
108 - (BOOL)windowShouldClose:(id)fPictureWindow
115 [fPictureFilterController release];
116 [fPreviewController release];
120 - (void) SetHandle: (hb_handle_t *) handle
124 [fWidthStepper setValueWraps: NO];
125 [fWidthStepper setIncrement: 16];
126 [fWidthStepper setMinValue: 64];
127 [fHeightStepper setValueWraps: NO];
128 [fHeightStepper setIncrement: 16];
129 [fHeightStepper setMinValue: 64];
131 [fCropTopStepper setIncrement: 2];
132 [fCropTopStepper setMinValue: 0];
133 [fCropBottomStepper setIncrement: 2];
134 [fCropBottomStepper setMinValue: 0];
135 [fCropLeftStepper setIncrement: 2];
136 [fCropLeftStepper setMinValue: 0];
137 [fCropRightStepper setIncrement: 2];
138 [fCropRightStepper setMinValue: 0];
140 [fPreviewController SetHandle: fHandle];
141 [fPictureFilterController SetHandle: fHandle];
146 - (void) SetTitle: (hb_title_t *) title
148 hb_job_t * job = title->job;
154 [fWidthStepper setMaxValue: title->width];
155 [fWidthStepper setIntValue: job->width];
156 [fWidthField setIntValue: job->width];
157 [fHeightStepper setMaxValue: title->height];
158 [fHeightStepper setIntValue: job->height];
159 [fHeightField setIntValue: job->height];
160 [fRatioCheck setState: job->keep_ratio ? NSOnState : NSOffState];
161 [fCropTopStepper setMaxValue: title->height/2-2];
162 [fCropBottomStepper setMaxValue: title->height/2-2];
163 [fCropLeftStepper setMaxValue: title->width/2-2];
164 [fCropRightStepper setMaxValue: title->width/2-2];
166 /* Populate the Anamorphic NSPopUp button here */
167 [fAnamorphicPopUp removeAllItems];
168 [fAnamorphicPopUp addItemWithTitle: @"None"];
169 [fAnamorphicPopUp addItemWithTitle: @"Strict"];
170 if (allowLooseAnamorphic)
172 [fAnamorphicPopUp addItemWithTitle: @"Loose"];
174 [fAnamorphicPopUp selectItemAtIndex: job->anamorphic.mode];
176 /* We initially set the previous state of keep ar to on */
177 keepAspectRatioPreviousState = 1;
180 [fCropMatrix selectCellAtRow: 1 column:0];
181 /* If auto, lets set the crop steppers according to current job->crop values */
182 [fCropTopStepper setIntValue: job->crop[0]];
183 [fCropTopField setIntValue: job->crop[0]];
184 [fCropBottomStepper setIntValue: job->crop[1]];
185 [fCropBottomField setIntValue: job->crop[1]];
186 [fCropLeftStepper setIntValue: job->crop[2]];
187 [fCropLeftField setIntValue: job->crop[2]];
188 [fCropRightStepper setIntValue: job->crop[3]];
189 [fCropRightField setIntValue: job->crop[3]];
193 [fCropMatrix selectCellAtRow: 0 column:0];
196 /* Set filters widgets according to the filters struct */
197 /* this has now been movied to the filters controller */
199 [fDetelecineCheck setState:fPictureFilterSettings.detelecine];
200 [fDeinterlacePopUp selectItemAtIndex: fPictureFilterSettings.deinterlace];
201 [fDenoisePopUp selectItemAtIndex: fPictureFilterSettings.denoise];
202 [fDeblockCheck setState: fPictureFilterSettings.deblock];
203 [fDecombCheck setState: fPictureFilterSettings.decomb];
207 MaxOutputWidth = title->width - job->crop[2] - job->crop[3];
208 MaxOutputHeight = title->height - job->crop[0] - job->crop[1];
210 [self SettingsChanged: nil];
215 - (IBAction) SettingsChanged: (id) sender
217 hb_job_t * job = fTitle->job;
219 autoCrop = ( [fCropMatrix selectedRow] == 0 );
220 [fCropTopStepper setEnabled: !autoCrop];
221 [fCropBottomStepper setEnabled: !autoCrop];
222 [fCropLeftStepper setEnabled: !autoCrop];
223 [fCropRightStepper setEnabled: !autoCrop];
227 memcpy( job->crop, fTitle->crop, 4 * sizeof( int ) );
231 job->crop[0] = [fCropTopStepper intValue];
232 job->crop[1] = [fCropBottomStepper intValue];
233 job->crop[2] = [fCropLeftStepper intValue];
234 job->crop[3] = [fCropRightStepper intValue];
237 if( [fAnamorphicPopUp indexOfSelectedItem] > 0 )
239 if ([fAnamorphicPopUp indexOfSelectedItem] == 2) // Loose anamorphic
241 job->anamorphic.mode = 2;
242 [fWidthStepper setEnabled: YES];
243 [fWidthField setEnabled: YES];
244 /* We set job->width and call hb_set_anamorphic_size in libhb to do a "dry run" to get
245 * the values to be used by libhb for loose anamorphic
247 /* if the sender is the anamorphic popup, then we know that loose anamorphic has just
248 * been turned on, so snap the width to full width for the source.
250 if (sender == fAnamorphicPopUp)
252 [fWidthStepper setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
253 [fWidthField setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
255 job->width = [fWidthStepper intValue];
256 hb_set_anamorphic_size(job, &output_width, &output_height, &output_par_width, &output_par_height);
257 [fHeightStepper setIntValue: output_height];
258 [fHeightField setIntValue: output_height];
259 job->height = [fHeightStepper intValue];
262 else // must be "1" or strict anamorphic
264 [fWidthStepper setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
265 [fWidthField setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]];
267 /* This will show correct anamorphic height values, but
268 show distorted preview picture ratio */
269 [fHeightStepper setIntValue: fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]];
270 [fHeightField setIntValue: fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]];
271 job->width = [fWidthStepper intValue];
272 job->height = [fHeightStepper intValue];
274 job->anamorphic.mode = 1;
275 [fWidthStepper setEnabled: NO];
276 [fWidthField setEnabled: NO];
279 /* if the sender is the Anamorphic checkbox, record the state
280 of KeepAspect Ratio so it can be reset if Anamorphic is unchecked again */
281 if (sender == fAnamorphicPopUp)
283 keepAspectRatioPreviousState = [fRatioCheck state];
285 [fRatioCheck setState:NSOffState];
286 [fRatioCheck setEnabled: NO];
289 [fHeightStepper setEnabled: NO];
290 [fHeightField setEnabled: NO];
295 job->width = [fWidthStepper intValue];
296 job->height = [fHeightStepper intValue];
297 job->anamorphic.mode = 0;
298 [fWidthStepper setEnabled: YES];
299 [fWidthField setEnabled: YES];
300 [fHeightStepper setEnabled: YES];
301 [fHeightField setEnabled: YES];
302 [fRatioCheck setEnabled: YES];
303 /* if the sender is the Anamorphic checkbox, we return the
304 keep AR checkbox to its previous state */
305 if (sender == fAnamorphicPopUp)
307 [fRatioCheck setState:keepAspectRatioPreviousState];
312 job->keep_ratio = ( [fRatioCheck state] == NSOnState );
314 if( job->keep_ratio )
316 if( sender == fWidthStepper || sender == fRatioCheck ||
317 sender == fCropTopStepper || sender == fCropBottomStepper )
319 hb_fix_aspect( job, HB_KEEP_WIDTH );
320 if( job->height > fTitle->height )
322 job->height = fTitle->height;
323 hb_fix_aspect( job, HB_KEEP_HEIGHT );
328 hb_fix_aspect( job, HB_KEEP_HEIGHT );
329 if( job->width > fTitle->width )
331 job->width = fTitle->width;
332 hb_fix_aspect( job, HB_KEEP_WIDTH );
335 // hb_get_preview can't handle sizes that are larger than the original title
337 if( job->width > fTitle->width )
338 job->width = fTitle->width;
340 if( job->height > fTitle->height )
341 job->height = fTitle->height;
344 [fWidthStepper setIntValue: job->width];
345 [fWidthField setIntValue: job->width];
346 if( [fAnamorphicPopUp indexOfSelectedItem] < 2 )
348 [fHeightStepper setIntValue: job->height];
349 [fHeightField setIntValue: job->height];
351 [fCropTopStepper setIntValue: job->crop[0]];
352 [fCropTopField setIntValue: job->crop[0]];
353 [fCropBottomStepper setIntValue: job->crop[1]];
354 [fCropBottomField setIntValue: job->crop[1]];
355 [fCropLeftStepper setIntValue: job->crop[2]];
356 [fCropLeftField setIntValue: job->crop[2]];
357 [fCropRightStepper setIntValue: job->crop[3]];
358 [fCropRightField setIntValue: job->crop[3]];
360 [fPreviewController SetTitle:fTitle];
361 /* Sanity Check Here for < 16 px preview to avoid
362 crashing hb_get_preview. In fact, just for kicks
363 lets getting previews at a min limit of 32, since
364 no human can see any meaningful detail below that */
365 if (job->width >= 64 && job->height >= 64)
368 // Purge the existing picture previews so they get recreated the next time
370 [fPreviewController purgeImageCache];
371 /* We actually call displayPreview now from pictureSliderChanged which keeps
372 * our picture preview slider in sync with the previews being shown
375 //[fPreviewController pictureSliderChanged:nil];
376 [self reloadStillPreview];
379 /* we get the sizing info to display from fPreviewController */
380 [fSizeInfoField setStringValue: [fPreviewController pictureSizeInfoString]];
384 [fHBController pictureSettingsDidChange];
389 - (NSString*) getPictureSizeInfoString
391 return [fSizeInfoField stringValue];
394 - (void)reloadStillPreview
396 hb_job_t * job = fTitle->job;
398 [fPreviewController SetTitle:fTitle];
399 /* Sanity Check Here for < 16 px preview to avoid
400 crashing hb_get_preview. In fact, just for kicks
401 lets getting previews at a min limit of 32, since
402 no human can see any meaningful detail below that */
403 if (job->width >= 64 && job->height >= 64)
406 // Purge the existing picture previews so they get recreated the next time
408 [fPreviewController purgeImageCache];
409 /* We actually call displayPreview now from pictureSliderChanged which keeps
410 * our picture preview slider in sync with the previews being shown
413 [fPreviewController pictureSliderChanged:nil];
425 - (void) setAutoCrop: (BOOL) setting
430 - (BOOL) allowLooseAnamorphic
432 return allowLooseAnamorphic;
435 - (void) setAllowLooseAnamorphic: (BOOL) setting
437 allowLooseAnamorphic = setting;
440 - (IBAction)showPreviewPanel: (id)sender forTitle: (hb_title_t *)title
442 [self SetTitle:title];
443 [self showWindow:sender];