1 /**********************************************************************
2 
3   Audacity: A Digital Audio Editor
4 
5   EffectsPrefs.cpp
6 
7   Brian Gunlogson
8   Joshua Haberman
9   Dominic Mazzoni
10   James Crook
11 
12 
13 *******************************************************************//**
14 
15 \class EffectsPrefs
16 \brief A PrefsPanel for general GUI preferences.
17 
18 *//*******************************************************************/
19 
20 
21 #include "EffectsPrefs.h"
22 
23 #include <wx/choice.h>
24 #include <wx/defs.h>
25 
26 #include "Languages.h"
27 #include "../PluginManager.h"
28 #include "Prefs.h"
29 #include "../ShuttleGui.h"
30 
EffectsPrefs(wxWindow * parent,wxWindowID winid)31 EffectsPrefs::EffectsPrefs(wxWindow * parent, wxWindowID winid)
32 :  PrefsPanel(parent, winid, XO("Effects"))
33 {
34    Populate();
35 }
36 
~EffectsPrefs()37 EffectsPrefs::~EffectsPrefs()
38 {
39 }
40 
GetSymbol()41 ComponentInterfaceSymbol EffectsPrefs::GetSymbol()
42 {
43    return EFFECTS_PREFS_PLUGIN_SYMBOL;
44 }
45 
GetDescription()46 TranslatableString EffectsPrefs::GetDescription()
47 {
48    return XO("Preferences for Effects");
49 }
50 
HelpPageName()51 ManualPageID EffectsPrefs::HelpPageName()
52 {
53    return "Effects_Preferences";
54 }
55 
Populate()56 void EffectsPrefs::Populate()
57 {
58    //------------------------- Main section --------------------
59    // Now construct the GUI itself.
60    // Use 'eIsCreatingFromPrefs' so that the GUI is
61    // initialised with values from gPrefs.
62    ShuttleGui S(this, eIsCreatingFromPrefs);
63    PopulateOrExchange(S);
64    // ----------------------- End of main section --------------
65 }
66 
67 ChoiceSetting EffectsGroupBy{
68    wxT("/Effects/GroupBy"),
69    {
70       ByColumns,
71       {
72          XO("Sorted by Effect Name") ,
73          XO("Sorted by Publisher and Effect Name") ,
74          XO("Sorted by Type and Effect Name") ,
75          XO("Grouped by Publisher") ,
76          XO("Grouped by Type") ,
77       },
78       {
79          wxT("sortby:name") ,
80          wxT("sortby:publisher:name") ,
81          wxT("sortby:type:name") ,
82          wxT("groupby:publisher") ,
83          wxT("groupby:type") ,
84       }
85    },
86    0 // "sortby:name"
87 };
88 
89 namespace {
90 
91 // Rather than hard-code an exhaustive list of effect families in this file,
92 // pretend we don't know, but discover them instead by querying the module and
93 // effect managers.
94 
95 // But then we would like to have prompts with accelerator characters that are
96 // distinct.  We collect some prompts in the following map.
97 
98 // It is not required that each module be found here, nor that each module
99 // mentioned here be found.
100 const std::map< wxString, TranslatableString > SuggestedPrompts{
101 
102 /* i18n-hint: Audio Unit is the name of an Apple audio software protocol */
103    { wxT("AudioUnit"), XXO("Audio Unit") },
104 
105 /* i18n-hint: abbreviates "Linux Audio Developer's Simple Plugin API"
106    (Application programming interface)
107  */
108    { wxT("LADSPA"),    XXO("&LADSPA") },
109 
110 /* i18n-hint: abbreviates
111    "Linux Audio Developer's Simple Plugin API (LADSPA) version 2" */
112    { wxT("LV2"),       XXO("LV&2") },
113 
114 /* i18n-hint: "Nyquist" is an embedded interpreted programming language in
115  Audacity, named in honor of the Swedish-American Harry Nyquist (or Nyqvist).
116  In the translations of this and other strings, you may transliterate the
117  name into another alphabet.  */
118    { wxT("Nyquist"),   XXO("N&yquist") },
119 
120 /* i18n-hint: Vamp is the proper name of a software protocol for sound analysis.
121    It is not an abbreviation for anything.  See http://vamp-plugins.org */
122    { wxT("Vamp"),      XXO("&Vamp") },
123 
124 /* i18n-hint: Abbreviates Virtual Studio Technology, an audio software protocol
125    developed by Steinberg GmbH */
126    { wxT("VST"),       XXO("V&ST") },
127 
128 };
129 
130 // Collect needed prompts and settings paths, at most once, on demand
131 struct Entry {
132    TranslatableString prompt;
133    wxString setting;
134 };
GetModuleData()135 static const std::vector< Entry > &GetModuleData()
136 {
137    struct ModuleData : public std::vector< Entry > {
138       ModuleData() {
139          auto &pm = PluginManager::Get();
140          for (auto &plug : pm.PluginsOfType(PluginTypeModule)) {
141             auto internal = plug.GetEffectFamily();
142             if ( internal.empty() )
143                continue;
144 
145             TranslatableString prompt;
146             auto iter = SuggestedPrompts.find( internal );
147             if ( iter == SuggestedPrompts.end() )
148                // For the built-in modules this Msgid includes " Effects",
149                // but those strings were never shown to the user,
150                // and the prompts in the table above do not include it.
151                // If there should be new modules, it is not important for them
152                // to follow the " Effects" convention, but instead they can
153                // have shorter msgids.
154                prompt = plug.GetSymbol().Msgid();
155             else
156                prompt = iter->second;
157 
158             auto setting = pm.GetPluginEnabledSetting( plug );
159 
160             push_back( { prompt, setting } );
161          }
162          // Guarantee some determinate ordering
163          std::sort( begin(), end(),
164             []( const Entry &a, const Entry &b ){
165                return a.setting < b.setting;
166             }
167          );
168       }
169    };
170    static ModuleData theData;
171    return theData;
172 }
173 
174 }
175 
PopulateOrExchange(ShuttleGui & S)176 void EffectsPrefs::PopulateOrExchange(ShuttleGui & S)
177 {
178    S.SetBorder(2);
179    S.StartScroller();
180 
181    S.StartStatic(XO("Enable Effects"));
182    {
183       for ( const auto &entry : GetModuleData() )
184       {
185          S.TieCheckBox(
186             entry.prompt,
187             {entry.setting,
188              true}
189          );
190       }
191    }
192    S.EndStatic();
193 
194    S.StartStatic(XO("Effect Options"));
195    {
196       S.StartMultiColumn(2);
197       {
198          wxChoice *c = S
199             .MinSize()
200             .TieChoice( XXO("S&ort or Group:"), EffectsGroupBy);
201 
202          S.TieIntegerTextBox(XXO("&Maximum effects per group (0 to disable):"),
203                              {wxT("/Effects/MaxPerGroup"),
204 #if defined(__WXGTK__)
205                               15
206 #else
207                               0
208 #endif
209                              },
210                              5);
211       }
212       S.EndMultiColumn();
213    }
214    S.EndStatic();
215 
216 #ifndef EXPERIMENTAL_EFFECT_MANAGEMENT
217    S.StartStatic(XO("Plugin Options"));
218    {
219       S.TieCheckBox(XXO("Check for updated plugins when Audacity starts"),
220                      {wxT("/Plugins/CheckForUpdates"),
221                      true});
222       S.TieCheckBox(XXO("Rescan plugins next time Audacity is started"),
223                      {wxT("/Plugins/Rescan"),
224                      false});
225    }
226    S.EndStatic();
227 #endif
228 
229 #ifdef EXPERIMENTAL_EQ_SSE_THREADED
230    S.StartStatic(XO("Instruction Set"));
231    {
232       S.TieCheckBox(XXO("&Use SSE/SSE2/.../AVX"),
233                     {wxT("/SSE/GUI"),
234                     true});
235    }
236    S.EndStatic();
237 #endif
238    S.EndScroller();
239 }
240 
Commit()241 bool EffectsPrefs::Commit()
242 {
243    ShuttleGui S(this, eIsSavingToPrefs);
244    PopulateOrExchange(S);
245 
246    return true;
247 }
248 
249 namespace{
250 PrefsPanel::Registration sAttachment{ "Effects",
251    [](wxWindow *parent, wxWindowID winid, AudacityProject *)
__anon543fb7c90402() 252    {
253       wxASSERT(parent); // to justify safenew
254       return safenew EffectsPrefs(parent, winid);
255    }
256 };
257 }
258