Audacity 3.2.0
EffectBase.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 EffectBase.cpp
6
7 Dominic Mazzoni
8 Vaughan Johnson
9 Martyn Shaw
10
11 Paul Licameli split from Effect.cpp
12
13*******************************************************************//*******************************************************************/
19
20
21#include "EffectBase.h"
22
23#include <thread>
24#include "AudioIO.h"
25#include "ConfigInterface.h"
27#include "../MixAndRender.h"
28#include "PluginManager.h"
29#include "ProjectAudioIO.h"
30#include "QualitySettings.h"
31#include "TransactionScope.h"
32#include "ViewInfo.h"
33#include "../WaveTrack.h"
34#include "../widgets/ProgressDialog.h"
35#include "../widgets/NumericTextCtrl.h"
36
37// Effect application counter
39
41{
42 // PRL: I think this initialization of mProjectRate doesn't matter
43 // because it is always reassigned in DoEffect before it is used
44 // STF: but can't call AudioIOBase::GetOptimalSupportedSampleRate() here.
45 // (Which is called to compute the default-default value.) (Bug 2280)
47}
48
49EffectBase::~EffectBase() = default;
50
52{
53 return 30.0;
54}
55
56// TODO: Lift the possible user-prompting part out of this function, so that
57// the recursive paths into this function via Effect::Delegate are simplified,
58// and we don't have both EffectSettings and EffectSettingsAccessPtr
59// If pAccess is not null, settings should have come from its Get()
61 TrackList *list,
63 NotifyingSelectedRegion &selectedRegion,
64 unsigned flags,
65 wxWindow *pParent,
66 const EffectDialogFactory &dialogFactory,
67 const EffectSettingsAccessPtr &pAccess)
68{
69 auto cleanup0 = valueRestorer(mUIFlags, flags);
70 wxASSERT(selectedRegion.duration() >= 0.0);
71
72 mOutputTracks.reset();
73
75 mProjectRate = projectRate;
76
77 SetTracks(list);
78 // Don't hold a dangling pointer when done
79 Finally Do([&]{ SetTracks(nullptr); });
80
81 // This is for performance purposes only, no additional recovery implied
82 auto &pProject = *const_cast<AudacityProject*>(FindProject()); // how to remove this const_cast?
83 TransactionScope trans(pProject, "Effect");
84
85 // Update track/group counts
87
88 bool isSelection = false;
89
90 auto duration = 0.0;
95
96 WaveTrack *newTrack{};
97 bool success = false;
98 auto oldDuration = duration;
99
100 auto cleanup = finally( [&] {
101 if (!success) {
102 if (newTrack) {
103 mTracks->Remove(newTrack);
104 }
105 // On failure, restore the old duration setting
106 settings.extra.SetDuration(oldDuration);
107 }
108 else
109 trans.Commit();
110
111 ReplaceProcessedTracks( false );
112 mPresetNames.clear();
113 } );
114
115 // We don't yet know the effect type for code in the Nyquist Prompt, so
116 // assume it requires a track and handle errors when the effect runs.
117 if ((GetType() == EffectTypeGenerate || GetPath() == NYQUIST_PROMPT_ID) && (mNumTracks == 0)) {
118 auto track = mFactory->Create();
120 newTrack = mTracks->Add(track);
121 newTrack->SetSelected(true);
122 }
123
124 mT0 = selectedRegion.t0();
125 mT1 = selectedRegion.t1();
126 if (mT1 > mT0)
127 {
128 // there is a selection: let's fit in there...
129 // MJS: note that this is just for the TTC and is independent of the track rate
130 // but we do need to make sure we have the right number of samples at the project rate
131 double quantMT0 = QUANTIZED_TIME(mT0, mProjectRate);
132 double quantMT1 = QUANTIZED_TIME(mT1, mProjectRate);
133 duration = quantMT1 - quantMT0;
134 isSelection = true;
135 mT1 = mT0 + duration;
136 }
137
138 // This is happening inside EffectSettingsAccess::ModifySettings
139 auto newFormat = isSelection
142 auto updater = [&](EffectSettings &settings) {
143 settings.extra.SetDuration(duration);
144 settings.extra.SetDurationFormat( newFormat );
145 return nullptr;
146 };
147 // Update our copy of settings; update the EffectSettingsAccess too,
148 // if we are going to show a dialog
149 updater(settings);
150 if (pAccess)
151 pAccess->ModifySettings(updater);
152
153#ifdef EXPERIMENTAL_SPECTRAL_EDITING
154 mF0 = selectedRegion.f0();
155 mF1 = selectedRegion.f1();
157 mPresetNames.push_back(L"control-f0");
159 mPresetNames.push_back(L"control-f1");
160
161#endif
163
164 // Allow the dialog factory to fill this in, but it might not
165 std::shared_ptr<EffectInstance> pInstance;
166
167 // Prompting will be bypassed when applying an effect that has already
168 // been configured, e.g. repeating the last effect on a different selection.
169 // Prompting may call EffectBase::Preview
170 if ( pParent && dialogFactory && pAccess &&
171 IsInteractive()) {
173 *pParent, dialogFactory, pInstance, *pAccess, true ) )
174 return false;
175 else if (!pInstance)
176 return false;
177 else
178 // Retrieve again after the dialog modified settings
179 settings = pAccess->Get();
180 }
181
182 auto pInstanceEx = std::dynamic_pointer_cast<EffectInstanceEx>(pInstance);
183 if (!pInstanceEx) {
184 // Path that skipped the dialog factory -- effect may be non-interactive
185 // or this is batch mode processing or repeat of last effect with stored
186 // settings.
187 pInstanceEx = std::dynamic_pointer_cast<EffectInstanceEx>(MakeInstance());
188 // Note: Init may read parameters from preferences
189 if (!pInstanceEx || !pInstanceEx->Init())
190 return false;
191 }
192
193
194 // If the dialog was shown, then it has been closed without errors or
195 // cancellation, and any change of duration has been saved in the config file
196
197 bool returnVal = true;
198 bool skipFlag = CheckWhetherSkipEffect(settings);
199 if (skipFlag == false)
200 {
201 using namespace BasicUI;
202 auto name = GetName();
203 auto progress = MakeProgress(
204 name,
205 XO("Applying %s...").Format( name ),
207 );
208 auto vr = valueRestorer( mProgress, progress.get() );
209
210 assert(pInstanceEx); // null check above
211 returnVal = pInstanceEx->Process(settings);
212 }
213
214 if (returnVal && (mT1 >= mT0 ))
215 {
216 selectedRegion.setTimes(mT0, mT1);
217 }
218
219 success = returnVal;
220 return returnVal;
221}
222
223void EffectBase::SetLinearEffectFlag(bool linearEffectFlag)
224{
225 mIsLinearEffect = linearEffectFlag;
226}
227
228void EffectBase::SetPreviewFullSelectionFlag(bool previewDurationFlag)
229{
230 mPreviewFullSelection = previewDurationFlag;
231}
232
233
235{
236 mPreviewWithNotSelected = includeNotSelected;
237}
238
239// If bGoodResult, replace mTracks tracks with successfully processed mOutputTracks copies.
240// Else clear and DELETE mOutputTracks copies.
241void EffectBase::ReplaceProcessedTracks(const bool bGoodResult)
242{
243 if (!bGoodResult) {
244 // Free resources, unless already freed.
245
246 // Processing failed or was cancelled so throw away the processed tracks.
247 if ( mOutputTracks )
248 mOutputTracks->Clear();
249
250 // Reset map
251 mIMap.clear();
252 mOMap.clear();
253
254 //TODO:undo the non-gui ODTask transfer
255 return;
256 }
257
258 // Assume resources need to be freed.
259 wxASSERT(mOutputTracks); // Make sure we at least did the CopyInputTracks().
260
261 auto iterOut = mOutputTracks->ListOfTracks::begin(),
262 iterEnd = mOutputTracks->ListOfTracks::end();
263
264 size_t cnt = mOMap.size();
265 size_t i = 0;
266
267 for (; iterOut != iterEnd; ++i) {
268 ListOfTracks::value_type o = *iterOut;
269 // If tracks were removed from mOutputTracks, then there will be
270 // tracks in the map that must be removed from mTracks.
271 while (i < cnt && mOMap[i] != o.get()) {
272 const auto t = mIMap[i];
273 if (t) {
274 mTracks->Remove(t);
275 }
276 i++;
277 }
278
279 // This should never happen
280 wxASSERT(i < cnt);
281
282 // Remove the track from the output list...don't DELETE it
283 iterOut = mOutputTracks->erase(iterOut);
284
285 const auto t = mIMap[i];
286 if (t == NULL)
287 {
288 // This track is a NEW addition to output tracks; add it to mTracks
289 mTracks->Add( o );
290 }
291 else
292 {
293 // Replace mTracks entry with the NEW track
294 mTracks->Replace(t, o);
295 }
296 }
297
298 // If tracks were removed from mOutputTracks, then there may be tracks
299 // left at the end of the map that must be removed from mTracks.
300 while (i < cnt) {
301 const auto t = mIMap[i];
302 if (t) {
303 mTracks->Remove(t);
304 }
305 i++;
306 }
307
308 // Reset map
309 mIMap.clear();
310 mOMap.clear();
311
312 // Make sure we processed everything
313 wxASSERT(mOutputTracks->empty());
314
315 // The output list is no longer needed
316 mOutputTracks.reset();
317 nEffectsDone++;
318}
319
321{
322 if (!inputTracks())
323 return nullptr;
324 return inputTracks()->GetOwner();
325}
326
328{
329 mNumTracks = mTracks->Selected< const WaveTrack >().size();
331}
332
333void EffectBase::Preview(EffectSettingsAccess &access, bool dryOnly)
334{
335 if (mNumTracks == 0) { // nothing to preview
336 return;
337 }
338
339 auto gAudioIO = AudioIO::Get();
340 if (gAudioIO->IsBusy()) {
341 return;
342 }
343
344 wxWindow *FocusDialog = wxWindow::FindFocus();
345
346 double previewDuration;
347 bool isNyquist = GetFamily() == NYQUISTEFFECTS_FAMILY;
348 bool isGenerator = GetType() == EffectTypeGenerate;
349
350 // Mix a few seconds of audio from all of the tracks
351 double previewLen;
352 gPrefs->Read(wxT("/AudioIO/EffectsPreviewLen"), &previewLen, 6.0);
353
354 const double rate = mProjectRate;
355
356 const auto &settings = access.Get();
357 if (isNyquist && isGenerator)
358 previewDuration = CalcPreviewInputLength(settings, previewLen);
359 else
360 previewDuration = std::min(settings.extra.GetDuration(),
361 CalcPreviewInputLength(settings, previewLen));
362
363 double t1 = mT0 + previewDuration;
364
365 if ((t1 > mT1) && !isGenerator) {
366 t1 = mT1;
367 }
368
369 if (t1 <= mT0)
370 return;
371
372 bool success = true;
373
374 auto cleanup = finally( [&] {
375
376 // Effect is already inited; we will call Process and then Init
377 // again, so the state is exactly the way it was before Preview
378 // was called.
379 if (!dryOnly)
380 // TODO remove this reinitialization of state within the Effect object
381 // It is done indirectly via Effect::Instance
382 if (auto pInstance =
383 std::dynamic_pointer_cast<EffectInstanceEx>(MakeInstance())
384 )
385 pInstance->Init();
386
387 // In case any dialog control depends on mT1 or mDuration:
388 if ( mUIDialog )
389 mUIDialog->TransferDataToWindow();
390 } );
391
392 auto vr0 = valueRestorer( mT0 );
393 auto vr1 = valueRestorer( mT1 );
394 // Most effects should stop at t1.
396 mT1 = t1;
397
398 // In case any dialog control depends on mT1 or mDuration:
399 if ( mUIDialog ) {
400 mUIDialog->TransferDataToWindow();
401 }
402
403 // Save the original track list
404 TrackList *saveTracks = mTracks;
405
406 auto cleanup2 = finally( [&] {
407 mTracks = saveTracks;
408 if (FocusDialog) {
409 FocusDialog->SetFocus();
410 }
411
412 // In case of failed effect, be sure to free memory.
413 ReplaceProcessedTracks( false );
414 } );
415
416 // Build NEW tracklist from rendering tracks
417 // Set the same owning project, so FindProject() can see it within Process()
418 const auto pProject = saveTracks->GetOwner();
419 auto uTracks = TrackList::Create( pProject );
420 mTracks = uTracks.get();
421
422 // Linear Effect preview optimised by pre-mixing to one track.
423 // Generators need to generate per track.
424 if (mIsLinearEffect && !isGenerator) {
425 WaveTrack::Holder mixLeft, mixRight;
426 MixAndRender(saveTracks->Selected<const WaveTrack>(),
427 Mixer::WarpOptions{ *saveTracks },
428 wxString{}, // Don't care about the name of the temporary tracks
429 mFactory, rate, floatSample, mT0, t1, mixLeft, mixRight);
430 if (!mixLeft)
431 return;
432
433 mixLeft->Offset(-mixLeft->GetStartTime());
434 mixLeft->SetSelected(true);
435 auto pLeft = mTracks->Add( mixLeft );
436 Track *pRight{};
437 if (mixRight) {
438 mixRight->Offset(-mixRight->GetStartTime());
439 mixRight->SetSelected(true);
440 pRight = mTracks->Add( mixRight );
441 mTracks->MakeMultiChannelTrack(*pLeft, 2, true);
442 }
443 }
444 else {
445 for (auto src : saveTracks->Any< const WaveTrack >()) {
446 if (src->GetSelected() || mPreviewWithNotSelected) {
447 auto dest = src->Copy(mT0, t1);
448 dest->SetSelected(src->GetSelected());
449 mTracks->Add( dest );
450 }
451 }
452 }
453
454 // NEW tracks start at time zero.
455 // Adjust mT0 and mT1 to be the times to process, and to
456 // play back in these tracks
457 mT1 -= mT0;
458 mT0 = 0.0;
459
460 // Update track/group counts
462
463 // Apply effect
464 if (!dryOnly) {
465 using namespace BasicUI;
466 auto progress = MakeProgress(
467 GetName(),
468 XO("Preparing preview"),
470 ); // Have only "Stop" button.
471 auto vr = valueRestorer( mProgress, progress.get() );
472
473 auto vr2 = valueRestorer( mIsPreview, true );
474
476 // Preview of non-realtime effect
477 auto pInstance =
478 std::dynamic_pointer_cast<EffectInstanceEx>(MakeInstance());
479 success = pInstance && pInstance->Process(settings);
480 return nullptr;
481 });
482 }
483
484 if (success)
485 {
486 auto tracks = TransportTracks{ *mTracks, true };
487
488 // Some effects (Paulstretch) may need to generate more
489 // than previewLen, so take the min.
490 t1 = std::min(mT0 + previewLen, mT1);
491
492 // Start audio playing
493 auto options = ProjectAudioIO::GetDefaultOptions(*pProject);
494 int token = gAudioIO->StartStream(tracks, mT0, t1, t1, options);
495
496 if (token) {
497 auto previewing = ProgressResult::Success;
498 // The progress dialog must be deleted before stopping the stream
499 // to allow events to flow to the app during StopStream processing.
500 // The progress dialog blocks these events.
501 {
502 ProgressDialog progress
503 (GetName(), XO("Previewing"), pdlgHideCancelButton);
504
505 while (gAudioIO->IsStreamActive(token) && previewing == ProgressResult::Success) {
506 using namespace std::chrono;
507 std::this_thread::sleep_for(100ms);
508 previewing = progress.Update(gAudioIO->GetStreamTime() - mT0, t1 - mT0);
509 }
510 }
511
512 gAudioIO->StopStream();
513
514 while (gAudioIO->IsBusy()) {
515 using namespace std::chrono;
516 std::this_thread::sleep_for(100ms);
517 }
518 }
519 else {
520 using namespace BasicUI;
522 wxWidgetsWindowPlacement{ FocusDialog }, XO("Error"),
523 XO("Error opening sound device.\nTry changing the audio host, playback device and the project sample rate."),
524 wxT("Error_opening_sound_device"),
525 ErrorDialogOptions{ ErrorDialogType::ModalErrorReport } );
526 }
527 }
528}
wxT("CloseDown"))
int min(int a, int b)
const TranslatableString name
Definition: Distortion.cpp:74
#define NYQUISTEFFECTS_FAMILY
Definition: EffectBase.h:146
const RegistryPath & CurrentSettingsGroup()
Component of a configuration key path, for last-used destructive settings.
@ EffectTypeGenerate
std::function< DialogFactoryResults(wxWindow &parent, EffectPlugin &, EffectUIClientInterface &, EffectSettingsAccess &) > EffectDialogFactory
Type of function that creates a dialog for an effect.
Definition: EffectPlugin.h:42
XO("Cut/Copy/Paste")
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
Definition: MemoryX.h:234
#define QUANTIZED_TIME(time, rate)
Definition: MemoryX.h:541
void MixAndRender(const TrackIterRange< const WaveTrack > &trackRange, const Mixer::WarpOptions &warpOptions, const wxString &newTrackName, WaveTrackFactory *trackFactory, double rate, sampleFormat format, double startTime, double endTime, WaveTrack::Holder &uLeft, WaveTrack::Holder &uRight)
Mixes together all input tracks, applying any envelopes, amplitude gain, panning, and real-time effec...
#define NYQUIST_PROMPT_ID
FileConfig * gPrefs
Definition: Prefs.cpp:70
@ pdlgHideCancelButton
static Settings & settings()
Definition: TrackInfo.cpp:87
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static AudioIO * Get()
Definition: AudioIO.cpp:147
Abstraction of a progress dialog with well defined time-to-completion estimate.
Definition: BasicUI.h:154
virtual PluginPath GetPath() const =0
TranslatableString GetName() const
int mNumTracks
Definition: EffectBase.h:138
double mT1
Definition: EffectBase.h:109
std::shared_ptr< TrackList > mOutputTracks
Definition: EffectBase.h:107
bool DoEffect(EffectSettings &settings, double projectRate, TrackList *list, WaveTrackFactory *factory, NotifyingSelectedRegion &selectedRegion, unsigned flags, wxWindow *pParent, const EffectDialogFactory &dialogFactory, const EffectSettingsAccessPtr &pAccess) override
Unfortunately complicated dual-use function.
Definition: EffectBase.cpp:60
WaveTrackFactory * mFactory
Definition: EffectBase.h:103
~EffectBase() override
TrackList * mTracks
Definition: EffectBase.h:127
void CountWaveTracks()
Definition: EffectBase.cpp:327
std::vector< Track * > mOMap
Definition: EffectBase.h:136
void SetPreviewFullSelectionFlag(bool previewDurationFlag)
Definition: EffectBase.cpp:228
void SetLinearEffectFlag(bool linearEffectFlag)
Definition: EffectBase.cpp:223
const TrackList * inputTracks() const
Definition: EffectBase.h:104
virtual bool CheckWhetherSkipEffect(const EffectSettings &settings) const =0
After Init(), tell whether Process() should be skipped.
double mProjectRate
Definition: EffectBase.h:101
bool mIsPreview
Definition: EffectBase.h:133
BasicUI::ProgressDialog * mProgress
Definition: EffectBase.h:100
bool mPreviewWithNotSelected
Definition: EffectBase.h:130
int mNumGroups
Definition: EffectBase.h:139
bool mPreviewFullSelection
Definition: EffectBase.h:131
virtual double CalcPreviewInputLength(const EffectSettings &settings, double previewLength) const =0
std::vector< Track * > mIMap
Definition: EffectBase.h:135
wxArrayString mPresetNames
Definition: EffectBase.h:114
double GetDefaultDuration()
Definition: EffectBase.cpp:51
wxWeakRef< wxDialog > mUIDialog
This weak pointer may be the same as mUIParent, or null.
Definition: EffectBase.h:121
double mT0
Definition: EffectBase.h:108
unsigned mUIFlags
Definition: EffectBase.h:115
void IncludeNotSelectedPreviewTracks(bool includeNotSelected)
Definition: EffectBase.cpp:234
void SetTracks(TrackList *pTracks)
Definition: EffectBase.h:38
void ReplaceProcessedTracks(const bool bGoodResult)
Definition: EffectBase.cpp:241
bool mIsLinearEffect
This weak pointer may be the same as mHostUIDialog, or null.
Definition: EffectBase.h:129
void Preview(EffectSettingsAccess &access, bool dryOnly) override
Definition: EffectBase.cpp:333
static int nEffectsDone
Definition: EffectBase.h:93
const AudacityProject * FindProject() const
Definition: EffectBase.cpp:320
virtual EffectType GetType() const =0
Type determines how it behaves.
virtual bool IsInteractive() const =0
Whether the effect needs a dialog for entry of settings.
virtual EffectFamilySymbol GetFamily() const =0
Report identifier and user-visible name of the effect protocol.
virtual std::shared_ptr< EffectInstance > MakeInstance() const =0
Make an object maintaining short-term state of an Effect.
std::shared_ptr< EffectSettingsAccess > EffectSettingsAccessPtr
Definition: EffectPlugin.h:57
virtual int ShowHostInterface(wxWindow &parent, const EffectDialogFactory &factory, std::shared_ptr< EffectInstance > &pInstance, EffectSettingsAccess &access, bool forceModal=false)=0
Usually applies factory to self and given access.
virtual const EffectSettingsManager & GetDefinition() const =0
void ModifySettings(Function &&function)
Do a correct read-modify-write of settings.
virtual const EffectSettings & Get()=0
static const RegistryPath & DurationKey()
Abstract base class used in importing a file.
double t1() const
Definition: ViewInfo.h:35
double f1() const
Definition: ViewInfo.h:37
double duration() const
Definition: ViewInfo.h:40
bool setTimes(double t0, double t1)
Definition: ViewInfo.cpp:50
double f0() const
Definition: ViewInfo.h:36
double t0() const
Definition: ViewInfo.h:34
static NumericFormatSymbol DefaultSelectionFormat()
static NumericFormatSymbol TimeAndSampleFormat()
static AudioIOStartStreamOptions GetDefaultOptions(AudacityProject &project, bool newDefaults=false)
Invoke the global hook, supplying a default argument.
static const int UndefinedFrequency
bool ReadWithDefault(T *pVar, const T &defaultValue) const
overload of ReadWithDefault returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:206
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:225
void Offset(double t)
Definition: Track.h:482
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1338
bool MakeMultiChannelTrack(Track &first, int nChannels, bool aligned)
Converts channels to a multichannel track.
Definition: Track.cpp:762
static std::shared_ptr< TrackList > Create(AudacityProject *pOwner)
Definition: Track.cpp:502
auto SelectedLeaders() -> TrackIterRange< TrackType >
Definition: Track.h:1488
ListOfTracks::value_type Replace(Track *t, const ListOfTracks::value_type &with)
Definition: Track.cpp:724
wxString MakeUniqueTrackName(const wxString &baseTrackName) const
Returns string that contains baseTrackName, but is guaranteed to be unique among other tracks in that...
Definition: Track.cpp:543
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
Definition: Track.h:1564
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1437
TrackNodePointer Remove(Track *t)
Remove the Track and return an iterator to what followed it.
Definition: Track.cpp:798
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1454
AudacityProject * GetOwner()
Definition: Track.h:1373
RAII for a database transaction, possibly nested.
bool Commit()
Commit the transaction.
Used to create or clone a WaveTrack, with appropriate context from the project that will own the trac...
Definition: WaveTrack.h:620
std::shared_ptr< WaveTrack > Create()
Creates an unnamed empty WaveTrack with default sample format and default rate.
Definition: WaveTrack.cpp:118
A Track that contains audio waveform data.
Definition: WaveTrack.h:57
static wxString GetDefaultAudioTrackNamePreference()
Definition: WaveTrack.cpp:100
std::shared_ptr< WaveTrack > Holder
Definition: WaveTrack.h:106
@ ProgressShowCancel
Definition: BasicUI.h:139
@ ProgressShowStop
Definition: BasicUI.h:138
void ShowErrorDialog(const WindowPlacement &placement, const TranslatableString &dlogTitle, const TranslatableString &message, const ManualPageID &helpPage, const ErrorDialogOptions &options={})
Show an error dialog with a link to the manual for further help.
Definition: BasicUI.h:254
std::unique_ptr< ProgressDialog > MakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags=(ProgressShowStop|ProgressShowCancel), const TranslatableString &remainingLabelText={})
Create and display a progress dialog.
Definition: BasicUI.h:284
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
PROJECT_RATE_API IntSetting DefaultSampleRate
static RegisteredToolbarFactory factory
Options for variations of error dialogs; the default is for modal dialogs.
Definition: BasicUI.h:49
Externalized state of a plug-in.
"finally" as in The C++ Programming Language, 4th ed., p. 358 Useful for defining ad-hoc RAII actions...
Definition: MemoryX.h:173
Immutable structure is an argument to Mixer's constructor.
Definition: MixerOptions.h:54
Window placement information for wxWidgetsBasicUI can be constructed from a wxWindow pointer.