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