Audacity 3.2.0
AudioUnitEffect.cpp
Go to the documentation of this file.
1/*!********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file AudioUnitEffect.cpp
6
7 Dominic Mazzoni
8 Leland Lucius
9
10*******************************************************************//*******************************************************************/
16
17#if USE_AUDIO_UNITS
18#include "AudioUnitEffect.h"
20#include "AudioUnitInstance.h"
21#include "AudioUnitEditor.h"
23#include "SampleCount.h"
24#include "ConfigInterface.h"
25
26#include <optional>
27#include <wx/defs.h>
28#include <wx/base64.h>
29#include <wx/control.h>
30#include <wx/crt.h>
31#include <wx/dir.h>
32
33#ifdef __WXMAC__
34#include <wx/evtloop.h>
35#endif
36
37#include <wx/filename.h>
38#include <wx/frame.h>
39#include <wx/listctrl.h>
40#include <wx/log.h>
41#include <wx/settings.h>
42#include <wx/stattext.h>
43#include <wx/textctrl.h>
44
45#include "SelectFile.h"
46#include "ShuttleGui.h"
47#include "AudacityMessageBox.h"
48#include "../../widgets/valnum.h"
49
50//
51// When a plug-in's state is saved to the settings file (as a preset),
52// it is in binary and gets base64 encoded before storing.
53//
54// When exporting, save as XML without base64 encoding.
55//
56// The advantages of XML format is less chance of failures occurring
57// when exporting. But, it can take a bit more space per preset int
58// the Audacity settings file.
59//
60// Using binary for now. Use kCFPropertyListXMLFormat_v1_0 if XML
61// format is desired.
62//
63#define PRESET_FORMAT kCFPropertyListBinaryFormat_v1_0
64
65// Name of the settings key to use for the above value
66#define PRESET_KEY wxT("Data")
67
68// Where the presets are located
69#define PRESET_LOCAL_PATH wxT("/Library/Audio/Presets")
70#define PRESET_USER_PATH wxT("~/Library/Audio/Presets")
71
73{
74}
75
76#if 0
78{
79 // Retrieve the tail time
80 Float64 tailTime = 0.0;
81 if (!GetFixedSizeProperty(kAudioUnitProperty_TailTime, tailTime))
82 return tailTime * mSampleRate;
83 return 0;
84}
85#endif
86
88 wxWindow &parent, wxDialog &dialog,
89 EffectEditor *, bool forceModal) const
90{
91 if ((SupportsRealtime() || GetType() == EffectTypeAnalyze) && !forceModal) {
92 dialog.Show();
93 return 0;
94 }
95 return dialog.ShowModal();
96}
97
98std::unique_ptr<EffectEditor> AudioUnitEffect::PopulateUI(
99 const EffectPlugin &, ShuttleGui &S,
100 EffectInstance &instance, EffectSettingsAccess &access,
101 const EffectOutputs *) const
102{
103 wxString uiType;
104 // Decide whether to build plain or fancy user interfaces
106 uiType, FullValue.MSGID().GET() /* Config stores un-localized string */);
107 return AudioUnitEditor::Create(*this, S, uiType, instance, access);
108}
109
110std::unique_ptr<EffectEditor> AudioUnitEffect::MakeEditor(
112 const EffectOutputs *) const
113{
115 assert(false);
116 return nullptr;
117}
118
119#if defined(HAVE_AUDIOUNIT_BASIC_SUPPORT)
120bool AudioUnitEffect::CreatePlain(wxWindow *parent)
121{
122 // TODO??? Never implemented...
123 return false;
124}
125#endif
126
128{
129#ifdef __WXMAC__
130#ifdef __WX_EVTLOOP_BUSY_WAITING__
131 wxEventLoop::SetBusyWaiting(false);
132#endif
133#endif
134 return true;
135}
136
138 const EffectPlugin &, const EffectSettings &settings) const
139{
140 // Generate the user domain path
141 wxFileName fn;
142 fn.SetPath(PRESET_USER_PATH);
143 fn.AppendDir(mVendor);
144 fn.AppendDir(mName);
145 fn.Normalize();
146 FilePath path = fn.GetFullPath();
147
148 if (!fn.Mkdir(fn.GetFullPath(), 0755, wxPATH_MKDIR_FULL)) {
149 wxLogError(wxT("Couldn't create the \"%s\" directory"), fn.GetPath());
150 return;
151 }
152
153 // Ask the user for the name to use
154 //
155 // Passing a valid parent will cause some effects dialogs to malfunction
156 // upon returning from the SelectFile().
157 path = SelectFile(FileNames::Operation::_None,
158 XO("Export Audio Unit Preset As %s:").Format(fn.GetFullPath()),
159 fn.GetFullPath(),
160 wxEmptyString,
161 wxT("aupreset"),
162 {
163 { XO("Standard Audio Unit preset file"), { wxT("aupreset") }, true },
164 },
165 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER,
166 NULL);
167
168 // User canceled...
169 if (path.empty())
170 return;
171
172 auto msg = Export(GetSettings(settings), path);
173 if (!msg.empty())
175 XO("Could not export \"%s\" preset\n\n%s").Format(path, msg),
176 XO("Export Audio Unit Presets"),
177 wxOK | wxCENTRE);
178}
179
181 const EffectPlugin &, EffectSettings &settings) const
182{
183 // Generate the user domain path
184 wxFileName fn;
185 fn.SetPath(PRESET_USER_PATH);
186 fn.AppendDir(mVendor);
187 fn.AppendDir(mName);
188 fn.Normalize();
189 FilePath path = fn.GetFullPath();
190
191 // Ask the user for the name to use
192 //
193 // Passing a valid parent will cause some effects dialogs to malfunction
194 // upon returning from the SelectFile().
195 path = SelectFile(FileNames::Operation::_None,
196 XO("Import Audio Unit Preset As %s:").Format(fn.GetFullPath()),
197 fn.GetFullPath(), wxEmptyString, wxT("aupreset"),
198 {
199 { XO("Standard Audio Unit preset file"), { wxT("aupreset") }, true },
200 },
201 wxFD_OPEN | wxRESIZE_BORDER,
202 nullptr);
203
204 // User canceled...
205 if (path.empty())
206 return {};
207
208 auto msg = Import(GetSettings(settings), path);
209 if (!msg.empty()) {
211 XO("Could not import \"%s\" preset\n\n%s").Format(path, msg),
212 XO("Import Audio Unit Presets"),
213 wxOK | wxCENTRE);
214 return {};
215 }
216
217 return { nullptr };
218}
219
221{
222 AudioUnitEffectOptionsDialog{ *this }.ShowModal();
223}
224
225// Inject factory hook to make AudioUnitEffect capable of UI
226static AudioUnitEffectsModule::Factory::SubstituteInUnique<AudioUnitEffect> scope;
227
228#endif
wxT("CloseDown"))
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
static AudioUnitEffectsModule::Factory::SubstituteInUnique< AudioUnitEffect > scope
#define PRESET_USER_PATH
constexpr auto OptionsKey
static const auto FullValue
constexpr auto UITypeKey
@ EffectTypeAnalyze
std::optional< std::unique_ptr< EffectSettingsAccess::Message > > OptionalMessage
XO("Cut/Copy/Paste")
wxString FilePath
Definition: Project.h:21
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
Definition: SelectFile.cpp:17
#define S(N)
Definition: ToChars.cpp:64
static Settings & settings()
Definition: TrackInfo.cpp:69
static const auto fn
static std::unique_ptr< EffectEditor > Create(const EffectUIServices &effect, ShuttleGui &S, const wxString &uiType, EffectInstance &instance, EffectSettingsAccess &access)
TranslatableString Export(const AudioUnitEffectSettings &settings, const wxString &path) const
TranslatableString Import(AudioUnitEffectSettings &settings, const wxString &path) const
EffectType GetType() const override
Type determines how it behaves.
~AudioUnitEffect() override
void ExportPresets(const EffectPlugin &plugin, const EffectSettings &settings) const override
virtual std::unique_ptr< EffectEditor > MakeEditor(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) const final
Will never be called.
std::unique_ptr< EffectEditor > PopulateUI(const EffectPlugin &plugin, ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) const override
Adds controls to a panel that is given as the parent window of S
void ShowOptions(const EffectPlugin &plugin) const override
OptionalMessage ImportPresets(const EffectPlugin &plugin, EffectSettings &settings) const override
int ShowClientInterface(const EffectPlugin &plugin, wxWindow &parent, wxDialog &dialog, EffectEditor *pEditor, bool forceModal) const override
bool CloseUI() const override
Performs effect computation.
virtual size_t GetTailSize() const
Hold values to send to effect output meters.
Factory of instances of an effect.
Definition: EffectPlugin.h:36
Abstract base class used in importing a file.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
OSStatus GetFixedSizeProperty(AudioUnitPropertyID inID, T &property, AudioUnitScope inScope=kAudioUnitScope_Global, AudioUnitElement inElement=0) const
static AudioUnitEffectSettings & GetSettings(EffectSettings &settings)
Externalized state of a plug-in.