1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-16 16:10:06 +02:00

Merge branch 'master' into scrubbing

This commit is contained in:
Paul Licameli 2015-05-27 18:46:47 -04:00
commit c14432bbe6
11 changed files with 128 additions and 148 deletions

3
include/audacity/EffectInterface.h Normal file → Executable file
View File

@ -94,7 +94,8 @@ public:
virtual ~EffectHostInterface() {};
virtual double GetDefaultDuration() = 0;
virtual double GetDuration(bool *isSelection = NULL) = 0;
virtual double GetDuration() = 0;
virtual wxString GetDurationFormat() = 0;
virtual void SetDuration(double seconds) = 0;
virtual bool Apply() = 0;

View File

@ -371,9 +371,11 @@ enum
STATE_COUNT
};
WX_DEFINE_ARRAY(PluginDescriptor *, DescriptorArray);
struct ItemData
{
PluginDescriptor *plug;
DescriptorArray plugs;
wxString name;
wxString path;
int state;
@ -582,7 +584,7 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
{
int x;
mEffects->GetTextExtent(mStates[i], &x, NULL);
colWidths[COL_State] = wxMax(colWidths[COL_State], x);
colWidths[COL_State] = wxMax(colWidths[COL_State], x + 4); // 2 pixel margin on each side
}
PluginManager & pm = PluginManager::Get();
@ -598,7 +600,7 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
wxString path = plug.GetPath();
ItemData & item = mItems[path]; // will create new entry
item.plug = &plug;
item.plugs.Add(&plug);
item.path = path;
item.state = plug.IsEnabled() ? STATE_Enabled : STATE_Disabled;
item.valid = plug.IsValid();
@ -614,7 +616,7 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S)
{
wxFileName fname = path;
item.name = fname.GetName().Trim(false).Trim(true);
if (!plug.IsValid())
if (!item.valid)
{
item.state = STATE_New;
}
@ -929,7 +931,7 @@ void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt))
ItemData & item = iter->second;
wxString path = item.path;
if (item.state == STATE_Enabled && item.plug->GetPluginType() == PluginTypeStub)
if (item.state == STATE_Enabled && item.plugs[0]->GetPluginType() == PluginTypeStub)
{
enableCount++;
}
@ -945,37 +947,45 @@ void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt))
ProgressDialog progress(_("Plugin Manager: Effects"), msg, pdlgHideStopButton);
progress.CenterOnParent();
int status;
int i = 0;
for (ItemDataMap::iterator iter = mItems.begin(); iter != mItems.end(); ++iter)
{
ItemData & item = iter->second;
wxString path = item.path;
if (item.state == STATE_Enabled && item.plug->GetPluginType() == PluginTypeStub)
if (item.state == STATE_Enabled && item.plugs[0]->GetPluginType() == PluginTypeStub)
{
last3 = last3.AfterFirst(wxT('\n')) + item.path + wxT("\n");
status = progress.Update(++i, enableCount, wxString::Format(_("Enabling effect:\n\n%s"), last3.c_str()));
int status = progress.Update(++i, enableCount, wxString::Format(_("Enabling effect:\n\n%s"), last3.c_str()));
if (!status)
{
break;
}
if (mm.RegisterPlugin(item.plug->GetProviderID(), path))
// Try to register the plugin via each provider until one succeeds
for (size_t j = 0, cnt = item.plugs.GetCount(); j < cnt; j++)
{
// Registration successful, so remove the stub
PluginID ID = item.plug->GetProviderID() + wxT("_") + path;
pm.mPlugins.erase(ID);
if (mm.RegisterPlugin(item.plugs[j]->GetProviderID(), path))
{
for (size_t j = 0, cnt = item.plugs.GetCount(); j < cnt; j++)
{
pm.mPlugins.erase(item.plugs[j]->GetProviderID() + wxT("_") + path);
}
break;
}
}
}
else if (item.state == STATE_New)
{
item.plug->SetValid(false);
for (size_t j = 0, cnt = item.plugs.GetCount(); j < cnt; j++)
{
item.plugs[j]->SetValid(false);
}
}
else if (item.state != STATE_New)
{
item.plug->SetEnabled(item.state == STATE_Enabled);
item.plug->SetValid(item.valid);
item.plugs[0]->SetEnabled(item.state == STATE_Enabled);
item.plugs[0]->SetValid(item.valid);
}
}
@ -2092,17 +2102,20 @@ void PluginManager::CheckForUpdates()
continue;
}
pathIndex.Add(plug.GetProviderID() + plug.GetPath().BeforeFirst(wxT(';')));
pathIndex.Add(plug.GetPath().BeforeFirst(wxT(';')));
}
ProviderMap map;
// Always check for and disable missing plugins
// Check all known plugins to ensure they are still valid and scan for new ones.
//
// Since the user's saved presets are in the registery, never delete them. That is
// a job for the plugin manager UI (once it is written).
// All new plugins get a stub entry created that will remain in place until the
// user enables or disables the plugin.
//
// Also check for plugins that are no longer valid.
// Becuase we use the plugins "path" as returned by the providers, we can actually
// have multiple providers report the same path since, at this point, they only
// know that the path might possibly be one supported by the provider.
//
// When the user enables the plugin, each provider that reported it will be asked
// to register the plugin.
for (PluginMap::iterator iter = mPlugins.begin(); iter != mPlugins.end(); ++iter)
{
PluginDescriptor & plug = iter->second;
@ -2120,6 +2133,7 @@ void PluginManager::CheckForUpdates()
{
if (!mm.IsProviderValid(plugID, plugPath))
{
plug.SetEnabled(false);
plug.SetValid(false);
}
else
@ -2128,11 +2142,17 @@ void PluginManager::CheckForUpdates()
wxArrayString paths = mm.FindPluginsForProvider(plugID, plugPath);
for (size_t i = 0, cnt = paths.GetCount(); i < cnt; i++)
{
wxString path = paths[i];
wxASSERT(!path.IsEmpty());
if (pathIndex.Index(plugID + path.BeforeFirst(wxT(';'))) == wxNOT_FOUND)
wxString path = paths[i].BeforeFirst(wxT(';'));;
if (pathIndex.Index(path) == wxNOT_FOUND)
{
map[path].Add(plugID);
PluginID ID = plugID + wxT("_") + path;
PluginDescriptor & plug = mPlugins[ID]; // This will create a new descriptor
plug.SetPluginType(PluginTypeStub);
plug.SetID(ID);
plug.SetProviderID(plugID);
plug.SetPath(path);
plug.SetEnabled(false);
plug.SetValid(false);
}
}
}
@ -2140,35 +2160,10 @@ void PluginManager::CheckForUpdates()
else if (plugType != PluginTypeNone && plugType != PluginTypeStub)
{
plug.SetValid(mm.IsPluginValid(plug.GetProviderID(), plugPath));
}
}
// The provider map now includes only paths that haven't been seen before,
// so create stub descriptors for them.
//
// In 2.1.0, they were called "placeholder" in the registry, but since 2.1.1+
// use them slightly differently, they are not called "stub" in the registry
// and the "placeholder" are left intact. This way switching between 2.1.0
// and 2.1.1+ doesn't cause rescans each time.
for (ProviderMap::iterator iter = map.begin(); iter != map.end(); ++iter)
{
wxString & path = iter->first;
wxArrayString & providers = iter->second;
// Create a descriptor for each provider. Don't know why there would
// be multiple providers for the same path, but might as well.
for (size_t i = 0, cnt = providers.GetCount(); i < cnt; i++)
{
PluginID ID = providers[i] + wxT("_") + path;
// Stub descriptors have a plugin type of PluginTypeNone and the ID
// is the path. They are also marked as disabled and not valid.
PluginDescriptor & plug = mPlugins[ID]; // This will create a new descriptor
plug.SetPluginType(PluginTypeStub);
plug.SetID(ID);
plug.SetProviderID(providers[i]);
plug.SetPath(path);
plug.SetEnabled(false);
plug.SetValid(false);
if (!plug.IsValid())
{
plug.SetEnabled(false);
}
}
}

11
src/effects/DtmfGen.cpp Normal file → Executable file
View File

@ -303,16 +303,13 @@ void EffectDtmf::PopulateOrExchange(ShuttleGui & S)
vldAmp.SetRange(MIN_Amplitude, MAX_Amplitude);
S.Id(ID_Amplitude).AddTextBox(_("Amplitude (0-1):"), wxT(""), 10)->SetValidator(vldAmp);
bool isSelection;
double duration = GetDuration(&isSelection);
S.AddPrompt(_("Duration:"));
mDtmfDurationT = new
NumericTextCtrl(NumericConverter::TIME,
S.GetParent(),
ID_Duration,
isSelection ? _("hh:mm:ss + samples") : _("hh:mm:ss + milliseconds"),
duration,
GetDurationFormat(),
GetDuration(),
mProjectRate,
wxDefaultPosition,
wxDefaultSize,
@ -370,8 +367,8 @@ bool EffectDtmf::TransferDataFromWindow()
return false;
}
// dtmfDutyCycle = (double) mDtmfDutyCycleS->GetValue() / SCL_DutyCycle;
// SetDuration(mDtmfDurationT->GetValue());
dtmfDutyCycle = (double) mDtmfDutyCycleS->GetValue() / SCL_DutyCycle;
SetDuration(mDtmfDurationT->GetValue());
// recalculate to make sure all values are up-to-date. This is especially
// important if the user did not change any values in the dialog

View File

@ -705,49 +705,21 @@ double Effect::GetDefaultDuration()
return 30.0;
}
double Effect::GetDuration(bool *isSelection)
double Effect::GetDuration()
{
if (mT1 > mT0)
{
// there is a selection: let's fit in there...
// MJS: note that this is just for the TTC and is independent of the track rate
// but we do need to make sure we have the right number of samples at the project rate
double quantMT0 = QUANTIZED_TIME(mT0, mProjectRate);
double quantMT1 = QUANTIZED_TIME(mT1, mProjectRate);
mDuration = quantMT1 - quantMT0;
if (isSelection)
{
*isSelection = true;
}
return mDuration;
}
if (isSelection)
{
*isSelection = false;
}
GetPrivateConfig(GetCurrentSettingsGroup(), wxT("LastUsedDuration"), mDuration, 0.0);
if (mDuration > 0.0)
{
return mDuration;
}
if (mDuration < 0.0)
{
mDuration = 0.0;
}
if (GetType() == EffectTypeGenerate)
{
mDuration = GetDefaultDuration();
}
return mDuration;
}
wxString Effect::GetDurationFormat()
{
return mDurationFormat;
}
void Effect::SetDuration(double seconds)
{
if (seconds < 0.0)
@ -755,14 +727,17 @@ void Effect::SetDuration(double seconds)
seconds = 0.0;
}
if (mDuration != seconds)
if (GetType() == EffectTypeGenerate)
{
SetPrivateConfig(GetCurrentSettingsGroup(), wxT("LastUsedDuration"), seconds);
}
mDuration = seconds;
mT1 = mT0 + mDuration;
mSetDuration = mDuration;
mIsSelection = false;
return;
}
@ -1170,9 +1145,33 @@ bool Effect::DoEffect(wxWindow *parent,
mProjectRate = projectRate;
mParent = parent;
mTracks = list;
bool isSelection = false;
mDuration = 0.0;
if (GetType() == EffectTypeGenerate)
{
GetPrivateConfig(GetCurrentSettingsGroup(), wxT("LastUsedDuration"), mDuration, GetDefaultDuration());
}
mT0 = selectedRegion->t0();
mT1 = selectedRegion->t1();
mDuration = GetDuration();
if (mT1 > mT0)
{
// there is a selection: let's fit in there...
// MJS: note that this is just for the TTC and is independent of the track rate
// but we do need to make sure we have the right number of samples at the project rate
double quantMT0 = QUANTIZED_TIME(mT0, mProjectRate);
double quantMT1 = QUANTIZED_TIME(mT1, mProjectRate);
mDuration = quantMT1 - quantMT0;
mT1 = mT0 + mDuration;
isSelection = true;
}
mDurationFormat = isSelection ? _("hh:mm:ss + samples") : _("hh:mm:ss + milliseconds");
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
mF0 = selectedRegion->f0();
mF1 = selectedRegion->f1();
@ -2523,21 +2522,24 @@ void Effect::Preview(bool dryOnly)
if (token) {
int previewing = eProgressSuccess;
mProgress = new ProgressDialog(GetName(),
_("Previewing"), pdlgHideCancelButton);
// The progress dialog must be deleted before stopping the stream
// to allow events to flow to the app during StopStream processing.
// The progress dialog blocks these events.
ProgressDialog *progress =
new ProgressDialog(GetName(), _("Previewing"), pdlgHideCancelButton);
while (gAudioIO->IsStreamActive(token) && previewing == eProgressSuccess) {
::wxMilliSleep(100);
previewing = mProgress->Update(gAudioIO->GetStreamTime() - mT0, mT1);
previewing = progress->Update(gAudioIO->GetStreamTime() - mT0, mT1);
}
delete progress;
gAudioIO->StopStream();
while (gAudioIO->IsBusy()) {
::wxMilliSleep(100);
}
delete mProgress;
mProgress = NULL;
}
else {
wxMessageBox(_("Error while opening sound device. Please check the playback device settings and the project sample rate."),

5
src/effects/Effect.h Normal file → Executable file
View File

@ -144,7 +144,8 @@ class AUDACITY_DLL_API Effect : public wxEvtHandler,
// EffectHostInterface implementation
virtual double GetDefaultDuration();
virtual double GetDuration(bool *isSelection = NULL);
virtual double GetDuration();
virtual wxString GetDurationFormat();
virtual void SetDuration(double duration);
virtual bool Apply();
@ -400,7 +401,9 @@ private:
bool mIsLinearEffect;
bool mPreviewWithNotSelected;
bool mIsSelection;
double mDuration;
wxString mDurationFormat;
// mSetDuration should ONLY be set when SetDuration() is called.
double mSetDuration;

19
src/effects/Noise.cpp Normal file → Executable file
View File

@ -224,20 +224,17 @@ void EffectNoise::PopulateOrExchange(ShuttleGui & S)
vldAmp.SetRange(MIN_Amp, MAX_Amp);
S.AddTextBox(_("Amplitude (0-1):"), wxT(""), 12)->SetValidator(vldAmp);
bool isSelection;
double duration = GetDuration(&isSelection);
S.AddPrompt(_("Duration:"));
mNoiseDurationT = new
NumericTextCtrl(NumericConverter::TIME,
S.GetParent(),
wxID_ANY,
isSelection ? _("hh:mm:ss + samples") : _("hh:mm:ss + milliseconds"),
duration,
mProjectRate,
wxDefaultPosition,
wxDefaultSize,
true);
S.GetParent(),
wxID_ANY,
GetDurationFormat(),
GetDuration(),
mProjectRate,
wxDefaultPosition,
wxDefaultSize,
true);
mNoiseDurationT->SetName(_("Duration"));
mNoiseDurationT->EnableMenu();
S.AddWindow(mNoiseDurationT, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL);

7
src/effects/Silence.cpp Normal file → Executable file
View File

@ -55,16 +55,13 @@ void EffectSilence::PopulateOrExchange(ShuttleGui & S)
{
S.StartHorizontalLay();
{
bool isSelection;
double duration = GetDuration(&isSelection);
S.AddPrompt(_("Duration:"));
mDurationT = new
NumericTextCtrl(NumericConverter::TIME,
S.GetParent(),
wxID_ANY,
isSelection ? _("hh:mm:ss + samples") : _("hh:mm:ss + milliseconds"),
duration,
GetDurationFormat(),
GetDuration(),
mProjectRate,
wxDefaultPosition,
wxDefaultSize,

19
src/effects/ToneGen.cpp Normal file → Executable file
View File

@ -394,20 +394,17 @@ void EffectToneGen::PopulateOrExchange(ShuttleGui & S)
t->SetValidator(vldAmplitude);
}
bool isSelection;
double duration = GetDuration(&isSelection);
S.AddPrompt(_("Duration:"));
mToneDurationT = new
NumericTextCtrl(NumericConverter::TIME,
S.GetParent(),
wxID_ANY,
isSelection ? _("hh:mm:ss + samples") : _("hh:mm:ss + milliseconds"),
duration,
mProjectRate,
wxDefaultPosition,
wxDefaultSize,
true);
S.GetParent(),
wxID_ANY,
GetDurationFormat(),
GetDuration(),
mProjectRate,
wxDefaultPosition,
wxDefaultSize,
true);
mToneDurationT->SetName(_("Duration"));
mToneDurationT->EnableMenu();
S.AddWindow(mToneDurationT, wxALIGN_LEFT | wxALL);

View File

@ -3515,17 +3515,14 @@ void VSTEffect::BuildPlain()
// Add the duration control for generators
if (GetType() == EffectTypeGenerate)
{
bool isSelection;
double duration = mHost->GetDuration(&isSelection);
wxControl *item = new wxStaticText(scroller, 0, _("Duration:"));
gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
mDuration = new
NumericTextCtrl(NumericConverter::TIME,
scroller,
ID_Duration,
isSelection ? _("hh:mm:ss + samples") : _("hh:mm:ss + milliseconds"),
duration,
mHost->GetDurationFormat(),
mHost->GetDuration(),
mSampleRate,
wxDefaultPosition,
wxDefaultSize,

7
src/effects/ladspa/LadspaEffect.cpp Normal file → Executable file
View File

@ -1146,17 +1146,14 @@ bool LadspaEffect::PopulateUI(wxWindow *parent)
// Add the duration control for generators
if (GetType() == EffectTypeGenerate)
{
bool isSelection;
double duration = mHost->GetDuration(&isSelection);
item = new wxStaticText(w, 0, _("Duration:"));
gridSizer->Add(item, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT | wxALL, 5);
mDuration = new
NumericTextCtrl(NumericConverter::TIME,
w,
ID_Duration,
isSelection ? _("hh:mm:ss + samples") : _("hh:mm:ss + milliseconds"),
duration,
mHost->GetDurationFormat(),
mHost->GetDuration(),
mSampleRate,
wxDefaultPosition,
wxDefaultSize,

7
src/effects/lv2/LV2Effect.cpp Normal file → Executable file
View File

@ -1579,17 +1579,14 @@ bool LV2Effect::BuildPlain()
wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
bool isSelection;
double duration = mHost->GetDuration(&isSelection);
wxWindow *item = new wxStaticText(w, 0, _("&Duration:"));
sizer->Add(item, 0, wxALIGN_CENTER | wxALL, 5);
mDuration = new
NumericTextCtrl(NumericConverter::TIME,
w,
ID_Duration,
isSelection ? _("hh:mm:ss + samples") : _("hh:mm:ss + milliseconds"),
duration,
mHost->GetDurationFormat(),
mHost->GetDuration(),
mSampleRate,
wxDefaultPosition,
wxDefaultSize,