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