]> git.sesse.net Git - vlc/commitdiff
macosx: added a profile management system to the audio effects (close #7342)
authorFelix Paul Kühne <fkuehne@videolan.org>
Fri, 14 Sep 2012 14:41:13 +0000 (16:41 +0200)
committerFelix Paul Kühne <fkuehne@videolan.org>
Fri, 14 Sep 2012 14:46:48 +0000 (16:46 +0200)
This way, you can keep multiple sets of filters with their respective values.

This implementation goes beyond custom EQ presets, which can be configured separately.

NEWS
extras/package/macosx/Resources/English.lproj/AudioEffects.xib
modules/gui/macosx/AudioEffects.h
modules/gui/macosx/AudioEffects.m

diff --git a/NEWS b/NEWS
index 65c104b1948bbeb009c90ba8d9ea9efe448a967a..59795fbeb71cf4af0642505190fd4abfe0816092 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -86,16 +86,18 @@ Mac OS X Interface:
    VLC's internal volume level
  * add the ability to create custom equalizer presets based upon the current
    selection and to manage the list of presets
+ * add custom profiles for video and audio effects, which let the user keep
+   multiple configuration sets of all the individual filters
  * add an option to disable skipping to next/previous file with the Apple Remote
  * add an option to show next / previous buttons
  * add an option to hide the shuffle and repeat buttons
  * add optional playlist columns for track number, genre, album, description,
-   date and language.
+   date and language
  * add options to the Advanced Open File dialog for start and stop time
  * add an option to play videos as a desktop background
  * add a new panel for media conversation and streaming
- * allow the OS to turn off the screen(s) when playing audio-only media while the user
-   is idle.
+ * allow the OS to turn off the screen(s) when playing audio-only media while
+   the user is idle
  * The Streaming/Transcoding wizard and the open dialog's output panel are
    deprecated now
 
index a635513ea2b62b5e09e0098b100ea587ec710560..07df62a687c905e1d476b012e57e6c41e9ec7d09 100644 (file)
@@ -2,10 +2,10 @@
 <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
   <data>
     <int key="IBDocument.SystemTarget">1050</int>
-    <string key="IBDocument.SystemVersion">11C74</string>
+    <string key="IBDocument.SystemVersion">11G45</string>
     <string key="IBDocument.InterfaceBuilderVersion">851</string>
-    <string key="IBDocument.AppKitVersion">1138.23</string>
-    <string key="IBDocument.HIToolboxVersion">567.00</string>
+    <string key="IBDocument.AppKitVersion">1138.51</string>
+    <string key="IBDocument.HIToolboxVersion">569.00</string>
     <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
       <bool key="EncodedWithXMLCoder">YES</bool>
       <object class="NSArray" key="dict.sortedKeys">
@@ -21,7 +21,7 @@
     </object>
     <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
       <bool key="EncodedWithXMLCoder">YES</bool>
-      <integer value="1"/>
+      <integer value="2"/>
     </object>
     <object class="NSArray" key="IBDocument.PluginDependencies">
       <bool key="EncodedWithXMLCoder">YES</bool>
@@ -46,7 +46,7 @@
       <object class="NSWindowTemplate" id="1005">
         <int key="NSWindowStyleMask">8211</int>
         <int key="NSWindowBacking">2</int>
-        <string key="NSWindowRect">{{196, 289}, {409, 220}}</string>
+        <string key="NSWindowRect">{{196, 254}, {409, 255}}</string>
         <int key="NSWTFlags">-260571136</int>
         <string key="NSWindowTitle">Audio Effects</string>
         <string key="NSWindowClass">NSPanel</string>
@@ -61,7 +61,7 @@
             <object class="BGHUDTabView" id="876119583">
               <reference key="NSNextResponder" ref="1006"/>
               <int key="NSvFlags">18</int>
-              <string key="NSFrame">{{-7, -10}, {424, 223}}</string>
+              <string key="NSFrame">{{-7, 25}, {424, 223}}</string>
               <reference key="NSSuperview" ref="1006"/>
               <object class="NSMutableArray" key="NSTabViewItems">
                 <bool key="EncodedWithXMLCoder">YES</bool>
@@ -1816,8 +1816,74 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
                 <reference ref="195046814"/>
               </object>
             </object>
+            <object class="NSPopUpButton" id="158673502">
+              <reference key="NSNextResponder" ref="1006"/>
+              <int key="NSvFlags">268</int>
+              <string key="NSFrame">{{110, 6}, {190, 22}}</string>
+              <reference key="NSSuperview" ref="1006"/>
+              <bool key="NSEnabled">YES</bool>
+              <object class="BGHUDPopUpButtonCell" key="NSCell" id="847287566">
+                <int key="NSCellFlags">-2076049856</int>
+                <int key="NSCellFlags2">133120</int>
+                <reference key="NSSupport" ref="26"/>
+                <reference key="NSControlView" ref="158673502"/>
+                <int key="NSButtonFlags">109199360</int>
+                <int key="NSButtonFlags2">1</int>
+                <string key="NSAlternateContents"/>
+                <string key="NSKeyEquivalent"/>
+                <int key="NSPeriodicDelay">400</int>
+                <int key="NSPeriodicInterval">75</int>
+                <object class="NSMenuItem" key="NSMenuItem" id="121725632">
+                  <reference key="NSMenu" ref="580552820"/>
+                  <string key="NSTitle">Item 1</string>
+                  <string key="NSKeyEquiv"/>
+                  <int key="NSKeyEquivModMask">1048576</int>
+                  <int key="NSMnemonicLoc">2147483647</int>
+                  <int key="NSState">1</int>
+                  <reference key="NSOnImage" ref="179255878"/>
+                  <reference key="NSMixedImage" ref="542579139"/>
+                  <string key="NSAction">_popUpItemAction:</string>
+                  <reference key="NSTarget" ref="847287566"/>
+                </object>
+                <bool key="NSMenuItemRespectAlignment">YES</bool>
+                <object class="NSMenu" key="NSMenu" id="580552820">
+                  <string key="NSTitle">OtherViews</string>
+                  <object class="NSMutableArray" key="NSMenuItems">
+                    <bool key="EncodedWithXMLCoder">YES</bool>
+                    <reference ref="121725632"/>
+                    <object class="NSMenuItem" id="210678812">
+                      <reference key="NSMenu" ref="580552820"/>
+                      <string key="NSTitle">Item 2</string>
+                      <string key="NSKeyEquiv"/>
+                      <int key="NSKeyEquivModMask">1048576</int>
+                      <int key="NSMnemonicLoc">2147483647</int>
+                      <reference key="NSOnImage" ref="179255878"/>
+                      <reference key="NSMixedImage" ref="542579139"/>
+                      <string key="NSAction">_popUpItemAction:</string>
+                      <reference key="NSTarget" ref="847287566"/>
+                    </object>
+                    <object class="NSMenuItem" id="403143245">
+                      <reference key="NSMenu" ref="580552820"/>
+                      <string key="NSTitle">Item 3</string>
+                      <string key="NSKeyEquiv"/>
+                      <int key="NSKeyEquivModMask">1048576</int>
+                      <int key="NSMnemonicLoc">2147483647</int>
+                      <reference key="NSOnImage" ref="179255878"/>
+                      <reference key="NSMixedImage" ref="542579139"/>
+                      <string key="NSAction">_popUpItemAction:</string>
+                      <reference key="NSTarget" ref="847287566"/>
+                    </object>
+                  </object>
+                </object>
+                <int key="NSPreferredEdge">1</int>
+                <bool key="NSUsesItemFromMenu">YES</bool>
+                <bool key="NSAltersState">YES</bool>
+                <int key="NSArrowPosition">2</int>
+                <string key="themeKey">gradientTheme</string>
+              </object>
+            </object>
           </object>
-          <string key="NSFrameSize">{409, 220}</string>
+          <string key="NSFrameSize">{409, 255}</string>
           <reference key="NSSuperview"/>
         </object>
         <string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
@@ -2587,6 +2653,22 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
           </object>
           <int key="connectionID">663</int>
         </object>
+        <object class="IBConnectionRecord">
+          <object class="IBOutletConnection" key="connection">
+            <string key="label">o_profile_pop</string>
+            <reference key="source" ref="687991793"/>
+            <reference key="destination" ref="158673502"/>
+          </object>
+          <int key="connectionID">707</int>
+        </object>
+        <object class="IBConnectionRecord">
+          <object class="IBActionConnection" key="connection">
+            <string key="label">profileSelectorAction:</string>
+            <reference key="source" ref="687991793"/>
+            <reference key="destination" ref="158673502"/>
+          </object>
+          <int key="connectionID">708</int>
+        </object>
       </object>
       <object class="IBMutableOrderedSet" key="objectRecords">
         <object class="NSArray" key="orderedObjects">
@@ -2633,6 +2715,7 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
             <object class="NSMutableArray" key="children">
               <bool key="EncodedWithXMLCoder">YES</bool>
               <reference ref="876119583"/>
+              <reference ref="158673502"/>
             </object>
             <reference key="parent" ref="1005"/>
           </object>
@@ -3926,6 +4009,50 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
             <reference key="object" ref="846216840"/>
             <reference key="parent" ref="235290804"/>
           </object>
+          <object class="IBObjectRecord">
+            <int key="objectID">701</int>
+            <reference key="object" ref="158673502"/>
+            <object class="NSMutableArray" key="children">
+              <bool key="EncodedWithXMLCoder">YES</bool>
+              <reference ref="847287566"/>
+            </object>
+            <reference key="parent" ref="1006"/>
+          </object>
+          <object class="IBObjectRecord">
+            <int key="objectID">702</int>
+            <reference key="object" ref="847287566"/>
+            <object class="NSMutableArray" key="children">
+              <bool key="EncodedWithXMLCoder">YES</bool>
+              <reference ref="580552820"/>
+            </object>
+            <reference key="parent" ref="158673502"/>
+          </object>
+          <object class="IBObjectRecord">
+            <int key="objectID">703</int>
+            <reference key="object" ref="580552820"/>
+            <object class="NSMutableArray" key="children">
+              <bool key="EncodedWithXMLCoder">YES</bool>
+              <reference ref="403143245"/>
+              <reference ref="210678812"/>
+              <reference ref="121725632"/>
+            </object>
+            <reference key="parent" ref="847287566"/>
+          </object>
+          <object class="IBObjectRecord">
+            <int key="objectID">704</int>
+            <reference key="object" ref="403143245"/>
+            <reference key="parent" ref="580552820"/>
+          </object>
+          <object class="IBObjectRecord">
+            <int key="objectID">705</int>
+            <reference key="object" ref="210678812"/>
+            <reference key="parent" ref="580552820"/>
+          </object>
+          <object class="IBObjectRecord">
+            <int key="objectID">706</int>
+            <reference key="object" ref="121725632"/>
+            <reference key="parent" ref="580552820"/>
+          </object>
         </object>
       </object>
       <object class="NSMutableDictionary" key="flattenedProperties">
@@ -4250,6 +4377,13 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
           <string>621.IBPluginDependency</string>
           <string>621.IBViewBoundsToFrameTransform</string>
           <string>622.IBPluginDependency</string>
+          <string>701.IBPluginDependency</string>
+          <string>701.IBViewBoundsToFrameTransform</string>
+          <string>702.IBPluginDependency</string>
+          <string>703.IBPluginDependency</string>
+          <string>704.IBPluginDependency</string>
+          <string>705.IBPluginDependency</string>
+          <string>706.IBPluginDependency</string>
           <string>80.IBAttributePlaceholdersKey</string>
           <string>80.IBPluginDependency</string>
           <string>80.IBViewBoundsToFrameTransform</string>
@@ -4288,9 +4422,9 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
         <object class="NSMutableArray" key="dict.values">
           <bool key="EncodedWithXMLCoder">YES</bool>
           <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-          <string>{{531, 398}, {409, 220}}</string>
+          <string>{{531, 363}, {409, 255}}</string>
           <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-          <string>{{531, 398}, {409, 220}}</string>
+          <string>{{531, 363}, {409, 255}}</string>
           <boolean value="NO"/>
           <string>{196, 240}</string>
           <string>{{357, 418}, {480, 270}}</string>
@@ -4737,6 +4871,15 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
             <bytes key="NSTransformStruct">P4AAAL+AAABDsAAAwxcAAA</bytes>
           </object>
           <string>com.binarymethod.BGHUDAppKitPlugin</string>
+          <string>com.binarymethod.BGHUDAppKitPlugin</string>
+          <object class="NSAffineTransform">
+            <bytes key="NSTransformStruct">P4AAAL+AAABCHAAAwbgAAA</bytes>
+          </object>
+          <string>com.binarymethod.BGHUDAppKitPlugin</string>
+          <string>com.binarymethod.BGHUDAppKitPlugin</string>
+          <string>com.binarymethod.BGHUDAppKitPlugin</string>
+          <string>com.binarymethod.BGHUDAppKitPlugin</string>
+          <string>com.binarymethod.BGHUDAppKitPlugin</string>
           <object class="NSMutableDictionary">
             <string key="NS.key.0">InitialTabViewItem</string>
             <object class="IBInitialTabViewItemAttribute" key="NS.object.0">
@@ -4810,7 +4953,7 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
         </object>
       </object>
       <nil key="sourceID"/>
-      <int key="maxID">700</int>
+      <int key="maxID">708</int>
     </object>
     <object class="IBClassDescriber" key="IBDocument.Classes">
       <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.1+">
@@ -4832,6 +4975,7 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
               <string>filter_enableHeadPhoneVirt:</string>
               <string>filter_enableVolumeNorm:</string>
               <string>filter_volNormSliderUpdated:</string>
+              <string>profileSelectorAction:</string>
               <string>resetCompressorValues:</string>
               <string>resetSpatializerValues:</string>
               <string>spat_enable:</string>
@@ -4855,6 +4999,7 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
               <string>id</string>
               <string>id</string>
               <string>id</string>
+              <string>id</string>
             </object>
           </object>
           <object class="NSMutableDictionary" key="actionInfosByName">
@@ -4871,6 +5016,7 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
               <string>filter_enableHeadPhoneVirt:</string>
               <string>filter_enableVolumeNorm:</string>
               <string>filter_volNormSliderUpdated:</string>
+              <string>profileSelectorAction:</string>
               <string>resetCompressorValues:</string>
               <string>resetSpatializerValues:</string>
               <string>spat_enable:</string>
@@ -4919,6 +5065,10 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
                 <string key="name">filter_volNormSliderUpdated:</string>
                 <string key="candidateClassName">id</string>
               </object>
+              <object class="IBActionInfo">
+                <string key="name">profileSelectorAction:</string>
+                <string key="candidateClassName">id</string>
+              </object>
               <object class="IBActionInfo">
                 <string key="name">resetCompressorValues:</string>
                 <string key="candidateClassName">id</string>
@@ -4987,6 +5137,7 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
               <string>o_filter_normLevel_ckb</string>
               <string>o_filter_normLevel_lbl</string>
               <string>o_filter_normLevel_sld</string>
+              <string>o_profile_pop</string>
               <string>o_spat_band1_fld</string>
               <string>o_spat_band1_lbl</string>
               <string>o_spat_band1_sld</string>
@@ -5070,6 +5221,7 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
               <string>id</string>
               <string>id</string>
               <string>id</string>
+              <string>id</string>
             </object>
           </object>
           <object class="NSMutableDictionary" key="toOneOutletInfosByName">
@@ -5118,6 +5270,7 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
               <string>o_filter_normLevel_ckb</string>
               <string>o_filter_normLevel_lbl</string>
               <string>o_filter_normLevel_sld</string>
+              <string>o_profile_pop</string>
               <string>o_spat_band1_fld</string>
               <string>o_spat_band1_lbl</string>
               <string>o_spat_band1_sld</string>
@@ -5308,6 +5461,10 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
                 <string key="name">o_filter_normLevel_sld</string>
                 <string key="candidateClassName">id</string>
               </object>
+              <object class="IBToOneOutletInfo">
+                <string key="name">o_profile_pop</string>
+                <string key="candidateClassName">id</string>
+              </object>
               <object class="IBToOneOutletInfo">
                 <string key="name">o_spat_band1_fld</string>
                 <string key="candidateClassName">id</string>
@@ -5416,8 +5573,8 @@ AADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AAA</bytes>
       </object>
       <object class="NSMutableArray" key="dict.values">
         <bool key="EncodedWithXMLCoder">YES</bool>
-        <string>{9, 8}</string>
-        <string>{7, 2}</string>
+        <string>{11, 11}</string>
+        <string>{10, 3}</string>
         <string>{15, 15}</string>
       </object>
     </object>
index a2c007e4a0c7d113903a7b4fd68c22ca5831edf9..6dcc718731292585e3016af6c7f50d69937d43b5 100644 (file)
@@ -29,6 +29,8 @@
     IBOutlet id o_tableView;
     IBOutlet id o_window;
     intf_thread_t *p_intf;
+    IBOutlet id o_profile_pop;
+    BOOL b_genericAudioProfileInInteraction;
 
     /* Equalizer */
     IBOutlet id o_eq_enable_ckb;
 + (VLCAudioEffects *)sharedInstance;
 - (IBAction)toggleWindow:(id)sender;
 - (void)setAudioFilter: (char *)psz_name on:(BOOL)b_on;
+- (IBAction)profileSelectorAction:(id)sender;
+- (IBAction)addAudioEffectsProfile:(id)sender;
+- (IBAction)removeAudioEffectsProfile:(id)sender;
 
 /* Equalizer */
 - (void)setupEqualizer;
index 3c6c4564ba6e36c621b12ef3ab02abb37ad2c656..1e47b851377dd5cec66ec8accd89c84a3cd39251 100644 (file)
 
 #import <vlc_common.h>
 #import <vlc_aout_intf.h>
+#import <vlc_strings.h>
 
 #import <math.h>
 
 #pragma mark -
-#pragma mark Initialization & Generic code
+#pragma mark Initialization
 
 @implementation VLCAudioEffects
 static VLCAudioEffects *_o_sharedInstance = nil;
@@ -75,7 +76,10 @@ static VLCAudioEffects *_o_sharedInstance = nil;
         [workNames addObject:[NSString stringWithUTF8String:preset_list[i]]];
     }
 
-    NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithArray:workValues], @"EQValues", [NSArray arrayWithArray:workPreamp], @"EQPreampValues", [NSArray arrayWithArray:workTitles], @"EQTitles", [NSArray arrayWithArray:workNames], @"EQNames", nil];
+    NSString *defaultProfile = [NSString stringWithFormat:@"%i;;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%i",
+                            0,.0,25.,100.,-11.,8.,2.5,7.,.85,1.,.4,.5,.5,2.,0];
+
+    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];
     [defaults registerDefaults:appDefaults];
 
     [workValues release];
@@ -143,15 +147,11 @@ static VLCAudioEffects *_o_sharedInstance = nil;
     [self resetCompressor];
     [self resetSpatializer];
     [self resetAudioFilters];
+    [self resetProfileSelector];
 }
 
-- (IBAction)toggleWindow:(id)sender
-{
-    if ([o_window isVisible])
-        [o_window orderOut:sender];
-    else
-        [o_window makeKeyAndOrderFront:sender];
-}
+#pragma mark -
+#pragma mark internal functions
 
 - (void)setAudioFilter: (char *)psz_name on:(BOOL)b_on
 {
@@ -184,6 +184,168 @@ static VLCAudioEffects *_o_sharedInstance = nil;
     }
 }
 
+- (void)resetProfileSelector
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    [o_profile_pop removeAllItems];
+
+    NSArray * profileNames = [defaults objectForKey:@"AudioEffectProfileNames"];
+    [o_profile_pop addItemsWithTitles:profileNames];
+
+    [[o_profile_pop menu] addItem:[NSMenuItem separatorItem]];
+    [o_profile_pop addItemWithTitle:_NS("Save selection as new profile...")];
+    [[o_profile_pop lastItem] setTarget: self];
+    [[o_profile_pop lastItem] setAction: @selector(addAudioEffectsProfile:)];
+
+    if ([profileNames count] > 1) {
+        [o_profile_pop addItemWithTitle:_NS("Organize Profiles...")];
+        [[o_profile_pop lastItem] setTarget: self];
+        [[o_profile_pop lastItem] setAction: @selector(removeAudioEffectsProfile:)];
+    }
+
+    [o_profile_pop selectItemAtIndex:[defaults integerForKey:@"AudioEffectSelectedProfile"]];
+    [self profileSelectorAction:self];
+}
+
+#pragma mark -
+#pragma mark generic code
+- (IBAction)toggleWindow:(id)sender
+{
+    if ([o_window isVisible])
+        [o_window orderOut:sender];
+    else
+        [o_window makeKeyAndOrderFront:sender];
+}
+
+- (IBAction)profileSelectorAction:(id)sender
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    NSUInteger selectedProfile = [o_profile_pop indexOfSelectedItem];
+
+    audio_output_t * p_aout = getAout();
+    playlist_t * p_playlist = pl_Get(p_intf);
+
+    if (p_aout) {
+        /* disable existing filters */
+        aout_EnableFilter(p_playlist, "equalizer", false);
+        aout_EnableFilter(p_playlist, "compressor", false);
+        aout_EnableFilter(p_playlist, "spatializer", false);
+        aout_EnableFilter(p_playlist, "compressor", false);
+        aout_EnableFilter(p_playlist, "headphone", false);
+        aout_EnableFilter(p_playlist, "normvol", false);
+    }
+
+    /* fetch preset */
+    NSArray *items = [[[defaults objectForKey:@"AudioEffectProfiles"] objectAtIndex:selectedProfile] componentsSeparatedByString:@";"];
+
+    /* eq preset */
+    vlc_object_t *p_object = VLC_OBJECT(getAout());
+    if (p_object == NULL)
+        p_object = vlc_object_hold(pl_Get(p_intf));
+    /* sanity check here, since the user may have removed the custom preset in the mean time */
+    if ([[items objectAtIndex:0] intValue] < [[defaults objectForKey:@"EQNames"] count])
+        var_SetString(p_object,"equalizer-preset",[[[defaults objectForKey:@"EQNames"] objectAtIndex:[[items objectAtIndex:0] intValue]]UTF8String]);
+    else
+        var_SetString(p_object,"equalizer-preset","flat");
+    vlc_object_release(p_object);
+
+    /* filter handling */
+    NSString *tempString = [NSString stringWithFormat:@"%s", vlc_b64_decode([[items objectAtIndex:1] UTF8String])];
+    NSArray *tempArray;
+    NSUInteger count;
+    /* enable the new filters, if we have an aout */
+    if (p_aout) {
+        if ([tempString length] > 0) {
+            tempArray = [tempString componentsSeparatedByString:@":"];
+            count = [tempArray count];
+            for (NSUInteger x = 0; x < count; x++)
+                aout_EnableFilter(p_playlist, (char *)[[tempArray objectAtIndex:x] UTF8String], true);
+        }
+    }
+    config_PutPsz(p_intf,"audio-filter",[tempString UTF8String]);
+
+    /* values */
+    config_PutFloat(p_intf, "compressor-rms-peak",[[items objectAtIndex:2] floatValue]);
+    config_PutFloat(p_intf, "compressor-attack",[[items objectAtIndex:3] floatValue]);
+    config_PutFloat(p_intf, "compressor-release",[[items objectAtIndex:4] floatValue]);
+    config_PutFloat(p_intf, "compressor-threshold",[[items objectAtIndex:5] floatValue]);
+    config_PutFloat(p_intf, "compressor-ratio",[[items objectAtIndex:6] floatValue]);
+    config_PutFloat(p_intf, "compressor-knee",[[items objectAtIndex:7] floatValue]);
+    config_PutFloat(p_intf, "compressor-makeup-gain",[[items objectAtIndex:8] floatValue]);
+    config_PutFloat(p_intf, "spatializer-roomsize",[[items objectAtIndex:9] floatValue]);
+    config_PutFloat(p_intf, "spatializer-width",[[items objectAtIndex:10] floatValue]);
+    config_PutFloat(p_intf, "spatializer-wet",[[items objectAtIndex:11] floatValue]);
+    config_PutFloat(p_intf, "spatializer-dry",[[items objectAtIndex:12] floatValue]);
+    config_PutFloat(p_intf, "spatializer-damp",[[items objectAtIndex:13] floatValue]);
+    config_PutFloat(p_intf, "norm-max-level",[[items objectAtIndex:14] floatValue]);
+    config_PutInt(p_intf, "equalizer-2pass",[[items objectAtIndex:15] intValue]);
+
+    /* set values on-the-fly if we have an aout */
+    if (p_aout) {
+        var_SetFloat(p_aout, "compressor-rms-peak", [[items objectAtIndex:2] floatValue]);
+        var_SetFloat(p_aout, "compressor-attack", [[items objectAtIndex:3] floatValue]);
+        var_SetFloat(p_aout, "compressor-release", [[items objectAtIndex:4] floatValue]);
+        var_SetFloat(p_aout, "compressor-threshold", [[items objectAtIndex:5] floatValue]);
+        var_SetFloat(p_aout, "compressor-ratio", [[items objectAtIndex:6] floatValue]);
+        var_SetFloat(p_aout, "compressor-knee", [[items objectAtIndex:7] floatValue]);
+        var_SetFloat(p_aout, "compressor-makeup-gain", [[items objectAtIndex:8] floatValue]);
+        var_SetFloat(p_aout, "spatializer-roomsize", [[items objectAtIndex:9] floatValue]);
+        var_SetFloat(p_aout, "spatializer-width", [[items objectAtIndex:10] floatValue]);
+        var_SetFloat(p_aout, "spatializer-wet", [[items objectAtIndex:11] floatValue]);
+        var_SetFloat(p_aout, "spatializer-dry", [[items objectAtIndex:12] floatValue]);
+        var_SetFloat(p_aout, "spatializer-damp", [[items objectAtIndex:13] floatValue]);
+        var_SetFloat(p_aout, "norm-max-level", [[items objectAtIndex:14] floatValue]);
+        var_SetBool(p_aout, "equalizer-2pass", (BOOL)[[items objectAtIndex:15] intValue]);
+    }
+
+    /* update UI */
+    if ([tempString rangeOfString:@"equalizer"].location == NSNotFound)
+        [o_eq_enable_ckb setState:NSOffState];
+    else
+        [o_eq_enable_ckb setState:NSOnState];
+    [o_eq_twopass_ckb setState:[[items objectAtIndex:15] intValue]];
+    [self resetCompressor];
+    [self resetSpatializer];
+    [self resetAudioFilters];
+    [self updatePresetSelector];
+
+    /* store current profile selection */
+    [defaults setInteger:selectedProfile forKey:@"AudioEffectSelectedProfile"];
+    [defaults synchronize];
+
+    if (p_aout)
+        vlc_object_release(p_aout);
+}
+
+- (IBAction)addAudioEffectsProfile:(id)sender
+{
+    /* show panel */
+    VLCEnterTextPanel * panel = [VLCEnterTextPanel sharedInstance];
+    [panel setTitle: _NS("Save current selection as new profile")];
+    [panel setSubTitle: _NS("Enter a name for the new profile:")];
+    [panel setCancelButtonLabel: _NS("Cancel")];
+    [panel setOKButtonLabel: _NS("Save")];
+    [panel setTarget:self];
+    b_genericAudioProfileInInteraction = YES;
+
+    [panel runModalForWindow:o_window];
+}
+
+- (IBAction)removeAudioEffectsProfile:(id)sender
+{
+    /* show panel */
+    VLCSelectItemInPopupPanel * panel = [VLCSelectItemInPopupPanel sharedInstance];
+    [panel setTitle:_NS("Remove a preset")];
+    [panel setSubTitle:_NS("Select the preset you would like to remove:")];
+    [panel setOKButtonLabel:_NS("Remove")];
+    [panel setCancelButtonLabel:_NS("Cancel")];
+    [panel setPopupButtonContent:[[NSUserDefaults standardUserDefaults] objectForKey:@"AudioEffectProfileNames"]];
+    [panel setTarget:self];
+    b_genericAudioProfileInInteraction = YES;
+
+    [panel runModalForWindow:o_window];
+}
+
 #pragma mark -
 #pragma mark Equalizer
 static bool GetEqualizerStatus(intf_thread_t *p_custom_intf,
@@ -224,10 +386,13 @@ static bool GetEqualizerStatus(intf_thread_t *p_custom_intf,
 
     NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
     NSArray * presets = [defaults objectForKey:@"EQNames"];
-    NSString * currentPreset = [NSString stringWithUTF8String:var_GetNonEmptyString(p_object, "equalizer-preset")];
-    NSInteger currentPresetIndex = [presets indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
-        return [obj isEqualToString:currentPreset];
-    }];
+    NSString * currentPreset = [NSString stringWithFormat:@"%s",var_GetNonEmptyString(p_object, "equalizer-preset")];
+    NSInteger currentPresetIndex = 0;
+    if ([currentPreset length] > 0) {
+        currentPresetIndex = [presets indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
+            return [obj isEqualToString:currentPreset];
+        }];
+    }
 
     char psz_bands[100];
     snprintf(psz_bands, sizeof(psz_bands),
@@ -273,10 +438,13 @@ static bool GetEqualizerStatus(intf_thread_t *p_custom_intf,
 
     NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
     NSArray * presets = [defaults objectForKey:@"EQNames"];
-    NSString * currentPreset = [NSString stringWithUTF8String:var_GetNonEmptyString(p_object, "equalizer-preset")];
-    NSInteger currentPresetIndex = [presets indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
-        return [obj isEqualToString:currentPreset];
-    }];
+    NSString * currentPreset = [NSString stringWithFormat:@"%s",var_GetNonEmptyString(p_object, "equalizer-preset")];
+    NSInteger currentPresetIndex = 0;
+    if ([currentPreset length] > 0) {
+        currentPresetIndex = [presets indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
+            return [obj isEqualToString:currentPreset];
+        }];
+    }
 
     [o_eq_presets_popup selectItemAtIndex:currentPresetIndex];
     [o_eq_preamp_sld setFloatValue:[[[defaults objectForKey:@"EQPreampValues"] objectAtIndex:currentPresetIndex] floatValue]];
@@ -466,6 +634,7 @@ static bool GetEqualizerStatus(intf_thread_t *p_custom_intf,
     [panel setCancelButtonLabel: _NS("Cancel")];
     [panel setOKButtonLabel: _NS("Save")];
     [panel setTarget:self];
+    b_genericAudioProfileInInteraction = NO;
 
     [panel runModalForWindow:o_window];
 }
@@ -475,38 +644,90 @@ static bool GetEqualizerStatus(intf_thread_t *p_custom_intf,
     if (value == NSOKButton) {
         if ([text length] > 0) {
             NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
-            NSMutableArray * workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]];
-            [workArray addObject:[self generatePresetString]];
-            [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"];
-            [workArray release];
-            workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]];
-            [workArray addObject:text];
-            [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"];
-            [workArray release];
-            workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]];
-            [workArray addObject:[NSString stringWithFormat:@"%.1f", [o_eq_preamp_sld floatValue]]];
-            [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"];
-            [workArray release];
-            workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]];
-            [workArray addObject:[text decomposedStringWithCanonicalMapping]];
-            [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"];
-            [workArray release];
-            [defaults synchronize];
-
-            /* update VLC internals */
-            vlc_object_t *p_object= VLC_OBJECT(getAout());
-            if (p_object == NULL)
-                p_object = vlc_object_hold(pl_Get(p_intf));
 
-            var_SetString(p_object , "equalizer-preset", [[text decomposedStringWithCanonicalMapping] UTF8String]);
-            config_PutPsz(p_object, "equalizer-preset", [[text decomposedStringWithCanonicalMapping] UTF8String]);
-
-            vlc_object_release(p_object);
-
-            /* update UI */
-            [self updatePresetSelector];
+            if (!b_genericAudioProfileInInteraction) {
+
+                NSMutableArray * workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]];
+                [workArray addObject:[self generatePresetString]];
+                [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"];
+                [workArray release];
+                workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]];
+                [workArray addObject:text];
+                [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"];
+                [workArray release];
+                workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]];
+                [workArray addObject:[NSString stringWithFormat:@"%.1f", [o_eq_preamp_sld floatValue]]];
+                [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"];
+                [workArray release];
+                workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]];
+                [workArray addObject:[text decomposedStringWithCanonicalMapping]];
+                [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"];
+                [workArray release];
+                [defaults synchronize];
+
+                /* update VLC internals */
+                vlc_object_t *p_object= VLC_OBJECT(getAout());
+                if (p_object == NULL)
+                    p_object = vlc_object_hold(pl_Get(p_intf));
+
+                var_SetString(p_object , "equalizer-preset", [[text decomposedStringWithCanonicalMapping] UTF8String]);
+                config_PutPsz(p_object, "equalizer-preset", [[text decomposedStringWithCanonicalMapping] UTF8String]);
+
+                vlc_object_release(p_object);
+
+                /* update UI */
+                [self updatePresetSelector];
+            } else {
+                vlc_object_t *p_object = VLC_OBJECT(getAout());
+                if (p_object == NULL)
+                    p_object = vlc_object_hold(pl_Get(p_intf));
+
+                NSArray * presets = [defaults objectForKey:@"EQNames"];
+                NSString * currentPreset = [NSString stringWithFormat:@"%s",var_GetNonEmptyString(p_object, "equalizer-preset")];
+                NSInteger currentPresetIndex = 0;
+                if ([currentPreset length] > 0) {
+                    currentPresetIndex = [presets indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
+                        return [obj isEqualToString:currentPreset];
+                    }];
+                }
+                NSString *newProfile = [NSString stringWithFormat:@"%li;%s;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%lli",
+                                        currentPresetIndex,
+                                        vlc_b64_encode(config_GetPsz(p_intf, "audio-filter")),
+                                        config_GetFloat(p_intf, "compressor-rms-peak"),
+                                        config_GetFloat(p_intf, "compressor-attack"),
+                                        config_GetFloat(p_intf, "compressor-release"),
+                                        config_GetFloat(p_intf, "compressor-threshold"),
+                                        config_GetFloat(p_intf, "compressor-ratio"),
+                                        config_GetFloat(p_intf, "compressor-knee"),
+                                        config_GetFloat(p_intf, "compressor-makeup-gain"),
+                                        config_GetFloat(p_intf, "spatializer-roomsize"),
+                                        config_GetFloat(p_intf, "spatializer-width"),
+                                        config_GetFloat(p_intf, "spatializer-wet"),
+                                        config_GetFloat(p_intf, "spatializer-dry"),
+                                        config_GetFloat(p_intf, "spatializer-damp"),
+                                        config_GetFloat(p_intf, "norm-max-level"),
+                                        config_GetInt(p_intf,"equalizer-2pass")];
+
+                /* add string to user defaults as well as a label */
+                NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+                NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]];
+                [workArray addObject:newProfile];
+                [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"];
+                [defaults setInteger:[workArray count] - 1 forKey:@"AudioEffectSelectedProfile"];
+                [workArray release];
+                workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfileNames"]];
+                [workArray addObject:text];
+                [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfileNames"];
+                [workArray release];
+
+                /* save defaults */
+                [defaults synchronize];
+                vlc_object_release(p_object);
+            }
         }
     }
+
+    [self resetProfileSelector];
 }
 
 - (IBAction)deletePresetAction:(id)sender
@@ -518,6 +739,7 @@ static bool GetEqualizerStatus(intf_thread_t *p_custom_intf,
     [panel setCancelButtonLabel:_NS("Cancel")];
     [panel setPopupButtonContent:[[NSUserDefaults standardUserDefaults] objectForKey:@"EQTitles"]];
     [panel setTarget:self];
+    b_genericAudioProfileInInteraction = NO;
 
     [panel runModalForWindow:o_window];
 }
@@ -525,28 +747,45 @@ static bool GetEqualizerStatus(intf_thread_t *p_custom_intf,
 - (void)panel:(VLCSelectItemInPopupPanel *)panel returnValue:(NSUInteger)value item:(NSUInteger)item
 {
     if (value == NSOKButton) {
-        /* remove requested profile from the arrays */
-        NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
-        NSMutableArray * workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]];
-        [workArray removeObjectAtIndex:item];
-        [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"];
-        [workArray release];
-        workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]];
-        [workArray removeObjectAtIndex:item];
-        [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"];
-        [workArray release];
-        workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]];
-        [workArray removeObjectAtIndex:item];
-        [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"];
-        [workArray release];
-        workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]];
-        [workArray removeObjectAtIndex:item];
-        [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"];
-        [workArray release];
-        [defaults synchronize];
-
-        /* update UI */
-        [self updatePresetSelector];
+        if (!b_genericAudioProfileInInteraction) {
+            /* remove requested profile from the arrays */
+            NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
+            NSMutableArray * workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQValues"]];
+            [workArray removeObjectAtIndex:item];
+            [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQValues"];
+            [workArray release];
+            workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQTitles"]];
+            [workArray removeObjectAtIndex:item];
+            [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQTitles"];
+            [workArray release];
+            workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQPreampValues"]];
+            [workArray removeObjectAtIndex:item];
+            [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQPreampValues"];
+            [workArray release];
+            workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"EQNames"]];
+            [workArray removeObjectAtIndex:item];
+            [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"EQNames"];
+            [workArray release];
+            [defaults synchronize];
+
+            /* update UI */
+            [self updatePresetSelector];
+        } else {
+            /* remove selected profile from settings */
+            NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+            NSMutableArray *workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfiles"]];
+            [workArray removeObjectAtIndex:item];
+            [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfiles"];
+            [workArray release];
+            workArray = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:@"AudioEffectProfileNames"]];
+            [workArray removeObjectAtIndex:item];
+            [defaults setObject:[NSArray arrayWithArray:workArray] forKey:@"AudioEffectProfileNames"];
+            [workArray release];
+
+            /* save defaults */
+            [defaults synchronize];
+            [self resetProfileSelector];
+        }
     }
 }