26#include "../ProjectWindowBase.h"
27#include "../TrackPanelAx.h"
95#include "../../images/Effect.h"
97#include "../CommonCommandFlags.h"
99#include "../prefs/GUISettings.h"
101#include "../ProjectAudioManager.h"
104#include "../commands/AudacityCommand.h"
105#include "../commands/CommandContext.h"
108#include "../widgets/AButton.h"
110#include <wx/button.h>
111#include <wx/checkbox.h>
112#include <wx/dcclient.h>
113#include <wx/dcmemory.h>
115#include <wx/settings.h>
117#include <wx/textctrl.h>
119#if defined(__WXMAC__)
120#include <Cocoa/Cocoa.h>
170 const std::shared_ptr<EffectSettingsAccess> &pSide = {});
173 std::unique_ptr<Message> pMessage)
override;
174 void Set(std::unique_ptr<Message> pMessage)
override;
175 void Flush()
override;
179 const std::shared_ptr<EffectSettingsAccess>
mpMain;
180 const std::weak_ptr<EffectSettingsAccess>
mwSide;
184EffectSettingsAccessTee::EffectSettingsAccessTee(
186 const std::shared_ptr<EffectSettingsAccess> &pSide
187) : mpMain{
main.shared_from_this() }
197 std::unique_ptr<Message> pMessage)
200 if (
auto pSide =
mwSide.lock())
202 pMessage ? pMessage->Clone() :
nullptr);
210 if (
auto pSide =
mwSide.lock())
211 pSide->Set(pMessage ? pMessage->Clone() :
nullptr);
213 mpMain->Set(std::move(pMessage));
219 if (
auto pSide =
mwSide.lock())
226 return mpMain->IsSameAs(other);
233 const std::shared_ptr<RealtimeEffectState> &pPriorState)
235 wxDefaultPosition, wxDefaultSize,
236 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX)
237, mEffectUIHost{ effect }
241, mpGivenAccess{ access.shared_from_this() }
242, mpAccess{ mpGivenAccess }
243, mwState{ pPriorState }
246, mSupportsRealtime{ mEffectUIHost.GetDefinition().SupportsRealtime() }
247, mHadPriorState{ (pPriorState != nullptr) }
248, mpInstance{ InitializeInstance() }
249, mpOutputs{ pPriorState ? pPriorState->GetOutputs() : nullptr }
253#if defined(__WXMAC__)
255 [ [((NSView *)GetHandle()) window] setLevel:NSFloatingWindowLevel];
262 SetExtraStyle(GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
280 const auto pServices =
282 return (!pServices || pServices->TransferDataToWindow(
mpAccess->Get())) &&
286 wxDialogWrapper::TransferDataToWindow();
292 if (!wxDialogWrapper::Validate())
296 if (!wxDialogWrapper::TransferDataFromWindow())
306 const auto pServices =
309 result = (!pServices || pServices->TransferDataFromWindow(
settings));
313 const auto seconds =
settings.extra.GetDuration();
339 return wxDialogWrapper::ShowModal();
351 wxDefaultPosition, wxDefaultSize,
true);
352 pBtn->SetImages(ImageOff, ImageOff, ImageOn, ImageOn, ImageOff);
362 constexpr int margin = 3;
366 S.SetBorder( margin );
368 S.StartHorizontalLay(wxEXPAND, 0);
375 .Position(wxALIGN_CENTER | wxTOP | wxBOTTOM)
381 .ToolTip(
XO(
"Manage presets and options"))
382 .AddButton(
XO(
"Presets && settings"), wxALIGN_CENTER | wxTOP | wxBOTTOM );
393 .ToolTip(
XO(
"Start and stop preview"))
395 wxALIGN_CENTER | wxTOP | wxBOTTOM );
403 .ToolTip(
XO(
"Preview effect"))
405 wxALIGN_CENTER | wxTOP | wxBOTTOM );
422 .AddButton(
XXO(
"&Apply"),
423 wxALIGN_CENTER | wxTOP | wxBOTTOM );
430 .AddButton(
XXO(
"Debu&g"),
431 wxALIGN_CENTER | wxTOP | wxBOTTOM );
434 S.EndHorizontalLay();
453 uw->SetMinSize(wxSize(wxMax(600,
mParent->GetSize().GetWidth() * 2 / 3),
454 mParent->GetSize().GetHeight() / 2));
465 S.StartHorizontalLay( wxEXPAND );
469 .AddWindow((w = uw.release()));
471 S.EndHorizontalLay();
493 SetMinSize(GetSize());
506 wxDialogWrapper::OnInitDialog(evt);
508#if wxCHECK_VERSION(3, 0, 0)
519 wxTextCtrl *focused = wxDynamicCast(
FindFocus(), wxTextCtrl);
522 focused->SelectAll();
602 EndModal(evt.GetId());
612 auto cleanup =
finally( [&] {
mApplyBtn->Enable(); } );
657 static const auto specialVersion =
XO(
"n/a");
659 if (result == specialVersion.MSGID())
660 result = specialVersion.Translation();
678 auto sub = std::make_unique<wxMenu>();
679 for (
size_t i = 0, cnt =
mUserPresets.size(); i < cnt; i++)
683 menu.Append(0,
_(
"User Presets"), sub.release());
694 auto sub = std::make_unique<wxMenu>();
695 for (
size_t i = 0, cnt =
mUserPresets.size(); i < cnt; i++)
699 menu.Append(0,
_(
"Delete Preset"), sub.release());
702 menu.AppendSeparator();
707 auto sub = std::make_unique<wxMenu>();
711 sub->AppendSeparator();
712 for (
size_t i = 0, cnt =
factory.size(); i < cnt; i++)
723 menu.Append(0,
_(
"Factory Presets"), sub.release());
726 menu.AppendSeparator();
731 menu.AppendSeparator();
734 menu.AppendSeparator();
737 auto sub = std::make_unique<wxMenu>();
740 sub->Append(
kDummyID, wxString::Format(
_(
"Type: %s"),
741 ::wxGetTranslation( definition.GetFamily().Translation() )));
742 sub->Append(
kDummyID, wxString::Format(
_(
"Name: %s"), definition.GetName().Translation()));
743 sub->Append(
kDummyID, wxString::Format(
_(
"Version: %s"),
745 sub->Append(
kDummyID, wxString::Format(
_(
"Vendor: %s"), definition.GetVendor().Translation()));
746 sub->Append(
kDummyID, wxString::Format(
_(
"Description: %s"), definition.GetDescription().Translation()));
747 sub->Bind(wxEVT_MENU, [](
auto&){},
kDummyID);
749 menu.Append(0,
_(
"About"), sub.release());
752 wxWindow *btn = FindWindow(
kMenuID);
753 wxRect r = btn->GetRect();
756 { r.GetLeft(), r.GetBottom() }
794 const auto &selectedRegion = viewInfo.selectedRegion;
795 const auto &playRegion = viewInfo.playRegion;
796 if ( playRegion.Active() )
801 else if (selectedRegion.t0() !=
mRegion.
t0() ||
814 projectAudioManager.PlayPlayRegion(
887 wxICON_QUESTION | wxYES_NO);
909 S.StartVerticalLay(1);
911 S.StartHorizontalLay(wxALIGN_LEFT, 0);
913 text =
S.AddTextBox(
XXO(
"Preset name:"),
name, 30);
915 S.EndHorizontalLay();
917 S.AddStandardButtons();
923 dlg.SetSize(dlg.GetSizer()->GetMinSize());
929 int rc = dlg.ShowModal();
936 name = text->GetValue();
941 XO(
"You must specify a name"),
952 XO(
"Preset already exists.\n\nReplace?"),
954 wxYES_NO | wxCANCEL | wxICON_EXCLAMATION );
956 int choice = md.ShowModal();
957 if (choice == wxID_CANCEL)
962 if (choice == wxID_NO)
1028 if (!IsEscapeKey(evt))
1054 wxBitmap mod(pic.GetWidth() + 6, pic.GetHeight() + 6, 24);
1055 dc.SelectObject(mod);
1057#if defined(__WXGTK__)
1058 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BACKGROUND);
1060 wxColour newColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
1063 dc.SetBackground(wxBrush(newColour));
1075 dc.DrawBitmap(pic, offset, offset,
true);
1077 dc.SelectObject(wxNullBitmap);
1133 std::shared_ptr<EffectInstance> result;
1135 auto mpState =
mwState.lock();
1137 bool priorState = (mpState !=
nullptr);
1141 mPlaying = gAudioIO->IsStreamActive();
1142 mCapturing = gAudioIO->IsStreamActive() && gAudioIO->GetNumCaptureChannels() > 0 && !gAudioIO->IsMonitoring();
1152 result = mpState->GetInstance();
1157 mpAccess = std::make_shared<EffectSettingsAccessTee>(
1168 switch (event.
type) {
1169 case AudioIOEvent::PLAYBACK:
1170 OnPlayback(event); break;
1171 case AudioIOEvent::CAPTURE:
1172 OnCapture(event); break;
1183 if (
auto pInstanceEx =
1184 std::dynamic_pointer_cast<EffectInstanceEx>(result)
1185 ; pInstanceEx && !pInstanceEx->Init())
1219 mPlayPos = gAudioIO->GetStreamTime();
1221 projectAudioManager.Stop();
1234 std::shared_ptr<EffectInstance> pInstance;
1236 *project, host, client, pInstance, access } };
1241 if (dlg->Initialize()) {
1242 auto pEditor = dlg->GetEditor();
1244 return { dlg.release(), pInstance, pEditor };
1251#include "../ProjectWindow.h"
1252#include "../SelectUtilities.h"
1253#include "../TrackPanel.h"
1255#include "../commands/CommandManager.h"
1280 XO(
"This plugin could not be loaded.\nIt may have been deleted."),
1282 .Caption(
XO(
"Plugin Error")));
1301 auto nTracksOriginally = tracks.size();
1303 wxWindow *parent =
nullptr;
1304 if (focus !=
nullptr) {
1305 parent = focus->GetParent();
1308 bool success =
false;
1309 auto cleanup =
finally( [&] {
1322 for (
auto t : tracks.Selected<
const WaveTrack >()) {
1323 if (t->GetEndTime() != 0.0)
1334 const auto pAccess =
1335 std::make_shared<SimpleEffectSettingsAccess>(*pSettings);
1338 -> std::optional<std::shared_ptr<EffectInstanceEx>>
1343 std::shared_ptr<EffectInstance> pInstance;
1344 std::shared_ptr<EffectInstanceEx> pInstanceEx;
1348 !pServices->ShowHostInterface(*effect,
1352 else if (!(pInstanceEx =
1353 std::dynamic_pointer_cast<EffectInstanceEx>(pInstance)
1360 return { pInstanceEx };
1363 success = effect->DoEffect(
settings, finder,
1394 auto lastEffectDesc =
XO(
"Repeat %s").Format(shortDesc);
1398 commandManager.Modify(
wxT(
"RepeatLastGenerator"), lastEffectDesc);
1399 menuManager.mLastGenerator = ID;
1403 commandManager.Modify(
wxT(
"RepeatLastEffect"), lastEffectDesc);
1404 menuManager.mLastEffect = ID;
1408 commandManager.Modify(
wxT(
"RepeatLastAnalyzer"), lastEffectDesc);
1409 menuManager.mLastAnalyzer = ID;
1414 commandManager.Modify(
wxT(
"RepeatLastTool"), lastEffectDesc);
1415 menuManager.mLastTool = ID;
1431 if (count == 0 || (clean && selectedRegion.t0() == 0.0))
1437 window.RedrawProject();
1439 if (focus !=
nullptr && focus->GetParent()==parent) {
1447 if( tracks.size() > nTracksOriginally ){
1449 trackPanel.VerticalScroll( 1.0 );
1452 auto pTrack = *tracks.Selected().begin();
1454 pTrack = *tracks.Any().begin();
1473 int additionalButtons)
1477 mAdditionalButtons = additionalButtons;
1495 S.StartVerticalLay(
true);
1504 SetMinSize(GetSize());
1559static RealtimeEffectState::EffectFactory::Scope
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.
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
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...
std::shared_ptr< RealtimeEffectState > AddState(AudacityProject &project, Track *pTrack, const PluginID &id)
Forwards to RealtimeEffectManager::AddState with proper init scope.
void RemoveState(AudacityProject &project, Track *pTrack, std::shared_ptr< RealtimeEffectState > pState)
Forwards to RealtimeEffectManager::RemoveState 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
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.
virtual std::shared_ptr< EffectInstance > MakeInstance() const =0
Make an object maintaining short-term state of an Effect.
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 void Preview(EffectSettingsAccess &access, std::function< void()> updateUI, bool dryOnly)=0
Calculate temporary tracks of limited length with effect applied and play.
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.
EffectPlugin & mEffectUIHost
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)
void OnPlayback(AudioIOEvent)
AudacityProject & mProject
std::shared_ptr< RealtimeEffectState > mpTempProjectState
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)
EffectUIServices & mClient
void OnClose(wxCloseEvent &evt)
void OnExport(wxCommandEvent &evt)
void OnSaveAs(wxCommandEvent &evt)
EffectUIHost(wxWindow *parent, AudacityProject &project, EffectPlugin &effect, EffectUIServices &client, std::shared_ptr< EffectInstance > &pInstance, EffectSettingsAccess &access, const std::shared_ptr< RealtimeEffectState > &pPriorState={})
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
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()
static AudioIOStartStreamOptions GetDefaultOptions(AudacityProject &project, bool newDefaults=false)
Invoke the global hook, supplying a default argument.
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)
Defines a selected portion of a project.
bool setTimes(double t0, double t1)
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, EffectPlugin &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.