27#include "../ProjectWindowBase.h"
28#include "../TrackPanelAx.h"
96#include "../../images/Effect.h"
98#include "../CommonCommandFlags.h"
100#include "../prefs/GUISettings.h"
102#include "../ProjectAudioManager.h"
105#include "../commands/AudacityCommand.h"
106#include "../commands/CommandContext.h"
109#include "../widgets/AButton.h"
111#include <wx/button.h>
112#include <wx/checkbox.h>
113#include <wx/dcclient.h>
114#include <wx/dcmemory.h>
116#include <wx/settings.h>
118#include <wx/textctrl.h>
167 const std::shared_ptr<EffectSettingsAccess> &pSide = {});
170 std::unique_ptr<Message> pMessage)
override;
171 void Set(std::unique_ptr<Message> pMessage)
override;
172 void Flush()
override;
176 const std::shared_ptr<EffectSettingsAccess>
mpMain;
177 const std::weak_ptr<EffectSettingsAccess>
mwSide;
181EffectSettingsAccessTee::EffectSettingsAccessTee(
183 const std::shared_ptr<EffectSettingsAccess> &pSide
184) : mpMain{
main.shared_from_this() }
194 std::unique_ptr<Message> pMessage)
197 if (
auto pSide =
mwSide.lock())
199 pMessage ? pMessage->Clone() :
nullptr);
207 if (
auto pSide =
mwSide.lock())
208 pSide->Set(pMessage ? pMessage->Clone() :
nullptr);
210 mpMain->Set(std::move(pMessage));
216 if (
auto pSide =
mwSide.lock())
223 return mpMain->IsSameAs(other);
230 const std::shared_ptr<RealtimeEffectState> &pPriorState)
232 wxDefaultPosition, wxDefaultSize,
233 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX)
234, mEffectUIHost{ effect }
238, mpGivenAccess{ access.shared_from_this() }
239, mpAccess{ mpGivenAccess }
240, mwState{ pPriorState }
243, mSupportsRealtime{ mEffectUIHost.GetDefinition().SupportsRealtime() }
244, mHadPriorState{ (pPriorState != nullptr) }
245, mpInstance{ InitializeInstance() }
246, mpOutputs{ pPriorState ? pPriorState->GetOutputs() : nullptr }
250#if defined(__WXMAC__)
258 SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
276 const auto pServices =
278 return (!pServices || pServices->TransferDataToWindow(
mpAccess->Get())) &&
282 wxDialogWrapper::TransferDataToWindow();
288 if (!wxDialogWrapper::Validate())
292 if (!wxDialogWrapper::TransferDataFromWindow())
302 const auto pServices =
305 result = (!pServices || pServices->TransferDataFromWindow(
settings));
309 const auto seconds =
settings.extra.GetDuration();
335 return wxDialogWrapper::ShowModal();
347 wxDefaultPosition, wxDefaultSize,
true);
348 pBtn->SetImages(ImageOff, ImageOff, ImageOn, ImageOn, ImageOff);
358 constexpr int margin = 3;
362 S.SetBorder( margin );
364 S.StartHorizontalLay(wxEXPAND, 0);
371 .Position(wxALIGN_CENTER | wxTOP | wxBOTTOM)
377 .ToolTip(
XO(
"Manage presets and options"))
378 .AddButton(
XO(
"Presets && settings"), wxALIGN_CENTER | wxTOP | wxBOTTOM );
389 .ToolTip(
XO(
"Preview effect"))
391 wxALIGN_CENTER | wxTOP | wxBOTTOM );
408 .AddButton(
XXO(
"&Apply"),
409 wxALIGN_CENTER | wxTOP | wxBOTTOM );
416 .AddButton(
XXO(
"Debu&g"),
417 wxALIGN_CENTER | wxTOP | wxBOTTOM );
420 S.EndHorizontalLay();
439 uw->SetMinSize(wxSize(wxMax(600,
mParent->GetSize().GetWidth() * 2 / 3),
440 mParent->GetSize().GetHeight() / 2));
451 S.StartHorizontalLay( wxEXPAND );
455 .AddWindow((w = uw.release()));
457 S.EndHorizontalLay();
479 SetMinSize(GetSize());
492 wxDialogWrapper::OnInitDialog(evt);
494#if wxCHECK_VERSION(3, 0, 0)
505 wxTextCtrl *focused = wxDynamicCast(
FindFocus(), wxTextCtrl);
508 focused->SelectAll();
582 EndModal(evt.GetId());
592 auto cleanup =
finally( [&] {
mApplyBtn->Enable(); } );
637 static const auto specialVersion =
XO(
"n/a");
639 if (result == specialVersion.MSGID())
640 result = specialVersion.Translation();
658 auto sub = std::make_unique<wxMenu>();
659 for (
size_t i = 0, cnt =
mUserPresets.size(); i < cnt; i++)
663 menu.Append(0,
_(
"User Presets"), sub.release());
674 auto sub = std::make_unique<wxMenu>();
675 for (
size_t i = 0, cnt =
mUserPresets.size(); i < cnt; i++)
679 menu.Append(0,
_(
"Delete Preset"), sub.release());
682 menu.AppendSeparator();
687 auto sub = std::make_unique<wxMenu>();
691 sub->AppendSeparator();
692 for (
size_t i = 0, cnt =
factory.size(); i < cnt; i++)
703 menu.Append(0,
_(
"Factory Presets"), sub.release());
706 menu.AppendSeparator();
711 menu.AppendSeparator();
714 menu.AppendSeparator();
717 auto sub = std::make_unique<wxMenu>();
720 sub->Append(
kDummyID, wxString::Format(
_(
"Type: %s"),
721 ::wxGetTranslation( definition.GetFamily().Translation() )));
722 sub->Append(
kDummyID, wxString::Format(
_(
"Name: %s"), definition.GetName().Translation()));
723 sub->Append(
kDummyID, wxString::Format(
_(
"Version: %s"),
725 sub->Append(
kDummyID, wxString::Format(
_(
"Vendor: %s"), definition.GetVendor().Translation()));
726 sub->Append(
kDummyID, wxString::Format(
_(
"Description: %s"), definition.GetDescription().Translation()));
727 sub->Bind(wxEVT_MENU, [](
auto&){},
kDummyID);
729 menu.Append(0,
_(
"About"), sub.release());
732 wxWindow *btn = FindWindow(
kMenuID);
733 wxRect r = btn->GetRect();
736 { r.GetLeft(), r.GetBottom() }
808 wxICON_QUESTION | wxYES_NO);
830 S.StartVerticalLay(1);
832 S.StartHorizontalLay(wxALIGN_LEFT, 0);
834 text =
S.AddTextBox(
XXO(
"Preset name:"),
name, 30);
836 S.EndHorizontalLay();
838 S.AddStandardButtons();
844 dlg.SetSize(dlg.GetSizer()->GetMinSize());
850 int rc = dlg.ShowModal();
857 name = text->GetValue();
862 XO(
"You must specify a name"),
873 XO(
"Preset already exists.\n\nReplace?"),
875 wxYES_NO | wxCANCEL | wxICON_EXCLAMATION );
877 int choice = md.ShowModal();
878 if (choice == wxID_CANCEL)
883 if (choice == wxID_NO)
949 if (!IsEscapeKey(evt))
975 wxBitmap mod(pic.GetWidth() + 6, pic.GetHeight() + 6, 24);
976 dc.SelectObject(mod);
978#if defined(__WXGTK__)
979 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND);
981 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
984 dc.SetBackground(wxBrush(newColour));
996 dc.DrawBitmap(pic, offset, offset,
true);
998 dc.SelectObject(wxNullBitmap);
1034 std::shared_ptr<EffectInstance> result;
1036 auto mpState =
mwState.lock();
1038 bool priorState = (mpState !=
nullptr);
1041 mCapturing = gAudioIO->IsStreamActive() && gAudioIO->GetNumCaptureChannels() > 0 && !gAudioIO->IsMonitoring();
1051 result = mpState->GetInstance();
1056 mpAccess = std::make_shared<EffectSettingsAccessTee>(
1067 switch (event.
type) {
1068 case AudioIOEvent::CAPTURE:
1069 OnCapture(event); break;
1115 std::shared_ptr<EffectInstance> pInstance;
1117 *
project, host, client, pInstance, access } };
1122 if (dlg->Initialize()) {
1123 auto pEditor = dlg->GetEditor();
1125 return { dlg.release(), pInstance, pEditor };
1132#include "../ProjectWindow.h"
1133#include "../SelectUtilities.h"
1134#include "../TrackPanel.h"
1136#include "../commands/CommandManager.h"
1161 XO(
"This plugin could not be loaded.\nIt may have been deleted."),
1163 .Caption(
XO(
"Plugin Error")));
1182 auto nTracksOriginally =
tracks.Size();
1184 wxWindow *parent =
nullptr;
1185 if (focus !=
nullptr) {
1186 parent = focus->GetParent();
1189 bool success =
false;
1190 auto cleanup =
finally( [&] {
1202 bool anyTracks = !range.empty();
1203 bool clean = std::all_of(range.begin(), range.end(),
1204 [](
const WaveTrack *t){ return t->GetEndTime() == 0; });
1212 const auto pAccess =
1213 std::make_shared<SimpleEffectSettingsAccess>(*pSettings);
1216 -> std::optional<std::shared_ptr<EffectInstanceEx>>
1221 std::shared_ptr<EffectInstance> pInstance;
1222 std::shared_ptr<EffectInstanceEx> pInstanceEx;
1226 !pServices->ShowHostInterface(*effect,
1230 else if (!(pInstanceEx =
1231 std::dynamic_pointer_cast<EffectInstanceEx>(pInstance)
1238 return { pInstanceEx };
1241 success = effect->DoEffect(
settings, finder,
1272 auto lastEffectDesc =
XO(
"Repeat %s").Format(shortDesc);
1276 commandManager.Modify(
wxT(
"RepeatLastGenerator"), lastEffectDesc);
1277 menuManager.mLastGenerator = ID;
1281 commandManager.Modify(
wxT(
"RepeatLastEffect"), lastEffectDesc);
1282 menuManager.mLastEffect = ID;
1286 commandManager.Modify(
wxT(
"RepeatLastAnalyzer"), lastEffectDesc);
1287 menuManager.mLastAnalyzer = ID;
1292 commandManager.Modify(
wxT(
"RepeatLastTool"), lastEffectDesc);
1293 menuManager.mLastTool = ID;
1309 if (!anyTracks || (clean && selectedRegion.t0() == 0.0))
1315 window.RedrawProject();
1317 if (focus !=
nullptr && focus->GetParent()==parent) {
1325 if (
tracks.Size() > nTracksOriginally) {
1327 trackPanel.VerticalScroll( 1.0 );
1330 auto pTrack = *
tracks.Selected().begin();
1332 pTrack = *
tracks.begin();
1351 int additionalButtons)
1355 mAdditionalButtons = additionalButtons;
1373 S.StartVerticalLay(
true);
1382 SetMinSize(GetSize());
EVT_MENU(OnSetPlayRegionToSelectionID, AdornedRulerPanel::OnSetPlayRegionToSelection) EVT_COMMAND(OnTogglePinnedStateID
wxEVT_COMMAND_BUTTON_CLICKED
int main(int argc, char *argv[])
EVT_MENU_RANGE(FileHistory::ID_RECENT_FIRST, FileHistory::ID_RECENT_LAST, AudacityApp::OnMRUFile) bool AudacityApp
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Toolkit-neutral facade for basic user interface services.
constexpr CommandFlag AlwaysEnabledFlag
const ReservedCommandFlag & TimeSelectedFlag()
const ReservedCommandFlag & WaveTracksSelectedFlag()
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
const TranslatableString name
RegistryPath UserPresetsGroup(const RegistryPath &name)
Compute part of a registry path, given a name which may be empty.
const RegistryPath & CurrentSettingsGroup()
Component of a configuration key path, for last-used destructive settings.
void EffectPreview(EffectBase &effect, EffectSettingsAccess &access, std::function< void()> updateUI, bool dryOnly)
Calculate temporary tracks of limited length with effect applied and play.
static PluginID GetID(EffectPlugin &effect)
static const int kImportID
static const int kExportID
static const int kOptionsID
static const int kCaptureID
static RealtimeEffectState::EffectFactory::Scope scope
Inject a factory for realtime effects.
static const int kDefaultsID
static const int kDummyID
static const int kPlaybackID
static const int kSaveAsID
static const int kUserPresetsDummyID
static const int kFactoryPresetsID
static const int kEnableID
static const int kDeletePresetDummyID
static const int kUserPresetsID
static const int kDeletePresetID
void MacMakeWindowFloating(NSView *handle)
XXO("&Cut/Copy/Paste Toolbar")
#define RTL_WORKAROUND(pWnd)
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
std::unique_ptr< T, Destroyer< T > > Destroy_ptr
a convenience for using Destroyer
#define NYQUIST_PROMPT_NAME
an object holding per-project preferred sample rate
AudacityProject * FindProjectFromWindow(wxWindow *pWindow)
RealtimeEffectStateChange
EffectReverbSettings preset
static Settings & settings()
Wrap wxMessageDialog so that caption IS translatable.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
void RemoveState(AudacityProject &project, ChannelGroup *pGroup, std::shared_ptr< RealtimeEffectState > pState)
Forwards to RealtimeEffectManager::RemoveState with proper init scope.
std::shared_ptr< RealtimeEffectState > AddState(AudacityProject &project, ChannelGroup *pGroup, const PluginID &id)
Forwards to RealtimeEffectManager::AddState with proper init scope.
void Popup(const BasicUI::WindowPlacement &window, const Point &pos={})
Display the menu at pos, invoke at most one action, then hide it.
CommandContext provides additional information to an 'Apply()' command. It provides the project,...
AudacityProject & project
static CommandManager & Get(AudacityProject &project)
virtual wxString GetVersion() const =0
TranslatableString GetName() const
Base class for many of the effects in Audacity.
static std::optional< InstancePointer > FindInstance(EffectPlugin &plugin)
EffectDefinitionInterface is a ComponentInterface that adds some basic read-only information about ef...
virtual EffectType GetType() const =0
Type determines how it behaves.
virtual bool EnablesDebug() const
Whether the effect dialog should have a Debug button; default, always false.
bool TransferDataToWindow() override
bool TransferDataFromWindow() override
virtual void OnPreview(wxCommandEvent &evt)
virtual void OnOk(wxCommandEvent &evt)
virtual void PopulateOrExchange(ShuttleGui &S)
static constexpr int kPlayID
Base class for many of the effects in Audacity.
EffectManager is the class that handles effects and effect categories.
void SetSkipStateFlag(bool flag)
EffectPlugin * GetEffect(const PluginID &ID)
static const EffectInstanceFactory * GetInstanceFactory(const PluginID &ID)
static EffectManager & Get()
EffectSettings * GetDefaultSettings(const PluginID &ID)
TranslatableString GetCommandName(const PluginID &ID)
TranslatableString GetCommandDescription(const PluginID &ID)
void SetAccept(bool accept)
bool AcceptsFocus() const override
bool AcceptsFocusFromKeyboard() const override
EffectPanel(wxWindow *parent)
Factory of instances of an effect.
virtual bool HasOptions() const =0
virtual bool CanExportPresets() const =0
Whether the effect supports export of presets to files, and importing too.
virtual const EffectSettingsManager & GetDefinition() const =0
virtual bool IsBatchProcessing() const =0
virtual RegistryPaths GetFactoryPresets() const =0
Report names of factory presets.
virtual bool SaveUserPreset(const RegistryPath &name, const EffectSettings &settings) const =0
Save settings in the configuration file as a user-named preset.
void OnEnable(wxCommandEvent &evt)
void OnFactoryPreset(wxCommandEvent &evt)
RegistryPaths mUserPresets
void OnDefaults(wxCommandEvent &evt)
Observer::Subscription mAudioIOSubscription
bool HandleCommandKeystrokes() override
wxPanel * BuildButtonBar(wxWindow *parent, bool graphicalUI)
void OnErase(wxEraseEvent &evt)
AudacityProject & mProject
std::shared_ptr< RealtimeEffectState > mpTempProjectState
EffectBase & mEffectUIHost
bool TransferDataToWindow() override
EffectPlugin::EffectSettingsAccessPtr mpAccess
const EffectOutputs *const mpOutputs
void OnUserPreset(wxCommandEvent &evt)
void OnDeletePreset(wxCommandEvent &evt)
void OnIdle(wxIdleEvent &evt)
wxButton * mPlayToggleBtn
Observer::Subscription mEffectStateSubscription
void OnCapture(AudioIOEvent)
EffectUIHost(wxWindow *parent, AudacityProject &project, EffectBase &effect, EffectUIServices &client, std::shared_ptr< EffectInstance > &pInstance, EffectSettingsAccess &access, const std::shared_ptr< RealtimeEffectState > &pPriorState={})
EffectUIServices & mClient
void OnClose(wxCloseEvent &evt)
void OnExport(wxCommandEvent &evt)
void OnSaveAs(wxCommandEvent &evt)
const bool mHadPriorState
void OnOptions(wxCommandEvent &evt)
void OnInitDialog(wxInitDialogEvent &evt)
void OnMenu(wxCommandEvent &evt)
void OnDebug(wxCommandEvent &evt)
void OnCharHook(wxKeyEvent &evt)
EffectPlugin::EffectSettingsAccessPtr mpAccess2
void OnImport(wxCommandEvent &evt)
std::unique_ptr< EffectEditor > mpEditor
std::shared_ptr< EffectInstance > InitializeInstance()
void OnApply(wxCommandEvent &evt)
const bool mSupportsRealtime
void OnPlay(wxCommandEvent &evt)
const std::shared_ptr< EffectInstance > mpInstance
void OnCancel(wxCommandEvent &evt)
std::weak_ptr< RealtimeEffectState > mwState
wxBitmap CreateBitmap(const char *const xpm[], bool up, bool pusher)
bool IsOpenedFromEffectPanel() const
bool TransferDataFromWindow() override
void OnPaint(wxPaintEvent &evt)
virtual void ShowOptions(const EffectPlugin &plugin) const =0
virtual std::unique_ptr< EffectEditor > PopulateUI(const EffectPlugin &plugin, ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) const =0
Adds controls to a panel that is given as the parent window of S
virtual OptionalMessage ImportPresets(const EffectPlugin &plugin, EffectSettings &settings) const =0
virtual void ExportPresets(const EffectPlugin &plugin, const EffectSettings &settings) const =0
typename GlobalVariable< EffectFactory, const std::function< const EffectInstanceFactory * >, nullptr, Options... >::Scope Scope
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
void Reset() noexcept
Breaks the connection (constant time)
EffectType GetEffectType() const
static PluginID GetID(PluginProvider *provider)
static bool IsPluginAvailable(const PluginDescriptor &plug)
const PluginDescriptor * GetPlugin(const PluginID &ID) const
static PluginManager & Get()
void Stop(bool stopStream=true)
static ProjectAudioManager & Get(AudacityProject &project)
void PushState(const TranslatableString &desc, const TranslatableString &shortDesc)
static ProjectHistory & Get(AudacityProject &project)
static ProjectRate & Get(AudacityProject &project)
static ProjectWindow & Get(AudacityProject &project)
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
wxImage & Image(int iIndex)
void EnsureVisible(bool modifyState=false)
static TrackList & Get(AudacityProject &project)
static TrackPanel & Get(AudacityProject &project)
Holds a msgid for the translation catalog; may also bind format arguments.
static const TranslatableString Inaudible
A special string value that will have no screen reader pronunciation.
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
static WaveTrackFactory & Get(AudacityProject &project)
A Track that contains audio waveform data.
void Set(EffectSettings &&settings, std::unique_ptr< Message > pMessage) override
const std::weak_ptr< EffectSettingsAccess > mwSide
void Set(std::unique_ptr< Message > pMessage) override
Message-only overload of Set(). In future, this should be the only one.
const std::shared_ptr< EffectSettingsAccess > mpMain
void Flush() override
Make the last Set changes "persistent" in underlying storage.
bool IsSameAs(const EffectSettingsAccess &other) const override
const EffectSettings & Get() override
void SetLabel(const TranslatableString &label)
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
MessageBoxResult ShowMessageBox(const TranslatableString &message, MessageBoxOptions options={})
Show a modal message box with either Ok or Yes and No, and optionally Cancel.
std::unique_ptr< WindowPlacement > FindFocus()
Find the window that is accepting keyboard input, if any.
AUDACITY_DLL_API bool DoEffect(const PluginID &ID, const CommandContext &context, unsigned flags)
'Repeat Last Effect'.
AUDACITY_DLL_API DialogFactoryResults DialogFactory(wxWindow &parent, EffectBase &host, EffectUIServices &client, EffectSettingsAccess &access)
bool RemoveConfigSubgroup(const EffectDefinitionInterface &ident, PluginSettings::ConfigurationType type, const RegistryPath &group)
bool GetConfigSubgroups(const EffectDefinitionInterface &ident, PluginSettings::ConfigurationType type, const RegistryPath &group, RegistryPaths &subgroups)
bool SetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, const Value &value)
void SelectAllIfNone(AudacityProject &project)
AButton * MakeBitmapToggleButton(wxWindow *parent, const wxImage &ImageOn, const wxImage &ImageOff)
wxString GetVersionForDisplay(const EffectDefinitionInterface &definition)
static RegisteredToolbarFactory factory
enum AudioIOEvent::Type type
AudacityProject * pProject
Externalized state of a plug-in.