]> git.sesse.net Git - vlc/blob - modules/gui/macosx/sfilters.m
* put a warning to prevent users from reporting known bugs for panel is which won...
[vlc] / modules / gui / macosx / sfilters.m
1 /*****************************************************************************
2  * sfilter.m: MacOS X Subpicture filters dialogue
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 core is partially based upon the 
28  * RC-interface, written by Antoine Cellerier and Mark F. Moriarty  
29  * (members of the VideoLAN team) 
30  *****************************************************************************/
31
32 #import "sfilters.h"
33 #import "intf.h"
34 #import <vlc/vout.h>
35
36 /* TODO:
37     - check for memory leaks
38     - save the preferences, if requested
39 */
40
41 @implementation VLCsFilters
42
43 static VLCsFilters *_o_sharedInstance = nil;
44
45 + (VLCsFilters *)sharedInstance
46 {
47     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
48 }
49
50 - (id)init
51 {
52     if (_o_sharedInstance) {
53         [self dealloc];
54     } else {
55         _o_sharedInstance = [super init];
56     }
57
58     return _o_sharedInstance;
59 }
60
61 - (void)dealloc
62 {
63     [o_colors release];
64
65     [super dealloc];
66 }
67
68 - (void)initStrings
69 {
70     [o_sfilter_win setTitle: _NS("Subpicture Filters")];
71     [[o_sfilter_tabView tabViewItemAtIndex: 0] setLabel: _NS("Logo")];
72     [[o_sfilter_tabView tabViewItemAtIndex: 1] setLabel: _NS("Time")];
73     [[o_sfilter_tabView tabViewItemAtIndex: 2] setLabel: _NS("Marquee")];
74     [o_sfilter_saveSettings_ckb setTitle: _NS("Save settings")];
75     [o_logo_image_btn setTitle: _NS("Browse...")];
76     [o_logo_enabled_ckb setTitle: _NS("Enabled")];
77     [o_logo_image_lbl setStringValue: [_NS("Image") \
78         stringByAppendingString: @":"]];
79     [o_logo_pos_lbl setStringValue: [_NS("Position") \
80         stringByAppendingString: @":"]];
81     [o_logo_opaque_lbl setStringValue: [_NS("Opaqueness") \
82         stringByAppendingString: @":"]];
83     [o_time_enabled_ckb setTitle: _NS("Enabled")];
84     [o_time_stamp_lbl setStringValue: [_NS("Timestamp") \
85         stringByAppendingString: @":"]];
86     [o_time_size_lbl setStringValue: [_NS("Size") \
87         stringByAppendingString: @":"]];
88     [o_time_color_lbl setStringValue: [_NS("Color") \
89         stringByAppendingString: @":"]];
90     [o_time_opaque_lbl setStringValue: [_NS("Opaqueness") \
91         stringByAppendingString: @":"]];
92     [o_time_pos_lbl setStringValue: [_NS("Position") \
93         stringByAppendingString: @":"]];
94     [o_time_size_inPx_lbl setStringValue: _NS("(in pixels)")];
95     [o_marq_enabled_ckb setTitle: _NS("Enabled")];
96     [o_marq_color_lbl setStringValue: [_NS("Color") \
97         stringByAppendingString: @":"]];
98     [o_marq_marq_lbl setStringValue: [_NS("Marquee") \
99         stringByAppendingString: @":"]];
100     [o_marq_opaque_lbl setStringValue: [_NS("Opaqueness") \
101         stringByAppendingString: @":"]];
102     [o_marq_tmOut_lbl setStringValue: [_NS("Timeout") \
103         stringByAppendingString: @":"]];
104     [o_marq_tmOut_ms_lbl setStringValue: _NS("ms")];
105     [o_marq_pos_lbl setStringValue: [_NS("Position") \
106         stringByAppendingString: @":"]];
107     [o_marq_size_lbl setStringValue: [_NS("Size") \
108         stringByAppendingString: @":"]];
109     [o_time_color_lbl setStringValue: _NS("(in pixels)")];
110 }
111
112 - (void)awakeFromNib
113 {
114     /* colors as implemented at the beginning of marq.c and time.c
115      * feel free to add more colors, but remember to add them to these files 
116      * as well to keep a certain level of consistency across the interfaces */
117     NSArray * o_default;
118     NSArray * o_black;
119     NSArray * o_gray;
120     NSArray * o_silver;
121     NSArray * o_white;
122     NSArray * o_maroon;
123     NSArray * o_red;
124     NSArray * o_fuchsia;
125     NSArray * o_yellow;
126     NSArray * o_olive;
127     NSArray * o_green;
128     NSArray * o_teal;
129     NSArray * o_lime;
130     NSArray * o_purple;
131     NSArray * o_navy;
132     NSArray * o_blue;
133     NSArray * o_aqua;
134     o_default = [NSArray arrayWithObjects: _NS("Default"), @"-1", nil];
135     o_black = [NSArray arrayWithObjects: _NS("Black"), @"0x000000", nil];
136     o_gray = [NSArray arrayWithObjects: _NS("Gray"), @"0x808080", nil];
137     o_silver = [NSArray arrayWithObjects: _NS("Silver"), @"0xC0C0C0", nil];
138     o_white = [NSArray arrayWithObjects: _NS("White"), @"0xFFFFFF", nil];
139     o_maroon = [NSArray arrayWithObjects: _NS("Maroon"), @"0x800000", nil];
140     o_red = [NSArray arrayWithObjects: _NS("Red"), @"0xFF0000", nil];
141     o_fuchsia = [NSArray arrayWithObjects: _NS("Fuchsia"), @"0xFF00FF", nil];
142     o_yellow = [NSArray arrayWithObjects: _NS("Yellow"), @"0xFFFF00", nil];
143     o_olive = [NSArray arrayWithObjects: _NS("Olive"), @"0x808000", nil];
144     o_green = [NSArray arrayWithObjects: _NS("Green"), @"0x008000", nil];
145     o_teal = [NSArray arrayWithObjects: _NS("Teal"), @"0x008080", nil];
146     o_lime = [NSArray arrayWithObjects: _NS("Lime"), @"0x00FF00", nil];
147     o_purple = [NSArray arrayWithObjects: _NS("Purple"), @"0x800080", nil];
148     o_navy = [NSArray arrayWithObjects: _NS("Navy"), @"0x000080", nil];
149     o_blue = [NSArray arrayWithObjects: _NS("Blue"), @"0x0000FF", nil];
150     o_aqua = [NSArray arrayWithObjects: _NS("Aqua"), @"0x00FFFF", nil];
151     o_colors = [[NSArray alloc] initWithObjects: o_default, o_black, o_gray, \
152         o_silver, o_white, o_maroon, o_red, o_fuchsia, o_yellow, o_olive, \
153         o_green, o_teal, o_lime, o_purple, o_navy, o_blue, o_aqua, nil];
154
155     unsigned int x = 0;
156     [o_marq_color_pop removeAllItems];
157     [o_time_color_pop removeAllItems];
158     
159     /* we are adding tags to the items, so we can easily identify them even if 
160      * the menu was sorted */
161     while (x != [o_colors count])
162     {
163         [o_marq_color_pop addItemWithTitle: [[o_colors objectAtIndex:x] \
164             objectAtIndex:0]];
165         [[o_marq_color_pop lastItem] setTag: x];
166         
167         [o_time_color_pop addItemWithTitle: [[o_colors objectAtIndex:x] \
168             objectAtIndex:0]];
169         [[o_time_color_pop lastItem] setTag: x];
170         
171         x = (x + 1);
172     }
173
174     [o_marq_color_pop selectItemAtIndex:0];
175     [o_time_color_pop selectItemAtIndex:0];
176
177     /* define the relative positions and copy them to the menues
178      * we can destroy the array afterwards, because we are saving the ints 
179      * as tags to the menu-items */
180     NSArray * o_cnt_cnt;
181     NSArray * o_lft_cnt;
182     NSArray * o_rht_cnt;
183     NSArray * o_cnt_top;
184     NSArray * o_lft_top;
185     NSArray * o_rht_top;
186     NSArray * o_cnt_btm;
187     NSArray * o_lft_btm;
188     NSArray * o_rht_btm;
189     NSArray * o_positions;
190     o_cnt_cnt = [NSArray arrayWithObjects: _NS("Center-Center"), @"0", nil];
191     o_lft_cnt = [NSArray arrayWithObjects: _NS("Left-Center"), @"1", nil];
192     o_rht_cnt = [NSArray arrayWithObjects: _NS("Right-Center"), @"2", nil];
193     o_cnt_top = [NSArray arrayWithObjects: _NS("Center-Top"), @"4", nil];
194     o_lft_top = [NSArray arrayWithObjects: _NS("Left-Top"), @"5", nil];
195     o_rht_top = [NSArray arrayWithObjects: _NS("Right-Top"), @"6", nil];
196     o_cnt_btm = [NSArray arrayWithObjects: _NS("Center-Bottom"), @"8", nil];
197     o_lft_btm = [NSArray arrayWithObjects: _NS("Left-Bottom"), @"9", nil];
198     o_rht_btm = [NSArray arrayWithObjects: _NS("Right-Bottom"), @"10", nil];
199     o_positions = [[NSArray alloc] initWithObjects: o_cnt_cnt, o_lft_cnt, \
200         o_rht_cnt, o_cnt_top, o_lft_top, o_rht_top, o_cnt_btm, o_lft_btm, \
201         o_rht_btm, nil];
202         
203     x = 0;
204     [o_time_pos_rel_pop removeAllItems];
205     [o_marq_pos_rel_pop removeAllItems];
206     [o_logo_pos_rel_pop removeAllItems];
207     
208     /* we are adding a tag here, so we can easily select an item later on */
209     while ( x != [o_positions count] )
210     {
211         [o_time_pos_rel_pop addItemWithTitle: [[o_positions objectAtIndex:x] \
212             objectAtIndex:0]];
213         [[o_time_pos_rel_pop lastItem] setTag: [[[o_positions objectAtIndex:x] \
214             objectAtIndex:1] intValue]];
215         [o_marq_pos_rel_pop addItemWithTitle: [[o_positions objectAtIndex:x] \
216             objectAtIndex:0]];
217         [[o_marq_pos_rel_pop lastItem] setTag: [[[o_positions objectAtIndex:x] \
218             objectAtIndex:1] intValue]];
219         [o_logo_pos_rel_pop addItemWithTitle: [[o_positions objectAtIndex:x] \
220             objectAtIndex:0]];
221         [[o_logo_pos_rel_pop lastItem] setTag: [[[o_positions objectAtIndex:x] \
222             objectAtIndex:1] intValue]];
223
224         x = (x + 1);
225     }
226     [o_positions release];
227
228     NSArray * o_sizes;
229     o_sizes = [[NSArray alloc] initWithObjects: @"6", @"8", @"10", @"11", @"12",\
230         @"14", @"13", @"16", @"18", @"24", @"36", @"48", @"64", @"72", @"96", \
231         @"144", @"288", nil];
232     [o_marq_size_pop removeAllItems];
233     [o_marq_size_pop addItemsWithTitles: o_sizes];
234     [o_time_size_pop removeAllItems];
235     [o_time_size_pop addItemsWithTitles: o_sizes];
236     [o_sizes release];
237 }
238
239 - (void)showAsPanel
240 {
241     /* called from intf.m */
242     [o_sfilter_win displayIfNeeded];
243     [o_sfilter_win makeKeyAndOrderFront:nil];
244
245     /* show a warning until the panel is removed for 0.8.5
246      * This isn't to be localised */
247     NSBeginCriticalAlertSheet( @"Implementation incomplete", @"OK", \
248         @"", @"", o_sfilter_win, nil, nil, nil, nil, @"The panel " \
249         "you just opened is not implemented completely and contains " \
250         "various limitations and certain bugs. Be warned.\n\nIt isn't going " \
251         "to be included within the final build of VLC 0.8.5." );
252
253     intf_thread_t * p_intf = VLCIntf;
254
255     /* retrieve the marquee settings */
256     int x = 0;
257     int tempInt = config_GetInt( p_intf, "marq-color" );
258     while( strtol([[[o_colors objectAtIndex:x] objectAtIndex:1] UTF8String], \
259         NULL, 0) != tempInt )
260     {
261         x = (x + 1);
262         
263         if( x >= [o_marq_color_pop numberOfItems] )
264         {
265             x = 0;
266             return;
267         }
268     }
269     [o_marq_color_pop selectItemAtIndex: x];
270     [o_marq_marq_fld setStringValue: [NSString stringWithUTF8String: \
271         config_GetPsz( p_intf, "marq-marquee" )]];
272     [o_marq_opaque_sld setIntValue: config_GetInt( p_intf, "marq-opacity")];
273     x = 0;
274     tempInt = config_GetInt( p_intf, "marq-position" );
275     while( tempInt != [[o_marq_pos_rel_pop itemAtIndex:x] tag] )
276     {
277         x = (x + 1);
278         
279         if( x >= [o_marq_pos_rel_pop numberOfItems] )
280         {
281             x = 0;
282             return;
283         }
284     }
285     [o_marq_pos_rel_pop selectItemAtIndex:x];
286     x = 0;
287     tempInt = config_GetInt( p_intf, "marq-size" );
288     while( [[[o_marq_size_pop itemAtIndex: x] title] intValue] != tempInt )
289         x = (x + 1);
290         
291         if( x >= [o_marq_size_pop numberOfItems] )
292         {
293             x = 0;
294             return;
295         }
296     [o_marq_size_pop selectItemAtIndex: x];
297     [o_marq_tmOut_fld setStringValue: [[NSNumber numberWithInt: \
298         config_GetInt( p_intf, "marq-timeout" )] stringValue]];
299     
300     /* retrieve the time settings */
301     x = 0;
302     tempInt = config_GetInt( p_intf, "time-color" );
303     while( strtol([[[o_colors objectAtIndex:x] objectAtIndex:1] UTF8String], \
304         NULL, 0) != tempInt )
305     {
306         x = (x + 1);
307         
308         if( x >= [o_time_color_pop numberOfItems] )
309         {
310             x = 0;
311             return;
312         }
313     }
314     [o_time_color_pop selectItemAtIndex: x];
315     [o_time_stamp_fld setStringValue: [NSString stringWithUTF8String: \
316         config_GetPsz( p_intf, "time-format" )]];
317     [o_time_opaque_sld setIntValue: config_GetInt( p_intf, "time-opacity")];
318     x = 0;
319     tempInt = config_GetInt( p_intf, "time-size" );
320     while( [[[o_time_size_pop itemAtIndex: x] title] intValue] != tempInt )
321         x = (x + 1);
322         
323         if( x >= [o_time_size_pop numberOfItems] )
324         {
325             x = 0;
326             return;
327         }
328     [o_time_size_pop selectItemAtIndex: x];
329     x = 0;
330     tempInt = config_GetInt( p_intf, "time-position" );
331     while( tempInt != [[o_time_pos_rel_pop itemAtIndex:x] tag] )
332     {
333         x = (x + 1);
334         
335         if( x >= [o_time_pos_rel_pop numberOfItems] )
336         {
337             x = 0;
338             return;
339         }
340     }
341     
342     /* retrieve the logo settings */
343     [o_logo_opaque_sld setIntValue: config_GetInt( p_intf, "logo-transparency")];
344     /* in case that no path has been saved yet */
345     NSString * tempString = [[NSString alloc] initWithUTF8String: \
346         config_GetPsz( p_intf, "logo-file" )];
347     if( [tempString length] == 0 )
348     {
349         [o_logo_image_fld setStringValue: @""];
350     }
351     else
352     {
353         [o_logo_image_fld setStringValue: tempString ];
354     }
355     [tempString release];
356     x = 0;
357     tempInt = config_GetInt( p_intf, "logo-position" );
358     while( tempInt != [[o_logo_pos_rel_pop itemAtIndex:x] tag] )
359     {
360         x = (x + 1);
361         
362         if( x >= [o_logo_pos_rel_pop numberOfItems] )
363         {
364             x = 0;
365             return;
366         }
367     }
368     
369     /* enable the wanted filters */
370     char * psz_subfilters;
371     psz_subfilters = config_GetPsz( p_intf, "sub-filter" );
372     if( psz_subfilters )
373     {
374         [o_marq_enabled_ckb setState: (int)strstr( psz_subfilters, "marq")];
375         [o_logo_enabled_ckb setState: (int)strstr( psz_subfilters, "logo")];
376         [o_time_enabled_ckb setState: (int)strstr( psz_subfilters, "time")];
377         [self enableMarq];
378         [self enableLogo];
379         [self enableTime];
380     }
381 }
382
383 - (IBAction)logo_selectFile:(id)sender
384 {
385     NSOpenPanel * openPanel = [NSOpenPanel openPanel];
386     SEL sel = @selector(logo_getFile:returnCode:contextInfo:);
387     [openPanel beginSheetForDirectory:nil file:nil types: [NSArray \
388         arrayWithObjects: @"png", @"PNG", @"'PNGf'", nil] modalForWindow: \
389         o_sfilter_win modalDelegate:self didEndSelector:sel contextInfo:nil];
390 }
391
392 - (void)logo_getFile: (NSOpenPanel *)sheet returnCode: \
393     (int)returnCode contextInfo: (void *)contextInfo
394 {
395     if (returnCode == NSOKButton)
396     {
397         [o_logo_image_fld setStringValue: [sheet filename]];
398     }
399 }
400
401 - (IBAction)propertyChanged:(id)sender
402 {
403     intf_thread_t * p_intf = VLCIntf;
404     input_thread_t * p_input = (input_thread_t *)vlc_object_find( p_intf, \
405         VLC_OBJECT_INPUT, FIND_ANYWHERE );
406
407     vlc_value_t val;
408
409     /* general properties */
410     if( sender == o_sfilter_saveSettings_ckb)
411     {
412         o_save_settings = [o_sfilter_saveSettings_ckb state]; 
413     }
414
415     /* marquee */
416     else if( sender == o_marq_marq_fld )
417     {
418         if( [[o_marq_marq_fld stringValue] length] == 0 )
419         {
420             val.psz_string = "";
421         }
422         else
423         {
424             val.psz_string = (char *)[[o_marq_marq_fld stringValue] UTF8String];
425         }
426
427         if( p_input )
428             var_Set( p_input->p_libvlc, "marq-marquee", val );
429
430         config_PutPsz( p_intf, "marq-marquee", val.psz_string );
431     }
432     
433     else if( sender == o_marq_pos_rel_pop )
434     {
435         val.i_int = [[o_marq_pos_rel_pop selectedItem] tag];
436
437         if( p_input )
438             var_Set( p_input->p_libvlc, "marq-position", val );
439
440         config_PutInt( p_intf, "marq-position", val.i_int );
441     }
442     
443     else if( sender == o_marq_color_pop )
444     {
445         val.i_int = strtol( [[[o_colors objectAtIndex: [o_marq_color_pop \
446             indexOfSelectedItem]] objectAtIndex: 1] UTF8String], NULL, 0 );
447
448         if( p_input )
449             var_Set( p_input->p_libvlc, "marq-color", val );
450
451         config_PutInt( p_intf, "marq-color", val.i_int );
452     }
453     
454     else if( sender == o_marq_opaque_sld )
455     {
456         val.i_int = [o_marq_opaque_sld intValue];
457
458         if( p_input )
459             var_Set( p_input->p_libvlc, "marq-opacity", val );
460
461         config_PutInt( p_intf, "marq-opacity", val.i_int );
462     }
463     
464     else if( sender == o_marq_size_pop )
465     {
466         val.i_int = [[o_marq_size_pop titleOfSelectedItem] intValue];
467
468         if( p_input )
469             var_Set( p_input->p_libvlc, "marq-size", val );
470
471         config_PutInt( p_intf, "marq-size", val.i_int );
472     }
473     
474     else if( sender == o_marq_tmOut_fld && [[sender stringValue] length] > 0 )
475     {
476         val.i_int = [o_marq_tmOut_fld intValue];
477
478         if( p_input )
479             var_Set( p_input->p_libvlc, "marq-timeout", val );
480
481         config_PutInt( p_intf, "marq-timeout", val.i_int );
482     }
483     
484     /* time */
485     
486     else if( sender == o_time_stamp_fld )
487     {
488         if( [[o_time_stamp_fld stringValue] length] == 0 )
489         {
490             val.psz_string = "";
491         }
492         else
493         {
494             val.psz_string = (char *)[[o_time_stamp_fld stringValue] UTF8String];
495         }
496
497         if( p_input )
498             var_Set( p_input->p_libvlc, "time-format", val );
499
500         config_PutPsz( p_intf, "time-format", val.psz_string );
501     }
502
503     else if( sender == o_time_pos_rel_pop )
504     {
505         val.i_int = [[o_time_pos_rel_pop selectedItem] tag];
506
507         if( p_input )
508             var_Set( p_input->p_libvlc, "time-position", val );
509
510         config_PutInt( p_intf, "time-position", val.i_int );
511     }
512     
513     else if( sender == o_time_color_pop )
514     {
515         val.i_int = strtol( [[[o_colors objectAtIndex: [o_time_color_pop \
516             indexOfSelectedItem]] objectAtIndex: 1] UTF8String], NULL, 0 );
517
518         if( p_input )
519             var_Set( p_input->p_libvlc, "time-color", val );
520
521         config_PutInt( p_intf, "time-color", val.i_int );
522     }
523     
524     else if( sender == o_time_opaque_sld )
525     {
526         val.i_int = [o_time_opaque_sld intValue];
527
528         if( p_input )
529             var_Set( p_input->p_libvlc, "time-opacity", val );
530
531         config_PutInt( p_intf, "time-opacity", val.i_int );
532     }
533     
534     else if( sender == o_time_size_pop )
535     {
536         val.i_int = [[o_time_size_pop titleOfSelectedItem] intValue];
537
538         if( p_input )
539             var_Set( p_input->p_libvlc, "time-size", val );
540
541         config_PutInt( p_intf, "time-size", val.i_int );
542     }
543
544     /* logo */
545     else if( sender == o_logo_opaque_sld )
546     {
547         val.i_int = [o_logo_opaque_sld intValue];
548
549         if( p_input )
550             var_Set( p_input->p_libvlc, "logo-transparency", val );
551
552         config_PutInt( p_intf, "logo-transparency", val.i_int );
553     }
554     
555     else if( sender == o_logo_pos_rel_pop )
556     {
557         val.i_int = [[o_logo_pos_rel_pop selectedItem] tag];
558
559         if( p_input )
560             var_Set( p_input->p_libvlc, "logo-position", val );
561
562         config_PutInt( p_intf, "logo-position", val.i_int );
563     }
564
565     /* clean up */
566     if ( p_input )
567     {
568         o_config_changed = YES;
569         vlc_object_release( p_input );
570     }
571 }
572
573 - (IBAction)enableFilter:(id)sender
574 {
575     if( sender == o_marq_enabled_ckb )
576     {
577         if( [o_marq_enabled_ckb state] == NSOnState )
578         {
579             [self changeFiltersString:"marq" onOrOff:VLC_TRUE];
580         }
581         else
582         {
583             [self changeFiltersString:"marq" onOrOff:VLC_FALSE];
584         }
585         [self enableMarq];
586     }
587     if( sender == o_logo_enabled_ckb )
588     {
589         if( [o_logo_enabled_ckb state] == NSOnState )
590         {
591             [self changeFiltersString:"logo" onOrOff:VLC_TRUE];
592         }
593         else
594         {
595             [self changeFiltersString:"logo" onOrOff:VLC_FALSE];
596         }
597         [self enableLogo];
598     }
599     if( sender == o_time_enabled_ckb )
600     {
601         if( [o_time_enabled_ckb state] == NSOnState )
602         {
603             [self changeFiltersString:"time" onOrOff:VLC_TRUE];
604         }
605         else
606         {
607             [self changeFiltersString:"time" onOrOff:VLC_FALSE];
608         }
609         [self enableTime];
610     }    
611 }
612
613 - (void)enableMarq
614 {
615     [o_marq_color_pop setEnabled: [o_marq_enabled_ckb state]];
616     [o_marq_marq_fld setEnabled: [o_marq_enabled_ckb state]];
617     [o_marq_opaque_sld setEnabled: [o_marq_enabled_ckb state]];
618     [o_marq_size_pop setEnabled: [o_marq_enabled_ckb state]];
619     [o_marq_tmOut_fld setEnabled: [o_marq_enabled_ckb state]];
620     [o_marq_pos_rel_pop setEnabled: [o_marq_enabled_ckb state]];
621 }
622
623 - (void)enableTime
624 {
625     [o_time_color_pop setEnabled: [o_time_enabled_ckb state]];
626     [o_time_stamp_fld setEnabled: [o_time_enabled_ckb state]];
627     [o_time_opaque_sld setEnabled: [o_time_enabled_ckb state]];
628     [o_time_size_pop setEnabled: [o_time_enabled_ckb state]];
629     [o_time_pos_rel_pop setEnabled: [o_time_enabled_ckb state]];
630 }
631
632 - (void)enableLogo
633 {
634     [o_logo_image_btn setEnabled: [o_logo_enabled_ckb state]];
635     [o_logo_image_fld setEnabled: [o_logo_enabled_ckb state]];
636     [o_logo_opaque_sld setEnabled: [o_logo_enabled_ckb state]];
637     [o_logo_pos_rel_pop setEnabled: [o_logo_enabled_ckb state]];
638 }
639
640 - (void)changeFiltersString:(char *)psz_name onOrOff:(vlc_bool_t )b_add
641 {
642     /* copied from ../wxwidgets/extrapanel.cpp
643      * renamed to conform with Cocoa's rules
644      * and slightly modified to suit our needs */
645
646     intf_thread_t * p_intf = VLCIntf;
647     
648     char *psz_parser, *psz_string;
649     psz_string = config_GetPsz( p_intf, "sub-filter" );
650     
651     if( !psz_string ) psz_string = strdup("");
652
653     psz_parser = strstr( psz_string, psz_name );
654
655     if( b_add )
656     {
657         if( !psz_parser )
658         {
659             psz_parser = psz_string;
660             asprintf( &psz_string, (*psz_string) ? "%s:%s" : "%s%s",
661                             psz_string, psz_name );
662             free( psz_parser );
663         }
664         else
665         {
666             return;
667         }
668     }
669     else
670     {
671         if( psz_parser )
672         {
673             memmove( psz_parser, psz_parser + strlen(psz_name) +
674                             (*(psz_parser + strlen(psz_name)) == ':' ? 1 : 0 ),
675                             strlen(psz_parser + strlen(psz_name)) + 1 );
676
677             /* Remove trailing : : */
678             if( *(psz_string+strlen(psz_string ) -1 ) == ':' )
679             {
680                 *(psz_string+strlen(psz_string ) -1 ) = '\0';
681             }
682          }
683          else
684          {
685              free( psz_string );
686              return;
687          }
688     }
689     
690     config_PutPsz( p_intf, "sub-filter", psz_string );
691     
692     /* Try to set on the fly */
693     /* FIXME: enable this once we support on-the-fly addition of this kind of
694      * filters...
695     vout_thread_t *p_vout;
696     p_vout = (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
697                                               FIND_ANYWHERE );
698     if( p_vout )
699     {
700         var_SetString( p_vout, "sub-filter", psz_string );
701         vlc_object_release( p_vout );
702     }*/
703
704     free( psz_string );
705
706     vlc_object_release( p_intf );
707
708     o_config_changed = YES;
709 }
710 @end