macosx: remove unused variable and empty tabulated line
[vlc.git] / modules / gui / macosx / VLCAudioEffectsWindowController.m
blob25f80fab3d88758c0afaee8d4048df6976cdb5dd
1 /*****************************************************************************
2  * VLCAudioEffectsWindowController.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2004-2017 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
8  *          Jérôme Decoodt <djc@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
25 #ifdef HAVE_CONFIG_H
26 # import "config.h"
27 #endif
29 #import "VLCMain.h"
30 #import "VLCAudioEffectsWindowController.h"
31 #import "../../audio_filter/equalizer_presets.h"
32 #import "CompatibilityFixes.h"
33 #import "VLCPopupPanelController.h"
34 #import "VLCTextfieldPanelController.h"
36 #import <vlc_common.h>
38 #import <math.h>
40 @interface VLCAudioEffectsWindowController ()
42     NSInteger i_old_profile_index;
44 - (void)resetProfileSelector;
45 - (void)updatePresetSelector;
46 - (void)setBandSliderValuesForPreset:(NSInteger)presetID;
47 @end
49 #pragma mark -
50 #pragma mark Initialization
52 @implementation VLCAudioEffectsWindowController
54 + (void)initialize
56     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
58     NSString *workString;
59     NSMutableArray *workValues = [[NSMutableArray alloc] initWithCapacity:NB_PRESETS];
60     NSMutableArray *workPreamp = [[NSMutableArray alloc] initWithCapacity:NB_PRESETS];
61     NSMutableArray *workTitles = [[NSMutableArray alloc] initWithCapacity:NB_PRESETS];
62     NSMutableArray *workNames = [[NSMutableArray alloc] initWithCapacity:NB_PRESETS];
64     for (int i = 0 ; i < NB_PRESETS ; i++) {
65         workString = [NSString stringWithFormat:@"%.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f",
66                       eqz_preset_10b[i].f_amp[0],
67                       eqz_preset_10b[i].f_amp[1],
68                       eqz_preset_10b[i].f_amp[2],
69                       eqz_preset_10b[i].f_amp[3],
70                       eqz_preset_10b[i].f_amp[4],
71                       eqz_preset_10b[i].f_amp[5],
72                       eqz_preset_10b[i].f_amp[6],
73                       eqz_preset_10b[i].f_amp[7],
74                       eqz_preset_10b[i].f_amp[8],
75                       eqz_preset_10b[i].f_amp[9]];
76         [workValues addObject:workString];
77         [workPreamp addObject:[NSString stringWithFormat:@"%1.f", eqz_preset_10b[i].f_preamp]];
78         [workTitles addObject:toNSStr(preset_list_text[i])];
79         [workNames addObject:toNSStr(preset_list[i])];
80     }
82     NSString *defaultProfile = [NSString stringWithFormat:@"ZmxhdA==;;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%i",
83                                 .0,25.,100.,-11.,8.,2.5,7.,.85,1.,.4,.5,.5,2.,0];
85     NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithArray:workValues], @"EQValues", [NSArray arrayWithArray:workPreamp], @"EQPreampValues", [NSArray arrayWithArray:workTitles], @"EQTitles", [NSArray arrayWithArray:workNames], @"EQNames", [NSArray arrayWithObject:defaultProfile], @"AudioEffectProfiles", [NSArray arrayWithObject:_NS("Default")], @"AudioEffectProfileNames", nil];
86     [defaults registerDefaults:appDefaults];
89 - (id)init
91     self = [super initWithWindowNibName:@"AudioEffects"];
92     if (self) {
93         i_old_profile_index = -1;
95         self.popupPanel = [[VLCPopupPanelController alloc] init];
96         self.textfieldPanel = [[VLCTextfieldPanelController alloc] init];
97     }
99     return self;
102 - (void)windowDidLoad
104     /* setup the user's language */
105     /* Equalizer */
106     [_equalizerEnableCheckbox setTitle:_NS("Enable")];
107     [_equalizerTwoPassCheckbox setTitle:_NS("2 Pass")];
108     [_equalizerTwoPassCheckbox setToolTip:_NS("Filter the audio twice. This provides a more "  \
109                                               "intense effect.")];
110     [_equalizerPreampLabel setStringValue:_NS("Preamp")];
111     [_equalizerPreampLabel setToolTip:_NS("Set the global gain in dB (-20 ... 20).")];
113     /* Compressor */
114     [_compressorEnableCheckbox setTitle:_NS("Enable dynamic range compressor")];
115     [_compressorResetButton setTitle:_NS("Reset")];
116     [_compressorBand1Label setStringValue:_NS("RMS/peak")];;
117     [_compressorBand2Label setStringValue:_NS("Attack")];
118     [_compressorBand3Label setStringValue:_NS("Release")];
119     [_compressorBand4Label setStringValue:_NS("Threshold")];
120     [_compressorBand5Label setStringValue:_NS("Ratio")];
121     [_compressorBand6Label setStringValue:_NS("Knee radius")];
122     [_compressorBand7Label setStringValue:_NS("Makeup gain")];
124     /* Spatializer */
125     [_spatializerEnableCheckbox setTitle:_NS("Enable Spatializer")];
126     [_spatializerResetButton setTitle:_NS("Reset")];
127     [_spatializerBand1Label setStringValue:_NS("Size")];
128     [_spatializerBand1Label setToolTip:_NS("Defines the virtual surface of the room" \
129                                            " emulated by the filter.")];
130     [_spatializerBand2Label setStringValue:_NS("Width")];
131     [_spatializerBand2Label setToolTip:_NS("Width of the virtual room")];
132     [_spatializerBand3Label setStringValue:_NS("Wet")];
133     [_spatializerBand4Label setStringValue:_NS("Dry")];
134     [_spatializerBand5Label setStringValue:_NS("Damp")];
136     /* Filter */
137     [_filterHeadPhoneCheckbox setTitle:_NS("Headphone virtualization")];
138     [_filterHeadPhoneCheckbox setToolTip:_NS("This effect gives you the feeling that you are standing in a room " \
139                                              "with a complete 7.1 speaker set when using only a headphone, " \
140                                              "providing a more realistic sound experience. It should also be " \
141                                              "more comfortable and less tiring when listening to music for " \
142                                              "long periods of time.\nIt works with any source format from mono " \
143                                              "to 7.1.")];
144     [_filterNormLevelCheckbox setTitle:_NS("Volume normalization")];
145     [_filterNormLevelCheckbox setToolTip:_NS("Volume normalizer")];
146     [_filterNormLevelLabel setToolTip:_NS("If the average power over the last N buffers " \
147                                           "is higher than this value, the volume will be normalized. " \
148                                           "This value is a positive floating point number. A value " \
149                                           "between 0.5 and 10 seems sensible.")];
150     [_filterNormLevelLabel setStringValue:_NS("Maximum level")];
151     [_filterKaraokeCheckbox setTitle:_NS("Karaoke")];
152     [_filterKaraokeCheckbox setToolTip:_NS("Simple Karaoke filter")];
153     [_filterScaleTempoCheckbox setTitle:_NS("Scaletempo")];
154     [_filterScaleTempoCheckbox setToolTip:_NS("Audio tempo scaler synched with rate")];
155     [_filterStereoEnhancerCheckbox setTitle:_NS("Stereo Enhancer")];
156     [_filterStereoEnhancerCheckbox setToolTip:_NS("This filter enhances the stereo effect by "\
157                                                   "suppressing mono (signal common to both channels) "\
158                                                   "and by delaying the signal of left into right and vice versa, "\
159                                                   "thereby widening the stereo effect.")];
161     /* generic */
162     [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"equalizer"]] setLabel:_NS("Equalizer")];
163     [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"compressor"]] setLabel:_NS("Compressor")];
164     [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"spatializer"]] setLabel:_NS("Spatializer")];
165     [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"filter"]] setLabel:_NS("Filter")];
166     [self.window setTitle:_NS("Audio Effects")];
167     [self.window setExcludedFromWindowsMenu:YES];
168     [self.window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
170     [self equalizerUpdated];
171     [self resetCompressor];
172     [self resetSpatializer];
173     [self resetAudioFilters];
174     [self resetProfileSelector];
177 #pragma mark -
178 #pragma mark internal functions
180 - (void)setAudioFilter: (char *)psz_name on:(BOOL)b_on
182     playlist_EnableAudioFilter(pl_Get(getIntf()), psz_name, b_on);
185 - (void)resetProfileSelector
187     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
188     [_profilePopup removeAllItems];
190     NSArray *profileNames = [defaults objectForKey:@"AudioEffectProfileNames"];
191     [_profilePopup addItemsWithTitles:profileNames];
193     [[_profilePopup menu] addItem:[NSMenuItem separatorItem]];
194     [_profilePopup addItemWithTitle:_NS("Duplicate current profile...")];
195     [[_profilePopup lastItem] setTarget: self];
196     [[_profilePopup lastItem] setAction: @selector(addAudioEffectsProfile:)];
198     if ([profileNames count] > 1) {
199         [_profilePopup addItemWithTitle:_NS("Organize Profiles...")];
200         [[_profilePopup lastItem] setTarget: self];
201         [[_profilePopup lastItem] setAction: @selector(removeAudioEffectsProfile:)];
202     }
204     [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
205     [self profileSelectorAction:self];
208 #pragma mark -
209 #pragma mark generic code
210 - (void)updateCocoaWindowLevel:(NSInteger)i_level
212     if (self.isWindowLoaded && [self.window isVisible] && [self.window level] != i_level)
213         [self.window setLevel: i_level];
216 - (IBAction)toggleWindow:(id)sender
218     if ([self.window isKeyWindow])
219         [self.window orderOut:sender];
220     else {
221         [self.window setLevel: [[[VLCMain sharedInstance] voutController] currentStatusWindowLevel]];
222         [self.window makeKeyAndOrderFront:sender];
223     }
226 - (NSString *)generateProfileString
228     intf_thread_t *p_intf = getIntf();
229     vlc_object_t *p_object = VLC_OBJECT(getAout());
230     if (p_object == NULL)
231         p_object = vlc_object_hold(pl_Get(p_intf));
233     NSString *o_str = [NSString stringWithFormat:@"%@;%@;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%lli",
234                        B64EncAndFree(var_GetNonEmptyString(p_object, "equalizer-preset")),
235                        B64EncAndFree(config_GetPsz(p_intf, "audio-filter")),
236                        config_GetFloat(p_intf, "compressor-rms-peak"),
237                        config_GetFloat(p_intf, "compressor-attack"),
238                        config_GetFloat(p_intf, "compressor-release"),
239                        config_GetFloat(p_intf, "compressor-threshold"),
240                        config_GetFloat(p_intf, "compressor-ratio"),
241                        config_GetFloat(p_intf, "compressor-knee"),
242                        config_GetFloat(p_intf, "compressor-makeup-gain"),
243                        config_GetFloat(p_intf, "spatializer-roomsize"),
244                        config_GetFloat(p_intf, "spatializer-width"),
245                        config_GetFloat(p_intf, "spatializer-wet"),
246                        config_GetFloat(p_intf, "spatializer-dry"),
247                        config_GetFloat(p_intf, "spatializer-damp"),
248                        config_GetFloat(p_intf, "norm-max-level"),
249                        config_GetInt(p_intf,"equalizer-2pass")];
251     vlc_object_release(p_object);
252     return o_str;
255 - (void)saveCurrentProfile
257     if (i_old_profile_index == -1)
258         return;
260     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
261     /* fetch all the current settings in a uniform string */
262     NSString *newProfile = [self generateProfileString];
264     NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]];
265     if (i_old_profile_index >= [workArray count])
266         return;
268     [workArray replaceObjectAtIndex:i_old_profile_index withObject:newProfile];
269     [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"];
270     [defaults synchronize];
273 - (IBAction)profileSelectorAction:(id)sender
275     intf_thread_t *p_intf = getIntf();
276     [self saveCurrentProfile];
277     i_old_profile_index = [_profilePopup indexOfSelectedItem];
279     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
280     NSInteger selectedProfile = [_profilePopup indexOfSelectedItem];
281     if (selectedProfile < 0)
282         return;
284     audio_output_t *p_aout = getAout();
285     playlist_t *p_playlist = pl_Get(p_intf);
287     if (p_aout) {
288         /* disable existing filters */
289         playlist_EnableAudioFilter(p_playlist, "equalizer", false);
290         playlist_EnableAudioFilter(p_playlist, "compressor", false);
291         playlist_EnableAudioFilter(p_playlist, "spatializer", false);
292         playlist_EnableAudioFilter(p_playlist, "compressor", false);
293         playlist_EnableAudioFilter(p_playlist, "headphone", false);
294         playlist_EnableAudioFilter(p_playlist, "normvol", false);
295         playlist_EnableAudioFilter(p_playlist, "karaoke", false);
296     }
298     /* fetch preset */
299     NSArray *items = [[[defaults objectForKey:@"AudioEffectProfiles"] objectAtIndex:(NSUInteger) selectedProfile] componentsSeparatedByString:@";"];
301     /* eq preset */
302     vlc_object_t *p_object = VLC_OBJECT(getAout());
303     if (p_object == NULL)
304         p_object = vlc_object_hold(pl_Get(p_intf));
305     var_SetString(p_object, "equalizer-preset", [B64DecNSStr([items firstObject]) UTF8String]);
306     vlc_object_release(p_object);
308     /* filter handling */
309     NSString *tempString = B64DecNSStr([items objectAtIndex:1]);
310     NSArray *tempArray;
311     NSUInteger count;
312     /* enable the new filters, if we have an aout */
313     if (p_aout) {
314         if ([tempString length] > 0) {
315             tempArray = [tempString componentsSeparatedByString:@":"];
316             count = [tempArray count];
317             for (NSUInteger x = 0; x < count; x++)
318                 playlist_EnableAudioFilter(p_playlist, [[tempArray objectAtIndex:x] UTF8String], true);
319         }
320     }
321     config_PutPsz(p_intf,"audio-filter",[tempString UTF8String]);
323     /* values */
324     config_PutFloat(p_intf, "compressor-rms-peak",[[items objectAtIndex:2] floatValue]);
325     config_PutFloat(p_intf, "compressor-attack",[[items objectAtIndex:3] floatValue]);
326     config_PutFloat(p_intf, "compressor-release",[[items objectAtIndex:4] floatValue]);
327     config_PutFloat(p_intf, "compressor-threshold",[[items objectAtIndex:5] floatValue]);
328     config_PutFloat(p_intf, "compressor-ratio",[[items objectAtIndex:6] floatValue]);
329     config_PutFloat(p_intf, "compressor-knee",[[items objectAtIndex:7] floatValue]);
330     config_PutFloat(p_intf, "compressor-makeup-gain",[[items objectAtIndex:8] floatValue]);
331     config_PutFloat(p_intf, "spatializer-roomsize",[[items objectAtIndex:9] floatValue]);
332     config_PutFloat(p_intf, "spatializer-width",[[items objectAtIndex:10] floatValue]);
333     config_PutFloat(p_intf, "spatializer-wet",[[items objectAtIndex:11] floatValue]);
334     config_PutFloat(p_intf, "spatializer-dry",[[items objectAtIndex:12] floatValue]);
335     config_PutFloat(p_intf, "spatializer-damp",[[items objectAtIndex:13] floatValue]);
336     config_PutFloat(p_intf, "norm-max-level",[[items objectAtIndex:14] floatValue]);
337     config_PutInt(p_intf, "equalizer-2pass",[[items objectAtIndex:15] intValue]);
339     /* set values on-the-fly if we have an aout */
340     if (p_aout) {
341         var_SetFloat(p_aout, "compressor-rms-peak", [[items objectAtIndex:2] floatValue]);
342         var_SetFloat(p_aout, "compressor-attack", [[items objectAtIndex:3] floatValue]);
343         var_SetFloat(p_aout, "compressor-release", [[items objectAtIndex:4] floatValue]);
344         var_SetFloat(p_aout, "compressor-threshold", [[items objectAtIndex:5] floatValue]);
345         var_SetFloat(p_aout, "compressor-ratio", [[items objectAtIndex:6] floatValue]);
346         var_SetFloat(p_aout, "compressor-knee", [[items objectAtIndex:7] floatValue]);
347         var_SetFloat(p_aout, "compressor-makeup-gain", [[items objectAtIndex:8] floatValue]);
348         var_SetFloat(p_aout, "spatializer-roomsize", [[items objectAtIndex:9] floatValue]);
349         var_SetFloat(p_aout, "spatializer-width", [[items objectAtIndex:10] floatValue]);
350         var_SetFloat(p_aout, "spatializer-wet", [[items objectAtIndex:11] floatValue]);
351         var_SetFloat(p_aout, "spatializer-dry", [[items objectAtIndex:12] floatValue]);
352         var_SetFloat(p_aout, "spatializer-damp", [[items objectAtIndex:13] floatValue]);
353         var_SetFloat(p_aout, "norm-max-level", [[items objectAtIndex:14] floatValue]);
354         var_SetBool(p_aout, "equalizer-2pass", (BOOL)[[items objectAtIndex:15] intValue]);
355     }
357     /* update UI */
358     BOOL b_equalizerEnabled = [tempString rangeOfString:@"equalizer"].location != NSNotFound;
359     [_equalizerView enableSubviews:b_equalizerEnabled];
360     [_equalizerEnableCheckbox setState:(b_equalizerEnabled ? NSOnState : NSOffState)];
362     [_equalizerTwoPassCheckbox setState:[[items objectAtIndex:15] intValue]];
363     [self resetCompressor];
364     [self resetSpatializer];
365     [self resetAudioFilters];
366     [self updatePresetSelector];
368     /* store current profile selection */
369     [defaults setInteger:selectedProfile forKey:@"AudioEffectSelectedProfile"];
370     [defaults synchronize];
372     if (p_aout)
373         vlc_object_release(p_aout);
376 - (void)addAudioEffectsProfile:(id)sender
378     /* show panel */
379     [_textfieldPanel setTitleString:_NS("Duplicate current profile for a new profile")];
380     [_textfieldPanel setSubTitleString:_NS("Enter a name for the new profile:")];
381     [_textfieldPanel setCancelButtonString:_NS("Cancel")];
382     [_textfieldPanel setOkButtonString:_NS("Save")];
384     __weak typeof(self) _self = self;
385     [_textfieldPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSString *resultingText) {
387         NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
388         if (returnCode != NSOKButton) {
389             [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
390             return;
391         }
393         NSArray *profileNames = [defaults objectForKey:@"AudioEffectProfileNames"];
395         // duplicate names are not allowed in the popup control
396         if ([resultingText length] == 0 || [profileNames containsObject:resultingText]) {
397             [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
399             NSAlert *alert = [[NSAlert alloc] init];
400             [alert setAlertStyle:NSCriticalAlertStyle];
401             [alert setMessageText:_NS("Please enter a unique name for the new profile.")];
402             [alert setInformativeText:_NS("Multiple profiles with the same name are not allowed.")];
404             [alert beginSheetModalForWindow:_self.window
405                               modalDelegate:nil
406                              didEndSelector:nil
407                                 contextInfo:nil];
408             return;
409         }
411         NSString *newProfile = [_self generateProfileString];
413         /* add string to user defaults as well as a label */
414         NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]];
415         [workArray addObject:newProfile];
416         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"];
417         [defaults setInteger:[workArray count] - 1 forKey:@"AudioEffectSelectedProfile"];
418         workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfileNames"]];
419         [workArray addObject:resultingText];
420         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfileNames"];
422         /* save defaults */
423         [defaults synchronize];
424         [_self resetProfileSelector];
426     }];
429 - (void)removeAudioEffectsProfile:(id)sender
431     /* show panel */
432     [_popupPanel setTitleString:_NS("Remove a preset")];
433     [_popupPanel setSubTitleString:_NS("Select the preset you would like to remove:")];
434     [_popupPanel setOkButtonString:_NS("Remove")];
435     [_popupPanel setCancelButtonString:_NS("Cancel")];
436     [_popupPanel setPopupButtonContent:[[NSUserDefaults standardUserDefaults] objectForKey:@"AudioEffectProfileNames"]];
438     __weak typeof(self) _self = self;
439     [_popupPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSInteger selectedIndex) {
441         NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
442         if (returnCode != NSOKButton) {
443             [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
444             return;
445         }
447         /* remove selected profile from settings */
448         NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]];
449         [workArray removeObjectAtIndex:selectedIndex];
450         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"];
451         workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfileNames"]];
452         [workArray removeObjectAtIndex:selectedIndex];
453         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfileNames"];
455         if (i_old_profile_index >= selectedIndex)
456             [defaults setInteger:i_old_profile_index - 1 forKey:@"AudioEffectSelectedProfile"];
458         /* save defaults */
459         [defaults synchronize];
460         [_self resetProfileSelector];
461     }];
464 #pragma mark -
465 #pragma mark Equalizer
466 static bool GetEqualizerStatus(intf_thread_t *p_custom_intf,
467                                char *psz_name)
469     char *psz_parser, *psz_string = NULL;
470     audio_output_t *p_aout = getAout();
471     if (!p_aout)
472         return false;
474     psz_string = var_InheritString(pl_Get(p_custom_intf), "audio-filter");
476     if (!psz_string)
477         psz_string = var_GetNonEmptyString(p_aout, "audio-filter");
479     vlc_object_release(p_aout);
481     if (!psz_string)
482         return false;
484     psz_parser = strstr(psz_string, psz_name);
486     free(psz_string);
488     if (psz_parser)
489         return true;
490     else
491         return false;
494 - (void)updatePresetSelector
496     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
497     NSArray *presets = [defaults objectForKey:@"EQNames"];
499     [_equalizerPresetsPopup removeAllItems];
500     [_equalizerPresetsPopup addItemsWithTitles:[[NSUserDefaults standardUserDefaults] objectForKey:@"EQTitles"]];
501     [[_equalizerPresetsPopup menu] addItem:[NSMenuItem separatorItem]];
502     [_equalizerPresetsPopup addItemWithTitle:_NS("Add new Preset...")];
503     [[_equalizerPresetsPopup lastItem] setTarget: self];
504     [[_equalizerPresetsPopup lastItem] setAction: @selector(addPresetAction:)];
506     if ([presets count] > 1) {
507         [_equalizerPresetsPopup addItemWithTitle:_NS("Organize Presets...")];
508         [[_equalizerPresetsPopup lastItem] setTarget: self];
509         [[_equalizerPresetsPopup lastItem] setAction: @selector(deletePresetAction:)];
510     }
512     audio_output_t *p_aout = getAout();
514     NSString *currentPreset = nil;
515     if (p_aout) {
516         char *psz_preset_string = var_GetNonEmptyString(p_aout, "equalizer-preset");
517         currentPreset = toNSStr(psz_preset_string);
518         free(psz_preset_string);
519         vlc_object_release(p_aout);
520     }
522     NSUInteger currentPresetIndex = 0;
523     if (currentPreset && [currentPreset length] > 0) {
524         currentPresetIndex = [presets indexOfObject:currentPreset];
526         if (currentPresetIndex == NSNotFound)
527             currentPresetIndex = [presets count] - 1;
528     }    
530     [_equalizerPresetsPopup selectItemAtIndex:currentPresetIndex];
531     [self equalizerChangePreset:_equalizerPresetsPopup];
533     [_equalizerPreampSlider setFloatValue:[[[defaults objectForKey:@"EQPreampValues"] objectAtIndex:currentPresetIndex] floatValue]];
534     [self setBandSliderValuesForPreset:currentPresetIndex];
537 - (void)equalizerUpdated
539     intf_thread_t *p_intf = getIntf();
540     bool b_2p = (BOOL)config_GetInt(p_intf, "equalizer-2pass");
541     bool bEnabled = GetEqualizerStatus(p_intf, (char *)"equalizer");
543     /* Setup sliders */
544     [self updatePresetSelector];
546     /* Set the the checkboxes */
547     [_equalizerView enableSubviews: bEnabled];
548     [_equalizerEnableCheckbox setState: bEnabled];
549     [_equalizerTwoPassCheckbox setState: b_2p];
552 - (id)sliderByIndex:(int)index
554     switch(index) {
555         case 0 : return _equalizerBand1Slider;
556         case 1 : return _equalizerBand2Slider;
557         case 2 : return _equalizerBand3Slider;
558         case 3 : return _equalizerBand4Slider;
559         case 4 : return _equalizerBand5Slider;
560         case 5 : return _equalizerBand6Slider;
561         case 6 : return _equalizerBand7Slider;
562         case 7 : return _equalizerBand8Slider;
563         case 8 : return _equalizerBand9Slider;
564         case 9 : return _equalizerBand10Slider;
565         default : return nil;
566     }
569 - (void)setBandSliderValuesForPreset:(NSInteger)presetID
571     NSString *preset = [[[NSUserDefaults standardUserDefaults] objectForKey:@"EQValues"] objectAtIndex:presetID];
572     NSArray *values = [preset componentsSeparatedByString:@" "];
573     NSUInteger count = [values count];
574     for (NSUInteger x = 0; x < count; x++)
575         [self setValue:[[values objectAtIndex:x] floatValue] forSlider:x];
578 - (NSString *)generatePresetString
580     return [NSString stringWithFormat:@"%.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f",
581             [_equalizerBand1Slider floatValue],
582             [_equalizerBand2Slider floatValue],
583             [_equalizerBand3Slider floatValue],
584             [_equalizerBand4Slider floatValue],
585             [_equalizerBand5Slider floatValue],
586             [_equalizerBand6Slider floatValue],
587             [_equalizerBand7Slider floatValue],
588             [_equalizerBand8Slider floatValue],
589             [_equalizerBand9Slider floatValue],
590             [_equalizerBand10Slider floatValue]];
593 - (void)setValue:(float)value forSlider:(int)index
595     id slider = [self sliderByIndex:index];
597     if (slider != nil)
598         [slider setFloatValue:value];
601 - (IBAction)equalizerEnable:(id)sender
603     [_equalizerView enableSubviews:[sender state]];
604     [self setAudioFilter: "equalizer" on:[sender state]];
607 - (IBAction)equalizerBandSliderUpdated:(id)sender
609     audio_output_t *p_aout = getAout();
610     if (p_aout) {
611         var_SetString(p_aout, "equalizer-bands", [[self generatePresetString] UTF8String]);
612         vlc_object_release(p_aout);
613     }
615     /* save changed to config */
616     config_PutPsz(getIntf(), "equalizer-bands", [[self generatePresetString] UTF8String]);
619 - (IBAction)equalizerChangePreset:(id)sender
621     intf_thread_t *p_intf = getIntf();
622     NSInteger numberOfChosenPreset = [sender indexOfSelectedItem];
623     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
625     NSString *preset = [[defaults objectForKey:@"EQValues"] objectAtIndex:numberOfChosenPreset];
626     NSString *preamp = [[defaults objectForKey:@"EQPreampValues"] objectAtIndex:numberOfChosenPreset];
628     audio_output_t *p_aout = getAout();
629     if (p_aout) {
630         var_SetString(p_aout, "equalizer-bands", [preset UTF8String]);
631         var_SetFloat(p_aout, "equalizer-preamp", [preamp floatValue]);
632         var_SetString(p_aout, "equalizer-preset" , [[[defaults objectForKey:@"EQNames"] objectAtIndex:numberOfChosenPreset] UTF8String]);
633         vlc_object_release(p_aout);
634     }
636     [_equalizerPreampSlider setFloatValue: [preamp floatValue]];
637     [self setBandSliderValuesForPreset:numberOfChosenPreset];
639     /* save changed to config */
640     config_PutPsz(p_intf, "equalizer-bands", [preset UTF8String]);
641     config_PutFloat(p_intf, "equalizer-preamp", [preamp floatValue]);
642     config_PutPsz(p_intf, "equalizer-preset", [[[defaults objectForKey:@"EQNames"] objectAtIndex:numberOfChosenPreset] UTF8String]);
645 - (IBAction)equalizerPreAmpSliderUpdated:(id)sender
647     float fPreamp = [sender floatValue] ;
649     audio_output_t *p_aout = getAout();
650     if (p_aout) {
651         var_SetFloat(p_aout, "equalizer-preamp", fPreamp);
652         vlc_object_release(p_aout);
653     }
654     
655     /* save changed to config */
656     config_PutFloat(getIntf(), "equalizer-preamp", fPreamp);
659 - (IBAction)equalizerTwoPass:(id)sender
661     bool b_2p = [sender state] ? true : false;
663     audio_output_t *p_aout = getAout();
664     if (p_aout) {
665         var_SetBool(p_aout, "equalizer-2pass", b_2p);
666         vlc_object_release(p_aout);
667     }
669     /* save changed to config */
670     config_PutInt(getIntf(), "equalizer-2pass", (int)b_2p);
673 - (IBAction)addPresetAction:(id)sender
675     /* show panel */
676     [_textfieldPanel setTitleString:_NS("Save current selection as new preset")];
677     [_textfieldPanel setSubTitleString:_NS("Enter a name for the new preset:")];
678     [_textfieldPanel setCancelButtonString:_NS("Cancel")];
679     [_textfieldPanel setOkButtonString:_NS("Save")];
681     __weak typeof(self) _self = self;
682     [_textfieldPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSString *resultingText) {
683         NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
685         // EQ settings
686         if (returnCode != NSOKButton || [resultingText length] == 0)
687             return;
689         NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]];
690         [workArray addObject:[self generatePresetString]];
691         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"];
692         workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]];
693         [workArray addObject:resultingText];
694         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"];
695         workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]];
696         [workArray addObject:[NSString stringWithFormat:@"%.1f", [_equalizerPreampSlider floatValue]]];
697         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"];
698         workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]];
699         [workArray addObject:[resultingText decomposedStringWithCanonicalMapping]];
700         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"];
701         [defaults synchronize];
703         /* update VLC internals */
704         audio_output_t *p_aout = getAout();
705         if (p_aout) {
706             var_SetString(p_aout, "equalizer-preset", [[resultingText decomposedStringWithCanonicalMapping] UTF8String]);
707             vlc_object_release(p_aout);
708         }
710         config_PutPsz(getIntf(), "equalizer-preset", [[resultingText decomposedStringWithCanonicalMapping] UTF8String]);
712         /* update UI */
713         [_self updatePresetSelector];
714     }];
717 - (IBAction)deletePresetAction:(id)sender
719     [_popupPanel setTitleString:_NS("Remove a preset")];
720     [_popupPanel setSubTitleString:_NS("Select the preset you would like to remove:")];
721     [_popupPanel setOkButtonString:_NS("Remove")];
722     [_popupPanel setCancelButtonString:_NS("Cancel")];
723     [_popupPanel setPopupButtonContent:[[NSUserDefaults standardUserDefaults] objectForKey:@"EQTitles"]];
725     __weak typeof(self) _self = self;
726     [_popupPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSInteger selectedIndex) {
728         if (returnCode != NSOKButton)
729             return;
731         /* remove requested profile from the arrays */
732         NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
733         NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]];
734         [workArray removeObjectAtIndex:selectedIndex];
735         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"];
736         workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]];
737         [workArray removeObjectAtIndex:selectedIndex];
738         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"];
739         workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]];
740         [workArray removeObjectAtIndex:selectedIndex];
741         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"];
742         workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]];
743         [workArray removeObjectAtIndex:selectedIndex];
744         [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"];
745         [defaults synchronize];
747         /* update UI */
748         [_self updatePresetSelector];
749     }];
752 #pragma mark -
753 #pragma mark Compressor
754 - (void)resetCompressor
756     intf_thread_t *p_intf = getIntf();
757     BOOL bEnable_compressor = NO;
758     char *psz_afilters;
759     psz_afilters = var_InheritString(pl_Get(p_intf), "audio-filter");
760     if (psz_afilters) {
761         bEnable_compressor = strstr(psz_afilters, "compressor") != NULL;
762         [_compressorEnableCheckbox setState: (NSInteger)strstr(psz_afilters, "compressor") ];
763         free(psz_afilters);
764     }
766     [_compressorView enableSubviews:bEnable_compressor];
767     [_compressorEnableCheckbox setState:(bEnable_compressor ? NSOnState : NSOffState)];
769     [_compressorBand1Slider setFloatValue: config_GetFloat(p_intf, "compressor-rms-peak")];
770     [_compressorBand1TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", [_compressorBand1Slider floatValue]]];
771     [_compressorBand2Slider setFloatValue: config_GetFloat(p_intf, "compressor-attack")];
772     [_compressorBand2TextField setStringValue:[NSString localizedStringWithFormat:@"%2.1f ms", [_compressorBand2Slider floatValue]]];
773     [_compressorBand3Slider setFloatValue: config_GetFloat(p_intf, "compressor-release")];
774     [_compressorBand3TextField setStringValue:[NSString localizedStringWithFormat:@"%3.1f ms", [_compressorBand3Slider floatValue]]];
775     [_compressorBand4Slider setFloatValue: config_GetFloat(p_intf, "compressor-threshold")];
776     [_compressorBand4TextField setStringValue:[NSString localizedStringWithFormat:@"%2.1f dB", [_compressorBand4Slider floatValue]]];
777     [_compressorBand5Slider setFloatValue: config_GetFloat(p_intf, "compressor-ratio")];
778     [_compressorBand5TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f:1", [_compressorBand5Slider floatValue]]];
779     [_compressorBand6Slider setFloatValue: config_GetFloat(p_intf, "compressor-knee")];
780     [_compressorBand6TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f dB", [_compressorBand6Slider floatValue]]];
781     [_compressorBand7Slider setFloatValue: config_GetFloat(p_intf, "compressor-makeup-gain")];
782     [_compressorBand7TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f dB", [_compressorBand7Slider floatValue]]];
785 - (IBAction)resetCompressorValues:(id)sender
787     intf_thread_t *p_intf = getIntf();
788     config_PutFloat(p_intf, "compressor-rms-peak", 0.000000);
789     config_PutFloat(p_intf, "compressor-attack", 25.000000);
790     config_PutFloat(p_intf, "compressor-release", 100.000000);
791     config_PutFloat(p_intf, "compressor-threshold", -11.000000);
792     config_PutFloat(p_intf, "compressor-ratio", 8.000000);
793     config_PutFloat(p_intf, "compressor-knee", 2.500000);
794     config_PutFloat(p_intf, "compressor-makeup-gain", 7.000000);
796     audio_output_t *p_aout = getAout();
797     if (p_aout) {
798         var_SetFloat(p_aout, "compressor-rms-peak", 0.000000);
799         var_SetFloat(p_aout, "compressor-attack", 25.000000);
800         var_SetFloat(p_aout, "compressor-release", 100.000000);
801         var_SetFloat(p_aout, "compressor-threshold", -11.000000);
802         var_SetFloat(p_aout, "compressor-ratio", 8.000000);
803         var_SetFloat(p_aout, "compressor-knee", 2.500000);
804         var_SetFloat(p_aout, "compressor-makeup-gain", 7.000000);
805         vlc_object_release(p_aout);
806     }
807     [self resetCompressor];
810 - (IBAction)compressorEnable:(id)sender
812     [_compressorView enableSubviews:[sender state]];
813     [self setAudioFilter:"compressor" on:[sender state]];
816 - (IBAction)compressorSliderUpdated:(id)sender
818     audio_output_t *p_aout = getAout();
819     char *value;
820     if (sender == _compressorBand1Slider)
821         value = "compressor-rms-peak";
822     else if (sender == _compressorBand2Slider)
823         value = "compressor-attack";
824     else if (sender == _compressorBand3Slider)
825         value = "compressor-release";
826     else if (sender == _compressorBand4Slider)
827         value = "compressor-threshold";
828     else if (sender == _compressorBand5Slider)
829         value = "compressor-ratio";
830     else if (sender == _compressorBand6Slider)
831         value = "compressor-knee";
832     else if (sender == _compressorBand7Slider)
833         value = "compressor-makeup-gain";
835     if (p_aout) {
836         var_SetFloat(p_aout, value, [sender floatValue]);
837         vlc_object_release(p_aout);
838     }
839     config_PutFloat(getIntf(), value, [sender floatValue]);
841     if (sender == _compressorBand1Slider)
842         [_compressorBand1TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", [sender floatValue]]];
843     else if (sender == _compressorBand2Slider)
844         [_compressorBand2TextField setStringValue:[NSString localizedStringWithFormat:@"%2.1f ms", [sender floatValue]]];
845     else if (sender == _compressorBand3Slider)
846         [_compressorBand3TextField setStringValue:[NSString localizedStringWithFormat:@"%3.1f ms", [sender floatValue]]];
847     else if (sender == _compressorBand4Slider)
848         [_compressorBand4TextField setStringValue:[NSString localizedStringWithFormat:@"%2.1f dB", [sender floatValue]]];
849     else if (sender == _compressorBand5Slider)
850         [_compressorBand5TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f:1", [sender floatValue]]];
851     else if (sender == _compressorBand6Slider)
852         [_compressorBand6TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f dB", [sender floatValue]]];
853     else if (sender == _compressorBand7Slider)
854         [_compressorBand7TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f dB", [sender floatValue]]];
857 #pragma mark -
858 #pragma mark Spatializer
859 - (void)resetSpatializer
861     intf_thread_t *p_intf = getIntf();
862     BOOL bEnable_spatializer = NO;
863     char *psz_afilters;
864     psz_afilters = var_InheritString(pl_Get(p_intf), "audio-filter");
865     if (psz_afilters) {
866         bEnable_spatializer = strstr(psz_afilters, "spatializer") != NULL;
867         free(psz_afilters);
868     }
870     [_spatializerView enableSubviews:bEnable_spatializer];
871     [_spatializerEnableCheckbox setState:(bEnable_spatializer ? NSOnState : NSOffState)];
874 #define setSlider(bandsld, bandfld, var) \
875 [bandsld setFloatValue: config_GetFloat(p_intf, var) * 10.]; \
876 [bandfld setStringValue:[NSString localizedStringWithFormat:@"%1.1f", [bandsld floatValue]]]
878     setSlider(_spatializerBand1Slider, _spatializerBand1TextField, "spatializer-roomsize");
879     setSlider(_spatializerBand2Slider, _spatializerBand2TextField, "spatializer-width");
880     setSlider(_spatializerBand3Slider, _spatializerBand3TextField, "spatializer-wet");
881     setSlider(_spatializerBand4Slider, _spatializerBand4TextField, "spatializer-dry");
882     setSlider(_spatializerBand5Slider, _spatializerBand5TextField, "spatializer-damp");
884 #undef setSlider
887 - (IBAction)resetSpatializerValues:(id)sender
889     intf_thread_t *p_intf = getIntf();
890     config_PutFloat(p_intf, "spatializer-roomsize", .85);
891     config_PutFloat(p_intf, "spatializer-width", 1.);
892     config_PutFloat(p_intf, "spatializer-wet", .4);
893     config_PutFloat(p_intf, "spatializer-dry", .5);
894     config_PutFloat(p_intf, "spatializer-damp", .5);
896     audio_output_t *p_aout = getAout();
897     if (p_aout) {
898         var_SetFloat(p_aout, "spatializer-roomsize", .85);
899         var_SetFloat(p_aout, "spatializer-width", 1.);
900         var_SetFloat(p_aout, "spatializer-wet", .4);
901         var_SetFloat(p_aout, "spatializer-dry", .5);
902         var_SetFloat(p_aout, "spatializer-damp", .5);
903         vlc_object_release(p_aout);
904     }
905     [self resetSpatializer];
908 - (IBAction)spatializerEnable:(id)sender
910     [_spatializerView enableSubviews:[sender state]];
911     [self setAudioFilter:"spatializer" on:[sender state]];
914 - (IBAction)spatializerSliderUpdated:(id)sender
916     audio_output_t *p_aout = getAout();
917     char *value = NULL;
918     if (sender == _spatializerBand1Slider)
919         value = "spatializer-roomsize";
920     else if (sender == _spatializerBand2Slider)
921         value = "spatializer-width";
922     else if (sender == _spatializerBand3Slider)
923         value = "spatializer-wet";
924     else if (sender == _spatializerBand4Slider)
925         value = "spatializer-dry";
926     else if (sender == _spatializerBand5Slider)
927         value = "spatializer-damp";
929     if (p_aout) {
930         var_SetFloat(p_aout, value, [sender floatValue] / 10.);
931         vlc_object_release(p_aout);
932     }
933     config_PutFloat(getIntf(), value, [sender floatValue] / 10.);
935     if (sender == _spatializerBand1Slider)
936         [_spatializerBand1TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", [sender floatValue]]];
937     else if (sender == _spatializerBand2Slider)
938         [_spatializerBand2TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", [sender floatValue]]];
939     else if (sender == _spatializerBand3Slider)
940         [_spatializerBand3TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", [sender floatValue]]];
941     else if (sender == _spatializerBand4Slider)
942         [_spatializerBand4TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", [sender floatValue]]];
943     else if (sender == _spatializerBand5Slider)
944         [_spatializerBand5TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", [sender floatValue]]];
947 #pragma mark -
948 #pragma mark Filter
949 - (void)resetAudioFilters
951     intf_thread_t *p_intf = getIntf();
952     BOOL bEnable_normvol = NO;
953     char *psz_afilters;
954     psz_afilters = var_InheritString(pl_Get(p_intf), "audio-filter");
955     if (psz_afilters) {
956         [_filterHeadPhoneCheckbox setState: (NSInteger)strstr(psz_afilters, "headphone") ];
957         [_filterKaraokeCheckbox setState: (NSInteger)strstr(psz_afilters, "karaoke") ];
958         [_filterScaleTempoCheckbox setState: (NSInteger)strstr(psz_afilters, "scaletempo") ];
959         [_filterStereoEnhancerCheckbox setState: (NSInteger)strstr(psz_afilters, "stereo_widen") ];
960         bEnable_normvol = strstr(psz_afilters, "normvol") != NULL;
961         free(psz_afilters);
962     } else {
963         [_filterHeadPhoneCheckbox setState: NSOffState];
964         [_filterKaraokeCheckbox setState: NSOffState];
965         [_filterScaleTempoCheckbox setState: NSOffState];
966         [_filterStereoEnhancerCheckbox setState: NSOffState];
967     }
969     [_filterNormLevelSlider setEnabled:bEnable_normvol];
970     [_filterNormLevelLabel setEnabled:bEnable_normvol];
971     [_filterNormLevelCheckbox setState:(bEnable_normvol ? NSOnState : NSOffState)];
973     [_filterNormLevelSlider setFloatValue: config_GetFloat(p_intf, "norm-max-level")];
976 - (IBAction)filterEnableHeadPhoneVirt:(id)sender
978     [self setAudioFilter:"headphone" on:[sender state]];
981 - (IBAction)filterEnableVolumeNorm:(id)sender
983     [_filterNormLevelSlider setEnabled:[sender state]];
984     [_filterNormLevelLabel setEnabled:[sender state]];
985     [self setAudioFilter:"normvol" on:[sender state]];
988 - (IBAction)filterVolumeNormSliderUpdated:(id)sender
990     audio_output_t *p_aout = getAout();
992     if (p_aout) {
993         var_SetFloat(p_aout, "norm-max-level", [_filterNormLevelSlider floatValue]);
994         vlc_object_release(p_aout);
995     }
997     config_PutFloat(getIntf(), "norm-max-level", [_filterNormLevelSlider floatValue]);
1000 - (IBAction)filterEnableKaraoke:(id)sender
1002     [self setAudioFilter:"karaoke" on:[sender state]];
1005 - (IBAction)filterEnableScaleTempo:(id)sender
1007     [self setAudioFilter:"scaletempo" on:[sender state]];
1010 - (IBAction)filterEnableStereoEnhancer:(id)sender
1012     [self setAudioFilter:"stereo_widen" on:[sender state]];
1015 @end