diff --git a/src/Experimental.h b/src/Experimental.h index f1e1f9be2..58356ca0d 100644 --- a/src/Experimental.h +++ b/src/Experimental.h @@ -180,7 +180,7 @@ #define EXPERIMENTAL_REALTIME_EFFECTS // Define to include the effects rack (such as it is). -#define EXPERIMENTAL_EFFECTS_RACK +//#define EXPERIMENTAL_EFFECTS_RACK // Define to make the meters look like a row of LEDs //#define EXPERIMENTAL_METER_LED_STYLE diff --git a/src/Menus.cpp b/src/Menus.cpp index 6a2591b19..23f192683 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -2768,8 +2768,12 @@ void AudacityProject::NextWindow() #endif } - // Move focus to the window and bring it to the fore +#if !defined(__WXMSW__) + // Move focus to the window and bring it to the fore. We don't do it on Windows + // because the Raise() below will cause an Activation event to be issued and the + // Project's OnActivation() handler will take care of setting the focus. w->SetFocus(); +#endif #if defined(__WXMAC__) // Yes, I know...why 2 SetFocus() calls? Without the second one, focus diff --git a/src/PluginManager.cpp b/src/PluginManager.cpp index b96daa8dc..5493eb5da 100644 --- a/src/PluginManager.cpp +++ b/src/PluginManager.cpp @@ -49,7 +49,7 @@ #include -WX_DECLARE_STRING_HASH_MAP(wxString, ProviderMap); +WX_DECLARE_STRING_HASH_MAP(wxArrayString, ProviderMap); // ============================================================================ // @@ -381,7 +381,7 @@ int wxCALLBACK SortCompare(long item1, long item2, long WXUNUSED(sortData)) wxString *str1 = (wxString *) item1; wxString *str2 = (wxString *) item2; - return str2->Cmp(*str1); + return str1->Cmp(*str2); } class PluginRegistrationDialog : public wxDialog @@ -549,6 +549,7 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S) int iPathLen = 0; int x, y; wxRect iconrect; + int i = 0; for (ProviderMap::iterator iter = mMap.begin(); iter != mMap.end(); iter++, i++) { @@ -557,10 +558,9 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S) wxFileName fname = iter->first; wxString name = fname.GetName(); wxString path = fname.GetFullPath(); - wxString *key = new wxString(iter->second + name); mEffects->InsertItem(i, name, SHOW_CHECKED); - mEffects->SetItemPtrData(i, (wxUIntPtr) key); + mEffects->SetItemPtrData(i, (wxUIntPtr) new wxString(name)); mEffects->SetItem(i, COL_PATH, path); // Only need to get the icon width once @@ -732,14 +732,15 @@ void PluginRegistrationDialog::OnOK(wxCommandEvent & WXUNUSED(evt)) if (miState[i] == SHOW_CHECKED) { - li.SetId(i); - li.SetColumn(COL_PATH); - li.SetMask(wxLIST_MASK_TEXT); - mEffects->GetItem(li); - wxString path = li.GetText(); - mEffects->SetItemImage(i, SHOW_ARROW); - mm.RegisterPlugin(mMap[path], path); + wxArrayString providers = mMap[path]; + for (size_t j = 0, cnt = providers.GetCount(); j < cnt; j++) + { + if (mm.RegisterPlugin(providers[j], path)) + { + break; + } + } mEffects->SetItemImage(i, SHOW_CHECKED); } wxYield(); @@ -1750,7 +1751,7 @@ void PluginManager::CheckForUpdates(bool forceRescan) wxArrayString paths = mm.FindPluginsForProvider(plugID, plugPath); for (size_t i = 0, cnt = paths.GetCount(); i < cnt; i++) { - map[paths[i]] = plugID; + map[paths[i]].Add(plugID); } } } @@ -1781,7 +1782,7 @@ void PluginManager::CheckForUpdates(bool forceRescan) } } } - + // Allow the user to choose which ones to enable if (map.size() != 0) { diff --git a/src/effects/Effect.cpp b/src/effects/Effect.cpp index fcfd69df6..9db683710 100644 --- a/src/effects/Effect.cpp +++ b/src/effects/Effect.cpp @@ -2008,21 +2008,29 @@ BEGIN_EVENT_TABLE(EffectUIHost, wxDialog) END_EVENT_TABLE() EffectUIHost::EffectUIHost(wxWindow *parent, - EffectHostInterface *host, + Effect *effect, EffectUIClientInterface *client) -: wxDialog(parent, wxID_ANY, host->GetName(), +: wxDialog(parent, wxID_ANY, effect->GetName(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) { + SetName(effect->GetName()); SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); mParent = parent; - mHost = host; + mEffect = effect; mClient = client; + + mInitialized = false; + mClient->SetUIHost(this); } EffectUIHost::~EffectUIHost() { + if (mInitialized) + { + } + if (mClient) { mClient->CloseUI(); @@ -2071,13 +2079,30 @@ bool EffectUIHost::Initialize() LoadUserPresets(); - mClient->LoadUserPreset(mHost->GetCurrentSettingsGroup()); + mClient->LoadUserPreset(mEffect->GetCurrentSettingsGroup()); + + // Initialize the effect realtime processing + if (!mEffect->RealtimeInitialize()) + { + return false; + } + + EffectManager::Get().RealtimeAddEffect(mEffect); + + mInitialized = true; return true; } void EffectUIHost::OnClose(wxCloseEvent & WXUNUSED(evt)) { + if (mInitialized) + { + EffectManager::Get().RealtimeRemoveEffect(mEffect); + mEffect->RealtimeFinalize(); + mInitialized = false; + } + Hide(); mClient->CloseUI(); @@ -2093,7 +2118,14 @@ void EffectUIHost::OnOk(wxCommandEvent & WXUNUSED(evt)) return; } - mClient->SaveUserPreset(mHost->GetCurrentSettingsGroup()); + mClient->SaveUserPreset(mEffect->GetCurrentSettingsGroup()); + + if (mInitialized) + { + EffectManager::Get().RealtimeRemoveEffect(mEffect); + mEffect->RealtimeFinalize(); + mInitialized = false; + } if (IsModal()) { @@ -2107,7 +2139,7 @@ void EffectUIHost::OnOk(wxCommandEvent & WXUNUSED(evt)) return; } - mHost->Apply(); + mEffect->Apply(); if (!mClient->HideUI()) { @@ -2123,6 +2155,13 @@ void EffectUIHost::OnOk(wxCommandEvent & WXUNUSED(evt)) void EffectUIHost::OnCancel(wxCommandEvent & WXUNUSED(evt)) { + if (mInitialized) + { + EffectManager::Get().RealtimeRemoveEffect(mEffect); + mEffect->RealtimeFinalize(); + mInitialized = false; + } + if (IsModal()) { SetReturnCode(false); @@ -2145,7 +2184,7 @@ void EffectUIHost::OnCancel(wxCommandEvent & WXUNUSED(evt)) void EffectUIHost::OnPreview(wxCommandEvent & WXUNUSED(evt)) { - mHost->Preview(); + mEffect->Preview(); } void EffectUIHost::OnSettings(wxCommandEvent & evt) @@ -2202,13 +2241,13 @@ void EffectUIHost::OnSettings(wxCommandEvent & evt) sub = new wxMenu(); - sub->Append(0, wxString::Format(_("Type: %s"), mHost->GetFamily().c_str())); - sub->Append(0, wxString::Format(_("Name: %s"), mHost->GetName().c_str())); - sub->Append(0, wxString::Format(_("Version: %s"), mHost->GetVersion().c_str())); - sub->Append(0, wxString::Format(_("Vendor: %s"), mHost->GetVendor().c_str())); - sub->Append(0, wxString::Format(_("Description: %s"), mHost->GetDescription().c_str())); -// sub->Append(0, wxString::Format(_("Audio In: %d"), mHost->GetAudioInCount())); -// sub->Append(0, wxString::Format(_("Audio Out: %d"), mHost->GetAudioOutCount())); + sub->Append(0, wxString::Format(_("Type: %s"), mEffect->GetFamily().c_str())); + sub->Append(0, wxString::Format(_("Name: %s"), mEffect->GetName().c_str())); + sub->Append(0, wxString::Format(_("Version: %s"), mEffect->GetVersion().c_str())); + sub->Append(0, wxString::Format(_("Vendor: %s"), mEffect->GetVendor().c_str())); + sub->Append(0, wxString::Format(_("Description: %s"), mEffect->GetDescription().c_str())); +// sub->Append(0, wxString::Format(_("Audio In: %d"), mEffect->GetAudioInCount())); +// sub->Append(0, wxString::Format(_("Audio Out: %d"), mEffect->GetAudioOutCount())); menu->Append(0, _("About"), sub); @@ -2254,7 +2293,7 @@ void EffectUIHost::OnSaveAs(wxCommandEvent & WXUNUSED(evt)) name = text->GetValue(); if (mUserPresets.Index(name) == wxNOT_FOUND) { - mClient->SaveUserPreset(mHost->GetUserPresetsGroup(name)); + mClient->SaveUserPreset(mEffect->GetUserPresetsGroup(name)); LoadUserPresets(); break; } @@ -2301,7 +2340,7 @@ void EffectUIHost::OnUserPreset(wxCommandEvent & evt) { int preset = evt.GetId() - kUserPresetsID; - mClient->LoadUserPreset(mHost->GetUserPresetsGroup(mUserPresets[preset])); + mClient->LoadUserPreset(mEffect->GetUserPresetsGroup(mUserPresets[preset])); return; } @@ -2315,7 +2354,7 @@ void EffectUIHost::OnFactoryPreset(wxCommandEvent & evt) void EffectUIHost::OnDeletePreset(wxCommandEvent & evt) { - mHost->RemovePrivateConfigSubgroup(mHost->GetUserPresetsGroup(mUserPresets[evt.GetId() - kDeletePresetID])); + mEffect->RemovePrivateConfigSubgroup(mEffect->GetUserPresetsGroup(mUserPresets[evt.GetId() - kDeletePresetID])); LoadUserPresets(); @@ -2329,7 +2368,7 @@ void EffectUIHost::OnDeleteAllPresets(wxCommandEvent & WXUNUSED(evt)) wxICON_QUESTION | wxYES_NO); if (res == wxID_YES) { - mHost->RemovePrivateConfigSubgroup(mHost->GetUserPresetsGroup(wxEmptyString)); + mEffect->RemovePrivateConfigSubgroup(mEffect->GetUserPresetsGroup(wxEmptyString)); mUserPresets.Clear(); } @@ -2340,7 +2379,7 @@ void EffectUIHost::LoadUserPresets() { mUserPresets.Clear(); - mHost->GetPrivateConfigSubgroups(mHost->GetUserPresetsGroup(wxEmptyString), mUserPresets); + mEffect->GetPrivateConfigSubgroups(mEffect->GetUserPresetsGroup(wxEmptyString), mUserPresets); mUserPresets.Sort(); diff --git a/src/effects/Effect.h b/src/effects/Effect.h index b1aaf4895..84bec08df 100644 --- a/src/effects/Effect.h +++ b/src/effects/Effect.h @@ -478,7 +478,7 @@ class EffectUIHost : public wxDialog, public: // constructors and destructors EffectUIHost(wxWindow *parent, - EffectHostInterface *host, + Effect *effect, EffectUIClientInterface *client); virtual ~EffectUIHost(); @@ -504,10 +504,11 @@ private: private: wxWindow *mParent; - EffectHostInterface *mHost; + Effect *mEffect; EffectUIClientInterface *mClient; wxArrayString mUserPresets; + bool mInitialized; DECLARE_EVENT_TABLE(); }; diff --git a/src/effects/EffectManager.cpp b/src/effects/EffectManager.cpp index 53459db48..fcee1f34b 100644 --- a/src/effects/EffectManager.cpp +++ b/src/effects/EffectManager.cpp @@ -179,8 +179,6 @@ EffectManager::EffectManager() #if defined(EXPERIMENTAL_REALTIME_EFFECTS) mRealtimeLock.Enter(); - mRealtimeEffects = NULL; - mRealtimeCount = 0; mRealtimeActive = false; mRealtimeSuspended = true; mRealtimeLatency = 0; @@ -204,13 +202,6 @@ EffectManager::~EffectManager() delete mCategories; #endif -#if defined(EXPERIMENTAL_REALTIME_EFFECTS) - if (mRealtimeEffects) - { - delete [] mRealtimeEffects; - } -#endif - #if defined(EXPERIMENTAL_EFFECTS_RACK) // wxWidgets has already destroyed the rack since it was derived from wxFrame. So // no need to delete it here. @@ -422,9 +413,7 @@ void EffectManager::ShowRack() { GetRack()->Show(!GetRack()->IsShown()); } -#endif -#if defined(EXPERIMENTAL_REALTIME_EFFECTS) void EffectManager::RealtimeSetEffects(const EffectArray & effects) { int newCount = (int) effects.GetCount(); @@ -497,10 +486,37 @@ void EffectManager::RealtimeSetEffects(const EffectArray & effects) } #endif +#if defined(EXPERIMENTAL_REALTIME_EFFECTS) +void EffectManager::RealtimeAddEffect(Effect *effect) +{ + // Block RealtimeProcess() + RealtimeSuspend(); + + // Add to list of active effects + mRealtimeEffects.Add(effect); + + // Allow RealtimeProcess() to, well, process + RealtimeResume(); +} + +void EffectManager::RealtimeRemoveEffect(Effect *effect) +{ + // Block RealtimeProcess() + RealtimeSuspend(); + + // Remove from list of active effects + mRealtimeEffects.Remove(effect); + + // Allow RealtimeProcess() to, well, process + RealtimeResume(); +} + +#endif + void EffectManager::RealtimeInitialize() { // No need to do anything if there are no effects - if (!mRealtimeCount) + if (mRealtimeEffects.IsEmpty()) { return; } @@ -513,7 +529,7 @@ void EffectManager::RealtimeInitialize() mRealtimeActive = true; // Tell each effect to get ready for action - for (int i = 0; i < mRealtimeCount; i++) + for (int i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++) { mRealtimeEffects[i]->RealtimeInitialize(); } @@ -531,7 +547,7 @@ void EffectManager::RealtimeFinalize() mRealtimeLatency = 0; // Tell each effect to clean up as well - for (int i = 0; i < mRealtimeCount; i++) + for (int i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++) { mRealtimeEffects[i]->RealtimeFinalize(); } @@ -554,7 +570,7 @@ void EffectManager::RealtimeSuspend() mRealtimeSuspended = true; // And make sure the effects don't either - for (int i = 0; i < mRealtimeCount; i++) + for (int i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++) { mRealtimeEffects[i]->RealtimeSuspend(); } @@ -574,7 +590,7 @@ void EffectManager::RealtimeResume() } // Tell the effects to get ready for more action - for (int i = 0; i < mRealtimeCount; i++) + for (int i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++) { mRealtimeEffects[i]->RealtimeResume(); } @@ -595,7 +611,7 @@ sampleCount EffectManager::RealtimeProcess(int group, int chans, float rate, flo // Can be suspended because of the audio stream being paused or because effects // have been suspended, so allow the samples to pass as-is. - if (mRealtimeSuspended || mRealtimeCount == 0) + if (mRealtimeSuspended || mRealtimeEffects.IsEmpty()) { mRealtimeLock.Leave(); return numSamples; @@ -619,7 +635,7 @@ sampleCount EffectManager::RealtimeProcess(int group, int chans, float rate, flo // Now call each effect in the chain while swapping buffer pointers to feed the // output of one effect as the input to the next effect - for (int i = 0; i < mRealtimeCount; i++) + for (int i = 0, cnt = mRealtimeEffects.GetCount(); i < cnt; i++) { mRealtimeEffects[i]->RealtimeProcess(group, chans, rate, ibuf, obuf, numSamples); @@ -635,7 +651,7 @@ sampleCount EffectManager::RealtimeProcess(int group, int chans, float rate, flo // Once we're done, we might wind up with the last effect storing its results // in the temporary buffers. If that's the case, we need to copy it over to // the caller's buffers. This happens when the number of effects is odd. - if (mRealtimeCount & 1) + if (mRealtimeEffects.GetCount() & 1) { for (int i = 0; i < chans; i++) { diff --git a/src/effects/EffectManager.h b/src/effects/EffectManager.h index fa330622f..4847de042 100644 --- a/src/effects/EffectManager.h +++ b/src/effects/EffectManager.h @@ -97,6 +97,8 @@ class AUDACITY_DLL_API EffectManager #if defined(EXPERIMENTAL_REALTIME_EFFECTS) // Realtime effect processing + void RealtimeAddEffect(Effect *effect); + void RealtimeRemoveEffect(Effect *effect); void RealtimeSetEffects(const EffectArray & mActive); void RealtimeInitialize(); void RealtimeFinalize(); @@ -161,8 +163,7 @@ private: #if defined(EXPERIMENTAL_REALTIME_EFFECTS) wxCriticalSection mRealtimeLock; - Effect **mRealtimeEffects; - int mRealtimeCount; + EffectArray mRealtimeEffects; int mRealtimeLatency; bool mRealtimeSuspended; bool mRealtimeActive;