28#include "../ProjectWindowBase.h"
29#include "../ProjectWindows.h"
99#include "../../images/Effect.h"
101#include "../CommonCommandFlags.h"
102#include "../prefs/GUISettings.h"
104#include "../ProjectAudioManager.h"
107#include "../commands/AudacityCommand.h"
111#include "../widgets/AButton.h"
113#include <wx/button.h>
114#include <wx/checkbox.h>
115#include <wx/dcclient.h>
116#include <wx/dcmemory.h>
118#include <wx/settings.h>
120#include <wx/textctrl.h>
169 const std::shared_ptr<EffectSettingsAccess> &pSide = {});
172 std::unique_ptr<Message> pMessage)
override;
173 void Set(std::unique_ptr<Message> pMessage)
override;
174 void Flush()
override;
178 const std::shared_ptr<EffectSettingsAccess>
mpMain;
179 const std::weak_ptr<EffectSettingsAccess>
mwSide;
183EffectSettingsAccessTee::EffectSettingsAccessTee(
185 const std::shared_ptr<EffectSettingsAccess> &pSide
186) : mpMain{
main.shared_from_this() }
196 std::unique_ptr<Message> pMessage)
199 if (
auto pSide =
mwSide.lock())
201 pMessage ? pMessage->Clone() :
nullptr);
209 if (
auto pSide =
mwSide.lock())
210 pSide->Set(pMessage ? pMessage->Clone() :
nullptr);
212 mpMain->Set(std::move(pMessage));
218 if (
auto pSide =
mwSide.lock())
225 return mpMain->IsSameAs(other);
232 const std::shared_ptr<RealtimeEffectState> &pPriorState)
234 wxDefaultPosition, wxDefaultSize,
235 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX)
236, mEffectUIHost{ effect }
240, mpGivenAccess{ access.shared_from_this() }
241, mpAccess{ mpGivenAccess }
242, mwState{ pPriorState }
245, mSupportsRealtime{ mEffectUIHost.GetDefinition().SupportsRealtime() }
246, mHadPriorState{ (pPriorState != nullptr) }
247, mpInstance{ InitializeInstance() }
248, mpOutputs{ pPriorState ? pPriorState->GetOutputs() : nullptr }
252#if defined(__WXMAC__)
260 SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
278 const auto pServices =
280 return (!pServices || pServices->TransferDataToWindow(
mpAccess->Get())) &&
284 wxDialogWrapper::TransferDataToWindow();
290 if (!wxDialogWrapper::Validate())
294 if (!wxDialogWrapper::TransferDataFromWindow())
304 const auto pServices =
307 result = (!pServices || pServices->TransferDataFromWindow(
settings));
311 const auto seconds =
settings.extra.GetDuration();
337 return wxDialogWrapper::ShowModal();
349 wxDefaultPosition, wxDefaultSize,
true);
350 pBtn->SetImages(ImageOff, ImageOff, ImageOn, ImageOn, ImageOff);
362 S.StartHorizontalLay(wxEXPAND, 0);
369 .Position(wxALIGN_CENTER | wxTOP | wxBOTTOM)
375 .ToolTip(
XO(
"Manage presets and options"))
376 .AddButton(
XO(
"Presets && settings"), wxALIGN_CENTER | wxTOP | wxBOTTOM );
385 .AddButton(
XXO(
"Debu&g"),
386 wxALIGN_CENTER | wxTOP | wxBOTTOM );
389 S.EndHorizontalLay();
410 uw->SetMinSize(wxSize(wxMax(600,
mParent->GetSize().GetWidth() * 2 / 3),
411 mParent->GetSize().GetHeight() / 2));
423 S.StartHorizontalLay( wxEXPAND );
427 .AddWindow((w = uw.release()));
429 S.EndHorizontalLay();
436 S.StartHorizontalLay(wxEXPAND, 0);
444 .ToolTip(
XO(
"Preview effect"))
445 .AddButton(
XXO(
"&Preview"),
446 wxALIGN_CENTER | wxTOP | wxBOTTOM );
452 .AddButton(
XXO(
"&Cancel"));
455 .AddButton(
XXO(
"&Apply"));
458 S.EndHorizontalLay();
483 SetMinSize(GetSize());
496 wxDialogWrapper::OnInitDialog(evt);
498#if wxCHECK_VERSION(3, 0, 0)
509 wxTextCtrl *focused = wxDynamicCast(
FindFocus(), wxTextCtrl);
512 focused->SelectAll();
586 EndModal(evt.GetId());
596 auto cleanup =
finally( [&] {
mApplyBtn->Enable(); } );
641 static const auto specialVersion =
XO(
"n/a");
643 if (result == specialVersion.MSGID())
644 result = specialVersion.Translation();
662 auto sub = std::make_unique<wxMenu>();
663 for (
size_t i = 0, cnt =
mUserPresets.size(); i < cnt; i++)
667 menu.Append(0,
_(
"User Presets"), sub.release());
678 auto sub = std::make_unique<wxMenu>();
679 for (
size_t i = 0, cnt =
mUserPresets.size(); i < cnt; i++)
683 menu.Append(0,
_(
"Delete Preset"), sub.release());
686 menu.AppendSeparator();
691 auto sub = std::make_unique<wxMenu>();
695 sub->AppendSeparator();
696 for (
size_t i = 0, cnt =
factory.size(); i < cnt; i++)
707 menu.Append(0,
_(
"Factory Presets"), sub.release());
710 menu.AppendSeparator();
715 menu.AppendSeparator();
718 menu.AppendSeparator();
721 auto sub = std::make_unique<wxMenu>();
724 sub->Append(
kDummyID, wxString::Format(
_(
"Type: %s"),
725 ::wxGetTranslation( definition.GetFamily().Translation() )));
726 sub->Append(
kDummyID, wxString::Format(
_(
"Name: %s"), definition.GetName().Translation()));
727 sub->Append(
kDummyID, wxString::Format(
_(
"Version: %s"),
729 sub->Append(
kDummyID, wxString::Format(
_(
"Vendor: %s"), definition.GetVendor().Translation()));
730 sub->Append(
kDummyID, wxString::Format(
_(
"Description: %s"), definition.GetDescription().Translation()));
731 sub->Bind(wxEVT_MENU, [](
auto&){},
kDummyID);
733 menu.Append(0,
_(
"About"), sub.release());
736 wxWindow *btn = FindWindow(
kMenuID);
737 wxRect r = btn->GetRect();
740 { r.GetLeft(), r.GetBottom() }
814 wxICON_QUESTION | wxYES_NO);
836 S.StartVerticalLay(1);
838 S.StartHorizontalLay(wxALIGN_LEFT, 0);
840 text =
S.AddTextBox(
XXO(
"Preset name:"),
name, 30);
842 S.EndHorizontalLay();
844 S.AddStandardButtons();
850 dlg.SetSize(dlg.GetSizer()->GetMinSize());
856 int rc = dlg.ShowModal();
863 name = text->GetValue();
868 XO(
"You must specify a name"),
879 XO(
"Preset already exists.\n\nReplace?"),
881 wxYES_NO | wxCANCEL | wxICON_EXCLAMATION );
883 int choice = md.ShowModal();
884 if (choice == wxID_CANCEL)
889 if (choice == wxID_NO)
955 if (!IsEscapeKey(evt))
981 wxBitmap mod(pic.GetWidth() + 6, pic.GetHeight() + 6, 24);
982 dc.SelectObject(mod);
984#if defined(__WXGTK__)
985 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND);
987 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
990 dc.SetBackground(wxBrush(newColour));
1002 dc.DrawBitmap(pic, offset, offset,
true);
1004 dc.SelectObject(wxNullBitmap);
1040 std::shared_ptr<EffectInstance> result;
1042 auto mpState =
mwState.lock();
1044 bool priorState = (mpState !=
nullptr);
1047 mCapturing = gAudioIO->IsStreamActive() && gAudioIO->GetNumCaptureChannels() > 0 && !gAudioIO->IsMonitoring();
1057 result = mpState->GetInstance();
1062 mpAccess = std::make_shared<EffectSettingsAccessTee>(
1073 switch (event.
type) {
1074 case AudioIOEvent::CAPTURE:
1075 OnCapture(event); break;
1121 std::shared_ptr<EffectInstance> pInstance;
1123 *
project, host, client, pInstance, access } };
1128 if (dlg->Initialize()) {
1129 auto pEditor = dlg->GetEditor();
1131 return { dlg.release(), pInstance, pEditor };
1138#include "../SelectUtilities.h"
1165 XO(
"This plugin could not be loaded.\nIt may have been deleted."),
1167 .Caption(
XO(
"Plugin Error")));
1186 auto nTracksOriginally =
tracks.Size();
1188 wxWindow *parent =
nullptr;
1189 if (focus !=
nullptr) {
1190 parent = focus->GetParent();
1193 bool success =
false;
1194 auto cleanup =
finally( [&] {
1206 bool anyTracks = !range.empty();
1207 bool clean = std::all_of(range.begin(), range.end(),
1208 [](
const WaveTrack *t){ return t->GetEndTime() == 0; });
1216 const auto pAccess =
1217 std::make_shared<SimpleEffectSettingsAccess>(*pSettings);
1220 -> std::optional<std::shared_ptr<EffectInstanceEx>>
1225 std::shared_ptr<EffectInstance> pInstance;
1226 std::shared_ptr<EffectInstanceEx> pInstanceEx;
1230 !pServices->ShowHostInterface(*effect,
1234 else if (!(pInstanceEx =
1235 std::dynamic_pointer_cast<EffectInstanceEx>(pInstance)
1242 return { pInstanceEx };
1276 auto lastEffectDesc =
XO(
"Repeat %s").Format(shortDesc);
1279 commandManager.Modify(
wxT(
"RepeatLastGenerator"), lastEffectDesc);
1280 commandManager.mLastGenerator = ID;
1284 commandManager.Modify(
wxT(
"RepeatLastEffect"), lastEffectDesc);
1285 commandManager.mLastEffect = ID;
1289 commandManager.Modify(
wxT(
"RepeatLastAnalyzer"), lastEffectDesc);
1290 commandManager.mLastAnalyzer = ID;
1291 commandManager.mLastAnalyzerRegistration =
1296 commandManager.Modify(
wxT(
"RepeatLastTool"), lastEffectDesc);
1297 commandManager.mLastTool = ID;
1298 commandManager.mLastToolRegistration =
1314 if (!anyTracks || (clean && selectedRegion.t0() == 0.0))
1315 viewport.ZoomFitHorizontally();
1321 if (focus !=
nullptr && focus->GetParent()==parent) {
1329 if (
tracks.Size() > nTracksOriginally) {
1330 viewport.ScrollToBottom();
1333 auto pTrack = *
tracks.Selected().begin();
1335 pTrack = *
tracks.begin();
1354 int additionalButtons)
1358 mAdditionalButtons = additionalButtons;
1376 S.StartVerticalLay(
true);
1385 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)
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
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)
void UpdateMenus(bool checkActive=true)
bool ReportIfActionNotAllowed(const TranslatableString &Name, CommandFlag &flags, CommandFlag flagsRqd)
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
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)
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 BuildTopBar(ShuttleGui &S)
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)
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
wxImage & Image(int iIndex)
static TrackList & 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.
static UndoManager & Get(AudacityProject &project)
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
void ShowTrack(const Track &track)
static Viewport & 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)
constexpr int InnerMargin
enum AudioIOEvent::Type type
AudacityProject * pProject
Externalized state of a plug-in.