OSDN Git Service

MacGui: Separate Picture Settings and Preview Window Initial Implementation
[handbrake-jp/handbrake-jp-git.git] / macosx / PictureController.mm
1 /* $Id: PictureController.mm,v 1.11 2005/08/01 15:10:44 titer Exp $
2
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. */
6
7 #import "PictureController.h"
8 #import "Controller.h"
9 #import "HBPreviewController.h"
10
11
12
13 @implementation PictureController
14
15 - (id)init
16 {
17         if (self = [super initWithWindowNibName:@"PictureSettings"])
18         {
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
23         // getter once.
24         //
25         // If/when we switch a lot of this stuff to bindings, this can probably
26         // go away.
27         [self window];
28         
29         fPreviewController = [[PreviewController alloc] init];
30     }
31         return self;
32 }
33
34 //------------------------------------------------------------------------------------
35 // Displays and brings the picture window to the front
36 //------------------------------------------------------------------------------------
37 - (IBAction) showPictureWindow: (id)sender
38 {
39     [self showWindow:sender];
40 }
41
42 - (IBAction) showPreviewWindow: (id)sender
43 {
44     [fPreviewController showWindow:sender];
45 }
46
47 - (void) setToFullScreenMode
48 {
49     [self showWindow:nil];
50     int32_t shieldLevel = CGShieldingWindowLevel(); 
51     
52     [fPictureWindow setLevel:shieldLevel]; 
53     // Show the window. 
54     [fPictureWindow makeKeyAndOrderFront:self];
55 }
56
57 - (void) setToWindowedMode
58 {
59     /* Set the window back to regular level */
60     
61     [self showWindow:nil];
62     
63     [[self window] setLevel:NSNormalWindowLevel];
64 }
65
66 - (void)setHBController: (HBController *)controller
67 {
68     fHBController = controller;
69     [fPreviewController   setHBController: controller];
70     
71 }
72
73 - (void)awakeFromNib
74 {
75     [fPictureWindow setDelegate:self];
76 }
77
78
79 - (void)windowWillClose:(NSNotification *)aNotification
80 {
81
82 }
83
84 - (BOOL)windowShouldClose:(id)fPictureWindow
85 {
86     return YES;
87 }
88
89 - (void) dealloc
90 {
91     [fPreviewController release];
92     [super dealloc];
93 }
94
95 - (void) SetHandle: (hb_handle_t *) handle
96 {
97     fHandle = handle;
98     
99     [fWidthStepper  setValueWraps: NO];
100     [fWidthStepper  setIncrement: 16];
101     [fWidthStepper  setMinValue: 64];
102     [fHeightStepper setValueWraps: NO];
103     [fHeightStepper setIncrement: 16];
104     [fHeightStepper setMinValue: 64];
105     
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];
114     
115     [fPreviewController SetHandle: fHandle];
116     
117
118 }
119
120 - (void) SetTitle: (hb_title_t *) title
121 {
122     hb_job_t * job = title->job;
123
124     fTitle = title;
125     
126     
127     
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];
139
140     /* Populate the Anamorphic NSPopUp button here */
141     [fAnamorphicPopUp removeAllItems];
142     [fAnamorphicPopUp addItemWithTitle: @"None"];
143     [fAnamorphicPopUp addItemWithTitle: @"Strict"];
144     if (allowLooseAnamorphic)
145     {
146     [fAnamorphicPopUp addItemWithTitle: @"Loose"];
147     }
148     [fAnamorphicPopUp selectItemAtIndex: job->pixel_ratio];
149     
150     /* We initially set the previous state of keep ar to on */
151     keepAspectRatioPreviousState = 1;
152         if (!autoCrop)
153         {
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]];
164         }
165         else
166         {
167         [fCropMatrix  selectCellAtRow: 0 column:0];
168         }
169         
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];
176     
177     fPicture = 0;
178     MaxOutputWidth = title->width - job->crop[2] - job->crop[3];
179     MaxOutputHeight = title->height - job->crop[0] - job->crop[1];
180     
181     //[fPreviewController SetTitle:fTitle];
182     
183     [self SettingsChanged: nil];
184 }
185
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
189 {
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"];
196     
197         /* Set deinterlaces level according to the integer in the main window */
198         [fDeinterlacePopUp selectItemAtIndex: fPictureFilterSettings.deinterlace];
199
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];
208     
209
210 }
211
212     
213     
214
215 - (IBAction) deblockSliderChanged: (id) sender
216 {
217     if ([fDeblockSlider floatValue] == 4.0)
218     {
219     [fDeblockField setStringValue: [NSString stringWithFormat: @"Off"]];
220     }
221     else
222     {
223     [fDeblockField setStringValue: [NSString stringWithFormat: @"%.0f", [fDeblockSlider floatValue]]];
224     }
225         [self SettingsChanged: sender];
226 }
227
228 - (IBAction) SettingsChanged: (id) sender
229 {
230     hb_job_t * job = fTitle->job;
231     
232     autoCrop = ( [fCropMatrix selectedRow] == 0 );
233     [fCropTopStepper    setEnabled: !autoCrop];
234     [fCropBottomStepper setEnabled: !autoCrop];
235     [fCropLeftStepper   setEnabled: !autoCrop];
236     [fCropRightStepper  setEnabled: !autoCrop];
237
238     if( autoCrop )
239     {
240         memcpy( job->crop, fTitle->crop, 4 * sizeof( int ) );
241     }
242     else
243     {
244         job->crop[0] = [fCropTopStepper    intValue];
245         job->crop[1] = [fCropBottomStepper intValue];
246         job->crop[2] = [fCropLeftStepper   intValue];
247         job->crop[3] = [fCropRightStepper  intValue];
248     }
249     
250         if( [fAnamorphicPopUp indexOfSelectedItem] > 0 )
251         {
252         if ([fAnamorphicPopUp indexOfSelectedItem] == 2) // Loose anamorphic
253         {
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
259              */
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.
262              */
263             if (sender == fAnamorphicPopUp)
264             {
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]];
267             }
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];
273             
274         }
275         else // must be "1" or strict anamorphic
276         {
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]];
279             
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];
286             
287             job->pixel_ratio = 1;
288             [fWidthStepper setEnabled: NO];
289             [fWidthField setEnabled: NO];
290         }
291         
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)
295         {
296             keepAspectRatioPreviousState = [fRatioCheck state];
297         }
298         [fRatioCheck setState:NSOffState];
299         [fRatioCheck setEnabled: NO];
300         
301         
302         [fHeightStepper setEnabled: NO];
303         [fHeightField setEnabled: NO];
304         
305     }
306     else
307         {
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)
319         {
320             [fRatioCheck setState:keepAspectRatioPreviousState];
321         }
322         
323         }
324         
325     job->keep_ratio  = ( [fRatioCheck state] == NSOnState );
326     
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)
332     {
333         job->deinterlace  = 1;
334     }
335     else
336     {
337         job->deinterlace  = 0;
338     }
339     fPictureFilterSettings.denoise     = [fDenoisePopUp indexOfSelectedItem];
340     
341     fPictureFilterSettings.detelecine  = [fDetelecineCheck state];
342     
343     if ([fDeblockField stringValue] == @"Off")
344     {
345     fPictureFilterSettings.deblock  = 0;
346     }
347     else
348     {
349     fPictureFilterSettings.deblock  = [fDeblockField intValue];
350     }
351     
352     fPictureFilterSettings.decomb = [fDecombCheck state];
353
354     if( job->keep_ratio )
355     {
356         if( sender == fWidthStepper || sender == fRatioCheck ||
357            sender == fCropTopStepper || sender == fCropBottomStepper )
358         {
359             hb_fix_aspect( job, HB_KEEP_WIDTH );
360             if( job->height > fTitle->height )
361             {
362                 job->height = fTitle->height;
363                 hb_fix_aspect( job, HB_KEEP_HEIGHT );
364             }
365         }
366         else
367         {
368             hb_fix_aspect( job, HB_KEEP_HEIGHT );
369             if( job->width > fTitle->width )
370             {
371                 job->width = fTitle->width;
372                 hb_fix_aspect( job, HB_KEEP_WIDTH );
373             }
374         }
375         // hb_get_preview can't handle sizes that are larger than the original title
376         // dimensions
377         if( job->width > fTitle->width )
378             job->width = fTitle->width;
379
380         if( job->height > fTitle->height )
381             job->height = fTitle->height;
382     }
383
384     [fWidthStepper      setIntValue: job->width];
385     [fWidthField        setIntValue: job->width];
386     if( [fAnamorphicPopUp indexOfSelectedItem] < 2 )
387         {
388         [fHeightStepper     setIntValue: job->height];
389         [fHeightField       setIntValue: job->height];
390     }
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]];
399     
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)
406     {
407        
408          // Purge the existing picture previews so they get recreated the next time
409         // they are needed.
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
413          */
414
415     [fPreviewController pictureSliderChanged:nil];
416
417     }
418
419     if (sender != nil)
420     {
421         [fHBController pictureSettingsDidChange];
422     }   
423     
424 }
425
426
427
428 #pragma mark -
429
430 - (BOOL) autoCrop
431 {
432     return autoCrop;
433 }
434 - (void) setAutoCrop: (BOOL) setting
435 {
436     autoCrop = setting;
437 }
438
439 - (BOOL) allowLooseAnamorphic
440 {
441     return allowLooseAnamorphic;
442 }
443
444 - (void) setAllowLooseAnamorphic: (BOOL) setting
445 {
446     allowLooseAnamorphic = setting;
447 }
448
449 - (int) detelecine
450 {
451     return fPictureFilterSettings.detelecine;
452 }
453
454 - (void) setDetelecine: (int) setting
455 {
456     fPictureFilterSettings.detelecine = setting;
457 }
458
459 - (int) deinterlace
460 {
461     return fPictureFilterSettings.deinterlace;
462 }
463
464 - (void) setDeinterlace: (int) setting {
465     fPictureFilterSettings.deinterlace = setting;
466 }
467 - (int) decomb
468 {
469     return fPictureFilterSettings.decomb;
470 }
471
472 - (void) setDecomb: (int) setting {
473     fPictureFilterSettings.decomb = setting;
474 }
475 - (int) denoise
476 {
477     return fPictureFilterSettings.denoise;
478 }
479
480 - (void) setDenoise: (int) setting
481 {
482     fPictureFilterSettings.denoise = setting;
483 }
484
485 - (int) deblock
486 {
487     return fPictureFilterSettings.deblock;
488 }
489
490 - (void) setDeblock: (int) setting
491 {
492     fPictureFilterSettings.deblock = setting;
493 }
494
495 - (IBAction)showPreviewPanel: (id)sender forTitle: (hb_title_t *)title
496 {
497     [self SetTitle:title];
498     [self showWindow:sender];
499
500 }
501
502 @end
503