]> git.sesse.net Git - vlc/blob - modules/gui/macosx/extended.m
macosx: we need to import intf.h before any import of vlc/vlc.h, because it includes...
[vlc] / modules / gui / macosx / extended.m
1 /*****************************************************************************
2  * extended.m: MacOS X Extended interface panel
3  *****************************************************************************
4  * Copyright (C) 2005-2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Felix Paul Kühne <fkuehne@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #import "extended.h"
30 #import "vout.h"
31 #import <vlc_aout.h>
32 #import <vlc_vout.h>
33 #import <vlc_interface.h>
34
35 /*****************************************************************************
36  * VLCExtended implementation
37  *****************************************************************************/
38
39 @implementation VLCExtended
40
41 static VLCExtended *_o_sharedInstance = nil;
42
43 + (VLCExtended *)sharedInstance
44 {
45     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
46 }
47
48 - (id)init
49 {
50     if (_o_sharedInstance) {
51         [self dealloc];
52     } else {
53         _o_sharedInstance = [super init];
54     }
55
56     return _o_sharedInstance;
57 }
58
59 /*****************************************************************************
60  * GUI methods
61  *****************************************************************************/
62
63 - (void)initStrings
64 {
65     /* localise GUI-strings */
66     /* method is called from intf.m (in method showExtended) */
67     [o_extended_window setTitle: _NS("Extended controls")];
68     [o_lbl_video setStringValue: _NS("Video")];
69     [o_lbl_audio setStringValue: _NS("Audio")];
70     [o_lbl_audioFlts setStringValue: _NS("Audio filters")];
71     [o_lbl_videoFlts setStringValue: _NS("Video filters")];
72     [o_lbl_adjustImage setStringValue: _NS("Image adjustment")];
73     [o_btn_vidFlts_mrInfo setToolTip: _NS("Shows more information about the available video filters.")];
74     [o_ckb_wave setTitle: _NS("Wave")];
75     [o_ckb_ripple setTitle: _NS("Ripple")];
76     [o_ckb_psycho setTitle: _NS("Psychedelic")];
77     [o_ckb_gradient setTitle: _NS("Gradient")];
78     [o_lbl_general setStringValue: _NS("General editing filters")];
79     [o_lbl_distort setStringValue: _NS("Distortion filters")];
80     [o_ckb_blur setTitle: _NS("Blur")];
81     [o_ckb_blur setToolTip: _NS("Adds motion blurring to the image")];
82     [o_ckb_imgClone setTitle: _NS("Image clone")];
83     [o_ckb_imgClone setToolTip: _NS("Creates several copies of the Video "
84                                     "output window" )];
85     [o_ckb_imgCrop setTitle: _NS("Image cropping")];
86     [o_ckb_imgCrop setToolTip: _NS("Crops a defined part of the image")];
87     [o_ckb_imgInvers setTitle: _NS("Invert colors")];
88     [o_ckb_imgInvers setToolTip: _NS("Inverts the colors of the image")];
89     [o_ckb_trnsform setTitle: _NS("Transformation")];
90     [o_ckb_trnsform setToolTip: _NS("Rotates or flips the image")];
91     [o_ckb_intZoom setTitle: _NS("Interactive Zoom")];
92     [o_ckb_intZoom setToolTip: _NS("Enables an interactive Zoom feature")];
93     [o_ckb_vlme_norm setTitle: _NS("Volume normalization")];
94     [o_ckb_vlme_norm setToolTip: _NS("Prevents the audio output from going "
95                                      "over a predefined value.")];
96     [o_ckb_hdphnVirt setTitle: _NS("Headphone virtualization")];
97     [o_ckb_hdphnVirt setToolTip: _NS("Imitates the effect of surround sound "
98                                      "when using headphones.")];
99     [o_lbl_maxLevel setStringValue: _NS("Maximum level")];
100     [o_btn_rstrDefaults setTitle: _NS("Restore Defaults")];
101     [o_ckb_enblAdjustImg setTitle: _NS("Enable")];
102     [o_lbl_brightness setStringValue: _NS("Brightness")];
103     [o_lbl_contrast setStringValue: _NS("Contrast")];
104     [o_lbl_gamma setStringValue: _NS("Gamma")];
105     [o_lbl_hue setStringValue: _NS("Hue")];
106     [o_lbl_saturation setStringValue: _NS("Saturation")];
107     [o_lbl_opaque setStringValue: _NS("Opaqueness")];
108  
109 }
110
111 - (void)awakeFromNib
112 {
113     /* set the adjust-filter-sliders to the values from the prefs and enable
114      * them, if wanted */
115     char * psz_vfilters;
116     intf_thread_t * p_intf = VLCIntf;
117     psz_vfilters = config_GetPsz( p_intf, "vout-filter" );
118     /* set the video-filter-checkboxes to the correct values */
119     if( psz_vfilters )
120     {
121         [o_ckb_blur setState: (int)strstr( psz_vfilters, "motionblur")];
122         [o_ckb_imgClone setState: (int)strstr( psz_vfilters, "clone")];
123         [o_ckb_imgCrop setState: (int)strstr( psz_vfilters, "crop")];
124         [o_ckb_trnsform setState: (int)strstr( psz_vfilters, "transform")];
125
126         free( psz_vfilters );
127     }
128  
129     /* set the video-filter checkboxes to the correct values */
130     char * psz_vifilters;
131     psz_vifilters = config_GetPsz( p_intf, "video-filter" );
132     if( psz_vifilters && strstr( psz_vifilters, "adjust" ) )
133     {
134         [o_ckb_enblAdjustImg setState: NSOnState];
135         [o_btn_rstrDefaults setEnabled: YES];
136         [o_sld_brightness setEnabled: YES];
137         [o_sld_contrast setEnabled: YES];
138         [o_sld_gamma setEnabled: YES];
139         [o_sld_hue setEnabled: YES];
140         [o_sld_saturation setEnabled: YES];
141     }
142     else
143     {
144         [o_ckb_enblAdjustImg setState: NSOffState];
145         [o_btn_rstrDefaults setEnabled: NO];
146         [o_sld_brightness setEnabled: NO];
147         [o_sld_contrast setEnabled: NO];
148         [o_sld_gamma setEnabled: NO];
149         [o_sld_hue setEnabled: NO];
150         [o_sld_saturation setEnabled: NO];
151     }
152     if( psz_vifilters )
153     {
154         [o_ckb_wave setState: (int)strstr( psz_vifilters, "wave")];
155         [o_ckb_psycho setState: (int)strstr( psz_vifilters, "psychedelic")];
156         [o_ckb_ripple setState: (int)strstr( psz_vifilters, "ripple")];
157         [o_ckb_gradient setState: (int)strstr( psz_vifilters, "gradient")];
158         [o_ckb_imgInvers setState: (int)strstr( psz_vifilters, "invert")];
159
160         free( psz_vifilters );
161     }
162  
163     /* set the audio-filter-checkboxes to the values taken from the prefs */
164     char * psz_afilters;
165     psz_afilters = config_GetPsz( p_intf, "audio-filter" );
166     if( psz_afilters )
167     {
168         [o_ckb_hdphnVirt setState: (int)strstr( psz_afilters, "headphone" ) ];
169         [o_ckb_vlme_norm setState: (int)strstr( psz_afilters, "normvol" ) ];
170  
171         free( psz_afilters );
172     }
173 }
174
175 - (void)collapsAll
176 {
177     /* collaps all views so Cocoa saves the window position correctly */
178     if( o_adjImg_expanded )
179         [self expandAdjustImage: nil];
180
181     if( o_audFlts_expanded )
182         [self expandAudioFilters: nil];
183
184     if( o_vidFlts_expanded )
185         [self expandVideoFilters: nil];
186 }
187
188 - (BOOL)getConfigChanged
189 {
190     return o_config_changed;
191 }
192
193 - (void)showPanel
194 {
195     /* get the correct slider values from the prefs, in case they were changed
196      * elsewhere */
197     intf_thread_t * p_intf = VLCIntf;
198
199     int i_value = config_GetInt( p_intf, "hue" );
200     if( i_value > 0 && i_value < 360 )
201     {
202         [o_sld_hue setIntValue: i_value];
203     }
204
205     float f_value;
206  
207     f_value = config_GetFloat( p_intf, "saturation" );
208     if( f_value > 0 && f_value < 5 )
209         [o_sld_saturation setIntValue: (int)(100 * f_value) ];
210
211     f_value = config_GetFloat( p_intf, "contrast" );
212     if( f_value > 0 && f_value < 4 )
213         [o_sld_contrast setIntValue: (int)(100 * f_value) ];
214
215     f_value = config_GetFloat( p_intf, "brightness" );
216     if( f_value > 0 && f_value < 2 )
217         [o_sld_brightness setIntValue: (int)(100 * f_value) ];
218
219     f_value = config_GetFloat( p_intf, "gamma" );
220     if( f_value > 0 && f_value < 10 )
221         [o_sld_gamma setIntValue: (int)(10 * f_value) ];
222
223     f_value = config_GetFloat( p_intf, "norm-max-level" );
224     if( f_value > 0 && f_value < 10 )
225         [o_sld_maxLevel setFloatValue: f_value ];
226
227     [o_sld_opaque setFloatValue: (config_GetFloat( p_intf,
228         "macosx-opaqueness") * 100)];
229
230     /* show the window */
231     [o_extended_window displayIfNeeded];
232     [o_extended_window makeKeyAndOrderFront:nil];
233 }
234
235 - (IBAction)enableAdjustImage:(id)sender
236 {
237     /* en-/disable the sliders */
238     if ([o_ckb_enblAdjustImg state] == NSOnState)
239     {
240         [o_btn_rstrDefaults setEnabled: YES];
241         [o_sld_brightness setEnabled: YES];
242         [o_sld_contrast setEnabled: YES];
243         [o_sld_gamma setEnabled: YES];
244         [o_sld_hue setEnabled: YES];
245         [o_sld_saturation setEnabled: YES];
246         [self changeVideoFiltersString: "adjust" onOrOff: VLC_TRUE];
247     }
248     else
249     {
250         [o_btn_rstrDefaults setEnabled: NO];
251         [o_sld_brightness setEnabled: NO];
252         [o_sld_contrast setEnabled: NO];
253         [o_sld_gamma setEnabled: NO];
254         [o_sld_hue setEnabled: NO];
255         [o_sld_saturation setEnabled: NO];
256         [self changeVideoFiltersString: "adjust" onOrOff: VLC_FALSE];
257     }
258 }
259
260 - (IBAction)restoreDefaultsForAdjustImage:(id)sender
261 {
262     /* reset the sliders */
263     [o_sld_brightness setIntValue: 100];
264     [o_sld_contrast setIntValue: 100];
265     [o_sld_gamma setIntValue: 10];
266     [o_sld_hue setIntValue: 0];
267     [o_sld_saturation setIntValue: 100];
268     [o_sld_opaque setIntValue: 100];
269
270     /* transmit the values */
271     [self sliderActionAdjustImage: o_sld_brightness];
272     [self sliderActionAdjustImage: o_sld_contrast];
273     [self sliderActionAdjustImage: o_sld_gamma];
274     [self sliderActionAdjustImage: o_sld_hue];
275     [self sliderActionAdjustImage: o_sld_saturation];
276     [self opaqueSliderAction: o_sld_opaque];
277 }
278
279 - (IBAction)sliderActionAdjustImage:(id)sender
280 {
281     /* read-out the sliders' values and apply them */
282     intf_thread_t * p_intf = VLCIntf;
283     vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find(p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE);
284     vlc_object_t *p_filter;
285
286     if( p_vout == NULL )
287     {
288         msg_Dbg( p_intf, "no vout present, saving settings anyway" );
289         if (sender == o_sld_brightness)
290         {
291             config_PutFloat( p_intf , "brightness" , [o_sld_brightness floatValue] / 100);
292         } 
293         else if (sender == o_sld_contrast)
294         {
295             config_PutFloat( p_intf , "contrast" , [o_sld_contrast floatValue] / 100);
296         } 
297         else if (sender == o_sld_gamma)
298         {
299             config_PutFloat( p_intf , "gamma" , [o_sld_gamma floatValue] / 10);
300         } 
301         else if (sender == o_sld_hue)
302         {
303             config_PutInt( p_intf , "hue" , [o_sld_hue intValue]);
304         } 
305         else if (sender == o_sld_saturation)
306         {
307             config_PutFloat( p_intf , "saturation" , [o_sld_saturation floatValue] / 100);
308         } 
309         else
310         {
311             msg_Warn( p_intf, "the corresponding subfilter coundn't be found" );
312         }
313     } 
314     else
315     {
316         msg_Dbg( p_intf, "we found a vout to adjust, let's look for the filter" );
317         p_filter = (vlc_object_t *)vlc_object_find_name( p_intf, "adjust", FIND_ANYWHERE );
318
319         if(! p_filter )
320         {
321             msg_Err( p_intf, "we're unable to find the adjust filter!" );
322             vlc_object_release( p_vout );
323             return;
324         }
325
326         if (sender == o_sld_brightness)
327         {
328             var_SetFloat( p_filter, "brightness", [o_sld_brightness floatValue] / 100 );
329             config_PutFloat( p_intf, "brightness", [o_sld_brightness floatValue] / 100 );
330         } 
331         else if (sender == o_sld_contrast)
332         {
333             var_SetFloat( p_filter, "contrast", [o_sld_contrast floatValue] / 100 );
334             config_PutFloat( p_intf, "contrast", [o_sld_contrast floatValue] / 100 );
335         } 
336         else if (sender == o_sld_gamma)
337         {
338             var_SetFloat( p_filter, "gamma", [o_sld_gamma floatValue] / 10 );
339             config_PutFloat( p_intf, "gamma", [o_sld_gamma floatValue] / 10 );
340         } 
341         else if (sender == o_sld_hue)
342         {
343             var_SetInteger( p_filter, "hue", [o_sld_hue intValue] );
344             config_PutInt( p_intf , "hue" , [o_sld_hue intValue] );
345         } 
346         else if (sender == o_sld_saturation)
347         {
348             var_SetFloat( p_filter, "saturation", [o_sld_saturation floatValue] / 100 );
349             config_PutFloat( p_intf , "saturation" , [o_sld_saturation floatValue] / 100 );
350         } 
351         else
352         {
353             msg_Warn( p_intf, "couldn't find variable for slider!" );
354         }
355         vlc_object_release( p_filter );
356         vlc_object_release( p_vout );
357     }
358
359     o_config_changed = YES;
360 }
361
362 /* change the opaqueness of the vouts */
363 - (IBAction)opaqueSliderAction:(id)sender
364 {
365     vlc_value_t val;
366     id o_window = [NSApp keyWindow];
367     NSArray *o_windows = [NSApp orderedWindows];
368     NSEnumerator *o_enumerator = [o_windows objectEnumerator];
369     playlist_t * p_playlist = pl_Yield( VLCIntf );
370     vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
371     vout_thread_t *p_real_vout;
372
373     val.f_float = [o_sld_opaque floatValue] / 100;
374
375     if( p_vout != NULL )
376     {
377         p_real_vout = [VLCVoutView getRealVout: p_vout];
378         var_Set( p_real_vout, "macosx-opaqueness", val );
379
380         while ((o_window = [o_enumerator nextObject]))
381         {
382             if( [[o_window className] isEqualToString: @"VLCVoutWindow"] ||
383                 [[[VLCMain sharedInstance] getEmbeddedList]
384                                     windowContainsEmbedded: o_window])
385             {
386                 [o_window setAlphaValue: val.f_float];
387             }
388             break;
389         }
390         vlc_object_release( p_vout );
391     }
392
393     /* store to prefs */
394     config_PutFloat( p_playlist , "macosx-opaqueness" , val.f_float );
395
396     vlc_object_release( p_playlist );
397
398     o_config_changed = YES;
399 }
400
401 - (IBAction)enableHeadphoneVirtualizer:(id)sender
402 {
403     /* en-/disable headphone virtualisation */
404     if ([o_ckb_hdphnVirt state] == NSOnState)
405         [self changeAFiltersString: "headphone_channel_mixer" onOrOff: VLC_TRUE ];
406     else
407         [self changeAFiltersString: "headphone_channel_mixer" onOrOff: VLC_FALSE ];
408 }
409
410 - (IBAction)sliderActionMaximumAudioLevel:(id)sender
411 {
412     /* read-out the slider's value and apply it */
413     intf_thread_t * p_intf = VLCIntf;
414     aout_instance_t * p_aout= (aout_instance_t *)vlc_object_find(p_intf, VLC_OBJECT_AOUT, FIND_ANYWHERE);
415
416     if( p_aout != NULL )
417     {
418         var_SetFloat( p_aout, "norm-max-level", [o_sld_maxLevel floatValue] );
419         vlc_object_release( p_aout );
420     }
421
422     config_PutFloat( p_intf, "norm-max-level", [o_sld_maxLevel floatValue] );
423
424     o_config_changed = YES;
425 }
426
427 - (IBAction)enableVolumeNormalization:(id)sender
428 {
429     /* en-/disable volume normalisation */
430     if( [o_ckb_vlme_norm state] == NSOnState )
431         [self changeAFiltersString: "normvol" onOrOff: YES ];
432     else
433         [self changeAFiltersString: "normvol" onOrOff: NO ];
434 }
435
436 - (IBAction)expandAdjustImage:(id)sender
437 {
438     /* expand or collapse adjImg */
439     NSRect o_win_rect = [o_extended_window frame];
440     NSRect o_box_audFlts_rect = [o_box_audFlts frame];
441     NSRect o_box_vidFlts_rect = [o_box_vidFlts frame];
442     NSRect o_box_adjImg_rect = [o_box_adjImg frame];
443  
444     if( o_adjImg_expanded )
445     {
446         /* move the window contents upwards (partially done through settings
447          * inside the nib) and resize the window */
448         o_win_rect.size.height = o_win_rect.size.height - 193;
449         o_win_rect.origin.y = [o_extended_window frame].origin.y + 193;
450         o_box_audFlts_rect.origin.y = o_box_audFlts_rect.origin.y + 193;
451         o_box_vidFlts_rect.origin.y = o_box_vidFlts_rect.origin.y + 193;
452  
453         /* remove the inserted view */
454         [o_adjustImg_view removeFromSuperviewWithoutNeedingDisplay];
455     }
456     else
457     {
458         /* move the window contents downwards and resize the window */
459         o_win_rect.size.height = o_win_rect.size.height + 193;
460         o_win_rect.origin.y = [o_extended_window frame].origin.y - 193;
461         o_box_audFlts_rect.origin.y = o_box_audFlts_rect.origin.y - 193;
462         o_box_vidFlts_rect.origin.y = o_box_vidFlts_rect.origin.y - 193;
463     }
464  
465     [o_box_audFlts setFrameFromContentFrame: o_box_audFlts_rect];
466     [o_box_vidFlts setFrameFromContentFrame: o_box_vidFlts_rect];
467     [o_extended_window displayIfNeeded];
468     [o_extended_window setFrame: o_win_rect display:YES animate: YES];
469  
470     if( o_adjImg_expanded )
471     {
472         o_box_adjImg_rect.size.height = [o_box_adjImg frame].size.height - 193;
473         o_adjImg_expanded = NO;
474     } 
475     else
476     {
477         /* insert view */
478         o_box_adjImg_rect.size.height = [o_box_adjImg frame].size.height + 193;
479         [o_adjustImg_view setFrame: NSMakeRect( 20, -10, 370, 203)];
480         [o_adjustImg_view setNeedsDisplay:YES];
481         [o_adjustImg_view setAutoresizesSubviews: YES];
482         [[o_box_adjImg contentView] addSubview: o_adjustImg_view];
483         o_adjImg_expanded = YES;
484     }
485     [o_box_adjImg setFrameFromContentFrame: o_box_adjImg_rect];
486 }
487
488 - (IBAction)expandAudioFilters:(id)sender
489 {
490     /* expand or collapse audFlts */
491     NSRect o_win_rect = [o_extended_window frame];
492     NSRect o_box_audFlts_rect = [o_box_audFlts frame];
493  
494     if( o_audFlts_expanded )
495     {
496         /* move the window contents upwards (partially done through settings
497          * inside the nib) and resize the window */
498         o_win_rect.size.height = o_win_rect.size.height - 66;
499         o_win_rect.origin.y = [o_extended_window frame].origin.y + 66;
500  
501         /* remove the inserted view */
502         [o_audioFlts_view removeFromSuperviewWithoutNeedingDisplay];
503     }
504     else
505     {
506         /* move the window contents downwards and resize the window */
507         o_win_rect.size.height = o_win_rect.size.height + 66;
508         o_win_rect.origin.y = [o_extended_window frame].origin.y - 66;
509     }
510     [o_extended_window displayIfNeeded];
511     [o_extended_window setFrame: o_win_rect display:YES animate: YES];
512  
513  
514     if( o_audFlts_expanded )
515     {
516         o_box_audFlts_rect.size.height = [o_box_audFlts frame].size.height - 66;
517         o_audFlts_expanded = NO;
518     } 
519     else
520     {
521         /* insert view */
522         o_box_audFlts_rect.size.height = [o_box_audFlts frame].size.height + 66;
523         [o_audioFlts_view setFrame: NSMakeRect( 20, -20, 370, 76)];
524         [o_audioFlts_view setNeedsDisplay:YES];
525         [o_audioFlts_view setAutoresizesSubviews: YES];
526         [[o_box_audFlts contentView] addSubview: o_audioFlts_view];
527         o_audFlts_expanded = YES;
528     }
529     [o_box_audFlts setFrameFromContentFrame: o_box_audFlts_rect];
530 }
531
532 - (IBAction)expandVideoFilters:(id)sender
533 {
534     /* expand or collapse vidFlts */
535     NSRect o_win_rect = [o_extended_window frame];
536     NSRect o_box_audFlts_rect = [o_box_audFlts frame];
537     NSRect o_box_vidFlts_rect = [o_box_vidFlts frame];
538  
539     if( o_vidFlts_expanded )
540     {
541         /* move the window contents upwards (partially done through settings
542          * inside the nib) and resize the window */
543         o_win_rect.size.height = o_win_rect.size.height - 172;
544         o_win_rect.origin.y = [o_extended_window frame].origin.y + 172;
545         o_box_audFlts_rect.origin.y = o_box_audFlts_rect.origin.y + 172;
546  
547         /* remove the inserted view */
548         [o_videoFilters_view removeFromSuperviewWithoutNeedingDisplay];
549     }
550     else
551     {
552         /* move the window contents downwards and resize the window */
553         o_win_rect.size.height = o_win_rect.size.height + 172;
554         o_win_rect.origin.y = [o_extended_window frame].origin.y - 172;
555         o_box_audFlts_rect.origin.y = o_box_audFlts_rect.origin.y - 172;
556     }
557  
558     [o_box_audFlts setFrameFromContentFrame: o_box_audFlts_rect];
559     [o_extended_window displayIfNeeded];
560     [o_extended_window setFrame: o_win_rect display:YES animate: YES];
561  
562     if( o_vidFlts_expanded )
563     {
564         o_box_vidFlts_rect.size.height = [o_box_vidFlts frame].size.height - 172;
565         o_vidFlts_expanded = NO;
566     } 
567     else
568     {
569         /* insert view */
570         o_box_vidFlts_rect.size.height = [o_box_vidFlts frame].size.height + 172;
571         [o_videoFilters_view setFrame: NSMakeRect( 20, -10, 370, 172)];
572         [o_videoFilters_view setNeedsDisplay:YES];
573         [o_videoFilters_view setAutoresizesSubviews: YES];
574         [[o_box_vidFlts contentView] addSubview: o_videoFilters_view];
575         o_vidFlts_expanded = YES;
576     }
577     [o_box_vidFlts setFrameFromContentFrame: o_box_vidFlts_rect];
578 }
579
580 - (IBAction)videoFilterAction:(id)sender
581 {
582     /* en-/disable video filters */
583     if (sender == o_ckb_blur)
584         [self changeVoutFiltersString: "motionblur" onOrOff: [o_ckb_blur state]];
585
586     else if (sender == o_ckb_imgClone)
587         [self changeVoutFiltersString: "clone" onOrOff: [o_ckb_imgClone state]];
588
589     else if (sender == o_ckb_imgCrop)
590         [self changeVoutFiltersString: "crop" onOrOff: [o_ckb_imgCrop state]];
591
592     else if (sender == o_ckb_imgInvers)
593         [self changeVideoFiltersString: "invert" onOrOff: [o_ckb_imgInvers state]];
594
595     else if (sender == o_ckb_trnsform)
596         [self changeVoutFiltersString: "transform" onOrOff: [o_ckb_trnsform state]];
597
598     else if (sender == o_ckb_intZoom )
599         [self changeVoutFiltersString: "magnify" onOrOff: [o_ckb_intZoom state]];
600
601     else if (sender == o_ckb_wave )
602         [self changeVideoFiltersString: "wave" onOrOff: [o_ckb_wave state]];
603
604     else if (sender == o_ckb_gradient )
605         [self changeVideoFiltersString: "gradient" onOrOff: [o_ckb_gradient state]];
606
607     else if (sender == o_ckb_psycho )
608         [self changeVideoFiltersString: "psychedelic" onOrOff: [o_ckb_psycho state]];
609
610     else if (sender == o_ckb_ripple )
611         [self changeVideoFiltersString: "ripple" onOrOff: [o_ckb_ripple state]];
612
613     else
614         msg_Err( VLCIntf, "cannot find switched video-filter" ); /* this can't happen */
615 }
616
617 - (IBAction)moreInfoVideoFilters:(id)sender
618 {
619     /* show info sheet */
620     NSBeginInformationalAlertSheet(_NS("About the video filters"), 
621                                    _NS("OK"), 
622                                    @"", 
623                                    @"",
624                                    o_extended_window, 
625                                    nil, 
626                                    nil, 
627                                    nil, 
628                                    nil, 
629                                    _NS("This panel allows on-the-fly selection of various video effects.\n"
630                                        "These filters can be configured individually in the Preferences, in "
631                                        "the subsections of Video/Filters.\n"
632                                        "To choose the order in which the filter are applied, a filter "
633                                        "option string can be set in the Preferences, Video / Filters section."));
634 }
635
636
637 /*****************************************************************************
638  * methods to communicate changes to VLC's core
639  *****************************************************************************/
640
641 - (void)changeVoutFiltersString:(char *)psz_name onOrOff:(vlc_bool_t )b_add
642 {
643     /* copied from ../wxwidgets/extrapanel.cpp
644      * renamed to conform with Cocoa's rules */
645     /* this method only changes 1st generation video filters (the ones that
646      * can't be used for transcoding). Have a look at changeVideoFiltersString
647      * for the 2nd generation filters. */
648  
649     vout_thread_t *p_vout;
650     intf_thread_t * p_intf = VLCIntf;
651  
652     char *psz_parser, *psz_string;
653     psz_string = config_GetPsz( p_intf, "vout-filter" );
654  
655     if( !psz_string ) psz_string = strdup("");
656
657     psz_parser = strstr( psz_string, psz_name );
658
659     if( b_add )
660     {
661         if( !psz_parser )
662         {
663             psz_parser = psz_string;
664             asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s",
665                             psz_string, psz_name );
666             free( psz_parser );
667         }
668         else
669         {
670             return;
671         }
672     }
673     else
674     {
675         if( psz_parser )
676         {
677             memmove( psz_parser, psz_parser + strlen(psz_name) +
678                             (*(psz_parser + strlen(psz_name)) == ':' ? 1 : 0 ),
679                             strlen(psz_parser + strlen(psz_name)) + 1 );
680
681             /* Remove trailing : : */
682             if( *(psz_string+strlen(psz_string ) -1 ) == ':' )
683             {
684                 *(psz_string+strlen(psz_string ) -1 ) = '\0';
685             }
686          }
687          else
688          {
689              free( psz_string );
690              return;
691          }
692     }
693     /* Vout is not kept, so put that in the config */
694     config_PutPsz( p_intf, "vout-filter", psz_string );
695
696     /* Try to set on the fly */
697     p_vout = (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
698                                               FIND_ANYWHERE );
699     if( p_vout )
700     {
701         var_SetString( p_vout, "vout-filter", psz_string );
702         vlc_object_release( p_vout );
703     }
704
705     free( psz_string );
706
707     o_config_changed = YES;
708 }
709
710
711 - (void)changeVideoFiltersString:(char *)psz_name onOrOff:(vlc_bool_t )b_add
712 {
713     /* same as changeVoutFiltersString but addressing the "video-filter"
714      * variable which represents the video filter 2 modules */
715  
716     vout_thread_t *p_vout;
717     intf_thread_t * p_intf = VLCIntf;
718  
719     char *psz_parser, *psz_string;
720     psz_string = config_GetPsz( p_intf, "video-filter" );
721  
722     if( !psz_string ) psz_string = strdup("");
723
724     psz_parser = strstr( psz_string, psz_name );
725
726     if( b_add )
727     {
728         if( !psz_parser )
729         {
730             psz_parser = psz_string;
731             asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s",
732                             psz_string, psz_name );
733             free( psz_parser );
734         }
735         else
736         {
737             return;
738         }
739     }
740     else
741     {
742         if( psz_parser )
743         {
744             memmove( psz_parser, psz_parser + strlen(psz_name) +
745                             (*(psz_parser + strlen(psz_name)) == ':' ? 1 : 0 ),
746                             strlen(psz_parser + strlen(psz_name)) + 1 );
747
748             /* Remove trailing : : */
749             if( *(psz_string+strlen(psz_string ) -1 ) == ':' )
750             {
751                 *(psz_string+strlen(psz_string ) -1 ) = '\0';
752             }
753          }
754          else
755          {
756              free( psz_string );
757              return;
758          }
759     }
760     /* Vout is not kept, so put that in the config */
761     config_PutPsz( p_intf, "video-filter", psz_string );
762
763     /* Try to set on the fly */
764     p_vout = (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
765                                               FIND_ANYWHERE );
766     if( p_vout )
767     {
768         var_SetString( p_vout, "video-filter", psz_string );
769         vlc_object_release( p_vout );
770     }
771
772     free( psz_string );
773
774     o_config_changed = YES;
775 }
776
777 - (void)changeAFiltersString: (char *)psz_name onOrOff: (vlc_bool_t )b_add;
778 {
779     /* copied from ../wxwidgets/extrapanel.cpp
780      * renamed to conform with Cocoa's rules */
781
782     char *psz_parser, *psz_string;
783     intf_thread_t * p_intf = VLCIntf;
784     aout_instance_t * p_aout= (aout_instance_t *)vlc_object_find(p_intf,
785                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
786
787     if( p_aout )
788     {
789         psz_string = var_GetNonEmptyString( p_aout, "audio-filter" );
790     }
791     else
792     {
793         psz_string = config_GetPsz( p_intf, "audio-filter" );
794     }
795
796     if( !psz_string ) psz_string = strdup("");
797
798     psz_parser = strstr( psz_string, psz_name );
799
800     if( b_add )
801     {
802         if( !psz_parser )
803         {
804             psz_parser = psz_string;
805             asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s",
806                             psz_string, psz_name );
807             free( psz_parser );
808         }
809         else
810         {
811             return;
812         }
813     }
814     else
815     {
816         if( psz_parser )
817         {
818             memmove( psz_parser, psz_parser + strlen(psz_name) +
819                             (*(psz_parser + strlen(psz_name)) == ':' ? 1 : 0 ),
820                             strlen(psz_parser + strlen(psz_name)) + 1 );
821
822             if( *(psz_string+strlen(psz_string ) -1 ) == ':' )
823             {
824                 *(psz_string+strlen(psz_string ) -1 ) = '\0';
825             }
826          }
827          else
828          {
829              free( psz_string );
830              return;
831          }
832     }
833
834     if( p_aout == NULL )
835     {
836         config_PutPsz( p_intf, "audio-filter", psz_string );
837     }
838     else
839     {
840         var_SetString( p_aout, "audio-filter", psz_string );
841         int i = 0;
842         while( i < p_aout->i_nb_inputs )
843         {
844             p_aout->pp_inputs[i]->b_restart = VLC_TRUE;
845             i = (i + 1);
846         }
847         vlc_object_release( p_aout );
848     }
849     free( psz_string );
850
851     o_config_changed = YES;
852 }
853
854 - (void)savePrefs
855 {
856     /* save the preferences to make sure that our module-changes will up on
857      * next launch again */
858     playlist_t * p_playlist = pl_Yield( VLCIntf );
859     int returnedValue;
860     NSArray * theModules;
861     theModules = [[NSArray alloc] initWithObjects: @"main", 
862         @"headphone",
863         @"transform", 
864         @"adjust", 
865         @"invert", 
866         @"motionblur", 
867         @"distort",
868         @"clone", 
869         @"crop", 
870         @"normvol", 
871         @"headphone_channel_mixer", 
872         @"macosx",
873         nil];
874     unsigned int x = 0;
875  
876     while ( x != [theModules count] )
877     {
878         returnedValue = config_SaveConfigFile( p_playlist, [[theModules
879             objectAtIndex: x] UTF8String] );
880
881         if (returnedValue != 0)
882         {
883             msg_Err(p_playlist, "unable to save the preferences of the "
884             "extended control attribute '%s' (%i)",
885             [[theModules objectAtIndex: x] UTF8String] , returnedValue);
886             [theModules release];
887             vlc_object_release( p_playlist );
888  
889             return;
890         }
891
892         x = ( x + 1 );
893     }
894  
895     msg_Dbg( VLCIntf, "VLCExtended: saved certain preferences successfully" );
896  
897     [theModules release];
898     vlc_object_release( p_playlist );
899 }
900 @end