1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
|
/**********************************************************************
Audacity: A Digital Audio Editor
Effect.cpp
Dominic Mazzoni
Vaughan Johnson
Martyn Shaw
*******************************************************************//**
\class Effect
\brief Base class for many of the effects in Audacity.
*//*******************************************************************/
#include "Effect.h"
#include "EffectOutputTracks.h"
#include <algorithm>
#include <wx/defs.h>
#include "BasicUI.h"
#include "ConfigInterface.h"
#include "ProjectNumericFormats.h"
#include "ShuttleAutomation.h"
#include "SyncLock.h"
#include "ViewInfo.h"
#include "WaveTrack.h"
#include "wxFileNameWrapper.h"
#include "NumericConverterFormats.h"
Effect::Effect()
{
}
Effect::~Effect()
{
}
// ComponentInterface implementation
PluginPath Effect::GetPath() const
{
return BUILTIN_EFFECT_PREFIX + GetSymbol().Internal();
}
ComponentInterfaceSymbol Effect::GetSymbol() const
{
return {};
}
VendorSymbol Effect::GetVendor() const
{
return XO("Audacity");
}
wxString Effect::GetVersion() const
{
return AUDACITY_VERSION_STRING;
}
TranslatableString Effect::GetDescription() const
{
return {};
}
EffectFamilySymbol Effect::GetFamily() const
{
// Unusually, the internal and visible strings differ for the built-in
// effect family.
return { wxT("Audacity"), XO("Built-in") };
}
bool Effect::IsInteractive() const
{
return true;
}
bool Effect::IsDefault() const
{
return true;
}
auto Effect::RealtimeSupport() const -> RealtimeSince
{
return RealtimeSince::Never;
}
bool Effect::SupportsAutomation() const
{
return true;
}
const EffectParameterMethods &Effect::Parameters() const
{
static const CapturedParameters<Effect> empty;
return empty;
}
bool Effect::VisitSettings(SettingsVisitor &visitor, EffectSettings &settings)
{
Parameters().Visit(*this, visitor, settings);
return true;
}
bool Effect::VisitSettings(
ConstSettingsVisitor &visitor, const EffectSettings &settings) const
{
Parameters().Visit(*this, visitor, settings);
return true;
}
bool Effect::SaveSettings(
const EffectSettings &settings, CommandParameters & parms) const
{
Parameters().Get( *this, settings, parms );
return true;
}
bool Effect::LoadSettings(
const CommandParameters & parms, EffectSettings &settings) const
{
// The first argument, and with it the const_cast, will disappear when
// all built-in effects are stateless.
return Parameters().Set( *const_cast<Effect*>(this), parms, settings );
}
OptionalMessage Effect::LoadUserPreset(
const RegistryPath & name, EffectSettings &settings) const
{
// Find one string in the registry and then reinterpret it
// as complete settings
wxString parms;
if (!GetConfig(GetDefinition(), PluginSettings::Private,
name, wxT("Parameters"), parms))
return {};
return LoadSettingsFromString(parms, settings);
}
bool Effect::SaveUserPreset(
const RegistryPath & name, const EffectSettings &settings) const
{
// Save all settings as a single string value in the registry
wxString parms;
if (!SaveSettingsAsString(settings, parms))
return false;
return SetConfig(GetDefinition(), PluginSettings::Private,
name, wxT("Parameters"), parms);
}
RegistryPaths Effect::GetFactoryPresets() const
{
return {};
}
OptionalMessage Effect::LoadFactoryPreset(int id, EffectSettings &settings) const
{
return { nullptr };
}
OptionalMessage Effect::LoadFactoryDefaults(EffectSettings &settings) const
{
return LoadUserPreset(FactoryDefaultsGroup(), settings);
}
bool Effect::CanExportPresets() const
{
return true;
}
bool Effect::HasOptions() const
{
return false;
}
// EffectPlugin implementation
const EffectSettingsManager& Effect::GetDefinition() const
{
return *this;
}
NumericFormatID Effect::GetSelectionFormat()
{
if( !IsBatchProcessing() && FindProject() )
return ProjectNumericFormats::Get( *FindProject() )
.GetSelectionFormat();
return NumericConverterFormats::HoursMinsSecondsFormat().Internal();
}
wxString Effect::GetSavedStateGroup()
{
return wxT("SavedState");
}
// Effect implementation
bool Effect::SaveSettingsAsString(
const EffectSettings &settings, wxString & parms) const
{
CommandParameters eap;
ShuttleGetAutomation S;
S.mpEap = &eap;
if( VisitSettings( S, settings ) ){
;// got eap value using VisitSettings.
}
// Won't be needed in future
else if (!SaveSettings(settings, eap))
{
return false;
}
return eap.GetParameters(parms);
}
OptionalMessage Effect::LoadSettingsFromString(
const wxString & parms, EffectSettings &settings) const
{
// If the string starts with one of certain significant substrings,
// then the rest of the string is reinterpreted as part of a registry key,
// and a user or factory preset is then loaded.
// (Where did these prefixes come from? See EffectPresetsDialog; and
// ultimately the uses of it by EffectManager::GetPreset, which is used by
// the macro management dialog)
wxString preset = parms;
OptionalMessage result;
if (preset.StartsWith(kUserPresetIdent))
{
preset.Replace(kUserPresetIdent, wxEmptyString, false);
result = LoadUserPreset(UserPresetsGroup(preset), settings);
}
else if (preset.StartsWith(kFactoryPresetIdent))
{
preset.Replace(kFactoryPresetIdent, wxEmptyString, false);
auto presets = GetFactoryPresets();
result = LoadFactoryPreset(
make_iterator_range( presets ).index( preset ), settings );
}
else if (preset.StartsWith(kCurrentSettingsIdent))
{
preset.Replace(kCurrentSettingsIdent, wxEmptyString, false);
result = LoadUserPreset(CurrentSettingsGroup(), settings);
}
else if (preset.StartsWith(kFactoryDefaultsIdent))
{
preset.Replace(kFactoryDefaultsIdent, wxEmptyString, false);
result = LoadUserPreset(FactoryDefaultsGroup(), settings);
}
else
{
// If the string did not start with any of the significant substrings,
// then use VisitSettings or LoadSettings to reinterpret it,
// or use LoadSettings.
// This interprets what was written by SaveSettings, above.
CommandParameters eap(parms);
ShuttleSetAutomation S;
S.SetForValidating( &eap );
// VisitSettings returns false if not defined for this effect.
// To do: fix const_cast in use of VisitSettings
if ( !const_cast<Effect*>(this)->VisitSettings(S, settings) ) {
// the old method...
if (LoadSettings(eap, settings))
return { nullptr };
}
else if( !S.bOK )
result = {};
else{
result = { nullptr };
S.SetForWriting( &eap );
const_cast<Effect*>(this)->VisitSettings(S, settings);
}
}
if (!result)
{
using namespace BasicUI;
ShowMessageBox(
XO("%s: Could not load settings below. Default settings will be used.\n\n%s")
.Format( GetName(), preset ),
MessageBoxOptions{}.Caption(GetName()));
// We are using default settings and we still wish to continue.
result = { nullptr };
}
return result;
}
unsigned Effect::TestUIFlags(unsigned mask) {
return mask & mUIFlags;
}
bool Effect::IsBatchProcessing() const
{
return mIsBatch;
}
void Effect::SetBatchProcessing()
{
mIsBatch = true;
// Save effect's internal state in a special registry path
// just for this purpose
// If effect is not stateful, this step doesn't really matter, and the
// settings object is a dummy
auto dummySettings = MakeSettings();
SaveUserPreset(GetSavedStateGroup(), dummySettings);
}
void Effect::UnsetBatchProcessing()
{
mIsBatch = false;
// Restore effect's internal state from registry
// If effect is not stateful, this call doesn't really matter, and the
// settings object is a dummy
auto dummySettings = MakeSettings();
// Ignore failure
(void ) LoadUserPreset(GetSavedStateGroup(), dummySettings);
}
bool Effect::Delegate(Effect &delegate, EffectSettings &settings,
InstanceFinder finder)
{
if (!finder)
finder = DefaultInstanceFinder(delegate);
NotifyingSelectedRegion region;
region.setTimes( mT0, mT1 );
return delegate.DoEffect(settings, finder, mProjectRate, mTracks.get(),
mFactory, region, mUIFlags, nullptr);
}
bool Effect::TotalProgress(double frac, const TranslatableString &msg) const
{
auto updateResult = (mProgress ?
mProgress->Poll(frac * 1000, 1000, msg) :
BasicUI::ProgressResult::Success);
return (updateResult != BasicUI::ProgressResult::Success);
}
bool Effect::TrackProgress(
int whichTrack, double frac, const TranslatableString &msg) const
{
auto updateResult = (mProgress ?
mProgress->Poll((whichTrack + frac) * 1000,
(double) mNumTracks * 1000, msg) :
BasicUI::ProgressResult::Success);
return (updateResult != BasicUI::ProgressResult::Success);
}
bool Effect::TrackGroupProgress(
int whichGroup, double frac, const TranslatableString &msg) const
{
auto updateResult = (mProgress ?
mProgress->Poll((whichGroup + frac) * 1000,
(double) mNumGroups * 1000, msg) :
BasicUI::ProgressResult::Success);
return (updateResult != BasicUI::ProgressResult::Success);
}
void Effect::GetBounds(
const WaveTrack &track, sampleCount *start, sampleCount *len)
{
const auto t0 = std::max(mT0, track.GetStartTime());
const auto t1 = std::min(mT1, track.GetEndTime());
if (t1 > t0) {
*start = track.TimeToLongSamples(t0);
auto end = track.TimeToLongSamples(t1);
*len = end - *start;
}
else {
*start = 0;
*len = 0;
}
}
bool Effect::CheckWhetherSkipEffect(const EffectSettings &) const
{
return false;
}
double Effect::CalcPreviewInputLength(
const EffectSettings &, double previewLength) const
{
return previewLength;
}
|