From 071cd0f066d010b26d89e7b84ad1a0dc1bf9184c Mon Sep 17 00:00:00 2001 From: lllucius Date: Thu, 27 Nov 2014 12:22:41 +0000 Subject: [PATCH] Disables the rack and fixes a couple of other things Needed to redo a bit of code so that effects would work without the rack in the middle. I wanted to disconnect it completely as I'm not sure it something that will be kept around. During realtime preview, effects will be applied in the order their dialogs were opened...hmmm...what happens if they don't have a dialog??? I look into that. Fixed the focus target for windows when cycling among active windows as suggested by David B. Fixed plugin registration if the plugins were located in the "Plug-ins" folder. I believe this problem may have played a role in the duplicate menu items. --- src/Experimental.h | 2 +- src/Menus.cpp | 6 ++- src/PluginManager.cpp | 27 ++++++------ src/effects/Effect.cpp | 77 ++++++++++++++++++++++++++--------- src/effects/Effect.h | 5 ++- src/effects/EffectManager.cpp | 54 +++++++++++++++--------- src/effects/EffectManager.h | 5 ++- 7 files changed, 119 insertions(+), 57 deletions(-) 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;