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