31#include <wx/scrolwin.h>
33#include <wx/tokenzr.h>
37#include "../../commands/ScriptCommandRelay.h"
38#include "../../tracks/playabletrack/wavetrack/ui/WaveChannelView.h"
39#include "../../widgets/NumericTextCtrl.h"
40#include "../../widgets/valnum.h"
41#include "../EffectEditor.h"
47#ifndef nyx_returns_start_and_end_time
48#error You need to update lib-src/libnyquist
91 parent,
factory, pInstance, access, forceModal);
100 if (!res || !mIsPrompt || mControls.size() == 0 || !pInstance)
119 auto newAccess = std::make_shared<SimpleEffectSettingsAccess>(newSettings);
121 if (IsBatchProcessing()) {
131 parent,
factory, pNewInstance, *newAccess, forceModal);
143 parent,
factory, pNewInstance, *newAccess,
false );
150 nyquistSettings.proxySettings = std::move(newSettings);
151 nyquistSettings.proxyDebug = this->mDebug;
152 nyquistSettings.controls = move(effect.
mControls);
219 for (
size_t i = 0, cnt =
mControls.size(); i < cnt; i++)
225 const auto count = ctrl.
choices.size();
227 int val = (int)ctrl.
val;
228 if (val < 0 || val >= (
int)count)
234 c->SetSelection(val);
239 double range = ctrl.
high - ctrl.
low;
240 int val = (int)(0.5 + ctrl.
ticks * (ctrl.
val - ctrl.
low) / range);
260 const wxString left =
wxT(
"\u201c"), right =
wxT(
"\u201d"), dumb =
'"';
264 const wxString leftSingle =
wxT(
"\u2018"), rightSingle =
wxT(
"\u2019"),
266 mInputCmd.Replace(leftSingle, dumbSingle,
true);
267 mInputCmd.Replace(rightSingle, dumbSingle,
true);
279 for (
unsigned int i = 0; i <
mControls.size(); i++)
303 if (ctrl->
valStr.StartsWith(
"\"", &path))
306 if (path.EndsWith(
"\"", &path))
308 path.Replace(
"\"\"",
"\"");
309 wxStringTokenizer tokenizer(path,
"\"");
310 while (tokenizer.HasMoreTokens())
312 wxString token = tokenizer.GetNextToken();
316 XO(
"\"%s\" is not a valid file path.").Format( token );
319 wxOK | wxICON_EXCLAMATION | wxCENTRE,
330 XO(
"Mismatched quotes in\n%s").Format( ctrl->
valStr );
333 wxOK | wxICON_EXCLAMATION | wxCENTRE,
346 XO(
"\"%s\" is not a valid file path.").Format( ctrl->
valStr );
349 wxOK | wxICON_EXCLAMATION | wxCENTRE,
364 ctrl->
lowStr.IsSameAs(
wxT(
"nil"),
false))
366 ctrl->
low = -(FLT_MAX);
374 ctrl->
high = INT_MAX;
379 ctrl->
high = FLT_MAX;
391 if (ctrl->
val < ctrl->
low)
414 S.StartVerticalLay();
416 S.StartMultiColumn(3, wxEXPAND);
420 S.AddVariableText(
XO(
"Enter Nyquist Command: "));
426 S.StartHorizontalLay(wxEXPAND, 1);
429 .MinSize( { 500, 200 } )
430 .AddTextWindow(
wxT(
""));
432 S.EndHorizontalLay();
434 S.StartHorizontalLay(wxALIGN_CENTER, 0);
439 S.EndHorizontalLay();
446 wxScrolledWindow *scroller =
S.Style(wxVSCROLL | wxTAB_TRAVERSAL)
449 S.StartMultiColumn(4);
451 for (
size_t i = 0; i <
mControls.size(); i++)
458 S.StartHorizontalLay(wxALIGN_LEFT, 0);
463 S.EndHorizontalLay();
464 S.StartMultiColumn(4);
468 auto prompt =
XXO(
"%s:").Format( ctrl.
name );
469 S.AddPrompt( prompt );
476 .Validator<wxGenericValidator>(&ctrl.
valStr)
478 .AddTextBox( {},
wxT(
""), 50);
505 .Position(wxALIGN_LEFT | wxALL)
516 if ( !type.extensions.empty() )
517 defaultExtension = type.extensions[0];
523 .AddTextBox( {},
wxT(
""), 40);
524 item->SetValidator(wxGenericValidator(&ctrl.
valStr));
526 if (ctrl.
label.empty())
528 ctrl.
label = wxGetTranslation( wxFileSelectorPromptStr );
543 double range = ctrl.
high - ctrl.
low;
544 S.Validator<FloatingPointValidator<double>>(
549 ? NumValidatorStyle::THREE_TRAILING_ZEROES
551 ? NumValidatorStyle::TWO_TRAILING_ZEROES
552 : NumValidatorStyle::ONE_TRAILING_ZERO),
558 S.Validator<IntegerValidator<double>>(
559 &ctrl.
val, NumValidatorStyle::DEFAULT,
560 (int) ctrl.
low, (
int) ctrl.
high);
564 .AddTextBox( {},
wxT(
""),
571 .Style(wxSL_HORIZONTAL)
572 .MinSize( { 150, -1 } )
573 .AddSlider( {}, 0, ctrl.
ticks, 0);
595 scroller->SetScrollRate(0, 20);
598 scroller->SetName(
wxT(
"\a"));
599 scroller->SetLabel(
wxT(
"\a"));
614 XO(
"Current program has been modified.\nDiscard changes?"),
623 XO(
"Load Nyquist script"),
629 FileNames::TextFiles,
632 wxFD_OPEN | wxRESIZE_BORDER);
651 XO(
"Save Nyquist script"),
659 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER);
679 int val = evt.GetInt();
680 double range = ctrl.
high - ctrl.
low;
681 double newVal = (val / (double)ctrl.
ticks) * range + ctrl.
low;
684 int precision = range < 1.0 ? 3 :
692 if (fabs(newVal - ctrl.
val) >= (1 / (double)ctrl.
ticks) * range &&
693 fabs(newVal - ctrl.
val) >= pow(0.1, precision) / 2)
696 newVal *= pow(10.0, precision);
697 newVal = floor(newVal + 0.5);
698 newVal /= pow(10.0, precision);
714 static double value = 0.0;
723 if (val < ctrl.low || val > ctrl.
high) {
724 const auto message =
XO(
"Value range:\n%s to %s")
734 else if (val > ctrl.
high)
749 unsigned int flags = 0;
752 wxStringTokenizer tokenizer(ctrl.
highStr,
",");
753 while ( tokenizer.HasMoreTokens() )
755 wxString token = tokenizer.GetNextToken().Trim(
true).Trim(
false);
756 if (token.IsSameAs(
"open",
false))
760 flags &= ~wxFD_OVERWRITE_PROMPT;
762 else if (token.IsSameAs(
"save",
false))
766 flags &= ~wxFD_MULTIPLE;
767 flags &= ~wxFD_FILE_MUST_EXIST;
769 else if (token.IsSameAs(
"overwrite",
false) && !(flags & wxFD_OPEN))
771 flags |= wxFD_OVERWRITE_PROMPT;
773 else if (token.IsSameAs(
"exists",
false) && !(flags & wxFD_SAVE))
775 flags |= wxFD_FILE_MUST_EXIST;
777 else if (token.IsSameAs(
"multiple",
false) && !(flags & wxFD_SAVE))
779 flags |= wxFD_MULTIPLE;
786 wxFileName fname = ctrl.
valStr;
787 wxString defaultDir = fname.GetPath();
788 wxString defaultFile = fname.GetName();
789 auto message =
XO(
"Select a file");
791 if (flags & wxFD_MULTIPLE)
792 message =
XO(
"Select one or more files");
793 else if (flags & wxFD_SAVE)
794 message =
XO(
"Save file as");
803 if (openFileDialog.
ShowModal() == wxID_CANCEL)
810 if (flags & wxFD_MULTIPLE)
812 wxArrayString selectedFiles;
813 openFileDialog.
GetPaths(selectedFiles);
815 for (
size_t sf = 0; sf < selectedFiles.size(); sf++) {
817 path += selectedFiles[sf];
836 if (wxDynamicCast(evt.GetEventObject(), wxWindow)->GetValidator()->TransferFromWindow())
840 int pos = (int)floor((ctrl.
val - ctrl.
low) /
844 slider->SetValue(pos);
862:
wxDialogWrapper{
nullptr, -1,
title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER }
870 S.AddVariableText(
XO(
"Debug Output: "),
false, wxALIGN_LEFT | wxLEFT | wxTOP | wxRIGHT );
875 .Position(wxEXPAND | wxALL)
876 .MinSize( { 480, 250 } )
877 .Style(wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH)
878 .AddTextWindow( message.Translation() );
882 S.StartHorizontalLay(wxALIGN_CENTRE | wxLEFT | wxBOTTOM | wxRIGHT, 0 );
885 S.Id(wxID_OK).AddButton(
XXO(
"OK"), wxALIGN_CENTRE,
true );
887 S.EndHorizontalLay();
892 GetSizer()->Fit(
this);
893 GetSizer()->SetSizeHints(
this);
909 return std::make_unique<NyquistEffect>(path);
916 return pView ? pView->GetDisplays() :
917 std::vector<WaveChannelSubView::Type> {};
924 dialog.CentreOnParent();
930 [](wxString* pIn, wxString* pOut) {
ExecFromMain(pIn, pOut); }
944#if defined(__WXMAC__)
wxEVT_COMMAND_BUTTON_CLICKED
Toolkit-neutral facade for basic user interface services.
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
std::function< DialogFactoryResults(wxWindow &parent, EffectBase &, EffectUIServices &, EffectSettingsAccess &) > EffectDialogFactory
Type of function that creates a dialog for an effect.
XXO("&Cut/Copy/Paste Toolbar")
wxString FileExtension
File extension, not including any leading dot.
const NumericConverterType & NumericConverterType_TIME()
static NyquistBase::ShowDebugOutputHook::Scope showDebugOutputHookScope
static NyquistBase::GetEffectHook::Scope getEffectHookScope
static const FileNames::FileType LispScripts
wxEVT_COMMAND_TEXT_UPDATED
static NyquistBase::YieldIfNeededHook::Scope yieldIfNeededHookScope
static const FileNames::FileType NyquistScripts
EVT_COMMAND_RANGE(ID_Slider, ID_Slider+99, wxEVT_COMMAND_SLIDER_UPDATED, NyquistEffect::OnSlider) EVT_COMMAND_RANGE(ID_Text
static NyquistBase::ExecFromMainHook::Scope execFromMainHookScope
static NyquistBase::GetDisplaysHook::Scope getDisplaysHookScope
NyquistEffect::OnText ID_Time
#define UNINITIALIZED_CONTROL
#define NYQUIST_WORKER_ID
int ExecFromMain(wxString *pIn, wxString *pOut)
Executes a command on the main (GUI) thread.
TranslatableStrings Msgids(const EnumValueSymbol strings[], size_t nStrings)
Convenience function often useful when adding choice controls.
static Settings & settings()
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
CommandParameters, derived from wxFileConfig, is essentially doing the same things as the SettingsVis...
bool GetParameters(wxString &parms)
bool SetParameters(const wxString &parms)
Base class for many of the effects in Audacity.
static bool EnablePreview(wxWindow *parent, bool enable=true)
void SetBatchProcessing() override
virtual NumericFormatID GetSelectionFormat()
unsigned TestUIFlags(unsigned mask)
Performs effect computation.
Hold values to send to effect output meters.
static int DoMessageBox(const EffectPlugin &plugin, const TranslatableString &message, long style=DefaultMessageBoxStyle, const TranslatableString &titleStr={})
virtual int ShowHostInterface(EffectBase &plugin, wxWindow &parent, const EffectDialogFactory &factory, std::shared_ptr< EffectInstance > &pInstance, EffectSettingsAccess &access, bool forceModal=false)
EffectSettings MakeSettings() const override
virtual wxString GetPath() const
virtual void GetPaths(wxArrayString &paths) const
static FormatterContext SampleRateContext(double sampleRate)
typename GlobalVariable< GetEffectHook, const std::function< std::unique_ptr< NyquistBase > >, nullptr, Options... >::Scope Scope
void SetValue(double newValue)
A control on a NyquistDialog.
std::vector< EnumValueSymbol > choices
FileNames::FileTypes fileTypes
void SetCommand(const wxString &cmd)
static void resolveFilePath(wxString &path, FileExtension extension={})
bool validatePath(wxString path)
bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
bool SaveSettings(const EffectSettings &settings, CommandParameters &parms) const override
Store settings as keys and values.
wxFileName mFileName
Name of the Nyquist script file this effect is loaded from.
static double GetCtrlValue(const wxString &s)
wxString ToTimeFormat(double t)
bool ParseCommand(const wxString &cmd)
std::vector< NyqControl > mControls
wxWeakRef< wxWindow > mUIParent
wxTextCtrl * mCommandText
bool TransferDataFromPromptWindow()
bool TransferDataFromWindow(EffectSettings &settings) override
void BuildEffectWindow(ShuttleGui &S)
void OnLoad(wxCommandEvent &evt)
bool TransferDataFromEffectWindow()
void OnFileButton(wxCommandEvent &evt)
bool TransferDataToPromptWindow()
int ShowHostInterface(EffectBase &plugin, wxWindow &parent, const EffectDialogFactory &factory, std::shared_ptr< EffectInstance > &pInstance, EffectSettingsAccess &access, bool forceModal=false) override
bool TransferDataToEffectWindow()
std::unique_ptr< EffectEditor > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
bool TransferDataToWindow(const EffectSettings &settings) override
void OnSlider(wxCommandEvent &evt)
void OnSave(wxCommandEvent &evt)
void BuildPromptWindow(ShuttleGui &S)
void OnTime(wxCommandEvent &evt)
void OnChoice(wxCommandEvent &evt)
void OnText(wxCommandEvent &evt)
Dialog used with NyquistBase.
void OnOk(wxCommandEvent &event)
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
std::shared_ptr< EffectInstance > MakeInstance() const override
Make an object maintaining short-term state of an Effect.
Holds a msgid for the translation catalog; may also bind format arguments.
static WaveChannelView * FindFirst(WaveTrack *pWt)
If pWt is not null, return a pointer to the view of the first channel.
A Track that contains audio waveform data.
void Yield()
Dispatch waiting events, including actions enqueued by CallAfter.
DynamicRangeProcessorSettings GetSettings(EffectSettingsAccess &access)
Externalized state of a plug-in.
"finally" as in The C++ Programming Language, 4th ed., p. 358 Useful for defining ad-hoc RAII actions...
Options & MenuEnabled(bool enable)
Options & AutoPos(bool enable)
Options & ReadOnly(bool enable)