]> git.sesse.net Git - vlc/blob - modules/gui/macosx/extended.m
* macosx/extended.*: finished the extended-controls for OSX (closes #268)
[vlc] / modules / gui / macosx / extended.m
1 /*****************************************************************************
2  * extended.m: MacOS X Extended interface panel
3  *****************************************************************************
4  * Copyright (C) 2005 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., 59 Temple Place - Suite 330, Boston, MA  02111, 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 <vlc/aout.h>
42 #import <aout_internal.h>
43 #import <vlc/vout.h>
44 #import <vlc/intf.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 - (void)initStrings
71 {
72     /* localise GUI-strings */
73     /* method is called from intf.m (in method showExtended) */
74     [o_extended_window setTitle: _NS("Extended controls")];
75     [o_lbl_video setStringValue: _NS("Video")];
76     [o_lbl_audio setStringValue: _NS("Audio")];
77     [o_lbl_audioFlts setStringValue: _NS("Audio filters")];
78     [o_lbl_videoFlts setStringValue: _NS("Video filters")];
79     [o_lbl_adjustImage setStringValue: _NS("Adjust Image")];
80     [o_btn_vidFlts_mrInfo setTitle: _NS("More Info")];
81     [o_ckb_blur setTitle: _NS("Blurring")];
82     [o_ckb_blur setToolTip: _NS("Creates a motion blurring on the image")];
83     [o_ckb_distortion setTitle: _NS("Distortion")];
84     [o_ckb_distortion setToolTip: _NS("Adds distorsion effects")];
85     [o_ckb_imgClone setTitle: _NS("Image clone")];
86     [o_ckb_imgClone setToolTip: _NS("Creates several clones of the image")];
87     [o_ckb_imgCrop setTitle: _NS("Image cropping")];
88     [o_ckb_imgCrop setToolTip: _NS("Crops the image")];
89     [o_ckb_imgInvers setTitle: _NS("Image inversion")];
90     [o_ckb_imgInvers setToolTip: _NS("Inverts the image colors")];
91     [o_ckb_trnsform setTitle: _NS("Transformation")];
92     [o_ckb_trnsform setToolTip: _NS("Rotates or flips the image")];
93     [o_ckb_vlme_norm setTitle: _NS("Volume normalization")];
94     [o_ckb_vlme_norm setToolTip: _NS("This filters prevents the audio output " \
95         "power from going over a defined value.")];
96     [o_ckb_hdphnVirt setTitle: _NS("Headphone virtualization")];
97     [o_ckb_hdphnVirt setToolTip: _NS("This filter gives the feeling of a " \
98         "5.1 speaker set when using a headphone.")];
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     
108 }
109
110 - (void)awakeFromNib
111 {
112     /* set the adjust-filter-sliders to the values from the prefs and enable
113      * them, if wanted */
114     char * psz_vfilters;
115     intf_thread_t * p_intf = VLCIntf;
116     psz_vfilters = config_GetPsz( p_intf, "vout-filter" );
117     if( psz_vfilters && strstr( psz_vfilters, "adjust" ) )
118     {
119         [o_ckb_enblAdjustImg setState: NSOnState];
120         [o_btn_rstrDefaults setEnabled: YES];
121         [o_sld_brightness setEnabled: YES];
122         [o_sld_contrast setEnabled: YES];
123         [o_sld_gamma setEnabled: YES];
124         [o_sld_hue setEnabled: YES];
125         [o_sld_saturation setEnabled: YES];
126     }
127     else
128     {
129         [o_ckb_enblAdjustImg setState: NSOffState];
130         [o_btn_rstrDefaults setEnabled: NO];
131         [o_sld_brightness setEnabled: NO];
132         [o_sld_contrast setEnabled: NO];
133         [o_sld_gamma setEnabled: NO];
134         [o_sld_hue setEnabled: NO];
135         [o_sld_saturation setEnabled: NO];
136     }
137
138     int i_value = config_GetInt( p_intf, "hue" );
139     if( i_value > 0 && i_value < 360 )
140     {
141         [o_sld_hue setIntValue: i_value];
142     }
143     
144     float f_value;
145     
146     f_value = config_GetFloat( p_intf, "saturation" );
147     if( f_value > 0 && f_value < 5 )
148     {
149         [o_sld_saturation setIntValue: (int)(100 * f_value) ];
150     }
151     
152     f_value = config_GetFloat( p_intf, "contrast" );
153     if( f_value > 0 && f_value < 4 )
154     {
155         [o_sld_contrast setIntValue: (int)(100 * f_value) ];
156     }
157     
158     f_value = config_GetFloat( p_intf, "brightness" );
159     if( f_value > 0 && f_value < 2 )
160     {
161         [o_sld_brightness setIntValue: (int)(100 * f_value) ];
162     }
163     
164     f_value = config_GetFloat( p_intf, "gamma" );
165     if( f_value > 0 && f_value < 10 )
166     {
167         [o_sld_gamma setIntValue: (int)(10 * f_value) ];
168     }
169     
170     /* set the other video-filter-checkboxes to the correct values */
171     if( psz_vfilters )
172     {
173         [o_ckb_blur setState: (int)strstr( psz_vfilters, "motionblur")];
174         [o_ckb_distortion setState: (int)strstr( psz_vfilters, "distort")];
175         [o_ckb_imgClone setState: (int)strstr( psz_vfilters, "clone")];
176         [o_ckb_imgCrop setState: (int)strstr( psz_vfilters, "crop")];
177         [o_ckb_imgInvers setState: (int)strstr( psz_vfilters, "invert")];
178         [o_ckb_trnsform setState: (int)strstr( psz_vfilters, "transform")];
179         
180         free( psz_vfilters );
181     }
182     
183     /* set the audio-filter-checkboxes to the values taken from the prefs */
184     char * psz_afilters;
185     psz_afilters = config_GetPsz( p_intf, "audio-filter" );
186     if( psz_afilters )
187     {
188         [o_ckb_hdphnVirt setState: (int)strstr( psz_afilters, "headphone" ) ];
189         [o_ckb_vlme_norm setState: (int)strstr( psz_afilters, "normvol" ) ];
190         
191         free( psz_afilters );
192     }
193     
194     [o_sld_maxLevel setFloatValue: (config_GetFloat(p_intf, "norm-max-level") \
195         * 10)];
196 }
197
198 - (void)showPanel
199 {
200     /* show the window */
201     [o_extended_window displayIfNeeded];
202     [o_extended_window makeKeyAndOrderFront:nil];
203 }
204
205 - (IBAction)adjImg_Enbl:(id)sender
206 {
207     /* en-/disable the sliders */
208     if ([o_ckb_enblAdjustImg state] == NSOnState)
209     {
210         [o_btn_rstrDefaults setEnabled: YES];
211         [o_sld_brightness setEnabled: YES];
212         [o_sld_contrast setEnabled: YES];
213         [o_sld_gamma setEnabled: YES];
214         [o_sld_hue setEnabled: YES];
215         [o_sld_saturation setEnabled: YES];
216         [self changeVFiltersString: "adjust" onOrOff: VLC_TRUE];
217     }else{
218         [o_btn_rstrDefaults setEnabled: NO];
219         [o_sld_brightness setEnabled: NO];
220         [o_sld_contrast setEnabled: NO];
221         [o_sld_gamma setEnabled: NO];
222         [o_sld_hue setEnabled: NO];
223         [o_sld_saturation setEnabled: NO];
224         [self changeVFiltersString: "adjust" onOrOff: VLC_FALSE];
225     }
226 }
227
228 - (IBAction)adjImg_rstrDefaults:(id)sender
229 {
230     /* reset the sliders */
231     [o_sld_brightness setIntValue: 100];
232     [o_sld_contrast setIntValue: 100];
233     [o_sld_gamma setIntValue: 10];
234     [o_sld_hue setIntValue: 0];
235     [o_sld_saturation setIntValue: 100];
236     
237     /* transmit the values */
238     [self adjImg_sliders: o_sld_brightness];
239     [self adjImg_sliders: o_sld_contrast];
240     [self adjImg_sliders: o_sld_gamma];
241     [self adjImg_sliders: o_sld_hue];
242     [self adjImg_sliders: o_sld_saturation];
243 }
244
245 - (IBAction)adjImg_sliders:(id)sender
246 {
247     /* read-out the sliders' values and apply them */
248     intf_thread_t * p_intf = VLCIntf;
249     vout_thread_t *p_vout = (vout_thread_t *)vlc_object_find(p_intf,
250                                  VLC_OBJECT_VOUT, FIND_ANYWHERE);
251     if( p_vout == NULL )
252     {
253         if (sender == o_sld_brightness)
254         {
255             config_PutFloat( p_intf , "brightness" , [o_sld_brightness floatValue] / 100);
256         } else if (sender == o_sld_contrast)
257         {
258             config_PutFloat( p_intf , "contrast" , [o_sld_contrast floatValue] / 100);
259         } else if (sender == o_sld_gamma)
260         {
261             config_PutFloat( p_intf , "gamma" , [o_sld_gamma floatValue] / 10);
262         } else if (sender == o_sld_hue)
263         {
264             config_PutInt( p_intf , "hue" , [o_sld_hue intValue]);
265         } else if (sender == o_sld_saturation)
266         {
267             config_PutFloat( p_intf , "saturation" , [o_sld_saturation floatValue] / 100);
268         } else {
269             msg_Warn( p_intf, "cannot find adjust-image-subfilter related to " \
270                 "moved slider");
271         }
272     } else {
273         vlc_value_t val;
274         if (sender == o_sld_brightness)
275         {
276             val.f_float = [o_sld_brightness floatValue] / 100;
277             var_Set( p_vout, "brightness", val );
278             config_PutFloat( p_intf , "brightness" , [o_sld_brightness floatValue] / 100);
279         } else if (sender == o_sld_contrast)
280         {
281             val.f_float = [o_sld_contrast floatValue] / 100;
282             var_Set( p_vout, "contrast", val );
283             config_PutFloat( p_intf , "contrast" , [o_sld_contrast floatValue] / 100);
284         } else if (sender == o_sld_gamma)
285         {
286             val.f_float = [o_sld_gamma floatValue] / 10;
287             var_Set( p_vout, "gamma", val );
288             config_PutFloat( p_intf , "gamma" , [o_sld_gamma floatValue] / 10);
289         } else if (sender == o_sld_hue)
290         {
291             val.i_int = [o_sld_hue intValue];
292             var_Set( p_vout, "hue", val );
293             config_PutInt( p_intf , "hue" , [o_sld_hue intValue]);
294         } else if (sender == o_sld_saturation)
295         {
296             val.f_float = [o_sld_saturation floatValue] / 100;
297             var_Set( p_vout, "saturation", val );
298             config_PutFloat( p_intf , "saturation" , [o_sld_saturation floatValue] / 100);
299         } else {
300             msg_Warn( p_intf, "cannot find adjust-image-subfilter related to " \
301                 "moved slider");
302         }
303         vlc_object_release( p_vout );
304     }
305 }
306
307 - (IBAction)audFtls_hdphnVirt:(id)sender
308 {
309     /* en-/disable headphone virtualisation */
310     if ([o_ckb_hdphnVirt state] == NSOnState)
311     {
312         [self changeAFiltersString: "headphone" onOrOff: VLC_TRUE ];
313     }else{
314         [self changeAFiltersString: "headphone" onOrOff: VLC_FALSE ];
315     }
316 }
317
318 - (IBAction)audFtls_maxLevelSld:(id)sender
319 {
320     /* read-out the slider's value and apply it */
321     intf_thread_t * p_intf = VLCIntf;
322     aout_instance_t * p_aout= (aout_instance_t *)vlc_object_find(p_intf,
323                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
324     if( p_aout != NULL )
325     {
326         var_SetFloat( p_aout, "norm-max-level", [o_sld_maxLevel floatValue] / 10 );
327         vlc_object_release( p_aout );
328     }
329     else
330     {
331         config_PutFloat( p_intf, "norm-max-level", [o_sld_maxLevel floatValue] /10 );
332     }
333 }
334
335 - (IBAction)audFtls_vlmeNorm:(id)sender
336 {
337     /* en-/disable volume normalisation */
338     if ([o_ckb_vlme_norm state] == NSOnState)
339     {
340         [self changeAFiltersString: "normvol" onOrOff: YES ];
341     }else{
342         [self changeAFiltersString: "normvol" onOrOff: NO ];
343     }
344 }
345
346 - (IBAction)extWin_exp_adjImg:(id)sender
347 {
348     /* expand or collapse adjImg */
349     NSRect o_win_rect = [o_extended_window frame];
350     NSRect o_box_audFlts_rect = [o_box_audFlts frame];
351     NSRect o_box_vidFlts_rect = [o_box_vidFlts frame];
352     NSRect o_box_adjImg_rect = [o_box_adjImg frame];
353     
354     if (o_adjImg_expanded)
355     {
356         /* move the window contents upwards (partially done through settings
357          * inside the nib) and resize the window */
358         o_win_rect.size.height = o_win_rect.size.height - 151;
359         o_win_rect.origin.y = [o_extended_window frame].origin.y + 151;
360         o_box_audFlts_rect.origin.y = o_box_audFlts_rect.origin.y + 151;
361         o_box_vidFlts_rect.origin.y = o_box_vidFlts_rect.origin.y + 151;
362         
363         /* remove the inserted view */
364         [o_adjustImg_view removeFromSuperviewWithoutNeedingDisplay];
365     }else{
366     
367         /* move the window contents downwards and resize the window */
368         o_win_rect.size.height = o_win_rect.size.height + 151;
369         o_win_rect.origin.y = [o_extended_window frame].origin.y - 151;
370         o_box_audFlts_rect.origin.y = o_box_audFlts_rect.origin.y - 151;
371         o_box_vidFlts_rect.origin.y = o_box_vidFlts_rect.origin.y - 151;
372     }
373     
374     [o_box_audFlts setFrameFromContentFrame: o_box_audFlts_rect];
375     [o_box_vidFlts setFrameFromContentFrame: o_box_vidFlts_rect];
376     [o_extended_window displayIfNeeded];
377     [o_extended_window setFrame: o_win_rect display:YES animate: YES];
378     
379     if (o_adjImg_expanded)
380     {
381         o_box_adjImg_rect.size.height = [o_box_adjImg frame].size.height - 151;
382         msg_Dbg( VLCIntf, "collapsed adjust-image section");
383         o_adjImg_expanded = NO;
384     } else {
385         /* insert view */
386         o_box_adjImg_rect.size.height = [o_box_adjImg frame].size.height + 151;
387         [o_adjustImg_view setFrame: NSMakeRect( 20, -10, 370, 161)];
388         [o_adjustImg_view setNeedsDisplay:YES];
389         [o_adjustImg_view setAutoresizesSubviews: YES];
390         [[o_box_adjImg contentView] addSubview: o_adjustImg_view];
391         msg_Dbg( VLCIntf, "expanded adjust-image section");
392         o_adjImg_expanded = YES;
393     }
394     [o_box_adjImg setFrameFromContentFrame: o_box_adjImg_rect];
395 }
396
397 - (IBAction)extWin_exp_audFlts:(id)sender
398 {
399     /* expand or collapse audFlts */
400     NSRect o_win_rect = [o_extended_window frame];
401     NSRect o_box_audFlts_rect = [o_box_audFlts frame];
402     
403     if (o_audFlts_expanded)
404     {
405         /* move the window contents upwards (partially done through settings
406          * inside the nib) and resize the window */
407         o_win_rect.size.height = o_win_rect.size.height - 66;
408         o_win_rect.origin.y = [o_extended_window frame].origin.y + 66;
409         
410         /* remove the inserted view */
411         [o_audioFlts_view removeFromSuperviewWithoutNeedingDisplay];
412     }else{
413         /* move the window contents downwards and resize the window */
414         o_win_rect.size.height = o_win_rect.size.height + 66;
415         o_win_rect.origin.y = [o_extended_window frame].origin.y - 66;
416     }
417     [o_extended_window displayIfNeeded];
418     [o_extended_window setFrame: o_win_rect display:YES animate: YES];
419     
420     
421     if (o_audFlts_expanded)
422     {
423         o_box_audFlts_rect.size.height = [o_box_audFlts frame].size.height - 66;
424         msg_Dbg( VLCIntf, "collapsed audio-filters section");
425         o_audFlts_expanded = NO;
426     } else {
427         /* insert view */
428         o_box_audFlts_rect.size.height = [o_box_audFlts frame].size.height + 66;
429         [o_audioFlts_view setFrame: NSMakeRect( 20, -20, 370, 76)];
430         [o_audioFlts_view setNeedsDisplay:YES];
431         [o_audioFlts_view setAutoresizesSubviews: YES];
432         [[o_box_audFlts contentView] addSubview: o_audioFlts_view];
433         msg_Dbg( VLCIntf, "expanded audio-filters section");
434         o_audFlts_expanded = YES;
435     }
436     [o_box_audFlts setFrameFromContentFrame: o_box_audFlts_rect];
437 }
438
439 - (IBAction)extWin_exp_vidFlts:(id)sender
440 {
441     /* expand or collapse vidFlts */
442     NSRect o_win_rect = [o_extended_window frame];
443     NSRect o_box_audFlts_rect = [o_box_audFlts frame];
444     NSRect o_box_vidFlts_rect = [o_box_vidFlts frame];
445     
446     if (o_vidFlts_expanded)
447     {
448         /* move the window contents upwards (partially done through settings
449          * inside the nib) and resize the window */
450         o_win_rect.size.height = o_win_rect.size.height - 134;
451         o_win_rect.origin.y = [o_extended_window frame].origin.y + 134;
452         o_box_audFlts_rect.origin.y = o_box_audFlts_rect.origin.y + 134;
453         
454         /* remove the inserted view */
455         [o_videoFilters_view removeFromSuperviewWithoutNeedingDisplay];
456     }else{
457     
458         /* move the window contents downwards and resize the window */
459         o_win_rect.size.height = o_win_rect.size.height + 134;
460         o_win_rect.origin.y = [o_extended_window frame].origin.y - 134;
461         o_box_audFlts_rect.origin.y = o_box_audFlts_rect.origin.y - 134;
462     }
463     
464     [o_box_audFlts setFrameFromContentFrame: o_box_audFlts_rect];
465     [o_extended_window displayIfNeeded];
466     [o_extended_window setFrame: o_win_rect display:YES animate: YES];
467     
468     if (o_vidFlts_expanded)
469     {
470         o_box_vidFlts_rect.size.height = [o_box_vidFlts frame].size.height - 134;
471         msg_Dbg( VLCIntf, "collapsed video-filters section");
472         o_vidFlts_expanded = NO;
473     } else {
474         /* insert view */
475         o_box_vidFlts_rect.size.height = [o_box_vidFlts frame].size.height + 134;
476         [o_videoFilters_view setFrame: NSMakeRect( 20, -10, 370, 144)];
477         [o_videoFilters_view setNeedsDisplay:YES];
478         [o_videoFilters_view setAutoresizesSubviews: YES];
479         [[o_box_vidFlts contentView] addSubview: o_videoFilters_view];
480         msg_Dbg( VLCIntf, "expanded video-filters section");
481         o_vidFlts_expanded = YES;
482     }
483     [o_box_vidFlts setFrameFromContentFrame: o_box_vidFlts_rect];
484 }
485
486 - (IBAction)vidFlts:(id)sender
487 {
488     /* en-/disable video filters */
489     if (sender == o_ckb_blur)
490     {
491         [self changeVFiltersString: "motionblur" onOrOff: [o_ckb_blur state]];
492     }
493     else if (sender == o_ckb_distortion)
494     {
495         [self changeVFiltersString: "distort" onOrOff: [o_ckb_distortion state]];
496     }
497     else if (sender == o_ckb_imgClone)
498     {
499         [self changeVFiltersString: "clone" onOrOff: [o_ckb_imgClone state]];
500     }
501     else if (sender == o_ckb_imgCrop)
502     {
503         [self changeVFiltersString: "crop" onOrOff: [o_ckb_imgCrop state]];
504     }
505     else if (sender == o_ckb_imgInvers)
506     {
507         [self changeVFiltersString: "invert" onOrOff: [o_ckb_imgInvers state]];
508     }
509     else if (sender == o_ckb_trnsform)
510     {
511         [self changeVFiltersString: "transform" onOrOff: [o_ckb_trnsform state]];
512     } else {
513         /* this shouldn't happen */
514         msg_Warn (VLCIntf, "cannot find selected video-filter");
515     }
516 }
517
518 - (IBAction)vidFlts_mrInfo:(id)sender
519 {
520     /* show info sheet */
521     NSBeginInformationalAlertSheet(_NS("More information"), _NS("OK"), @"", @"", \
522         o_extended_window, nil, nil, nil, nil, _NS("Select the video effects " \
523         "filters to apply. You must restart the stream for these settings to " \
524         "take effect.\nTo configure the filters, go to the Preferences, and " \
525         "go to Modules/Video Filters. You can then configure each filter.\n" \
526         "If you want fine control over the filters ( to choose the order in " \
527         "which they are applied ), you need to enter manually a filters " \
528         "string (Preferences / Video / Filters)."));
529 }
530
531 - (void)changeVFiltersString:(char *)psz_name onOrOff:(vlc_bool_t )b_add 
532 {
533     /* copied from ../wxwidgets/extrapanel.cpp
534      * renamed to conform with Cocoa's rules */
535      
536     vout_thread_t *p_vout;
537     intf_thread_t * p_intf = VLCIntf;
538     
539     char *psz_parser, *psz_string;
540     psz_string = config_GetPsz( p_intf, "vout-filter" );
541     
542     if( !psz_string ) psz_string = strdup("");
543
544     psz_parser = strstr( psz_string, psz_name );
545
546     if( b_add )
547     {
548         if( !psz_parser )
549         {
550             psz_parser = psz_string;
551             asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s",
552                             psz_string, psz_name );
553             free( psz_parser );
554         }
555         else
556         {
557             return;
558         }
559     }
560     else
561     {
562         if( psz_parser )
563         {
564             memmove( psz_parser, psz_parser + strlen(psz_name) +
565                             (*(psz_parser + strlen(psz_name)) == ':' ? 1 : 0 ),
566                             strlen(psz_parser + strlen(psz_name)) + 1 );
567
568             /* Remove trailing : : */
569             if( *(psz_string+strlen(psz_string ) -1 ) == ':' )
570             {
571                 *(psz_string+strlen(psz_string ) -1 ) = '\0';
572             }
573          }
574          else
575          {
576              free( psz_string );
577              return;
578          }
579     }
580     /* Vout is not kept, so put that in the config */
581     config_PutPsz( p_intf, "vout-filter", psz_string );
582
583     /* Try to set on the fly */
584     p_vout = (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
585                                               FIND_ANYWHERE );
586     if( p_vout )
587     {
588         var_SetString( p_vout, "vout-filter", psz_string );
589         vlc_object_release( p_vout );
590     }
591
592     free( psz_string );
593     
594     [self savePrefs];
595 }
596
597
598 - (void)changeAFiltersString: (char *)psz_name onOrOff: (vlc_bool_t )b_add;
599 {
600     char *psz_parser, *psz_string;
601     intf_thread_t * p_intf = VLCIntf;
602     aout_instance_t * p_aout= (aout_instance_t *)vlc_object_find(p_intf,
603                                  VLC_OBJECT_AOUT, FIND_ANYWHERE);
604
605     if( p_aout )
606     {
607         psz_string = var_GetString( p_aout, "audio-filter" );
608     }
609     else
610     {
611         psz_string = config_GetPsz( p_intf, "audio-filter" );
612     }
613
614     if( !psz_string ) psz_string = strdup("");
615
616     psz_parser = strstr( psz_string, psz_name );
617
618     if( b_add )
619     {
620         if( !psz_parser )
621         {
622             psz_parser = psz_string;
623             asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s",
624                             psz_string, psz_name );
625             free( psz_parser );
626         }
627         else
628         {
629             return;
630         }
631     }
632     else
633     {
634         if( psz_parser )
635         {
636             memmove( psz_parser, psz_parser + strlen(psz_name) +
637                             (*(psz_parser + strlen(psz_name)) == ':' ? 1 : 0 ),
638                             strlen(psz_parser + strlen(psz_name)) + 1 );
639
640             if( *(psz_string+strlen(psz_string ) -1 ) == ':' )
641             {
642                 *(psz_string+strlen(psz_string ) -1 ) = '\0';
643             }
644          }
645          else
646          {
647              free( psz_string );
648              return;
649          }
650     }
651
652     if( p_aout == NULL )
653     {
654         config_PutPsz( p_intf, "audio-filter", psz_string );
655     }
656     else
657     {
658         var_SetString( p_aout, "audio-filter", psz_string );
659         int i = 0;
660         while( i < p_aout->i_nb_inputs )
661         {
662             p_aout->pp_inputs[i]->b_restart = VLC_TRUE;
663             i = (i + 1);
664         }
665         vlc_object_release( p_aout );
666     }
667     free( psz_string );
668     
669     [self savePrefs];
670 }
671
672 - (void)savePrefs
673 {    
674     /* save the preferences to make sure that our module-changes will up on
675      * next launch again */
676     intf_thread_t * p_intf = VLCIntf;
677     int returnedValue;
678     
679     returnedValue = config_SaveConfigFile( p_intf, NULL);
680     if (returnedValue == 0)
681     {
682         msg_Dbg(p_intf, "VLCExtended: saved preferences successfully");
683     } else {
684         msg_Dbg(p_intf, "VLCExtended: error while saving the preferences (%i) " \
685             , returnedValue);
686     }
687 }
688 @end