1 /*****************************************************************************
2 * VLCAudioEffectsWindowController.m: MacOS X interface module
3 *****************************************************************************
4 * Copyright (C) 2004-2017 VLC authors and VideoLAN
7 * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
8 * Jérôme Decoodt <djc@videolan.org>
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.
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.
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 *****************************************************************************/
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>
40 @interface VLCAudioEffectsWindowController ()
42 NSInteger i_old_profile_index;
44 - (void)resetProfileSelector;
45 - (void)updatePresetSelector;
46 - (void)setBandSliderValuesForPreset:(NSInteger)presetID;
50 #pragma mark Initialization
52 @implementation VLCAudioEffectsWindowController
56 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
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])];
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];
91 self = [super initWithWindowNibName:@"AudioEffects"];
93 i_old_profile_index = -1;
95 self.popupPanel = [[VLCPopupPanelController alloc] init];
96 self.textfieldPanel = [[VLCTextfieldPanelController alloc] init];
98 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"AudioEffectApplyProfileOnStartup"])
100 [self equalizerUpdated];
101 [self resetCompressor];
102 [self resetSpatializer];
103 [self resetAudioFilters];
111 - (NSInteger)getPresetIndexForProfile:(NSInteger)profileIndex
113 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
114 NSString *profile = [[defaults objectForKey:@"AudioEffectProfiles"] objectAtIndex:profileIndex];
115 NSString *presetName = B64DecNSStr([[profile componentsSeparatedByString:@";"] firstObject]);
116 return [[defaults objectForKey:@"EQNames"] indexOfObject:presetName];
121 intf_thread_t *p_intf = getIntf();
122 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
123 NSInteger selectedProfile = [defaults integerForKey:@"AudioEffectSelectedProfile"];
124 playlist_t *p_playlist = pl_Get(p_intf);
126 /* disable existing filters */
127 playlist_EnableAudioFilter(p_playlist, "equalizer", false);
128 playlist_EnableAudioFilter(p_playlist, "compressor", false);
129 playlist_EnableAudioFilter(p_playlist, "spatializer", false);
130 playlist_EnableAudioFilter(p_playlist, "compressor", false);
131 playlist_EnableAudioFilter(p_playlist, "headphone", false);
132 playlist_EnableAudioFilter(p_playlist, "normvol", false);
133 playlist_EnableAudioFilter(p_playlist, "karaoke", false);
136 NSArray *items = [[[defaults objectForKey:@"AudioEffectProfiles"] objectAtIndex:(NSUInteger) selectedProfile] componentsSeparatedByString:@";"];
139 char const *psz_eq_preset = [B64DecNSStr([items firstObject]) UTF8String];
140 audio_output_t *p_aout = getAout();
142 var_SetString(p_aout, "equalizer-preset", psz_eq_preset);
143 var_SetString(p_playlist, "equalizer-preset", psz_eq_preset);
145 /* filter handling */
146 NSString *tempString = B64DecNSStr([items objectAtIndex:1]);
149 /* enable the new filters */
150 if ([tempString length] > 0) {
151 tempArray = [tempString componentsSeparatedByString:@":"];
152 count = [tempArray count];
153 for (NSUInteger x = 0; x < count; x++)
154 playlist_EnableAudioFilter(p_playlist, [[tempArray objectAtIndex:x] UTF8String], true);
157 NSInteger presetIndex = [self getPresetIndexForProfile:selectedProfile];
160 var_SetFloat(p_playlist, "compressor-rms-peak",[[items objectAtIndex:2] floatValue]);
161 var_SetFloat(p_playlist, "compressor-attack",[[items objectAtIndex:3] floatValue]);
162 var_SetFloat(p_playlist, "compressor-release",[[items objectAtIndex:4] floatValue]);
163 var_SetFloat(p_playlist, "compressor-threshold",[[items objectAtIndex:5] floatValue]);
164 var_SetFloat(p_playlist, "compressor-ratio",[[items objectAtIndex:6] floatValue]);
165 var_SetFloat(p_playlist, "compressor-knee",[[items objectAtIndex:7] floatValue]);
166 var_SetFloat(p_playlist, "compressor-makeup-gain",[[items objectAtIndex:8] floatValue]);
167 var_SetFloat(p_playlist, "spatializer-roomsize",[[items objectAtIndex:9] floatValue]);
168 var_SetFloat(p_playlist, "spatializer-width",[[items objectAtIndex:10] floatValue]);
169 var_SetFloat(p_playlist, "spatializer-wet",[[items objectAtIndex:11] floatValue]);
170 var_SetFloat(p_playlist, "spatializer-dry",[[items objectAtIndex:12] floatValue]);
171 var_SetFloat(p_playlist, "spatializer-damp",[[items objectAtIndex:13] floatValue]);
172 var_SetFloat(p_playlist, "norm-max-level",[[items objectAtIndex:14] floatValue]);
173 var_SetBool(p_playlist, "equalizer-2pass",(BOOL)[[items objectAtIndex:15] intValue]);
174 var_SetString(p_playlist, "equalizer-bands", [[[defaults objectForKey:@"EQValues"] objectAtIndex:presetIndex] UTF8String]);
175 var_SetFloat(p_playlist, "equalizer-preamp", [[[defaults objectForKey:@"EQPreampValues"] objectAtIndex:presetIndex] floatValue]);
176 var_SetString(p_playlist, "equalizer-preset", [[[defaults objectForKey:@"EQNames"] objectAtIndex:presetIndex] UTF8String]);
178 /* set values on-the-fly if we have an aout */
180 var_SetFloat(p_aout, "compressor-rms-peak", [[items objectAtIndex:2] floatValue]);
181 var_SetFloat(p_aout, "compressor-attack", [[items objectAtIndex:3] floatValue]);
182 var_SetFloat(p_aout, "compressor-release", [[items objectAtIndex:4] floatValue]);
183 var_SetFloat(p_aout, "compressor-threshold", [[items objectAtIndex:5] floatValue]);
184 var_SetFloat(p_aout, "compressor-ratio", [[items objectAtIndex:6] floatValue]);
185 var_SetFloat(p_aout, "compressor-knee", [[items objectAtIndex:7] floatValue]);
186 var_SetFloat(p_aout, "compressor-makeup-gain", [[items objectAtIndex:8] floatValue]);
187 var_SetFloat(p_aout, "spatializer-roomsize", [[items objectAtIndex:9] floatValue]);
188 var_SetFloat(p_aout, "spatializer-width", [[items objectAtIndex:10] floatValue]);
189 var_SetFloat(p_aout, "spatializer-wet", [[items objectAtIndex:11] floatValue]);
190 var_SetFloat(p_aout, "spatializer-dry", [[items objectAtIndex:12] floatValue]);
191 var_SetFloat(p_aout, "spatializer-damp", [[items objectAtIndex:13] floatValue]);
192 var_SetFloat(p_aout, "norm-max-level", [[items objectAtIndex:14] floatValue]);
193 var_SetBool(p_aout, "equalizer-2pass", (BOOL)[[items objectAtIndex:15] intValue]);
194 var_SetString(p_aout, "equalizer-bands", [[[defaults objectForKey:@"EQValues"] objectAtIndex:presetIndex] UTF8String]);
195 var_SetFloat(p_aout, "equalizer-preamp", [[[defaults objectForKey:@"EQPreampValues"] objectAtIndex:presetIndex] floatValue]);
196 var_SetString(p_aout, "equalizer-preset", [[[defaults objectForKey:@"EQNames"] objectAtIndex:presetIndex] UTF8String]);
200 BOOL b_equalizerEnabled = [tempString rangeOfString:@"equalizer"].location != NSNotFound;
201 [_equalizerView enableSubviews:b_equalizerEnabled];
202 [_equalizerEnableCheckbox setState:(b_equalizerEnabled ? NSOnState : NSOffState)];
204 [_equalizerTwoPassCheckbox setState:[[items objectAtIndex:15] intValue]];
206 /* store current profile selection */
207 [defaults setInteger:selectedProfile forKey:@"AudioEffectSelectedProfile"];
208 [defaults synchronize];
211 vlc_object_release(p_aout);
214 - (void)windowDidLoad
216 [_applyProfileCheckbox setState:[[NSUserDefaults standardUserDefaults] boolForKey:@"AudioEffectApplyProfileOnStartup"]];
218 /* setup the user's language */
220 [_equalizerEnableCheckbox setTitle:_NS("Enable")];
221 [_equalizerTwoPassCheckbox setTitle:_NS("2 Pass")];
222 [_equalizerTwoPassCheckbox setToolTip:_NS("Filter the audio twice. This provides a more " \
224 [_equalizerPreampLabel setStringValue:_NS("Preamp")];
225 [_equalizerPreampLabel setToolTip:_NS("Set the global gain in dB (-20 ... 20).")];
228 [_compressorEnableCheckbox setTitle:_NS("Enable dynamic range compressor")];
229 [_compressorResetButton setTitle:_NS("Reset")];
230 [_compressorBand1Label setStringValue:_NS("RMS/peak")];;
231 [_compressorBand2Label setStringValue:_NS("Attack")];
232 [_compressorBand3Label setStringValue:_NS("Release")];
233 [_compressorBand4Label setStringValue:_NS("Threshold")];
234 [_compressorBand5Label setStringValue:_NS("Ratio")];
235 [_compressorBand6Label setStringValue:_NS("Knee radius")];
236 [_compressorBand7Label setStringValue:_NS("Makeup gain")];
239 [_spatializerEnableCheckbox setTitle:_NS("Enable Spatializer")];
240 [_spatializerResetButton setTitle:_NS("Reset")];
241 [_spatializerBand1Label setStringValue:_NS("Size")];
242 [_spatializerBand1Label setToolTip:_NS("Defines the virtual surface of the room" \
243 " emulated by the filter.")];
244 [_spatializerBand2Label setStringValue:_NS("Width")];
245 [_spatializerBand2Label setToolTip:_NS("Width of the virtual room")];
246 [_spatializerBand3Label setStringValue:_NS("Wet")];
247 [_spatializerBand4Label setStringValue:_NS("Dry")];
248 [_spatializerBand5Label setStringValue:_NS("Damp")];
251 [_filterHeadPhoneCheckbox setTitle:_NS("Headphone virtualization")];
252 [_filterHeadPhoneCheckbox setToolTip:_NS("This effect gives you the feeling that you are standing in a room " \
253 "with a complete 7.1 speaker set when using only a headphone, " \
254 "providing a more realistic sound experience. It should also be " \
255 "more comfortable and less tiring when listening to music for " \
256 "long periods of time.\nIt works with any source format from mono " \
258 [_filterNormLevelCheckbox setTitle:_NS("Volume normalization")];
259 [_filterNormLevelCheckbox setToolTip:_NS("Volume normalizer")];
260 [_filterNormLevelLabel setToolTip:_NS("If the average power over the last N buffers " \
261 "is higher than this value, the volume will be normalized. " \
262 "This value is a positive floating point number. A value " \
263 "between 0.5 and 10 seems sensible.")];
264 [_filterNormLevelLabel setStringValue:_NS("Maximum level")];
265 [_filterKaraokeCheckbox setTitle:_NS("Karaoke")];
266 [_filterKaraokeCheckbox setToolTip:_NS("Simple Karaoke filter")];
267 [_filterScaleTempoCheckbox setTitle:_NS("Scaletempo")];
268 [_filterScaleTempoCheckbox setToolTip:_NS("Audio tempo scaler synched with rate")];
269 [_filterStereoEnhancerCheckbox setTitle:_NS("Stereo Enhancer")];
270 [_filterStereoEnhancerCheckbox setToolTip:_NS("This filter enhances the stereo effect by "\
271 "suppressing mono (signal common to both channels) "\
272 "and by delaying the signal of left into right and vice versa, "\
273 "thereby widening the stereo effect.")];
276 [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"equalizer"]] setLabel:_NS("Equalizer")];
277 [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"compressor"]] setLabel:_NS("Compressor")];
278 [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"spatializer"]] setLabel:_NS("Spatializer")];
279 [[_tabView tabViewItemAtIndex:[_tabView indexOfTabViewItemWithIdentifier:@"filter"]] setLabel:_NS("Filter")];
280 [self.window setTitle:_NS("Audio Effects")];
281 [self.window setExcludedFromWindowsMenu:YES];
282 [self.window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenAuxiliary];
284 [self equalizerUpdated];
285 [self resetCompressor];
286 [self resetSpatializer];
287 [self resetAudioFilters];
288 [self resetProfileSelector];
292 #pragma mark internal functions
294 - (void)setAudioFilter: (char *)psz_name on:(BOOL)b_on
296 playlist_EnableAudioFilter(pl_Get(getIntf()), psz_name, b_on);
299 - (void)resetProfileSelector
301 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
302 [_profilePopup removeAllItems];
304 NSArray *profileNames = [defaults objectForKey:@"AudioEffectProfileNames"];
305 [_profilePopup addItemsWithTitles:profileNames];
307 [[_profilePopup menu] addItem:[NSMenuItem separatorItem]];
308 [_profilePopup addItemWithTitle:_NS("Duplicate current profile...")];
309 [[_profilePopup lastItem] setTarget: self];
310 [[_profilePopup lastItem] setAction: @selector(addAudioEffectsProfile:)];
312 if ([profileNames count] > 1) {
313 [_profilePopup addItemWithTitle:_NS("Organize Profiles...")];
314 [[_profilePopup lastItem] setTarget: self];
315 [[_profilePopup lastItem] setAction: @selector(removeAudioEffectsProfile:)];
318 [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
319 if (i_old_profile_index || [[NSUserDefaults standardUserDefaults] integerForKey:@"AudioEffectSelectedProfile"])
320 [self profileSelectorAction:self];
324 #pragma mark generic code
325 - (void)updateCocoaWindowLevel:(NSInteger)i_level
327 if (self.isWindowLoaded && [self.window isVisible] && [self.window level] != i_level)
328 [self.window setLevel: i_level];
331 - (IBAction)toggleWindow:(id)sender
333 if ([self.window isKeyWindow])
334 [self.window orderOut:sender];
336 [self.window setLevel: [[[VLCMain sharedInstance] voutController] currentStatusWindowLevel]];
337 [self.window makeKeyAndOrderFront:sender];
341 - (NSString *)generateProfileString
343 playlist_t *p_playlist = pl_Get(getIntf());
344 return [NSString stringWithFormat:@"%@;%@;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%i",
345 B64EncAndFree(var_GetNonEmptyString(p_playlist, "equalizer-preset")),
346 B64EncAndFree(var_InheritString(p_playlist, "audio-filter")),
347 var_InheritFloat(p_playlist, "compressor-rms-peak"),
348 var_InheritFloat(p_playlist, "compressor-attack"),
349 var_InheritFloat(p_playlist, "compressor-release"),
350 var_InheritFloat(p_playlist, "compressor-threshold"),
351 var_InheritFloat(p_playlist, "compressor-ratio"),
352 var_InheritFloat(p_playlist, "compressor-knee"),
353 var_InheritFloat(p_playlist, "compressor-makeup-gain"),
354 var_InheritFloat(p_playlist, "spatializer-roomsize"),
355 var_InheritFloat(p_playlist, "spatializer-width"),
356 var_InheritFloat(p_playlist, "spatializer-wet"),
357 var_InheritFloat(p_playlist, "spatializer-dry"),
358 var_InheritFloat(p_playlist, "spatializer-damp"),
359 var_InheritFloat(p_playlist, "norm-max-level"),
360 var_InheritBool(p_playlist,"equalizer-2pass")];
363 - (void)saveCurrentProfile
365 if (!i_old_profile_index || i_old_profile_index == -1)
368 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
369 /* fetch all the current settings in a uniform string */
370 NSString *newProfile = [self generateProfileString];
372 NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]];
373 if (i_old_profile_index >= [workArray count])
376 [workArray replaceObjectAtIndex:i_old_profile_index withObject:newProfile];
377 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"];
378 [defaults synchronize];
381 - (void)saveCurrentProfileAtTerminate
383 if (i_old_profile_index)
384 return [self saveCurrentProfile];
386 playlist_t *p_playlist = pl_Get(getIntf());
387 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
388 NSString *newPresetString = [NSString stringWithCString:var_InheritString(p_playlist, "equalizer-bands") encoding:NSASCIIStringEncoding];
389 float newPresetPreamp = var_InheritFloat(p_playlist, "equalizer-preamp");
391 NSInteger defaultPresetIndex = [self getPresetIndexForProfile:0];
392 NSString *defaultPresetString = [[defaults objectForKey:@"EQValues"] objectAtIndex:defaultPresetIndex];
393 float defaultPresetPreamp = [[[defaults objectForKey:@"EQPreampValues"] objectAtIndex:defaultPresetIndex] floatValue];
394 if ([[self generateProfileString] compare:[[defaults objectForKey:@"AudioEffectProfiles"] firstObject]] == NSOrderedSame &&
395 [newPresetString compare:defaultPresetString] == NSOrderedSame &&
396 newPresetPreamp == defaultPresetPreamp)
399 NSMutableArray *workArray;
402 if ([newPresetString compare:defaultPresetString] != NSOrderedSame ||
403 newPresetPreamp != defaultPresetPreamp)
406 NSArray<NSString *> *presetTitles = [defaults objectForKey:@"EQTitles"];
407 NSString *newPresetTitle;
411 newPresetTitle = [@"Custom" stringByAppendingString:[NSString stringWithFormat:@"%03i",num_custom++]];
412 while ([presetTitles containsObject:newPresetTitle]);
414 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]];
415 [workArray addObject:newPresetTitle];
416 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"];
419 NSString *decomposedStringWithCanonicalMapping = [newPresetTitle decomposedStringWithCanonicalMapping];
420 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]];
421 [workArray addObject:decomposedStringWithCanonicalMapping];
422 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"];
423 var_SetString(p_playlist, "equalizer-preset", [decomposedStringWithCanonicalMapping UTF8String]);
426 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]];
427 [workArray addObject:newPresetString];
428 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"];
431 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]];
432 [workArray addObject:[NSString stringWithFormat:@"%.1f", [_equalizerPreampSlider floatValue]]];
433 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"];
437 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]];
438 [workArray addObject:[self generateProfileString]];
439 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"];
442 NSArray<NSString *> *profileNames = [defaults objectForKey:@"AudioEffectProfileNames"];
443 NSString *newProfileName;
447 newProfileName = [@"Custom" stringByAppendingString:[NSString stringWithFormat:@"%03i",num_custom++]];
448 while ([profileNames containsObject:newProfileName]);
450 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfileNames"]];
451 [workArray addObject:newProfileName];
452 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfileNames"];
454 [defaults synchronize];
457 - (IBAction)profileSelectorAction:(id)sender
459 [self saveCurrentProfile];
460 i_old_profile_index = [_profilePopup indexOfSelectedItem];
461 [[NSUserDefaults standardUserDefaults] setInteger:i_old_profile_index forKey:@"AudioEffectSelectedProfile"];
465 [self resetCompressor];
466 [self resetSpatializer];
467 [self resetAudioFilters];
468 [self updatePresetSelector];
471 - (void)addAudioEffectsProfile:(id)sender
474 [_textfieldPanel setTitleString:_NS("Duplicate current profile for a new profile")];
475 [_textfieldPanel setSubTitleString:_NS("Enter a name for the new profile:")];
476 [_textfieldPanel setCancelButtonString:_NS("Cancel")];
477 [_textfieldPanel setOkButtonString:_NS("Save")];
479 __weak typeof(self) _self = self;
480 [_textfieldPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSString *resultingText) {
482 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
483 if (returnCode != NSOKButton) {
484 [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
488 NSArray *profileNames = [defaults objectForKey:@"AudioEffectProfileNames"];
490 // duplicate names are not allowed in the popup control
491 if ([resultingText length] == 0 || [profileNames containsObject:resultingText]) {
492 [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
494 NSAlert *alert = [[NSAlert alloc] init];
495 [alert setAlertStyle:NSCriticalAlertStyle];
496 [alert setMessageText:_NS("Please enter a unique name for the new profile.")];
497 [alert setInformativeText:_NS("Multiple profiles with the same name are not allowed.")];
499 [alert beginSheetModalForWindow:_self.window
506 NSString *newProfile = [_self generateProfileString];
508 /* add string to user defaults as well as a label */
509 NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]];
510 [workArray addObject:newProfile];
511 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"];
512 [defaults setInteger:[workArray count] - 1 forKey:@"AudioEffectSelectedProfile"];
513 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfileNames"]];
514 [workArray addObject:resultingText];
515 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfileNames"];
518 [defaults synchronize];
519 [_self resetProfileSelector];
524 - (void)removeAudioEffectsProfile:(id)sender
527 [_popupPanel setTitleString:_NS("Remove a preset")];
528 [_popupPanel setSubTitleString:_NS("Select the preset you would like to remove:")];
529 [_popupPanel setOkButtonString:_NS("Remove")];
530 [_popupPanel setCancelButtonString:_NS("Cancel")];
531 [_popupPanel setPopupButtonContent:[[NSUserDefaults standardUserDefaults] objectForKey:@"AudioEffectProfileNames"]];
533 __weak typeof(self) _self = self;
534 [_popupPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSInteger selectedIndex) {
536 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
537 if (returnCode != NSOKButton) {
538 [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
542 if (!selectedIndex) { // TODO: add popup to notify user
543 [_profilePopup selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
547 /* remove selected profile from settings */
548 NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]];
549 [workArray removeObjectAtIndex:selectedIndex];
550 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"];
551 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfileNames"]];
552 [workArray removeObjectAtIndex:selectedIndex];
553 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfileNames"];
555 if (i_old_profile_index >= selectedIndex)
556 [defaults setInteger:i_old_profile_index - 1 forKey:@"AudioEffectSelectedProfile"];
559 [defaults synchronize];
560 [_self resetProfileSelector];
564 - (IBAction)applyProfileCheckboxChanged:(id)sender
566 [[NSUserDefaults standardUserDefaults] setBool:[sender state] forKey:@"AudioEffectApplyProfileOnStartup"];
570 #pragma mark Equalizer
571 static bool GetEqualizerStatus(intf_thread_t *p_custom_intf,
574 char *psz_parser, *psz_string = NULL;
575 audio_output_t *p_aout = getAout();
579 psz_string = var_InheritString(pl_Get(p_custom_intf), "audio-filter");
582 psz_string = var_GetNonEmptyString(p_aout, "audio-filter");
584 vlc_object_release(p_aout);
589 psz_parser = strstr(psz_string, psz_name);
599 - (void)updatePresetSelector
601 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
602 NSArray *presets = [defaults objectForKey:@"EQNames"];
604 [_equalizerPresetsPopup removeAllItems];
605 [_equalizerPresetsPopup addItemsWithTitles:[[NSUserDefaults standardUserDefaults] objectForKey:@"EQTitles"]];
606 [[_equalizerPresetsPopup menu] addItem:[NSMenuItem separatorItem]];
607 [_equalizerPresetsPopup addItemWithTitle:_NS("Add new Preset...")];
608 [[_equalizerPresetsPopup lastItem] setTarget: self];
609 [[_equalizerPresetsPopup lastItem] setAction: @selector(addPresetAction:)];
611 if ([presets count] > 1) {
612 [_equalizerPresetsPopup addItemWithTitle:_NS("Organize Presets...")];
613 [[_equalizerPresetsPopup lastItem] setTarget: self];
614 [[_equalizerPresetsPopup lastItem] setAction: @selector(deletePresetAction:)];
617 audio_output_t *p_aout = getAout();
619 NSString *currentPreset = nil;
621 char *psz_preset_string = var_GetNonEmptyString(p_aout, "equalizer-preset");
622 currentPreset = toNSStr(psz_preset_string);
623 free(psz_preset_string);
624 vlc_object_release(p_aout);
627 NSUInteger currentPresetIndex = 0;
628 if (currentPreset && [currentPreset length] > 0) {
629 currentPresetIndex = [presets indexOfObject:currentPreset];
631 if (currentPresetIndex == NSNotFound)
632 currentPresetIndex = [presets count] - 1;
635 [_equalizerPresetsPopup selectItemAtIndex:currentPresetIndex];
636 [self equalizerChangePreset:_equalizerPresetsPopup];
638 [_equalizerPreampSlider setFloatValue:[[[defaults objectForKey:@"EQPreampValues"] objectAtIndex:currentPresetIndex] floatValue]];
639 [self setBandSliderValuesForPreset:currentPresetIndex];
642 - (void)equalizerUpdated
644 intf_thread_t *p_intf = getIntf();
645 playlist_t *p_playlist = pl_Get(p_intf);
646 bool b_2p = var_CreateGetBool(p_playlist, "equalizer-2pass");
647 bool bEnabled = GetEqualizerStatus(p_intf, (char *)"equalizer");
650 var_Create(p_playlist, "equalizer-preset",
651 VLC_VAR_STRING | VLC_VAR_DOINHERIT);
652 var_Create(p_playlist, "equalizer-bands",
653 VLC_VAR_STRING | VLC_VAR_DOINHERIT);
654 var_Create(p_playlist, "equalizer-preamp",
655 VLC_VAR_FLOAT | VLC_VAR_DOINHERIT);
656 [self updatePresetSelector];
658 /* Set the the checkboxes */
659 [_equalizerView enableSubviews: bEnabled];
660 [_equalizerEnableCheckbox setState: bEnabled];
661 [_equalizerTwoPassCheckbox setState: b_2p];
664 - (id)sliderByIndex:(int)index
667 case 0 : return _equalizerBand1Slider;
668 case 1 : return _equalizerBand2Slider;
669 case 2 : return _equalizerBand3Slider;
670 case 3 : return _equalizerBand4Slider;
671 case 4 : return _equalizerBand5Slider;
672 case 5 : return _equalizerBand6Slider;
673 case 6 : return _equalizerBand7Slider;
674 case 7 : return _equalizerBand8Slider;
675 case 8 : return _equalizerBand9Slider;
676 case 9 : return _equalizerBand10Slider;
677 default : return nil;
681 - (void)setBandSliderValuesForPreset:(NSInteger)presetID
683 NSString *preset = [[[NSUserDefaults standardUserDefaults] objectForKey:@"EQValues"] objectAtIndex:presetID];
684 NSArray *values = [preset componentsSeparatedByString:@" "];
685 NSUInteger count = [values count];
686 for (NSUInteger x = 0; x < count; x++)
687 [self setValue:[[values objectAtIndex:x] floatValue] forSlider:x];
690 - (NSString *)generatePresetString
692 return [NSString stringWithFormat:@"%.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f",
693 [_equalizerBand1Slider floatValue],
694 [_equalizerBand2Slider floatValue],
695 [_equalizerBand3Slider floatValue],
696 [_equalizerBand4Slider floatValue],
697 [_equalizerBand5Slider floatValue],
698 [_equalizerBand6Slider floatValue],
699 [_equalizerBand7Slider floatValue],
700 [_equalizerBand8Slider floatValue],
701 [_equalizerBand9Slider floatValue],
702 [_equalizerBand10Slider floatValue]];
705 - (void)setValue:(float)value forSlider:(int)index
707 id slider = [self sliderByIndex:index];
710 [slider setFloatValue:value];
713 - (IBAction)equalizerEnable:(id)sender
715 [_equalizerView enableSubviews:[sender state]];
716 [self setAudioFilter: "equalizer" on:[sender state]];
719 - (IBAction)equalizerBandSliderUpdated:(id)sender
721 audio_output_t *p_aout = getAout();
722 char const *psz_preset_values = [[self generatePresetString] UTF8String];
724 var_SetString(p_aout, "equalizer-bands", psz_preset_values);
725 vlc_object_release(p_aout);
727 var_SetString(pl_Get(getIntf()), "equalizer-bands", psz_preset_values);
730 - (IBAction)equalizerChangePreset:(id)sender
732 NSInteger numberOfChosenPreset = [sender indexOfSelectedItem];
733 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
735 char const *psz_eq_bands = [[[defaults objectForKey:@"EQValues"] objectAtIndex:numberOfChosenPreset] UTF8String];
736 float f_eq_preamp = [[[defaults objectForKey:@"EQPreampValues"] objectAtIndex:numberOfChosenPreset] floatValue];
737 char const *psz_eq_preset = [[[defaults objectForKey:@"EQNames"] objectAtIndex:numberOfChosenPreset] UTF8String];
739 audio_output_t *p_aout = getAout();
741 var_SetString(p_aout, "equalizer-bands", psz_eq_bands);
742 var_SetFloat(p_aout, "equalizer-preamp", f_eq_preamp);
743 var_SetString(p_aout, "equalizer-preset" , psz_eq_preset);
744 vlc_object_release(p_aout);
747 [_equalizerPreampSlider setFloatValue: f_eq_preamp];
748 [self setBandSliderValuesForPreset:numberOfChosenPreset];
750 var_SetString(pl_Get(getIntf()), "equalizer-bands", psz_eq_bands);
751 var_SetFloat(pl_Get(getIntf()), "equalizer-preamp", f_eq_preamp);
752 var_SetString(pl_Get(getIntf()), "equalizer-preset", psz_eq_preset);
755 - (IBAction)equalizerPreAmpSliderUpdated:(id)sender
757 float fPreamp = [sender floatValue] ;
759 audio_output_t *p_aout = getAout();
761 var_SetFloat(p_aout, "equalizer-preamp", fPreamp);
762 vlc_object_release(p_aout);
764 var_SetFloat(pl_Get(getIntf()), "equalizer-preamp", fPreamp);
767 - (IBAction)equalizerTwoPass:(id)sender
769 bool b_2p = [sender state] ? true : false;
771 audio_output_t *p_aout = getAout();
773 var_SetBool(p_aout, "equalizer-2pass", b_2p);
774 vlc_object_release(p_aout);
777 var_SetBool(pl_Get(getIntf()), "equalizer-2pass", b_2p);
780 - (IBAction)addPresetAction:(id)sender
783 [_textfieldPanel setTitleString:_NS("Save current selection as new preset")];
784 [_textfieldPanel setSubTitleString:_NS("Enter a name for the new preset:")];
785 [_textfieldPanel setCancelButtonString:_NS("Cancel")];
786 [_textfieldPanel setOkButtonString:_NS("Save")];
788 __weak typeof(self) _self = self;
789 [_textfieldPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSString *resultingText) {
790 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
793 if (returnCode != NSOKButton || [resultingText length] == 0)
796 NSString *decomposedStringWithCanonicalMapping = [resultingText decomposedStringWithCanonicalMapping];
797 NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]];
798 [workArray addObject:[self generatePresetString]];
799 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"];
800 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]];
801 [workArray addObject:resultingText];
802 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"];
803 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]];
804 [workArray addObject:[NSString stringWithFormat:@"%.1f", [_equalizerPreampSlider floatValue]]];
805 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"];
806 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]];
807 [workArray addObject:decomposedStringWithCanonicalMapping];
808 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"];
809 [defaults synchronize];
811 /* update VLC internals */
812 char const *psz_eq_preset = [decomposedStringWithCanonicalMapping UTF8String];
813 audio_output_t *p_aout = getAout();
815 var_SetString(p_aout, "equalizer-preset", psz_eq_preset);
816 vlc_object_release(p_aout);
819 var_SetString(pl_Get(getIntf()), "equalizer-preset", psz_eq_preset);
822 [_self updatePresetSelector];
826 - (IBAction)deletePresetAction:(id)sender
828 [_popupPanel setTitleString:_NS("Remove a preset")];
829 [_popupPanel setSubTitleString:_NS("Select the preset you would like to remove:")];
830 [_popupPanel setOkButtonString:_NS("Remove")];
831 [_popupPanel setCancelButtonString:_NS("Cancel")];
832 [_popupPanel setPopupButtonContent:[[NSUserDefaults standardUserDefaults] objectForKey:@"EQTitles"]];
834 __weak typeof(self) _self = self;
835 [_popupPanel runModalForWindow:self.window completionHandler:^(NSInteger returnCode, NSInteger selectedIndex) {
837 if (returnCode != NSOKButton)
840 /* remove requested profile from the arrays */
841 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
842 NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]];
843 [workArray removeObjectAtIndex:selectedIndex];
844 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"];
845 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]];
846 [workArray removeObjectAtIndex:selectedIndex];
847 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"];
848 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]];
849 [workArray removeObjectAtIndex:selectedIndex];
850 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"];
851 workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]];
852 [workArray removeObjectAtIndex:selectedIndex];
853 [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"];
854 [defaults synchronize];
857 [_self updatePresetSelector];
862 #pragma mark Compressor
863 - (void)resetCompressor
865 intf_thread_t *p_intf = getIntf();
866 playlist_t *p_playlist = pl_Get(p_intf);
867 BOOL bEnable_compressor = NO;
869 psz_afilters = var_InheritString(p_playlist, "audio-filter");
871 bEnable_compressor = strstr(psz_afilters, "compressor") != NULL;
872 [_compressorEnableCheckbox setState: (NSInteger)strstr(psz_afilters, "compressor") ];
876 [_compressorView enableSubviews:bEnable_compressor];
877 [_compressorEnableCheckbox setState:(bEnable_compressor ? NSOnState : NSOffState)];
879 [_compressorBand1Slider setFloatValue: var_CreateGetFloat(p_playlist, "compressor-rms-peak")];
880 [_compressorBand1TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", [_compressorBand1Slider floatValue]]];
881 [_compressorBand2Slider setFloatValue: var_CreateGetFloat(p_playlist, "compressor-attack")];
882 [_compressorBand2TextField setStringValue:[NSString localizedStringWithFormat:@"%2.1f ms", [_compressorBand2Slider floatValue]]];
883 [_compressorBand3Slider setFloatValue: var_CreateGetFloat(p_playlist, "compressor-release")];
884 [_compressorBand3TextField setStringValue:[NSString localizedStringWithFormat:@"%3.1f ms", [_compressorBand3Slider floatValue]]];
885 [_compressorBand4Slider setFloatValue: var_CreateGetFloat(p_playlist, "compressor-threshold")];
886 [_compressorBand4TextField setStringValue:[NSString localizedStringWithFormat:@"%2.1f dB", [_compressorBand4Slider floatValue]]];
887 [_compressorBand5Slider setFloatValue: var_CreateGetFloat(p_playlist, "compressor-ratio")];
888 [_compressorBand5TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f:1", [_compressorBand5Slider floatValue]]];
889 [_compressorBand6Slider setFloatValue: var_CreateGetFloat(p_playlist, "compressor-knee")];
890 [_compressorBand6TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f dB", [_compressorBand6Slider floatValue]]];
891 [_compressorBand7Slider setFloatValue: var_CreateGetFloat(p_playlist, "compressor-makeup-gain")];
892 [_compressorBand7TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f dB", [_compressorBand7Slider floatValue]]];
895 - (IBAction)resetCompressorValues:(id)sender
897 playlist_t *p_playlist = pl_Get(getIntf());
898 var_SetFloat(p_playlist, "compressor-rms-peak", 0.000000);
899 var_SetFloat(p_playlist, "compressor-attack", 25.000000);
900 var_SetFloat(p_playlist, "compressor-release", 100.000000);
901 var_SetFloat(p_playlist, "compressor-threshold", -11.000000);
902 var_SetFloat(p_playlist, "compressor-ratio", 8.000000);
903 var_SetFloat(p_playlist, "compressor-knee", 2.500000);
904 var_SetFloat(p_playlist, "compressor-makeup-gain", 7.000000);
906 audio_output_t *p_aout = getAout();
908 var_SetFloat(p_aout, "compressor-rms-peak", 0.000000);
909 var_SetFloat(p_aout, "compressor-attack", 25.000000);
910 var_SetFloat(p_aout, "compressor-release", 100.000000);
911 var_SetFloat(p_aout, "compressor-threshold", -11.000000);
912 var_SetFloat(p_aout, "compressor-ratio", 8.000000);
913 var_SetFloat(p_aout, "compressor-knee", 2.500000);
914 var_SetFloat(p_aout, "compressor-makeup-gain", 7.000000);
915 vlc_object_release(p_aout);
917 [self resetCompressor];
920 - (IBAction)compressorEnable:(id)sender
922 [_compressorView enableSubviews:[sender state]];
923 [self setAudioFilter:"compressor" on:[sender state]];
926 - (IBAction)compressorSliderUpdated:(id)sender
928 audio_output_t *p_aout = getAout();
930 float f_value = [sender floatValue];
932 if (sender == _compressorBand1Slider)
933 psz_property = "compressor-rms-peak";
934 else if (sender == _compressorBand2Slider)
935 psz_property = "compressor-attack";
936 else if (sender == _compressorBand3Slider)
937 psz_property = "compressor-release";
938 else if (sender == _compressorBand4Slider)
939 psz_property = "compressor-threshold";
940 else if (sender == _compressorBand5Slider)
941 psz_property = "compressor-ratio";
942 else if (sender == _compressorBand6Slider)
943 psz_property = "compressor-knee";
944 else if (sender == _compressorBand7Slider)
945 psz_property = "compressor-makeup-gain";
948 var_SetFloat(p_aout, psz_property, f_value);
949 vlc_object_release(p_aout);
951 var_SetFloat(pl_Get(getIntf()), psz_property, f_value);
953 if (sender == _compressorBand1Slider)
954 [_compressorBand1TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", f_value]];
955 else if (sender == _compressorBand2Slider)
956 [_compressorBand2TextField setStringValue:[NSString localizedStringWithFormat:@"%2.1f ms", f_value]];
957 else if (sender == _compressorBand3Slider)
958 [_compressorBand3TextField setStringValue:[NSString localizedStringWithFormat:@"%3.1f ms", f_value]];
959 else if (sender == _compressorBand4Slider)
960 [_compressorBand4TextField setStringValue:[NSString localizedStringWithFormat:@"%2.1f dB", f_value]];
961 else if (sender == _compressorBand5Slider)
962 [_compressorBand5TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f:1", f_value]];
963 else if (sender == _compressorBand6Slider)
964 [_compressorBand6TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f dB", f_value]];
965 else if (sender == _compressorBand7Slider)
966 [_compressorBand7TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f dB", f_value]];
970 #pragma mark Spatializer
971 - (void)resetSpatializer
973 playlist_t *p_playlist = pl_Get(getIntf());
974 BOOL bEnable_spatializer = NO;
976 psz_afilters = var_InheritString(p_playlist, "audio-filter");
978 bEnable_spatializer = strstr(psz_afilters, "spatializer") != NULL;
982 [_spatializerView enableSubviews:bEnable_spatializer];
983 [_spatializerEnableCheckbox setState:(bEnable_spatializer ? NSOnState : NSOffState)];
986 #define setSlider(bandsld, bandfld, var) \
987 [bandsld setFloatValue: var_CreateGetFloat(p_playlist, var) * 10.]; \
988 [bandfld setStringValue:[NSString localizedStringWithFormat:@"%1.1f", [bandsld floatValue]]]
990 setSlider(_spatializerBand1Slider, _spatializerBand1TextField, "spatializer-roomsize");
991 setSlider(_spatializerBand2Slider, _spatializerBand2TextField, "spatializer-width");
992 setSlider(_spatializerBand3Slider, _spatializerBand3TextField, "spatializer-wet");
993 setSlider(_spatializerBand4Slider, _spatializerBand4TextField, "spatializer-dry");
994 setSlider(_spatializerBand5Slider, _spatializerBand5TextField, "spatializer-damp");
999 - (IBAction)resetSpatializerValues:(id)sender
1001 playlist_t *p_playlist = pl_Get(getIntf());
1002 var_SetFloat(p_playlist, "spatializer-roomsize", .85);
1003 var_SetFloat(p_playlist, "spatializer-width", 1.);
1004 var_SetFloat(p_playlist, "spatializer-wet", .4);
1005 var_SetFloat(p_playlist, "spatializer-dry", .5);
1006 var_SetFloat(p_playlist, "spatializer-damp", .5);
1008 audio_output_t *p_aout = getAout();
1010 var_SetFloat(p_aout, "spatializer-roomsize", .85);
1011 var_SetFloat(p_aout, "spatializer-width", 1.);
1012 var_SetFloat(p_aout, "spatializer-wet", .4);
1013 var_SetFloat(p_aout, "spatializer-dry", .5);
1014 var_SetFloat(p_aout, "spatializer-damp", .5);
1015 vlc_object_release(p_aout);
1017 [self resetSpatializer];
1020 - (IBAction)spatializerEnable:(id)sender
1022 [_spatializerView enableSubviews:[sender state]];
1023 [self setAudioFilter:"spatializer" on:[sender state]];
1026 - (IBAction)spatializerSliderUpdated:(id)sender
1028 audio_output_t *p_aout = getAout();
1029 char *psz_property = NULL;
1030 float f_value = [sender floatValue];
1032 if (sender == _spatializerBand1Slider)
1033 psz_property = "spatializer-roomsize";
1034 else if (sender == _spatializerBand2Slider)
1035 psz_property = "spatializer-width";
1036 else if (sender == _spatializerBand3Slider)
1037 psz_property = "spatializer-wet";
1038 else if (sender == _spatializerBand4Slider)
1039 psz_property = "spatializer-dry";
1040 else if (sender == _spatializerBand5Slider)
1041 psz_property = "spatializer-damp";
1044 var_SetFloat(p_aout, psz_property, f_value / 10.f);
1045 vlc_object_release(p_aout);
1047 var_SetFloat(pl_Get(getIntf()), psz_property, f_value / 10.f);
1049 if (sender == _spatializerBand1Slider)
1050 [_spatializerBand1TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", f_value]];
1051 else if (sender == _spatializerBand2Slider)
1052 [_spatializerBand2TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", f_value]];
1053 else if (sender == _spatializerBand3Slider)
1054 [_spatializerBand3TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", f_value]];
1055 else if (sender == _spatializerBand4Slider)
1056 [_spatializerBand4TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", f_value]];
1057 else if (sender == _spatializerBand5Slider)
1058 [_spatializerBand5TextField setStringValue:[NSString localizedStringWithFormat:@"%1.1f", f_value]];
1063 - (void)resetAudioFilters
1065 playlist_t *p_playlist = pl_Get(getIntf());
1066 BOOL bEnable_normvol = NO;
1068 psz_afilters = var_InheritString(p_playlist, "audio-filter");
1070 [_filterHeadPhoneCheckbox setState: (NSInteger)strstr(psz_afilters, "headphone") ];
1071 [_filterKaraokeCheckbox setState: (NSInteger)strstr(psz_afilters, "karaoke") ];
1072 [_filterScaleTempoCheckbox setState: (NSInteger)strstr(psz_afilters, "scaletempo") ];
1073 [_filterStereoEnhancerCheckbox setState: (NSInteger)strstr(psz_afilters, "stereo_widen") ];
1074 bEnable_normvol = strstr(psz_afilters, "normvol") != NULL;
1077 [_filterHeadPhoneCheckbox setState: NSOffState];
1078 [_filterKaraokeCheckbox setState: NSOffState];
1079 [_filterScaleTempoCheckbox setState: NSOffState];
1080 [_filterStereoEnhancerCheckbox setState: NSOffState];
1083 [_filterNormLevelSlider setEnabled:bEnable_normvol];
1084 [_filterNormLevelLabel setEnabled:bEnable_normvol];
1085 [_filterNormLevelCheckbox setState:(bEnable_normvol ? NSOnState : NSOffState)];
1087 [_filterNormLevelSlider setFloatValue: var_CreateGetFloat(p_playlist, "norm-max-level")];
1090 - (IBAction)filterEnableHeadPhoneVirt:(id)sender
1092 [self setAudioFilter:"headphone" on:[sender state]];
1095 - (IBAction)filterEnableVolumeNorm:(id)sender
1097 [_filterNormLevelSlider setEnabled:[sender state]];
1098 [_filterNormLevelLabel setEnabled:[sender state]];
1099 [self setAudioFilter:"normvol" on:[sender state]];
1102 - (IBAction)filterVolumeNormSliderUpdated:(id)sender
1104 audio_output_t *p_aout = getAout();
1105 float f_value = [_filterNormLevelSlider floatValue];
1108 var_SetFloat(p_aout, "norm-max-level", f_value);
1109 vlc_object_release(p_aout);
1112 var_SetFloat(pl_Get(getIntf()), "norm-max-level", f_value);
1115 - (IBAction)filterEnableKaraoke:(id)sender
1117 [self setAudioFilter:"karaoke" on:[sender state]];
1120 - (IBAction)filterEnableScaleTempo:(id)sender
1122 [self setAudioFilter:"scaletempo" on:[sender state]];
1125 - (IBAction)filterEnableStereoEnhancer:(id)sender
1127 [self setAudioFilter:"stereo_widen" on:[sender state]];