37#include <wx/checkbox.h>
39#include <wx/datetime.h>
41#include <wx/scrolwin.h>
44#include <wx/sstream.h>
45#include <wx/stattext.h>
46#include <wx/textdlg.h>
47#include <wx/tokenzr.h>
48#include <wx/txtstrm.h>
50#include <wx/wfstream.h>
51#include <wx/numformatter.h>
52#include <wx/stdpaths.h>
57#include "../../prefs/GUIPrefs.h"
58#include "../../prefs/SpectrogramSettings.h"
59#include "../../tracks/playabletrack/wavetrack/ui/WaveChannelView.h"
60#include "../../tracks/playabletrack/wavetrack/ui/WaveChannelViewConstants.h"
61#include "../../widgets/NumericTextCtrl.h"
62#include "../../widgets/valnum.h"
63#include "../EffectEditor.h"
88#ifndef nyx_returns_start_and_end_time
89#error You need to update lib-src/libnyquist
98#define NYQUIST_WORKER_ID wxT("Nyquist Worker")
116#define NYQ_MAX_LEN (std::numeric_limits<int64_t>::max())
118#define UNINITIALIZED_CONTROL ((double)99999999.99)
148 mAction =
XO(
"Applying Nyquist Effect...");
152 mRedirectOutput =
false;
157 mReleaseVersion =
XO(
"n/a");
158 mCopyright =
XO(
"n/a");
161 mRestoreSplits =
true;
187 mName =
XO(
"Nyquist Worker");
194 mName =
Verbatim( mFileName.GetName() );
195 mFileModified = mFileName.GetModificationTime();
198 if (!mOK && mInitError.empty())
199 mInitError =
XO(
"Ill-formed Nyquist plug-in header");
228 return XO(
"Audacity");
249 ? wxString(
"Nyquist_Prompt")
259 for (
size_t i = 0, cnt = paths.size(); i < cnt; i++) {
260 fileName = wxFileName(paths[i] +
wxT(
"/") +
mHelpFile).GetFullPath();
261 if (wxFileExists(fileName))
263 return {
true, fileName };
266 return {
false, wxEmptyString };
349 visitor.
Define( d,
static_cast<const wxChar*
>( ctrl.var.c_str() ),
350 (
double)0.0, ctrl.low, ctrl.high, 1.0);
353 visitor.
Define( x,
static_cast<const wxChar*
>( ctrl.var.c_str() ), 0,
354 static_cast<int>(ctrl.low),
static_cast<int>(ctrl.high), 1);
361 visitor.
DefineEnum( x,
static_cast<const wxChar*
>( ctrl.var.c_str() ),
362 0, ctrl.choices.data(), ctrl.choices.size() );
365 visitor.
Define( ctrl.valStr, ctrl.var,
366 wxString{}, ctrl.lowStr, ctrl.highStr );
384 for (
size_t c = 0, cnt =
mControls.size(); c < cnt; c++)
397 parms.Write(ctrl.
var, d);
401 parms.Write(ctrl.
var, (
int) d);
451 pParms = &localParms;
471 const auto kTestOnly =
true;
472 const auto kTestAndSet =
false;
501 for (
size_t c = 0, cnt =
mControls.size(); c < cnt; c++)
522 good = parms.Read(ctrl.
var, &val) &&
525 if (good && !bTestOnly)
531 good = parms.Read(ctrl.
var, &val) &&
534 if (good && !bTestOnly)
535 ctrl.
val = (double)val;
544 if (good && !bTestOnly)
545 ctrl.
val = (double)val;
550 good = parms.Read(ctrl.
var, &val);
551 if (good && !bTestOnly)
560 badCount += !good ? 1 : 0;
592 bool bAllowSpectralEditing =
false;
593 bool hasSpectral =
false;
600 const auto displays = pView->GetDisplays();
601 if (displays.end() != std::find(
602 displays.begin(), displays.end(),
604 WaveChannelViewConstants::Spectrum, {} }))
609 bAllowSpectralEditing =
true;
614 if (!bAllowSpectralEditing || ((
mF0 < 0.0) && (
mF1 < 0.0))) {
617 XO(
"Enable track spectrogram view before\n"
618 "applying 'Spectral' effects."),
619 wxOK | wxICON_EXCLAMATION | wxCENTRE,
623 XO(
"To use 'Spectral effects', enable 'Spectral Selection'\n"
624 "in the track Spectrogram settings and select the\n"
625 "frequency range for the effect to act on."),
626 wxOK | wxICON_EXCLAMATION | wxCENTRE,
634 if (!mIsPrompt && !mExternal)
644 if (mFileName.GetModificationTime().IsLaterThan(mFileModified))
648 auto dummySettings = MakeSettings();
649 constexpr auto key = L
"TemporarySettings";
650 SaveUserPreset(
key, dummySettings);
654 mFileModified = mFileName.GetModificationTime();
657 (void) LoadUserPreset(
key, dummySettings);
678 int64_t start, int64_t len, int64_t totlen);
680 int64_t start, int64_t len, int64_t totlen);
682 int64_t start, int64_t len, int64_t totlen,
void *userdata);
684 int64_t start, int64_t len, int64_t totlen,
void *userdata);
714 auto cleanup =
finally([&]{
716 nyquistSettings.proxySettings = {};
720 proxy.mDebug = nyquistSettings.proxyDebug;
721 proxy.mControls = move(nyquistSettings.controls);
722 auto result =
Delegate(proxy, nyquistSettings.proxySettings);
772 std::optional<EffectOutputTracks> oOutputs;
780 : oOutputs->Get().Selected<
const WaveTrack>()
786"error: File \"%s\" specified in header but not found in plug-in path.\n")
796 mProps += wxString::Format(
wxT(
"(putprop '*AUDACITY* (list %d %d %d) 'VERSION)\n"), AUDACITY_VERSION, AUDACITY_RELEASE, AUDACITY_REVISION);
798 lang = (lang.empty())
801 mProps += wxString::Format(
wxT(
"(putprop '*AUDACITY* \"%s\" 'LANGUAGE)\n"), lang);
803 mProps += wxString::Format(
wxT(
"(setf *DECIMAL-SEPARATOR* #\\%c)\n"), wxNumberFormatter::GetDecimalSeparator());
811 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-DIR* \"%s\" 'HOME)\n"),
EscapeString(wxGetHomeDir()));
815 for (
size_t i = 0, cnt = paths.size(); i < cnt; i++)
819 list = list.RemoveLast();
821 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-DIR* (list %s) 'PLUGIN)\n"), list);
822 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-DIR* (list %s) 'PLUG-IN)\n"), list);
823 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-DIR* \"%s\" 'USER-PLUG-IN)\n"),
827 wxDateTime now = wxDateTime::Now();
828 int year = now.GetYear();
829 int doy = now.GetDayOfYear();
830 int dom = now.GetDay();
832 wxDateTime::Month month = now.GetMonth();
833 wxDateTime::WeekDay day = now.GetWeekDay();
836 mProps += wxString::Format(
wxT(
"(setf *SYSTEM-TIME* (list %d %d %d %d %d))\n"),
837 year, doy, now.GetHour(), now.GetMinute(), now.GetSecond());
839 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'DATE)\n"), now.FormatDate());
840 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'TIME)\n"), now.FormatTime());
841 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'ISO-DATE)\n"), now.FormatISODate());
842 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'ISO-TIME)\n"), now.FormatISOTime());
843 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* %d 'YEAR)\n"), year);
844 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* %d 'DAY)\n"), dom);
845 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* %d 'MONTH)\n"), month);
846 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'MONTH-NAME)\n"), now.GetMonthName(month));
847 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'DAY-NAME)\n"), now.GetWeekDayName(day));
849 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'PROJECTS)\n"),
858 wxString waveTrackList;
862 for (
auto t : countRange) {
865 if (t->GetSelected())
866 waveTrackList += wxString::Format(
wxT(
"%d "), 1 + numTracks);
871 #if defined(USE_MIDI)
881 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* (float %s) 'RATE)\n"),
883 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'TRACKS)\n"), numTracks);
884 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'WAVETRACKS)\n"), numWave);
885 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'LABELTRACKS)\n"), numLabel);
886 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'MIDITRACKS)\n"), numMidi);
887 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'TIMETRACKS)\n"), numTime);
889 double previewLen = 6.0;
890 gPrefs->
Read(
wxT(
"/AudioIO/EffectsPreviewLen"), &previewLen);
891 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* (float %s) 'PREVIEW-DURATION)\n"),
896 mProps += wxString::Format(
wxT(
"(setf *PREVIEWP* %s)\n"), isPreviewing);
898 mProps += wxString::Format(
wxT(
"(putprop '*SELECTION* (list %s) 'TRACKS)\n"), waveTrackList);
904 auto message =
XO(
"Audio selection required.");
907 wxOK | wxCENTRE | wxICON_EXCLAMATION,
908 XO(
"Nyquist Error") );
911 std::optional<TrackIterRange<WaveTrack>> pRange;
913 pRange.emplace(oOutputs->Get().Selected<
WaveTrack>());
919 Track *gtLast = NULL;
920 double progressTot{};
923 bOnePassTool || pRange->first != pRange->second;
924 (void) (!pRange || (++pRange->first,
true))
932 scale, progressTot };
933 auto &mCurNumChannels = nyxContext.mCurNumChannels;
934 auto &mCurChannelGroup = nyxContext.mCurChannelGroup;
935 auto &mCurTrack = nyxContext.mCurTrack;
936 auto &mCurStart = nyxContext.mCurStart;
937 auto &mCurLen = nyxContext.mCurLen;
939 mCurChannelGroup = pRange ? *pRange->first :
nullptr;
940 mCurTrack[0] = mCurChannelGroup
941 ? (*mCurChannelGroup->Channels().begin()).get()
944 assert(mCurChannelGroup !=
nullptr || bOnePassTool);
945 if ( (
mT1 >=
mT0) || bOnePassTool ) {
949 if (
auto channels = mCurChannelGroup->Channels()
950 ; channels.size() > 1
957 mCurTrack[1] = (* ++ channels.first).get();
965 mCurStart = mCurChannelGroup->TimeToLongSamples(
mT0);
966 auto end = mCurChannelGroup->TimeToLongSamples(
mT1);
967 mCurLen =
end - mCurStart;
983 wxString prevlocale = wxSetlocale(LC_NUMERIC, NULL);
984 wxSetlocale(LC_NUMERIC, wxString(
wxT(
"C")));
990 auto cleanup =
finally( [&] {
991 nyx_capture_output(NULL, (
void *)NULL);
992 nyx_set_os_callback(NULL, (
void *)NULL);
1000 wxString lowHz =
wxT(
"nil");
1001 wxString highHz =
wxT(
"nil");
1002 wxString centerHz =
wxT(
"nil");
1003 wxString bandwidth =
wxT(
"nil");
1013 if ((
mF0 >= 0.0) && (
mF1 >= 0.0)) {
1020 double bw = log(
mF1 /
mF0) / log(2.0);
1021 if (!std::isinf(bw)) {
1026 mPerTrackProps += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'LOW-HZ)\n"), lowHz);
1027 mPerTrackProps += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'CENTER-HZ)\n"), centerHz);
1028 mPerTrackProps += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'HIGH-HZ)\n"), highHz);
1029 mPerTrackProps += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'BANDWIDTH)\n"), bandwidth);
1032 mCurChannelGroup ? mCurChannelGroup->SnapToSample(
mT0) :
mT0;
1034 mCurChannelGroup ? mCurChannelGroup->SnapToSample(
mT1) :
mT1;
1036 wxT(
"(putprop '*SELECTION* (float %s) 'START)\n"),
1039 wxT(
"(putprop '*SELECTION* (float %s) 'END)\n"),
1043 success =
ProcessOne(nyxContext, oOutputs ? &*oOutputs :
nullptr);
1046 wxSetlocale(LC_NUMERIC, prevlocale);
1048 if (!success || bOnePassTool) {
1051 progressTot += nyxContext.mProgressIn + nyxContext.mProgressOut;
1054 mCount += mCurNumChannels;
1069 XO(
"Debug Output: "),
1071 dlog.CentreOnParent();
1086 mT0 = selectedRegion.t0();
1087 mT1 = selectedRegion.t1();
1107 int res = wxID_APPLY;
1111 parent,
factory, pInstance, access, forceModal);
1139 auto newAccess = std::make_shared<SimpleEffectSettingsAccess>(newSettings);
1151 parent,
factory, pNewInstance, *newAccess, forceModal);
1163 parent,
factory, pNewInstance, *newAccess,
false );
1170 nyquistSettings.proxySettings = std::move(newSettings);
1171 nyquistSettings.proxyDebug = this->
mDebug;
1172 nyquistSettings.controls = move(effect.
mControls);
1240 const auto wt =
dynamic_cast<const WaveTrack*
>(t);
1247 for (
size_t i = 0, n = ca.size(); i < n; ++i)
1251 clips += wxString::Format(
1252 wxT(
"(list (float %s) (float %s))"),
1280 cmd +=
wxT(
"(snd-set-latency 0.1)");
1285 cmd +=
wxT(
"(setf S 0.25)\n");
1287 nyx_set_audio_name(
"*TRACK*");
1288 cmd +=
wxT(
"(setf S 0.25)\n");
1291 nyx_set_audio_name(
"S");
1292 cmd +=
wxT(
"(setf *TRACK* '*unbound*)\n");
1307 wxString spectralEditp;
1318 auto displays = pView->GetDisplays();
1319 auto format = [&](
decltype(displays[0]) display ) {
1322 return wxString::Format(
wxT(
"\"%s\""),
1323 display.name.Stripped().Debug() );
1325 if (displays.empty())
1327 else if (displays.size() == 1)
1328 view =
format( displays[0] );
1330 view =
wxT(
"(list");
1331 for (
auto display : displays )
1332 view += wxString(
wxT(
" ")) +
format( display );
1337#if defined(USE_MIDI)
1340 view =
wxT(
"\"Midi\"");
1344 type =
wxT(
"label");
1345 view =
wxT(
"\"Label\"");
1349 view =
wxT(
"\"Time\"");
1353 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* %d 'INDEX)\n"), ++
mTrackIndex);
1354 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* \"%s\" 'NAME)\n"),
EscapeString(mCurChannelGroup->GetName()));
1355 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* \"%s\" 'TYPE)\n"), type);
1357 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* %s 'VIEW)\n"), view);
1358 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* %d 'CHANNELS)\n"), mCurNumChannels);
1361 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* %s 'SPECTRAL-EDIT-ENABLED)\n"), spectralEditp);
1363 const double startTime = mCurChannelGroup->GetStartTime();
1364 const double endTime = mCurChannelGroup->GetEndTime();
1366 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* (float %s) 'START-TIME)\n"),
1368 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* (float %s) 'END-TIME)\n"),
1370 cmd += wxString::Format(
1371 wxT(
"(putprop '*TRACK* (float %s) 'GAIN)\n"),
1377 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* (float %s) 'PAN)\n"),
1379 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* (float %s) 'RATE)\n"),
1382 switch (mCurChannelGroup->GetSampleFormat())
1385 bitFormat =
wxT(
"16");
1388 bitFormat =
wxT(
"24");
1391 bitFormat =
wxT(
"32.0");
1394 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* %s 'FORMAT)\n"), bitFormat);
1396 float maxPeakLevel = 0.0;
1400 wxString inClips, outClips, peakString, rmsString;
1402 for (
size_t i = 0; i < mCurNumChannels; i++) {
1403 float maxPeak = 0.0;
1404 if (mCurNumChannels > 1)
1406 inClips +=
wxT(
"(list ");
1407 outClips +=
wxT(
"(list ");
1409 inClips += inClipBoundaries;
1410 outClips += outClipBoundaries;
1411 if (mCurNumChannels > 1)
1413 inClips +=
wxT(
" )");
1414 outClips +=
wxT(
" )");
1419 min = pair.first, max = pair.second;
1420 maxPeak = wxMax(wxMax(fabs(
min), fabs(max)), maxPeak);
1421 maxPeakLevel = wxMax(maxPeakLevel, maxPeak);
1424 if (!std::isinf(maxPeak) && !std::isnan(maxPeak) && (maxPeak < FLT_MAX)) {
1427 peakString +=
wxT(
"nil ");
1432 if (!std::isinf(rms) && !std::isnan(rms)) {
1435 rmsString +=
wxT(
"NIL ");
1439 cmd += wxString::Format(
1440 wxT(
"(putprop '*TRACK* %s%s ) 'INCLIPS)\n"),
1441 (mCurNumChannels == 1) ?
wxT(
"(list ") :
wxT(
"(vector "), inClips);
1442 cmd += wxString::Format(
1443 wxT(
"(putprop '*TRACK* %s%s ) 'CLIPS)\n"),
1444 (mCurNumChannels == 1) ?
wxT(
"(list ") :
wxT(
"(vector "), outClips);
1446 (mCurNumChannels > 1)?
1447 cmd += wxString::Format(
wxT(
"(putprop '*SELECTION* (vector %s) 'PEAK)\n"), peakString) :
1448 cmd += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'PEAK)\n"), peakString);
1450 if (!std::isinf(maxPeakLevel) && !std::isnan(maxPeakLevel) && (maxPeakLevel < FLT_MAX)) {
1451 cmd += wxString::Format(
wxT(
"(putprop '*SELECTION* (float %s) 'PEAK-LEVEL)\n"),
1455 (mCurNumChannels > 1)?
1456 cmd += wxString::Format(
wxT(
"(putprop '*SELECTION* (vector %s) 'RMS)\n"), rmsString) :
1457 cmd += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'RMS)\n"), rmsString);
1462 nyx_set_audio_params(44100, 0);
1464 nyx_set_audio_params(mCurChannelGroup->GetRate(), 0);
1467 nyx_set_audio_params(mCurChannelGroup->GetRate(), curLen);
1469 (
int)mCurNumChannels, curLen, mCurChannelGroup->GetRate());
1475 cmd +=
wxT(
"(setf s 0.25)\n");
1479 cmd +=
wxT(
"(setf *tracenable* T)\n");
1481 cmd +=
wxT(
"(setf *breakenable* T)\n");
1488 cmd +=
wxT(
"(setf *tracenable* NIL)\n");
1491 for (
unsigned int j = 0; j <
mControls.size(); j++) {
1498 cmd += wxString::Format(
wxT(
"(setf %s %s)\n"),
1505 cmd += wxString::Format(
wxT(
"(setf %s %d)\n"),
1510 cmd +=
wxT(
"(setf ");
1515 cmd +=
wxT(
"\")\n");
1526 str +=
wxT(
"\nset aud:result = main()\n");
1532 cmd +=
wxT(
"(setf *tracenable* nil)\n");
1533 cmd +=
wxT(
"(setf *breakenable* nil)\n");
1534 cmd +=
wxT(
"(setf *sal-traceback* t)\n");
1538 cmd +=
wxT(
"(setf *sal-compiler-debug* t)\n");
1541 cmd +=
wxT(
"(setf *sal-call-stack* nil)\n");
1545 cmd +=
wxT(
"(setf aud:result nil)\n");
1546 cmd +=
wxT(
"(sal-compile-audacity \"") +
str +
wxT(
"\" t t nil)\n");
1550 cmd +=
wxT(
"(prog1 aud:result (setf aud:result nil))\n");
1558 rval = nyx_eval_expression(cmd.mb_str(wxConvUTF8));
1564 wxLogMessage(
wxT(
"\'%s\' returned:\n%s"),
1573 if (mCurNumChannels == 1) {
1585 XO(
"';type tool' effects cannot return audio from Nyquist.\n")
1594 XO(
"';type tool' effects cannot return labels from Nyquist.\n")
1599 if (rval == nyx_error) {
1616 if (rval == nyx_list) {
1617 wxLogMessage(
"Nyquist returned nyx_list");
1622 XO(
"Nyquist returned a list.") );
1627 if (rval == nyx_string) {
1653 if (rval == nyx_double) {
1654 auto str =
XO(
"Nyquist returned the value: %f")
1655 .Format(nyx_get_double());
1660 if (rval == nyx_int) {
1661 auto str =
XO(
"Nyquist returned the value: %d")
1662 .Format(nyx_get_int());
1667 if (rval == nyx_labels) {
1674 unsigned int numLabels = nyx_get_num_labels();
1678 auto newTrack = std::make_shared<LabelTrack>();
1685 for (l = 0; l < numLabels; l++) {
1691 nyx_get_label(l, &t0, &t1, &
str);
1698 wxASSERT(rval == nyx_audio);
1700 int outChannels = nyx_get_audio_num_channels();
1701 if (outChannels > (
int)mCurNumChannels) {
1703 XO(
"Nyquist returned too many audio channels.\n"));
1707 if (outChannels == -1) {
1709 XO(
"Nyquist returned one audio channel as an array.\n"));
1713 if (outChannels == 0) {
1715 XO(
"Nyquist returned an empty array.\n"));
1719 nyxContext.
mOutputTrack = mCurChannelGroup->EmptyCopy();
1727 std::rethrow_exception(pException);
1735 *
this,
XO(
"Nyquist returned nil audio.\n"));
1740 if (outChannels <
static_cast<int>(mCurNumChannels)) {
1746 tempTrack = out->MonoToStereo();
1757 ? (out->TimeToLongSamples(
mT0) + out->TimeToLongSamples(
mOutputTime)
1758 == out->TimeToLongSamples(
mT1))
1761 mCurChannelGroup->ClearAndPaste(
1769 t->SyncLockAdjust(
mT1,
mT0 + out->GetEndTime());
1785 wxString
str(nyqString, wxConvUTF8);
1786 if (nyqString != NULL && nyqString[0] &&
str.empty()) {
1788 str =
_(
"[Warning: Nyquist returned invalid UTF-8 string, converted here as Latin-1]");
1798 wxString
str = inStr;
1808 std::vector<EnumValueSymbol> results;
1809 if (text[0] ==
wxT(
'(')) {
1813 auto &choices = tzer.
tokens;
1815 for (
auto &choice : choices) {
1828 auto choices = wxStringTokenize(
1829 text[0] ==
wxT(
'"') ? text.Mid(1, text.length() - 2) : text,
1832 for (
auto &choice : choices)
1833 results.push_back( { choice.Trim(
true).Trim(
false) } );
1842 if (text[0] ==
wxT(
'(')) {
1845 for (
const auto &token : tzer.
tokens)
1846 results.push_back(
UnQuote( token ) );
1855 if (text[0] ==
wxT(
'(')) {
1858 auto &tokens = tzer.
tokens;
1859 if ( tokens.size() == 2 )
1870 if (text[0] ==
wxT(
'(')) {
1873 auto &types = tzer.
tokens;
1874 if ( !types.empty() && types[0][0] ==
wxT(
'(') )
1875 for (
auto &type : types)
1878 if ( results.empty() ) {
1882 auto pieces = wxSplit(
str,
'|' );
1884 auto size = pieces.size();
1885 if (
size % 2 == 1 )
1886 --
size, pieces.pop_back();
1887 for (
size_t ii = 0; ii <
size; ii += 2 ) {
1889 auto extensionStrings = wxSplit( pieces[ii + 1],
';' );
1890 for (
const auto &extensionString : extensionStrings )
1891 if ( extensionString.StartsWith(
wxT(
"*.") ) ) {
1892 auto ext = extensionString.substr( 2 );
1893 if (ext ==
wxT(
"*"))
1896 extensions.push_back( ext );
1898 results.push_back( {
Verbatim( pieces[ii] ), extensions } );
1934 wxString *pExtraString)
1937 *pExtraString = wxString{};
1939 int len = s.length();
1940 if (len >= 2 && s[0] ==
wxT(
'\"') && s[len - 1] ==
wxT(
'\"')) {
1941 auto unquoted = s.Mid(1, len - 2);
1946 else if (allowParens &&
1947 len >= 2 && s[0] ==
wxT(
'(') && s[len - 1] ==
wxT(
')')) {
1950 auto &tokens = tzer.
tokens;
1951 if (tokens.size() > 1) {
1952 if (pExtraString && tokens[1][0] ==
'(') {
1956 *pExtraString =
UnQuote(tokens[0],
false);
1975 wxString *pExtraString)
1999 const wxString &line,
bool eof,
2000 size_t trimStart,
size_t trimEnd)
2002 auto endToken = [&]{
2011 if (
q && !
sl && c ==
wxT(
'\\')) {
2017 if (!
sl && c ==
wxT(
'"')) {
2037 else if (!
q && !
paren && (c ==
wxT(
' ') || c ==
wxT(
'\t')))
2041 else if (!
q && c ==
wxT(
';'))
2047 else if (!
q && c ==
wxT(
'(')) {
2051 endToken(),
tok += c;
2056 else if (!
q && c ==
wxT(
')')) {
2060 tok += c, endToken();
2063 paren = 0, endToken();
2084 if (eof || (!
q && !
paren)) {
2098 Tokenizer &tzer,
const wxString &line,
bool eof,
bool first)
2100 if ( !tzer.
Tokenize(line, eof, first ? 1 : 0, 0) )
2103 const auto &tokens = tzer.
tokens;
2104 int len = tokens.size();
2111 if (len == 2 && tokens[0] ==
wxT(
"nyquist") &&
2112 (tokens[1] ==
wxT(
"plug-in") || tokens[1] ==
wxT(
"plugin"))) {
2117 if (len >= 2 && tokens[0] ==
wxT(
"type")) {
2118 wxString tok = tokens[1];
2120 if (tok ==
wxT(
"tool")) {
2134 if (tok ==
wxT(
"process")) {
2137 else if (tok ==
wxT(
"generate")) {
2140 else if (tok ==
wxT(
"analyze")) {
2144 if (len >= 3 && tokens[2] ==
wxT(
"spectral")) {;
2150 if (len == 2 && tokens[0] ==
wxT(
"codetype")) {
2152 if (tokens[1] ==
wxT(
"lisp")) {
2156 else if (tokens[1] ==
wxT(
"sal")) {
2163 if (len >= 2 && tokens[0] ==
wxT(
"debugflags")) {
2164 for (
int i = 1; i < len; i++) {
2167 if (tokens[i] ==
wxT(
"trace")) {
2170 else if (tokens[i] ==
wxT(
"notrace")) {
2173 else if (tokens[i] ==
wxT(
"compiler")) {
2176 else if (tokens[i] ==
wxT(
"nocompiler")) {
2187 if (len >= 2 && tokens[0] ==
wxT(
"version")) {
2189 tokens[1].ToLong(&v);
2190 if (v < 1 || v > 4) {
2194"This version of Audacity does not support Nyquist plug-in version %ld")
2201 if (len >= 2 && tokens[0] ==
wxT(
"name")) {
2211 if (
name.EndsWith(
wxT(
"...")))
2217 if (len >= 2 && tokens[0] ==
wxT(
"action")) {
2222 if (len >= 2 && tokens[0] ==
wxT(
"info")) {
2227 if (len >= 2 && tokens[0] ==
wxT(
"preview")) {
2228 if (tokens[1] ==
wxT(
"enabled") || tokens[1] ==
wxT(
"true")) {
2232 else if (tokens[1] ==
wxT(
"linear")) {
2236 else if (tokens[1] ==
wxT(
"selection")) {
2240 else if (tokens[1] ==
wxT(
"disabled") || tokens[1] ==
wxT(
"false")) {
2248 if (len >= 2 && tokens[0] ==
wxT(
"maxlen")) {
2250 tokens[1].ToLongLong(&v);
2254 if (len >= 2 && tokens[0] ==
wxT(
"mergeclips")) {
2257 tokens[1].ToLong(&v);
2262 if (len >= 2 && tokens[0] ==
wxT(
"restoresplits")) {
2265 tokens[1].ToLong(&v);
2270 if (len >= 2 && tokens[0] ==
wxT(
"author")) {
2275 if (len >= 2 && tokens[0] ==
wxT(
"release")) {
2282 if (len >= 2 && tokens[0] ==
wxT(
"copyright")) {
2288 if (len >= 2 && tokens[0] ==
wxT(
"manpage")) {
2295 if (len >= 2 && tokens[0] ==
wxT(
"helpfile")) {
2302 if (len >= 2 && tokens[0] ==
wxT(
"debugbutton")) {
2303 if (tokens[1] ==
wxT(
"disabled") || tokens[1] ==
wxT(
"false")) {
2310 if (len >= 3 && tokens[0] ==
wxT(
"control")) {
2313 if (len == 3 && tokens[1] ==
wxT(
"text")) {
2314 ctrl.
var = tokens[1];
2320 ctrl.
var = tokens[1];
2323 ctrl.
label = tokens[4];
2326 ctrl.
valStr = len > 5 ? tokens[5] : wxString{};
2328 if (ctrl.
valStr.length() > 0 &&
2336 if (tokens[3] ==
wxT(
"string")) {
2340 else if (tokens[3] ==
wxT(
"choice")) {
2345 else if (tokens[3] ==
wxT(
"file")) {
2359 if ((tokens[3] ==
wxT(
"float")) ||
2360 (tokens[3] ==
wxT(
"real")))
2362 else if (tokens[3] ==
wxT(
"int"))
2364 else if (tokens[3] ==
wxT(
"float-text"))
2366 else if (tokens[3] ==
wxT(
"int-text"))
2368 else if (tokens[3] ==
wxT(
"time"))
2373 str.Printf(
wxT(
"Bad Nyquist 'control' type specification: '%s' in plug-in file '%s'.\nControl not created."),
2393 ctrl.
low = -(FLT_MAX);
2404 ctrl.
high = INT_MAX;
2409 ctrl.
high = FLT_MAX;
2419 if (ctrl.
val < ctrl.
low) {
2442 if (len >= 2 && tokens[0] ==
wxT(
"categories")) {
2443 for (
size_t i = 1; i < tokens.size(); ++i) {
2458 wxTextInputStream pgm(stream,
wxT(
" \t"), wxConvAuto());
2480 while (!stream.Eof() && stream.IsOk())
2482 wxString line = pgm.ReadLine();
2483 if (line.length() > 1 &&
2487 (line[0] ==
wxT(
';') || line[0] ==
wxT(
'$')) )
2490 unsigned nLines = 1;
2494 line[0] ==
wxT(
'$') || line.StartsWith(
wxT(
";control") );
2496 done =
Parse(tzer, line, !control || stream.Eof(), nLines == 1);
2498 (line = pgm.ReadLine(), ++nLines,
true));
2509 if (line[0] ==
wxT(
'(') ||
2510 (line[0] ==
wxT(
'#') && line.length() > 1 && line[1] ==
wxT(
'|')))
2515 else if (line.Upper().Find(
wxT(
"RETURN")) != wxNOT_FOUND)
2530"Your code looks like SAL syntax, but there is no \'return\' statement.\n\
2531For SAL, use a return statement such as:\n\treturn *track* * 0.1\n\
2532or for LISP, begin with an open parenthesis such as:\n\t(mult *track* 0.1)\n ."),
2534 XO(
"Error in Nyquist code") );
2550 wxFileInputStream rawStream(
mFileName.GetFullPath());
2551 wxBufferedInputStream stream(rawStream, 10000);
2558 wxStringInputStream stream(cmd +
wxT(
" "));
2564 int64_t start, int64_t len, int64_t totlen,
void *userdata)
2566 auto This =
static_cast<NyxContext*
>(userdata);
2567 return This->
GetCallback(buffer, channel, start, len, totlen);
2571 int64_t start, int64_t len, int64_t)
2573 if (mCurBuffer[ch]) {
2574 if ((mCurStart + start) < mCurBufferStart[ch] ||
2575 (mCurStart + start) + len >
2576 mCurBufferStart[ch] + mCurBufferLen[ch]) {
2577 mCurBuffer[ch].reset();
2581 if (!mCurBuffer[ch]) {
2582 mCurBufferStart[ch] = (mCurStart + start);
2583 mCurBufferLen[ch] = mCurTrack[ch]->GetBestBlockSize(mCurBufferStart[ch]);
2585 if (mCurBufferLen[ch] < (
size_t) len)
2586 mCurBufferLen[ch] = mCurTrack[ch]->GetIdealBlockSize();
2589 mCurStart + mCurLen - mCurBufferStart[ch]);
2593 mCurBuffer[ch] =
Buffer{
safenew float[ mCurBufferLen[ch] ] };
2595 mCurTrack[ch]->GetFloats( mCurBuffer[ch].get(),
2596 mCurBufferStart[ch], mCurBufferLen[ch]);
2600 mpException = std::current_exception();
2607 auto offset = (mCurStart + start - mCurBufferStart[ch]).as_size_t();
2608 const void *src = &mCurBuffer[ch][offset];
2609 std::memcpy(buffer, src, len *
sizeof(
float));
2612 double progress = mScale * ((start + len) / mCurLen.as_double());
2613 if (progress > mProgressIn)
2614 mProgressIn = progress;
2615 if (mProgressReport(mProgressIn + mProgressOut + mProgressTot))
2623 int64_t start, int64_t len, int64_t totlen,
void *userdata)
2625 auto This =
static_cast<NyxContext*
>(userdata);
2626 return This->
PutCallback(buffer, channel, start, len, totlen);
2630 int64_t start, int64_t len, int64_t totlen)
2633 return GuardedCall<int>( [&] {
2635 double progress = mScale * ((float)(start + len) / totlen);
2636 if (progress > mProgressOut)
2637 mProgressOut = progress;
2638 if (mProgressReport(mProgressIn + mProgressOut + mProgressTot))
2642 auto iChannel = mOutputTrack->Channels().begin();
2664 std::cout << (char)c;
2697#if defined(__WXMAC__)
2707 for (
size_t i = 0; i < audacityPathList.size(); i++)
2709 wxString prefix = audacityPathList[i] + wxFILE_SEP_PATH;
2728 for (
size_t i = 0, cnt =
mControls.size(); i < cnt; i++)
2734 const auto count = ctrl.
choices.size();
2736 int val = (int)ctrl.
val;
2737 if (val < 0 || val >= (
int)count)
2743 c->SetSelection(val);
2748 double range = ctrl.
high - ctrl.
low;
2749 int val = (int)(0.5 + ctrl.
ticks * (ctrl.
val - ctrl.
low) / range);
2769 const wxString left =
wxT(
"\u201c"), right =
wxT(
"\u201d"), dumb =
'"';
2773 const wxString leftSingle =
wxT(
"\u2018"), rightSingle =
wxT(
"\u2019"),
2775 mInputCmd.Replace(leftSingle, dumbSingle,
true);
2776 mInputCmd.Replace(rightSingle, dumbSingle,
true);
2788 for (
unsigned int i = 0; i <
mControls.size(); i++)
2812 if (ctrl->
valStr.StartsWith(
"\"", &path))
2815 if (path.EndsWith(
"\"", &path))
2817 path.Replace(
"\"\"",
"\"");
2818 wxStringTokenizer tokenizer(path,
"\"");
2819 while (tokenizer.HasMoreTokens())
2821 wxString token = tokenizer.GetNextToken();
2824 const auto message =
2825 XO(
"\"%s\" is not a valid file path.").Format( token );
2828 wxOK | wxICON_EXCLAMATION | wxCENTRE,
2837 const auto message =
2839 XO(
"Mismatched quotes in\n%s").Format( ctrl->
valStr );
2842 wxOK | wxICON_EXCLAMATION | wxCENTRE,
2854 const auto message =
2855 XO(
"\"%s\" is not a valid file path.").Format( ctrl->
valStr );
2858 wxOK | wxICON_EXCLAMATION | wxCENTRE,
2870 ctrl->
low = INT_MIN;
2873 ctrl->
lowStr.IsSameAs(
wxT(
"nil"),
false))
2875 ctrl->
low = -(FLT_MAX);
2883 ctrl->
high = INT_MAX;
2888 ctrl->
high = FLT_MAX;
2900 if (ctrl->
val < ctrl->
low)
2923 S.StartVerticalLay();
2925 S.StartMultiColumn(3, wxEXPAND);
2927 S.SetStretchyCol(1);
2929 S.AddVariableText(
XO(
"Enter Nyquist Command: "));
2935 S.StartHorizontalLay(wxEXPAND, 1);
2938 .MinSize( { 500, 200 } )
2939 .AddTextWindow(
wxT(
""));
2941 S.EndHorizontalLay();
2943 S.StartHorizontalLay(wxALIGN_CENTER, 0);
2948 S.EndHorizontalLay();
2955 wxScrolledWindow *scroller =
S.Style(wxVSCROLL | wxTAB_TRAVERSAL)
2958 S.StartMultiColumn(4);
2960 for (
size_t i = 0; i <
mControls.size(); i++)
2967 S.StartHorizontalLay(wxALIGN_LEFT, 0);
2972 S.EndHorizontalLay();
2973 S.StartMultiColumn(4);
2977 auto prompt =
XXO(
"%s:").Format( ctrl.
name );
2978 S.AddPrompt( prompt );
2985 .Validator<wxGenericValidator>(&ctrl.
valStr)
2987 .AddTextBox( {},
wxT(
""), 50);
3014 .Position(wxALIGN_LEFT | wxALL)
3025 if ( !type.extensions.empty() )
3026 defaultExtension = type.extensions[0];
3032 .AddTextBox( {},
wxT(
""), 40);
3033 item->SetValidator(wxGenericValidator(&ctrl.
valStr));
3035 if (ctrl.
label.empty())
3037 ctrl.
label = wxGetTranslation( wxFileSelectorPromptStr );
3052 double range = ctrl.
high - ctrl.
low;
3053 S.Validator<FloatingPointValidator<double>>(
3058 ? NumValidatorStyle::THREE_TRAILING_ZEROES
3060 ? NumValidatorStyle::TWO_TRAILING_ZEROES
3061 : NumValidatorStyle::ONE_TRAILING_ZERO),
3067 S.Validator<IntegerValidator<double>>(
3068 &ctrl.
val, NumValidatorStyle::DEFAULT,
3069 (int) ctrl.
low, (
int) ctrl.
high);
3071 wxTextCtrl *item =
S
3073 .AddTextBox( {},
wxT(
""),
3080 .Style(wxSL_HORIZONTAL)
3081 .MinSize( { 150, -1 } )
3082 .AddSlider( {}, 0, ctrl.
ticks, 0);
3104 scroller->SetScrollRate(0, 20);
3107 scroller->SetName(
wxT(
"\a"));
3108 scroller->SetLabel(
wxT(
"\a"));
3130 XO(
"Current program has been modified.\nDiscard changes?"),
3139 XO(
"Load Nyquist script"),
3145 FileNames::TextFiles,
3148 wxFD_OPEN | wxRESIZE_BORDER);
3167 XO(
"Save Nyquist script"),
3175 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER);
3195 int val = evt.GetInt();
3196 double range = ctrl.
high - ctrl.
low;
3197 double newVal = (val / (double)ctrl.
ticks) * range + ctrl.
low;
3200 int precision = range < 1.0 ? 3 :
3208 if (fabs(newVal - ctrl.
val) >= (1 / (double)ctrl.
ticks) * range &&
3209 fabs(newVal - ctrl.
val) >= pow(0.1, precision) / 2)
3212 newVal *= pow(10.0, precision);
3213 newVal = floor(newVal + 0.5);
3214 newVal /= pow(10.0, precision);
3229 int i = evt.GetId() -
ID_Time;
3230 static double value = 0.0;
3239 if (val < ctrl.low || val > ctrl.
high) {
3240 const auto message =
XO(
"Value range:\n%s to %s")
3245 XO(
"Value Error") );
3250 else if (val > ctrl.
high)
3260 int i = evt.GetId() -
ID_FILE;
3265 unsigned int flags = 0;
3268 wxStringTokenizer tokenizer(ctrl.
highStr,
",");
3269 while ( tokenizer.HasMoreTokens() )
3271 wxString token = tokenizer.GetNextToken().Trim(
true).Trim(
false);
3272 if (token.IsSameAs(
"open",
false))
3275 flags &= ~wxFD_SAVE;
3276 flags &= ~wxFD_OVERWRITE_PROMPT;
3278 else if (token.IsSameAs(
"save",
false))
3281 flags &= ~wxFD_OPEN;
3282 flags &= ~wxFD_MULTIPLE;
3283 flags &= ~wxFD_FILE_MUST_EXIST;
3285 else if (token.IsSameAs(
"overwrite",
false) && !(flags & wxFD_OPEN))
3287 flags |= wxFD_OVERWRITE_PROMPT;
3289 else if (token.IsSameAs(
"exists",
false) && !(flags & wxFD_SAVE))
3291 flags |= wxFD_FILE_MUST_EXIST;
3293 else if (token.IsSameAs(
"multiple",
false) && !(flags & wxFD_SAVE))
3295 flags |= wxFD_MULTIPLE;
3302 wxFileName fname = ctrl.
valStr;
3303 wxString defaultDir = fname.GetPath();
3304 wxString defaultFile = fname.GetName();
3305 auto message =
XO(
"Select a file");
3307 if (flags & wxFD_MULTIPLE)
3308 message =
XO(
"Select one or more files");
3309 else if (flags & wxFD_SAVE)
3310 message =
XO(
"Save file as");
3319 if (openFileDialog.
ShowModal() == wxID_CANCEL)
3326 if (flags & wxFD_MULTIPLE)
3328 wxArrayString selectedFiles;
3329 openFileDialog.
GetPaths(selectedFiles);
3331 for (
size_t sf = 0; sf < selectedFiles.size(); sf++) {
3333 path += selectedFiles[sf];
3356#if defined(__WXMSW__)
3357 path.Replace(
"/", wxFileName::GetPathSeparator());
3360 path.Trim(
true).Trim(
false);
3362 typedef std::unordered_map<wxString, FilePath> map;
3364 {
"*home*", wxGetHomeDir()},
3365 {
"~", wxGetHomeDir()},
3372 int characters = path.Find(wxFileName::GetPathSeparator());
3373 if(characters == wxNOT_FOUND)
3378 if (pathKeys.find(path) != pathKeys.end())
3381 path = pathKeys[path] + wxFileName::GetPathSeparator();
3385 path = pathKeys[
"*default*"] + wxFileName::GetPathSeparator() + path;
3390 wxString firstDir = path.Left(characters);
3391 wxString rest = path.Mid(characters);
3393 if (pathKeys.find(firstDir) != pathKeys.end())
3395 path = pathKeys[firstDir] + rest;
3399 wxFileName fname = path;
3403 if (fname.wxFileName::IsOk() && fname.GetFullName().empty())
3405 path = fname.GetPathWithSep() +
_(
"untitled");
3414 wxFileName fname = path;
3415 wxString dir = fname.GetPath();
3417 return (fname.wxFileName::IsOk() &&
3418 wxFileName::DirExists(dir) &&
3419 !fname.GetFullName().empty());
3425 int seconds =
static_cast<int>(t);
3426 int hh = seconds / 3600;
3427 int mm = seconds % 3600;
3429 return wxString::Format(
"%d:%d:%.3f", hh, mm, t - (hh * 3600 + mm * 60));
3435 int i = evt.GetId() -
ID_Text;
3439 if (wxDynamicCast(evt.GetEventObject(), wxWindow)->GetValidator()->TransferFromWindow())
3443 int pos = (int)floor((ctrl.
val - ctrl.
low) /
3447 slider->SetValue(pos);
3467:
wxDialogWrapper{ parent,
id,
title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER }
3475 S.AddVariableText( prompt,
false, wxALIGN_LEFT | wxLEFT | wxTOP | wxRIGHT );
3480 .Position(wxEXPAND | wxALL)
3481 .MinSize( { 480, 250 } )
3482 .Style(wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH)
3483 .AddTextWindow( message.Translation() );
3487 S.StartHorizontalLay(wxALIGN_CENTRE | wxLEFT | wxBOTTOM | wxRIGHT, 0 );
3490 S.Id(wxID_OK).AddButton(
XXO(
"OK"), wxALIGN_CENTRE,
true );
3492 S.EndHorizontalLay();
3496 SetAutoLayout(
true);
3497 GetSizer()->Fit(
this);
3498 GetSizer()->SetSizeHints(
this);
3511#include "../../../lib-src/libnyquist/nyquist/xlisp/xlisp.h"
3515 auto string =
UTF8CTOWX(getstring(xlgastring()));
3516#if !HAS_I18N_CONTEXTS
3527#if HAS_I18N_CONTEXTS
3528 auto string =
UTF8CTOWX(getstring(xlgastring()));
3529 auto context =
UTF8CTOWX(getstring(xlgastring()));
3531 return cvstring(wxGetTranslation(
string,
"", 0,
"", context )
3532 .mb_str(wxConvUTF8));
3540 auto string1 =
UTF8CTOWX(getstring(xlgastring()));
3541 auto string2 =
UTF8CTOWX(getstring(xlgastring()));
3542 auto number = getfixnum(xlgafixnum());
3543#if !HAS_I18N_CONTEXTS
3550 wxGetTranslation(string1, string2, number).mb_str(wxConvUTF8));
3555#if HAS_I18N_CONTEXTS
3556 auto string1 =
UTF8CTOWX(getstring(xlgastring()));
3557 auto string2 =
UTF8CTOWX(getstring(xlgastring()));
3558 auto number = getfixnum(xlgafixnum());
3559 auto context =
UTF8CTOWX(getstring(xlgastring()));
3561 return cvstring(wxGetTranslation( string1, string2, number,
"", context )
3562 .mb_str(wxConvUTF8));
3570 unsigned char * dstp;
3571 dst = new_string((
int)(
size+2));
3572 dstp = getstring(dst);
3586 wxString Left = Str.BeforeLast(
'\n').BeforeLast(
'\n').ToAscii();
3587 wxString Right = Str.BeforeLast(
'\n').AfterLast(
'\n').ToAscii();
3588 message = cvstring(Left);
3589 success = Right.EndsWith(
"OK") ? s_true :
nullptr;
3590 dst = cons(message, success);
3594#include "../../commands/ScriptCommandRelay.h"
3602 unsigned char *leftp;
3610 leftp = getstring(src);
3624 static bool firstTime =
true;
3629 static const FUNDEF functions[] = {
3637 xlbindfunctions( functions, WXSIZEOF( functions ) );
wxEVT_COMMAND_BUTTON_CLICKED
SimpleGuard< R > MakeSimpleGuard(R value) noexcept(noexcept(SimpleGuard< R >{ value }))
Convert a value to a handler function returning that value, suitable for GuardedCall<R>
Toolkit-neutral facade for basic user interface services.
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
const TranslatableString name
#define NYQUISTEFFECTS_FAMILY
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.
wxString PluginPath
type alias for identifying a Plugin supplied by a module, each module defining its own interpretation...
STRINGS_API const wxString & GetCustomTranslation(const wxString &str1)
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
const NumericConverterType & NumericConverterType_TIME()
#define UNINITIALIZED_CONTROL
void * nyq_make_opaque_string(int size, unsigned char *src)
void * nyq_reformat_aud_do_response(const wxString &Str)
static const FileNames::FileType LispScripts
wxEVT_COMMAND_TEXT_UPDATED
static const wxChar * KEY_Command
static const FileNames::FileType NyquistScripts
EVT_COMMAND_RANGE(ID_Slider, ID_Slider+99, wxEVT_COMMAND_SLIDER_UPDATED, NyquistEffect::OnSlider) EVT_COMMAND_RANGE(ID_Text
#define NYQUIST_WORKER_ID
static const wxChar * KEY_Parameters
NyquistEffect::OnText ID_Time
static void RegisterFunctions()
#define NYQUIST_PROMPT_ID
#define NYQUIST_PROMPT_NAME
audacity::BasicSettings * gPrefs
an object holding per-project preferred sample rate
size_t limitSampleBufferSize(size_t bufferSize, sampleCount limit)
void * ExecForLisp(char *pIn)
TranslatableStrings Msgids(const EnumValueSymbol strings[], size_t nStrings)
Convenience function often useful when adding choice controls.
Contains declarations for TimeWarper, IdentityTimeWarper, ShiftTimeWarper, LinearTimeWarper,...
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 WriteEnum(const wxString &key, int value, const EnumValueSymbol choices[], size_t nChoices)
bool GetParameters(wxString &parms)
bool ReadEnum(const wxString &key, int *pi, const EnumValueSymbol choices[], size_t nChoices, const ObsoleteMap obsoletes[]=nullptr, size_t nObsoletes=0) const
bool SetParameters(const wxString &parms)
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Base class for many of the effects in Audacity.
void SetPreviewFullSelectionFlag(bool previewDurationFlag)
bool IsPreviewing() const
void SetLinearEffectFlag(bool linearEffectFlag)
const TrackList * inputTracks() const
std::shared_ptr< TrackList > mTracks
wxArrayString mPresetNames
const AudacityProject * FindProject() const
static bool EnablePreview(wxWindow *parent, bool enable=true)
bool TrackGroupProgress(int whichGroup, double frac, const TranslatableString &={}) const
void SetBatchProcessing() override
bool Delegate(Effect &delegate, EffectSettings &settings, InstanceFinder finder={})
Re-invoke DoEffect on another Effect object that implements the work.
virtual NumericFormatID GetSelectionFormat()
bool TotalProgress(double frac, const TranslatableString &={}) const
bool TrackProgress(int whichTrack, double frac, const TranslatableString &={}) const
bool IsBatchProcessing() const override
unsigned TestUIFlags(unsigned mask)
int GetNumWaveGroups() const
Performs effect computation.
EffectManager is the class that handles effects and effect categories.
void SetSkipStateFlag(bool flag)
static EffectManager & Get()
Use this object to copy the input tracks to tentative outputTracks.
const Track * GetMatchingInput(const Track &outTrack) const
Gets the matching input track for the given output track if it finds its match, else nullptr.
Track * AddToOutputTracks(const std::shared_ptr< Track > &t)
Use this to add an output track, not corresponding to an input.
std::pair< double, double > TimeInterval
TrackList & Get()
Expose the output track list for iterations or even erasures.
Hold values to send to effect output meters.
void ModifySettings(Function &&function)
Do a correct read-modify-write of settings.
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)
static NyquistSettings & GetSettings(EffectSettings &settings)
Assume settings originated from MakeSettings() and copies thereof.
EffectSettings MakeSettings() const override
virtual wxString GetPath() const
virtual void GetPaths(wxArrayString &paths) const
std::vector< FileType > FileTypes
static FormatterContext SampleRateContext(double sampleRate)
static wxString ToString(double numberToConvert, int digitsAfterDecimalPoint=-1)
Convert a number to a string, always uses the dot as decimal separator.
static bool CompatibleToDouble(const wxString &stringToConvert, double *result)
Convert a string to a number.
A LabelTrack is a Track that holds labels (LabelStruct).
static wxString GetDefaultName()
A Track that is used for Midi notes. (Somewhat old code).
void SetValue(double newValue)
A control on a NyquistDialog.
std::vector< EnumValueSymbol > choices
FileNames::FileTypes fileTypes
An Effect that calls up a Nyquist (XLISP) plug-in, i.e. many possible effects from this one class.
bool Process(EffectInstance &instance, EffectSettings &settings) override
static TranslatableString UnQuoteMsgid(const wxString &s, bool allowParens=true, wxString *pExtraString=nullptr)
TranslatableString GetDescription() const override
wxWeakRef< wxWindow > mUIParent
static double GetCtrlValue(const wxString &s)
wxTextCtrl * mCommandText
bool ParseCommand(const wxString &cmd)
TranslatableString mDebugOutput
std::pair< bool, FilePath > CheckHelpPage() const
bool TransferDataFromPromptWindow()
TranslatableString mCopyright
bool TransferDataFromWindow(EffectSettings &settings) override
TranslatableString mPromptName
bool SaveSettings(const EffectSettings &settings, CommandParameters &parms) const override
Store settings as keys and values.
bool ProcessOne(NyxContext &nyxContext, EffectOutputTracks *pOutputs)
void OutputCallback(int c)
bool Parse(Tokenizer &tokenizer, const wxString &line, bool eof, bool first)
FileExtensions ParseFileExtensions(const wxString &text)
void BuildEffectWindow(ShuttleGui &S)
bool IsDefault() const override
Whether the effect sorts "above the line" in the menus.
ManualPageID ManualPage() const override
Name of a page in the Audacity alpha manual, default is empty.
EffectFamilySymbol GetFamily() const override
Report identifier and user-visible name of the effect protocol.
bool ParseProgram(wxInputStream &stream)
static void StaticOSCallback(void *userdata)
bool DoLoadSettings(const CommandParameters &parms, EffectSettings &settings)
int SetLispVarsFromParameters(const CommandParameters &parms, bool bTestOnly)
void OnLoad(wxCommandEvent &evt)
bool EnablesDebug() const override
Whether the effect dialog should have a Debug button; default, always false.
static void StaticOutputCallback(int c, void *userdata)
bool TransferDataFromEffectWindow()
void OnFileButton(wxCommandEvent &evt)
bool TransferDataToPromptWindow()
wxString ToTimeFormat(double t)
int ShowHostInterface(EffectBase &plugin, wxWindow &parent, const EffectDialogFactory &factory, std::shared_ptr< EffectInstance > &pInstance, EffectSettingsAccess &access, bool forceModal=false) override
EffectType GetType() const override
Type determines how it behaves.
bool validatePath(wxString path)
bool TransferDataToEffectWindow()
TranslatableString mAuthor
FileNames::FileTypes ParseFileTypes(const wxString &text)
unsigned mNumSelectedChannels
EffectType GetClassification() const override
Determines which menu it appears in; default same as GetType().
static FilePaths GetNyquistSearchPath()
std::unique_ptr< EffectEditor > PopulateOrExchange(ShuttleGui &S, EffectInstance &instance, EffectSettingsAccess &access, const EffectOutputs *pOutputs) override
Add controls to effect panel; always succeeds.
wxFileName mFileName
Name of the Nyquist script file this effect is loaded from.
bool TransferDataToWindow(const EffectSettings &settings) override
void OnSlider(wxCommandEvent &evt)
void OnSave(wxCommandEvent &evt)
TranslatableString mName
Name of the Effect (untranslated)
wxString EscapeString(const wxString &inStr)
TranslatableString mAction
FilePath HelpPage() const override
Fully qualified local help file name, default is empty.
std::vector< NyqControl > mControls
static wxString NyquistToWxString(const char *nyqString)
void SetCommand(const wxString &cmd)
ComponentInterfaceSymbol GetSymbol() const override
FileNames::FileType ParseFileType(const wxString &text)
bool IsInteractive() const override
Whether the effect needs a dialog for entry of settings.
void BuildPromptWindow(ShuttleGui &S)
void OnTime(wxCommandEvent &evt)
PluginPath GetPath() const override
wxArrayString mCategories
static std::vector< EnumValueSymbol > ParseChoice(const wxString &text)
TranslatableString mReleaseVersion
bool VisitSettings(SettingsVisitor &visitor, EffectSettings &settings) override
bool LoadSettings(const CommandParameters &parms, EffectSettings &settings) const override
Restore settings from keys and values.
static wxString UnQuote(const wxString &s, bool allowParens=true, wxString *pExtraString=nullptr)
TranslatableString mInitError
static void resolveFilePath(wxString &path, FileExtension extension={})
void OnChoice(wxCommandEvent &evt)
void OnText(wxCommandEvent &evt)
VendorSymbol GetVendor() const override
wxString GetVersion() const override
Dialog used with NyquistEffect.
void OnOk(wxCommandEvent &event)
Unit slope but with either a jump (pasting more) or a flat interval (pasting less)
static ProjectRate & Get(AudacityProject &project)
Defines a selected portion of a project.
Visitor of effect or command parameters. This is a base class with lots of virtual functions that do ...
virtual void Define(Arg< bool > var, const wxChar *key, bool vdefault, bool vmin=false, bool vmax=false, bool vscl=false)
virtual void DefineEnum(Arg< int > var, const wxChar *key, int vdefault, const EnumValueSymbol strings[], size_t nStrings)
SettingsVisitor that gets parameter values into a string.
SettingsVisitor that retrieves a JSON format definition of a command's parameters.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
SettingsVisitor that sets parameters to a value (from a string)
bool SpectralSelectionEnabled() const
static SpectrogramSettings & Get(const WaveTrack &track)
std::shared_ptr< EffectInstance > MakeInstance() const override
Make an object maintaining short-term state of an Effect.
static TrackIterRange< Track > Group(Track &track)
static bool IsSyncLockSelected(const Track &track)
A kind of Track used to 'warp time'.
Abstract base class for an object holding data associated with points on a time axis.
R TypeSwitch(const Functions &...functions)
auto Any() -> TrackIterRange< TrackType >
static TrackList & Get(AudacityProject &project)
auto Selected() -> TrackIterRange< TrackType >
Holds a msgid for the translation catalog; may also bind format arguments.
wxString Translation() const
TranslatableString & Format(Args &&...args) &
Capture variadic format arguments (by copy) when there is no plural.
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
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.
IntervalHolders SortedIntervalArray()
Return all WaveClips sorted by clip play start time.
size_t NChannels() const override
A constant property.
std::shared_ptr< WaveTrack > Holder
virtual bool Read(const wxString &key, bool *value) const =0
Positions or offsets within audio files need a wide type.
long long as_long_long() const
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
void Yield()
Dispatch waiting events, including actions enqueued by CallAfter.
FILES_API FilePath PlugInDir()
The user plug-in directory (not a system one)
FILES_API FilePath HtmlHelpDir()
FILES_API wxFileNameWrapper DefaultToDocumentsFolder(const wxString &preference)
FILES_API void AddUniquePathToPathList(const FilePath &path, FilePaths &pathList)
FILES_API FilePath BaseDir()
FILES_API FilePath DataDir()
Audacity user data directory.
FILES_API FilePath FindDefaultPath(Operation op)
FILES_API const FilePaths & AudacityPathList()
A list of directories that should be searched for Audacity files (plug-ins, help files,...
wxString GetSystemLanguageCode(const FilePaths &pathList)
FILES_API wxString TempDir()
WAVE_TRACK_API std::pair< float, float > GetMinMax(const WaveChannel &channel, double t0, double t1, bool mayThrow=true)
WAVE_TRACK_API float GetRMS(const WaveChannel &channel, double t0, double t1, bool mayThrow=true)
ProjectFileIOExtensionRegistry::Extension extension
wxString GetClipBoundaries(const Track *t)
const char * end(const char *str) noexcept
const char * begin(const char *str) noexcept
__finl float_x4 __vecc sqrt(const float_x4 &a)
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)
WaveTrack * mCurChannelGroup
static int StaticPutCallback(float *buffer, int channel, int64_t start, int64_t len, int64_t totlen, void *userdata)
std::exception_ptr mpException
unsigned mCurNumChannels
Not used in the callbacks.
int GetCallback(float *buffer, int channel, int64_t start, int64_t len, int64_t totlen)
WaveChannel * mCurTrack[2]
std::unique_ptr< float[]> Buffer
Buffer mCurBuffer[2]
used only in GetCallback
const double mProgressTot
WaveTrack::Holder mOutputTrack
std::function< bool(double)> ProgressReport
const ProgressReport mProgressReport
static int StaticGetCallback(float *buffer, int channel, int64_t start, int64_t len, int64_t totlen, void *userdata)
sampleCount mCurBufferStart[2]
NyxContext(ProgressReport progressReport, double scale, double progressTot)
int PutCallback(float *buffer, int channel, int64_t start, int64_t len, int64_t totlen)
bool Tokenize(const wxString &line, bool eof, size_t trimStart, size_t trimEnd)