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>
54#include "../../LabelTrack.h"
56#include "../../ShuttleGetDefinition.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"
64#include "../EffectManager.h"
87#ifndef nyx_returns_start_and_end_time
88#error You need to update lib-src/libnyquist
97#define NYQUIST_WORKER_ID wxT("Nyquist Worker")
115#define NYQ_MAX_LEN (std::numeric_limits<int64_t>::max())
117#define UNINITIALIZED_CONTROL ((double)99999999.99)
147 mAction =
XO(
"Applying Nyquist Effect...");
151 mRedirectOutput =
false;
156 mReleaseVersion =
XO(
"n/a");
157 mCopyright =
XO(
"n/a");
160 mRestoreSplits =
true;
186 mName =
XO(
"Nyquist Worker");
193 mName =
Verbatim( mFileName.GetName() );
194 mFileModified = mFileName.GetModificationTime();
197 if (!mOK && mInitError.empty())
198 mInitError =
XO(
"Ill-formed Nyquist plug-in header");
227 return XO(
"Audacity");
248 ? wxString(
"Nyquist_Prompt")
258 for (
size_t i = 0, cnt = paths.size(); i < cnt; i++) {
259 fileName = wxFileName(paths[i] +
wxT(
"/") +
mHelpFile).GetFullPath();
260 if (wxFileExists(fileName))
262 return {
true, fileName };
265 return {
false, wxEmptyString };
348 visitor.
Define( d,
static_cast<const wxChar*
>( ctrl.var.c_str() ),
349 (
double)0.0, ctrl.low, ctrl.high, 1.0);
352 visitor.
Define( x,
static_cast<const wxChar*
>( ctrl.var.c_str() ), 0,
353 static_cast<int>(ctrl.low),
static_cast<int>(ctrl.high), 1);
360 visitor.
DefineEnum( x,
static_cast<const wxChar*
>( ctrl.var.c_str() ),
361 0, ctrl.choices.data(), ctrl.choices.size() );
364 visitor.
Define( ctrl.valStr, ctrl.var,
365 wxString{}, ctrl.lowStr, ctrl.highStr );
383 for (
size_t c = 0, cnt =
mControls.size(); c < cnt; c++)
396 parms.Write(ctrl.
var, d);
400 parms.Write(ctrl.
var, (
int) d);
450 pParms = &localParms;
470 const auto kTestOnly =
true;
471 const auto kTestAndSet =
false;
500 for (
size_t c = 0, cnt =
mControls.size(); c < cnt; c++)
521 good = parms.Read(ctrl.
var, &val) &&
524 if (good && !bTestOnly)
530 good = parms.Read(ctrl.
var, &val) &&
533 if (good && !bTestOnly)
534 ctrl.
val = (double)val;
543 if (good && !bTestOnly)
544 ctrl.
val = (double)val;
549 good = parms.Read(ctrl.
var, &val);
550 if (good && !bTestOnly)
559 badCount += !good ? 1 : 0;
591 bool bAllowSpectralEditing =
false;
592 bool hasSpectral =
false;
599 const auto displays = pView->GetDisplays();
600 if (displays.end() != std::find(
601 displays.begin(), displays.end(),
603 WaveChannelViewConstants::Spectrum, {} }))
608 bAllowSpectralEditing =
true;
613 if (!bAllowSpectralEditing || ((mF0 < 0.0) && (mF1 < 0.0))) {
616 XO(
"Enable track spectrogram view before\n"
617 "applying 'Spectral' effects."),
618 wxOK | wxICON_EXCLAMATION | wxCENTRE,
622 XO(
"To use 'Spectral effects', enable 'Spectral Selection'\n"
623 "in the track Spectrogram settings and select the\n"
624 "frequency range for the effect to act on."),
625 wxOK | wxICON_EXCLAMATION | wxCENTRE,
633 if (!mIsPrompt && !mExternal)
643 if (mFileName.GetModificationTime().IsLaterThan(mFileModified))
647 auto dummySettings = MakeSettings();
648 constexpr auto key = L
"TemporarySettings";
649 SaveUserPreset(
key, dummySettings);
653 mFileModified = mFileName.GetModificationTime();
656 (void) LoadUserPreset(
key, dummySettings);
677 int64_t start, int64_t len, int64_t totlen);
679 int64_t start, int64_t len, int64_t totlen);
681 int64_t start, int64_t len, int64_t totlen,
void *userdata);
683 int64_t start, int64_t len, int64_t totlen,
void *userdata);
713 auto cleanup =
finally([&]{
715 nyquistSettings.proxySettings = {};
719 proxy.mDebug = nyquistSettings.proxyDebug;
720 proxy.mControls = move(nyquistSettings.controls);
721 auto result =
Delegate(proxy, nyquistSettings.proxySettings);
771 std::optional<EffectOutputTracks> oOutputs;
779 : oOutputs->Get().Selected<
const WaveTrack>()
785"error: File \"%s\" specified in header but not found in plug-in path.\n")
795 mProps += wxString::Format(
wxT(
"(putprop '*AUDACITY* (list %d %d %d) 'VERSION)\n"), AUDACITY_VERSION, AUDACITY_RELEASE, AUDACITY_REVISION);
797 lang = (lang.empty())
800 mProps += wxString::Format(
wxT(
"(putprop '*AUDACITY* \"%s\" 'LANGUAGE)\n"), lang);
802 mProps += wxString::Format(
wxT(
"(setf *DECIMAL-SEPARATOR* #\\%c)\n"), wxNumberFormatter::GetDecimalSeparator());
810 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-DIR* \"%s\" 'HOME)\n"),
EscapeString(wxGetHomeDir()));
814 for (
size_t i = 0, cnt = paths.size(); i < cnt; i++)
818 list = list.RemoveLast();
820 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-DIR* (list %s) 'PLUGIN)\n"), list);
821 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-DIR* (list %s) 'PLUG-IN)\n"), list);
822 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-DIR* \"%s\" 'USER-PLUG-IN)\n"),
826 wxDateTime now = wxDateTime::Now();
827 int year = now.GetYear();
828 int doy = now.GetDayOfYear();
829 int dom = now.GetDay();
831 wxDateTime::Month month = now.GetMonth();
832 wxDateTime::WeekDay day = now.GetWeekDay();
835 mProps += wxString::Format(
wxT(
"(setf *SYSTEM-TIME* (list %d %d %d %d %d))\n"),
836 year, doy, now.GetHour(), now.GetMinute(), now.GetSecond());
838 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'DATE)\n"), now.FormatDate());
839 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'TIME)\n"), now.FormatTime());
840 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'ISO-DATE)\n"), now.FormatISODate());
841 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'ISO-TIME)\n"), now.FormatISOTime());
842 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* %d 'YEAR)\n"), year);
843 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* %d 'DAY)\n"), dom);
844 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* %d 'MONTH)\n"), month);
845 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'MONTH-NAME)\n"), now.GetMonthName(month));
846 mProps += wxString::Format(
wxT(
"(putprop '*SYSTEM-TIME* \"%s\" 'DAY-NAME)\n"), now.GetWeekDayName(day));
848 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'PROJECTS)\n"),
857 wxString waveTrackList;
861 for (
auto t : countRange) {
864 if (t->GetSelected())
865 waveTrackList += wxString::Format(
wxT(
"%d "), 1 + numTracks);
870 #if defined(USE_MIDI)
880 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* (float %s) 'RATE)\n"),
882 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'TRACKS)\n"), numTracks);
883 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'WAVETRACKS)\n"), numWave);
884 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'LABELTRACKS)\n"), numLabel);
885 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'MIDITRACKS)\n"), numMidi);
886 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* %d 'TIMETRACKS)\n"), numTime);
888 double previewLen = 6.0;
889 gPrefs->
Read(
wxT(
"/AudioIO/EffectsPreviewLen"), &previewLen);
890 mProps += wxString::Format(
wxT(
"(putprop '*PROJECT* (float %s) 'PREVIEW-DURATION)\n"),
895 mProps += wxString::Format(
wxT(
"(setf *PREVIEWP* %s)\n"), isPreviewing);
897 mProps += wxString::Format(
wxT(
"(putprop '*SELECTION* (list %s) 'TRACKS)\n"), waveTrackList);
903 auto message =
XO(
"Audio selection required.");
906 wxOK | wxCENTRE | wxICON_EXCLAMATION,
907 XO(
"Nyquist Error") );
910 std::optional<TrackIterRange<WaveTrack>> pRange;
912 pRange.emplace(oOutputs->Get().Selected<
WaveTrack>());
918 Track *gtLast = NULL;
919 double progressTot{};
922 bOnePassTool || pRange->first != pRange->second;
923 (void) (!pRange || (++pRange->first,
true))
931 scale, progressTot };
932 auto &mCurNumChannels = nyxContext.mCurNumChannels;
933 auto &mCurChannelGroup = nyxContext.mCurChannelGroup;
934 auto &mCurTrack = nyxContext.mCurTrack;
935 auto &mCurStart = nyxContext.mCurStart;
936 auto &mCurLen = nyxContext.mCurLen;
938 mCurChannelGroup = pRange ? *pRange->first :
nullptr;
939 mCurTrack[0] = mCurChannelGroup;
941 if ( (
mT1 >=
mT0) || bOnePassTool ) {
945 if (
auto channels = mCurChannelGroup->Channels()
946 ; channels.size() > 1
953 mCurTrack[1] = (* ++ channels.first).get();
961 mCurStart = mCurChannelGroup->TimeToLongSamples(
mT0);
962 auto end = mCurChannelGroup->TimeToLongSamples(
mT1);
963 mCurLen =
end - mCurStart;
979 wxString prevlocale = wxSetlocale(LC_NUMERIC, NULL);
980 wxSetlocale(LC_NUMERIC, wxString(
wxT(
"C")));
986 auto cleanup =
finally( [&] {
987 nyx_capture_output(NULL, (
void *)NULL);
988 nyx_set_os_callback(NULL, (
void *)NULL);
996 wxString lowHz =
wxT(
"nil");
997 wxString highHz =
wxT(
"nil");
998 wxString centerHz =
wxT(
"nil");
999 wxString bandwidth =
wxT(
"nil");
1001#if defined(EXPERIMENTAL_SPECTRAL_EDITING)
1010 if ((mF0 >= 0.0) && (mF1 >= 0.0)) {
1014 if ((mF0 > 0.0) && (mF1 >= mF0)) {
1017 double bw = log(mF1 / mF0) / log(2.0);
1018 if (!std::isinf(bw)) {
1024 mPerTrackProps += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'LOW-HZ)\n"), lowHz);
1025 mPerTrackProps += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'CENTER-HZ)\n"), centerHz);
1026 mPerTrackProps += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'HIGH-HZ)\n"), highHz);
1027 mPerTrackProps += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'BANDWIDTH)\n"), bandwidth);
1030 mCurChannelGroup ? mCurChannelGroup->SnapToSample(
mT0) :
mT0;
1032 mCurChannelGroup ? mCurChannelGroup->SnapToSample(
mT1) :
mT1;
1034 wxT(
"(putprop '*SELECTION* (float %s) 'START)\n"),
1037 wxT(
"(putprop '*SELECTION* (float %s) 'END)\n"),
1041 success =
ProcessOne(nyxContext, oOutputs ? &*oOutputs :
nullptr);
1044 wxSetlocale(LC_NUMERIC, prevlocale);
1046 if (!success || bOnePassTool) {
1049 progressTot += nyxContext.mProgressIn + nyxContext.mProgressOut;
1052 mCount += mCurNumChannels;
1067 XO(
"Debug Output: "),
1069 dlog.CentreOnParent();
1084 mT0 = selectedRegion.t0();
1085 mT1 = selectedRegion.t1();
1105 int res = wxID_APPLY;
1109 parent,
factory, pInstance, access, forceModal);
1137 auto newAccess = std::make_shared<SimpleEffectSettingsAccess>(newSettings);
1149 parent,
factory, pNewInstance, *newAccess, forceModal);
1161 parent,
factory, pNewInstance, *newAccess,
false );
1168 nyquistSettings.proxySettings = std::move(newSettings);
1169 nyquistSettings.proxyDebug = this->
mDebug;
1170 nyquistSettings.controls = move(effect.
mControls);
1238 const auto wt =
dynamic_cast<const WaveTrack*
>(t);
1245 for (
size_t i = 0, n = ca.size(); i < n; ++i)
1249 clips += wxString::Format(
1250 wxT(
"(list (float %s) (float %s))"),
1278 cmd +=
wxT(
"(snd-set-latency 0.1)");
1283 cmd +=
wxT(
"(setf S 0.25)\n");
1285 nyx_set_audio_name(
"*TRACK*");
1286 cmd +=
wxT(
"(setf S 0.25)\n");
1289 nyx_set_audio_name(
"S");
1290 cmd +=
wxT(
"(setf *TRACK* '*unbound*)\n");
1305 wxString spectralEditp;
1316 auto displays = pView->GetDisplays();
1317 auto format = [&](
decltype(displays[0]) display ) {
1320 return wxString::Format(
wxT(
"\"%s\""),
1321 display.name.Stripped().Debug() );
1323 if (displays.empty())
1325 else if (displays.size() == 1)
1326 view =
format( displays[0] );
1328 view =
wxT(
"(list");
1329 for (
auto display : displays )
1330 view += wxString(
wxT(
" ")) +
format( display );
1335#if defined(USE_MIDI)
1338 view =
wxT(
"\"Midi\"");
1342 type =
wxT(
"label");
1343 view =
wxT(
"\"Label\"");
1347 view =
wxT(
"\"Time\"");
1351 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* %d 'INDEX)\n"), ++
mTrackIndex);
1352 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* \"%s\" 'NAME)\n"),
EscapeString(mCurChannelGroup->GetName()));
1353 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* \"%s\" 'TYPE)\n"), type);
1355 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* %s 'VIEW)\n"), view);
1356 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* %d 'CHANNELS)\n"), mCurNumChannels);
1359 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* %s 'SPECTRAL-EDIT-ENABLED)\n"), spectralEditp);
1361 const double startTime = mCurChannelGroup->GetStartTime();
1362 const double endTime = mCurChannelGroup->GetEndTime();
1364 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* (float %s) 'START-TIME)\n"),
1366 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* (float %s) 'END-TIME)\n"),
1368 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* (float %s) 'GAIN)\n"),
1370 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* (float %s) 'PAN)\n"),
1372 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* (float %s) 'RATE)\n"),
1375 switch (mCurChannelGroup->GetSampleFormat())
1378 bitFormat =
wxT(
"16");
1381 bitFormat =
wxT(
"24");
1384 bitFormat =
wxT(
"32.0");
1387 cmd += wxString::Format(
wxT(
"(putprop '*TRACK* %s 'FORMAT)\n"), bitFormat);
1389 float maxPeakLevel = 0.0;
1393 wxString inClips, outClips, peakString, rmsString;
1395 for (
size_t i = 0; i < mCurNumChannels; i++) {
1396 float maxPeak = 0.0;
1397 if (mCurNumChannels > 1)
1399 inClips +=
wxT(
"(list ");
1400 outClips +=
wxT(
"(list ");
1402 inClips += inClipBoundaries;
1403 outClips += outClipBoundaries;
1404 if (mCurNumChannels > 1)
1406 inClips +=
wxT(
" )");
1407 outClips +=
wxT(
" )");
1410 auto pair = mCurTrack[i]->GetMinMax(
mT0,
mT1);
1411 min = pair.first, max = pair.second;
1412 maxPeak = wxMax(wxMax(fabs(
min), fabs(max)), maxPeak);
1413 maxPeakLevel = wxMax(maxPeakLevel, maxPeak);
1416 if (!std::isinf(maxPeak) && !std::isnan(maxPeak) && (maxPeak < FLT_MAX)) {
1419 peakString +=
wxT(
"nil ");
1422 float rms = mCurTrack[i]->GetRMS(
mT0,
mT1);
1423 if (!std::isinf(rms) && !std::isnan(rms)) {
1426 rmsString +=
wxT(
"NIL ");
1430 cmd += wxString::Format(
1431 wxT(
"(putprop '*TRACK* %s%s ) 'INCLIPS)\n"),
1432 (mCurNumChannels == 1) ?
wxT(
"(list ") :
wxT(
"(vector "), inClips);
1433 cmd += wxString::Format(
1434 wxT(
"(putprop '*TRACK* %s%s ) 'CLIPS)\n"),
1435 (mCurNumChannels == 1) ?
wxT(
"(list ") :
wxT(
"(vector "), outClips);
1437 (mCurNumChannels > 1)?
1438 cmd += wxString::Format(
wxT(
"(putprop '*SELECTION* (vector %s) 'PEAK)\n"), peakString) :
1439 cmd += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'PEAK)\n"), peakString);
1441 if (!std::isinf(maxPeakLevel) && !std::isnan(maxPeakLevel) && (maxPeakLevel < FLT_MAX)) {
1442 cmd += wxString::Format(
wxT(
"(putprop '*SELECTION* (float %s) 'PEAK-LEVEL)\n"),
1446 (mCurNumChannels > 1)?
1447 cmd += wxString::Format(
wxT(
"(putprop '*SELECTION* (vector %s) 'RMS)\n"), rmsString) :
1448 cmd += wxString::Format(
wxT(
"(putprop '*SELECTION* %s 'RMS)\n"), rmsString);
1453 nyx_set_audio_params(44100, 0);
1455 nyx_set_audio_params(mCurChannelGroup->GetRate(), 0);
1458 nyx_set_audio_params(mCurChannelGroup->GetRate(), curLen);
1460 (
int)mCurNumChannels, curLen, mCurChannelGroup->GetRate());
1466 cmd +=
wxT(
"(setf s 0.25)\n");
1470 cmd +=
wxT(
"(setf *tracenable* T)\n");
1472 cmd +=
wxT(
"(setf *breakenable* T)\n");
1479 cmd +=
wxT(
"(setf *tracenable* NIL)\n");
1482 for (
unsigned int j = 0; j <
mControls.size(); j++) {
1489 cmd += wxString::Format(
wxT(
"(setf %s %s)\n"),
1496 cmd += wxString::Format(
wxT(
"(setf %s %d)\n"),
1501 cmd +=
wxT(
"(setf ");
1506 cmd +=
wxT(
"\")\n");
1517 str +=
wxT(
"\nset aud:result = main()\n");
1523 cmd +=
wxT(
"(setf *tracenable* nil)\n");
1524 cmd +=
wxT(
"(setf *breakenable* nil)\n");
1525 cmd +=
wxT(
"(setf *sal-traceback* t)\n");
1529 cmd +=
wxT(
"(setf *sal-compiler-debug* t)\n");
1532 cmd +=
wxT(
"(setf *sal-call-stack* nil)\n");
1536 cmd +=
wxT(
"(setf aud:result nil)\n");
1537 cmd +=
wxT(
"(sal-compile-audacity \"") +
str +
wxT(
"\" t t nil)\n");
1541 cmd +=
wxT(
"(prog1 aud:result (setf aud:result nil))\n");
1549 rval = nyx_eval_expression(cmd.mb_str(wxConvUTF8));
1555 wxLogMessage(
wxT(
"\'%s\' returned:\n%s"),
1564 if (mCurNumChannels == 1) {
1576 XO(
"';type tool' effects cannot return audio from Nyquist.\n")
1585 XO(
"';type tool' effects cannot return labels from Nyquist.\n")
1590 if (rval == nyx_error) {
1607 if (rval == nyx_list) {
1608 wxLogMessage(
"Nyquist returned nyx_list");
1613 XO(
"Nyquist returned a list.") );
1618 if (rval == nyx_string) {
1644 if (rval == nyx_double) {
1645 auto str =
XO(
"Nyquist returned the value: %f")
1646 .Format(nyx_get_double());
1651 if (rval == nyx_int) {
1652 auto str =
XO(
"Nyquist returned the value: %d")
1653 .Format(nyx_get_int());
1658 if (rval == nyx_labels) {
1665 unsigned int numLabels = nyx_get_num_labels();
1669 auto newTrack = std::make_shared<LabelTrack>();
1672 assert(newTrack->IsLeader());
1677 for (l = 0; l < numLabels; l++) {
1683 nyx_get_label(l, &t0, &t1, &
str);
1690 wxASSERT(rval == nyx_audio);
1692 int outChannels = nyx_get_audio_num_channels();
1693 if (outChannels > (
int)mCurNumChannels) {
1695 XO(
"Nyquist returned too many audio channels.\n"));
1699 if (outChannels == -1) {
1701 XO(
"Nyquist returned one audio channel as an array.\n"));
1705 if (outChannels == 0) {
1707 XO(
"Nyquist returned an empty array.\n"));
1711 nyxContext.
mOutputTracks = mCurChannelGroup->WideEmptyCopy();
1713 ->SharedPointer<WaveTrack>();
1720 std::rethrow_exception(pException);
1728 *
this,
XO(
"Nyquist returned nil audio.\n"));
1732 std::shared_ptr<TrackList> tempList;
1733 if (outChannels <
static_cast<int>(mCurNumChannels)) {
1739 tempList = out->MonoToStereo();
1750 ? (out->TimeToLongSamples(
mT0) + out->TimeToLongSamples(
mOutputTime)
1751 == out->TimeToLongSamples(
mT1))
1754 mCurChannelGroup->ClearAndPaste(
1762 t->SyncLockAdjust(
mT1,
mT0 + out->GetEndTime());
1778 wxString
str(nyqString, wxConvUTF8);
1779 if (nyqString != NULL && nyqString[0] &&
str.empty()) {
1781 str =
_(
"[Warning: Nyquist returned invalid UTF-8 string, converted here as Latin-1]");
1791 wxString
str = inStr;
1801 std::vector<EnumValueSymbol> results;
1802 if (text[0] ==
wxT(
'(')) {
1806 auto &choices = tzer.
tokens;
1808 for (
auto &choice : choices) {
1821 auto choices = wxStringTokenize(
1822 text[0] ==
wxT(
'"') ? text.Mid(1, text.length() - 2) : text,
1825 for (
auto &choice : choices)
1826 results.push_back( { choice.Trim(
true).Trim(
false) } );
1835 if (text[0] ==
wxT(
'(')) {
1838 for (
const auto &token : tzer.
tokens)
1839 results.push_back(
UnQuote( token ) );
1848 if (text[0] ==
wxT(
'(')) {
1851 auto &tokens = tzer.
tokens;
1852 if ( tokens.size() == 2 )
1863 if (text[0] ==
wxT(
'(')) {
1866 auto &types = tzer.
tokens;
1867 if ( !types.empty() && types[0][0] ==
wxT(
'(') )
1868 for (
auto &type : types)
1871 if ( results.empty() ) {
1875 auto pieces = wxSplit(
str,
'|' );
1877 auto size = pieces.size();
1878 if (
size % 2 == 1 )
1879 --
size, pieces.pop_back();
1880 for (
size_t ii = 0; ii <
size; ii += 2 ) {
1882 auto extensionStrings = wxSplit( pieces[ii + 1],
';' );
1883 for (
const auto &extensionString : extensionStrings )
1884 if ( extensionString.StartsWith(
wxT(
"*.") ) ) {
1885 auto ext = extensionString.substr( 2 );
1886 if (ext ==
wxT(
"*"))
1889 extensions.push_back( ext );
1891 results.push_back( {
Verbatim( pieces[ii] ), extensions } );
1927 wxString *pExtraString)
1930 *pExtraString = wxString{};
1932 int len = s.length();
1933 if (len >= 2 && s[0] ==
wxT(
'\"') && s[len - 1] ==
wxT(
'\"')) {
1934 auto unquoted = s.Mid(1, len - 2);
1939 else if (allowParens &&
1940 len >= 2 && s[0] ==
wxT(
'(') && s[len - 1] ==
wxT(
')')) {
1943 auto &tokens = tzer.
tokens;
1944 if (tokens.size() > 1) {
1945 if (pExtraString && tokens[1][0] ==
'(') {
1949 *pExtraString =
UnQuote(tokens[0],
false);
1968 wxString *pExtraString)
1992 const wxString &line,
bool eof,
1993 size_t trimStart,
size_t trimEnd)
1995 auto endToken = [&]{
2004 if (
q && !
sl && c ==
wxT(
'\\')) {
2010 if (!
sl && c ==
wxT(
'"')) {
2030 else if (!
q && !
paren && (c ==
wxT(
' ') || c ==
wxT(
'\t')))
2034 else if (!
q && c ==
wxT(
';'))
2040 else if (!
q && c ==
wxT(
'(')) {
2044 endToken(),
tok += c;
2049 else if (!
q && c ==
wxT(
')')) {
2053 tok += c, endToken();
2056 paren = 0, endToken();
2077 if (eof || (!
q && !
paren)) {
2091 Tokenizer &tzer,
const wxString &line,
bool eof,
bool first)
2093 if ( !tzer.
Tokenize(line, eof, first ? 1 : 0, 0) )
2096 const auto &tokens = tzer.
tokens;
2097 int len = tokens.size();
2104 if (len == 2 && tokens[0] ==
wxT(
"nyquist") &&
2105 (tokens[1] ==
wxT(
"plug-in") || tokens[1] ==
wxT(
"plugin"))) {
2110 if (len >= 2 && tokens[0] ==
wxT(
"type")) {
2111 wxString tok = tokens[1];
2113 if (tok ==
wxT(
"tool")) {
2127 if (tok ==
wxT(
"process")) {
2130 else if (tok ==
wxT(
"generate")) {
2133 else if (tok ==
wxT(
"analyze")) {
2137 if (len >= 3 && tokens[2] ==
wxT(
"spectral")) {;
2143 if (len == 2 && tokens[0] ==
wxT(
"codetype")) {
2145 if (tokens[1] ==
wxT(
"lisp")) {
2149 else if (tokens[1] ==
wxT(
"sal")) {
2156 if (len >= 2 && tokens[0] ==
wxT(
"debugflags")) {
2157 for (
int i = 1; i < len; i++) {
2160 if (tokens[i] ==
wxT(
"trace")) {
2163 else if (tokens[i] ==
wxT(
"notrace")) {
2166 else if (tokens[i] ==
wxT(
"compiler")) {
2169 else if (tokens[i] ==
wxT(
"nocompiler")) {
2180 if (len >= 2 && tokens[0] ==
wxT(
"version")) {
2182 tokens[1].ToLong(&v);
2183 if (v < 1 || v > 4) {
2187"This version of Audacity does not support Nyquist plug-in version %ld")
2194 if (len >= 2 && tokens[0] ==
wxT(
"name")) {
2204 if (
name.EndsWith(
wxT(
"...")))
2210 if (len >= 2 && tokens[0] ==
wxT(
"action")) {
2215 if (len >= 2 && tokens[0] ==
wxT(
"info")) {
2220 if (len >= 2 && tokens[0] ==
wxT(
"preview")) {
2221 if (tokens[1] ==
wxT(
"enabled") || tokens[1] ==
wxT(
"true")) {
2225 else if (tokens[1] ==
wxT(
"linear")) {
2229 else if (tokens[1] ==
wxT(
"selection")) {
2233 else if (tokens[1] ==
wxT(
"disabled") || tokens[1] ==
wxT(
"false")) {
2241 if (len >= 2 && tokens[0] ==
wxT(
"maxlen")) {
2243 tokens[1].ToLongLong(&v);
2247#if defined(EXPERIMENTAL_NYQUIST_SPLIT_CONTROL)
2248 if (len >= 2 && tokens[0] ==
wxT(
"mergeclips")) {
2251 tokens[1].ToLong(&v);
2256 if (len >= 2 && tokens[0] ==
wxT(
"restoresplits")) {
2259 tokens[1].ToLong(&v);
2265 if (len >= 2 && tokens[0] ==
wxT(
"author")) {
2270 if (len >= 2 && tokens[0] ==
wxT(
"release")) {
2277 if (len >= 2 && tokens[0] ==
wxT(
"copyright")) {
2283 if (len >= 2 && tokens[0] ==
wxT(
"manpage")) {
2290 if (len >= 2 && tokens[0] ==
wxT(
"helpfile")) {
2297 if (len >= 2 && tokens[0] ==
wxT(
"debugbutton")) {
2298 if (tokens[1] ==
wxT(
"disabled") || tokens[1] ==
wxT(
"false")) {
2305 if (len >= 3 && tokens[0] ==
wxT(
"control")) {
2308 if (len == 3 && tokens[1] ==
wxT(
"text")) {
2309 ctrl.
var = tokens[1];
2315 ctrl.
var = tokens[1];
2318 ctrl.
label = tokens[4];
2321 ctrl.
valStr = len > 5 ? tokens[5] : wxString{};
2323 if (ctrl.
valStr.length() > 0 &&
2331 if (tokens[3] ==
wxT(
"string")) {
2335 else if (tokens[3] ==
wxT(
"choice")) {
2340 else if (tokens[3] ==
wxT(
"file")) {
2354 if ((tokens[3] ==
wxT(
"float")) ||
2355 (tokens[3] ==
wxT(
"real")))
2357 else if (tokens[3] ==
wxT(
"int"))
2359 else if (tokens[3] ==
wxT(
"float-text"))
2361 else if (tokens[3] ==
wxT(
"int-text"))
2363 else if (tokens[3] ==
wxT(
"time"))
2368 str.Printf(
wxT(
"Bad Nyquist 'control' type specification: '%s' in plug-in file '%s'.\nControl not created."),
2388 ctrl.
low = -(FLT_MAX);
2399 ctrl.
high = INT_MAX;
2404 ctrl.
high = FLT_MAX;
2414 if (ctrl.
val < ctrl.
low) {
2437 if (len >= 2 && tokens[0] ==
wxT(
"categories")) {
2438 for (
size_t i = 1; i < tokens.size(); ++i) {
2453 wxTextInputStream pgm(stream,
wxT(
" \t"), wxConvAuto());
2475 while (!stream.Eof() && stream.IsOk())
2477 wxString line = pgm.ReadLine();
2478 if (line.length() > 1 &&
2482 (line[0] ==
wxT(
';') || line[0] ==
wxT(
'$')) )
2485 unsigned nLines = 1;
2489 line[0] ==
wxT(
'$') || line.StartsWith(
wxT(
";control") );
2491 done =
Parse(tzer, line, !control || stream.Eof(), nLines == 1);
2493 (line = pgm.ReadLine(), ++nLines,
true));
2504 if (line[0] ==
wxT(
'(') ||
2505 (line[0] ==
wxT(
'#') && line.length() > 1 && line[1] ==
wxT(
'|')))
2510 else if (line.Upper().Find(
wxT(
"RETURN")) != wxNOT_FOUND)
2525"Your code looks like SAL syntax, but there is no \'return\' statement.\n\
2526For SAL, use a return statement such as:\n\treturn *track* * 0.1\n\
2527or for LISP, begin with an open parenthesis such as:\n\t(mult *track* 0.1)\n ."),
2529 XO(
"Error in Nyquist code") );
2545 wxFileInputStream rawStream(
mFileName.GetFullPath());
2546 wxBufferedInputStream stream(rawStream, 10000);
2553 wxStringInputStream stream(cmd +
wxT(
" "));
2559 int64_t start, int64_t len, int64_t totlen,
void *userdata)
2561 auto This =
static_cast<NyxContext*
>(userdata);
2562 return This->
GetCallback(buffer, channel, start, len, totlen);
2566 int64_t start, int64_t len, int64_t)
2568 if (mCurBuffer[ch]) {
2569 if ((mCurStart + start) < mCurBufferStart[ch] ||
2570 (mCurStart + start) + len >
2571 mCurBufferStart[ch] + mCurBufferLen[ch]) {
2572 mCurBuffer[ch].reset();
2576 if (!mCurBuffer[ch]) {
2577 mCurBufferStart[ch] = (mCurStart + start);
2578 mCurBufferLen[ch] = mCurTrack[ch]->GetBestBlockSize(mCurBufferStart[ch]);
2580 if (mCurBufferLen[ch] < (
size_t) len)
2581 mCurBufferLen[ch] = mCurTrack[ch]->GetIdealBlockSize();
2584 mCurStart + mCurLen - mCurBufferStart[ch]);
2588 mCurBuffer[ch] =
Buffer{
safenew float[ mCurBufferLen[ch] ] };
2590 mCurTrack[ch]->GetFloats( mCurBuffer[ch].get(),
2591 mCurBufferStart[ch], mCurBufferLen[ch]);
2595 mpException = std::current_exception();
2602 auto offset = (mCurStart + start - mCurBufferStart[ch]).as_size_t();
2603 const void *src = &mCurBuffer[ch][offset];
2604 std::memcpy(buffer, src, len *
sizeof(
float));
2607 double progress = mScale * ((start + len) / mCurLen.as_double());
2608 if (progress > mProgressIn)
2609 mProgressIn = progress;
2610 if (mProgressReport(mProgressIn + mProgressOut + mProgressTot))
2618 int64_t start, int64_t len, int64_t totlen,
void *userdata)
2620 auto This =
static_cast<NyxContext*
>(userdata);
2621 return This->
PutCallback(buffer, channel, start, len, totlen);
2625 int64_t start, int64_t len, int64_t totlen)
2628 return GuardedCall<int>( [&] {
2630 double progress = mScale * ((float)(start + len) / totlen);
2631 if (progress > mProgressOut)
2632 mProgressOut = progress;
2633 if (mProgressReport(mProgressIn + mProgressOut + mProgressTot))
2660 std::cout << (char)c;
2693#if defined(__WXMAC__)
2703 for (
size_t i = 0; i < audacityPathList.size(); i++)
2705 wxString prefix = audacityPathList[i] + wxFILE_SEP_PATH;
2724 for (
size_t i = 0, cnt =
mControls.size(); i < cnt; i++)
2730 const auto count = ctrl.
choices.size();
2732 int val = (int)ctrl.
val;
2733 if (val < 0 || val >= (
int)count)
2739 c->SetSelection(val);
2744 double range = ctrl.
high - ctrl.
low;
2745 int val = (int)(0.5 + ctrl.
ticks * (ctrl.
val - ctrl.
low) / range);
2765 const wxString left =
wxT(
"\u201c"), right =
wxT(
"\u201d"), dumb =
'"';
2769 const wxString leftSingle =
wxT(
"\u2018"), rightSingle =
wxT(
"\u2019"),
2771 mInputCmd.Replace(leftSingle, dumbSingle,
true);
2772 mInputCmd.Replace(rightSingle, dumbSingle,
true);
2784 for (
unsigned int i = 0; i <
mControls.size(); i++)
2808 if (ctrl->
valStr.StartsWith(
"\"", &path))
2811 if (path.EndsWith(
"\"", &path))
2813 path.Replace(
"\"\"",
"\"");
2814 wxStringTokenizer tokenizer(path,
"\"");
2815 while (tokenizer.HasMoreTokens())
2817 wxString token = tokenizer.GetNextToken();
2820 const auto message =
2821 XO(
"\"%s\" is not a valid file path.").Format( token );
2824 wxOK | wxICON_EXCLAMATION | wxCENTRE,
2833 const auto message =
2835 XO(
"Mismatched quotes in\n%s").Format( ctrl->
valStr );
2838 wxOK | wxICON_EXCLAMATION | wxCENTRE,
2850 const auto message =
2851 XO(
"\"%s\" is not a valid file path.").Format( ctrl->
valStr );
2854 wxOK | wxICON_EXCLAMATION | wxCENTRE,
2866 ctrl->
low = INT_MIN;
2869 ctrl->
lowStr.IsSameAs(
wxT(
"nil"),
false))
2871 ctrl->
low = -(FLT_MAX);
2879 ctrl->
high = INT_MAX;
2884 ctrl->
high = FLT_MAX;
2896 if (ctrl->
val < ctrl->
low)
2919 S.StartVerticalLay();
2921 S.StartMultiColumn(3, wxEXPAND);
2923 S.SetStretchyCol(1);
2925 S.AddVariableText(
XO(
"Enter Nyquist Command: "));
2931 S.StartHorizontalLay(wxEXPAND, 1);
2934 .MinSize( { 500, 200 } )
2935 .AddTextWindow(
wxT(
""));
2937 S.EndHorizontalLay();
2939 S.StartHorizontalLay(wxALIGN_CENTER, 0);
2944 S.EndHorizontalLay();
2951 wxScrolledWindow *scroller =
S.Style(wxVSCROLL | wxTAB_TRAVERSAL)
2954 S.StartMultiColumn(4);
2956 for (
size_t i = 0; i <
mControls.size(); i++)
2963 S.StartHorizontalLay(wxALIGN_LEFT, 0);
2968 S.EndHorizontalLay();
2969 S.StartMultiColumn(4);
2973 auto prompt =
XXO(
"%s:").Format( ctrl.
name );
2974 S.AddPrompt( prompt );
2981 .Validator<wxGenericValidator>(&ctrl.
valStr)
2983 .AddTextBox( {},
wxT(
""), 50);
3010 .Position(wxALIGN_LEFT | wxALL)
3021 if ( !type.extensions.empty() )
3022 defaultExtension = type.extensions[0];
3028 .AddTextBox( {},
wxT(
""), 40);
3029 item->SetValidator(wxGenericValidator(&ctrl.
valStr));
3031 if (ctrl.
label.empty())
3033 ctrl.
label = wxGetTranslation( wxFileSelectorPromptStr );
3048 double range = ctrl.
high - ctrl.
low;
3049 S.Validator<FloatingPointValidator<double>>(
3054 ? NumValidatorStyle::THREE_TRAILING_ZEROES
3056 ? NumValidatorStyle::TWO_TRAILING_ZEROES
3057 : NumValidatorStyle::ONE_TRAILING_ZERO),
3063 S.Validator<IntegerValidator<double>>(
3064 &ctrl.
val, NumValidatorStyle::DEFAULT,
3065 (int) ctrl.
low, (
int) ctrl.
high);
3067 wxTextCtrl *item =
S
3069 .AddTextBox( {},
wxT(
""),
3076 .Style(wxSL_HORIZONTAL)
3077 .MinSize( { 150, -1 } )
3078 .AddSlider( {}, 0, ctrl.
ticks, 0);
3100 scroller->SetScrollRate(0, 20);
3103 scroller->SetName(
wxT(
"\a"));
3104 scroller->SetLabel(
wxT(
"\a"));
3126 XO(
"Current program has been modified.\nDiscard changes?"),
3135 XO(
"Load Nyquist script"),
3141 FileNames::TextFiles,
3144 wxFD_OPEN | wxRESIZE_BORDER);
3163 XO(
"Save Nyquist script"),
3171 wxFD_SAVE | wxFD_OVERWRITE_PROMPT | wxRESIZE_BORDER);
3191 int val = evt.GetInt();
3192 double range = ctrl.
high - ctrl.
low;
3193 double newVal = (val / (double)ctrl.
ticks) * range + ctrl.
low;
3196 int precision = range < 1.0 ? 3 :
3204 if (fabs(newVal - ctrl.
val) >= (1 / (double)ctrl.
ticks) * range &&
3205 fabs(newVal - ctrl.
val) >= pow(0.1, precision) / 2)
3208 newVal *= pow(10.0, precision);
3209 newVal = floor(newVal + 0.5);
3210 newVal /= pow(10.0, precision);
3225 int i = evt.GetId() -
ID_Time;
3226 static double value = 0.0;
3235 if (val < ctrl.low || val > ctrl.
high) {
3236 const auto message =
XO(
"Value range:\n%s to %s")
3241 XO(
"Value Error") );
3246 else if (val > ctrl.
high)
3256 int i = evt.GetId() -
ID_FILE;
3261 unsigned int flags = 0;
3264 wxStringTokenizer tokenizer(ctrl.
highStr,
",");
3265 while ( tokenizer.HasMoreTokens() )
3267 wxString token = tokenizer.GetNextToken().Trim(
true).Trim(
false);
3268 if (token.IsSameAs(
"open",
false))
3271 flags &= ~wxFD_SAVE;
3272 flags &= ~wxFD_OVERWRITE_PROMPT;
3274 else if (token.IsSameAs(
"save",
false))
3277 flags &= ~wxFD_OPEN;
3278 flags &= ~wxFD_MULTIPLE;
3279 flags &= ~wxFD_FILE_MUST_EXIST;
3281 else if (token.IsSameAs(
"overwrite",
false) && !(flags & wxFD_OPEN))
3283 flags |= wxFD_OVERWRITE_PROMPT;
3285 else if (token.IsSameAs(
"exists",
false) && !(flags & wxFD_SAVE))
3287 flags |= wxFD_FILE_MUST_EXIST;
3289 else if (token.IsSameAs(
"multiple",
false) && !(flags & wxFD_SAVE))
3291 flags |= wxFD_MULTIPLE;
3298 wxFileName fname = ctrl.
valStr;
3299 wxString defaultDir = fname.GetPath();
3300 wxString defaultFile = fname.GetName();
3301 auto message =
XO(
"Select a file");
3303 if (flags & wxFD_MULTIPLE)
3304 message =
XO(
"Select one or more files");
3305 else if (flags & wxFD_SAVE)
3306 message =
XO(
"Save file as");
3315 if (openFileDialog.
ShowModal() == wxID_CANCEL)
3322 if (flags & wxFD_MULTIPLE)
3324 wxArrayString selectedFiles;
3325 openFileDialog.
GetPaths(selectedFiles);
3327 for (
size_t sf = 0; sf < selectedFiles.size(); sf++) {
3329 path += selectedFiles[sf];
3352#if defined(__WXMSW__)
3353 path.Replace(
"/", wxFileName::GetPathSeparator());
3356 path.Trim(
true).Trim(
false);
3358 typedef std::unordered_map<wxString, FilePath> map;
3360 {
"*home*", wxGetHomeDir()},
3361 {
"~", wxGetHomeDir()},
3368 int characters = path.Find(wxFileName::GetPathSeparator());
3369 if(characters == wxNOT_FOUND)
3374 if (pathKeys.find(path) != pathKeys.end())
3377 path = pathKeys[path] + wxFileName::GetPathSeparator();
3381 path = pathKeys[
"*default*"] + wxFileName::GetPathSeparator() + path;
3386 wxString firstDir = path.Left(characters);
3387 wxString rest = path.Mid(characters);
3389 if (pathKeys.find(firstDir) != pathKeys.end())
3391 path = pathKeys[firstDir] + rest;
3395 wxFileName fname = path;
3399 if (fname.wxFileName::IsOk() && fname.GetFullName().empty())
3401 path = fname.GetPathWithSep() +
_(
"untitled");
3402 if (!extension.empty())
3403 path = path +
'.' + extension;
3410 wxFileName fname = path;
3411 wxString dir = fname.GetPath();
3413 return (fname.wxFileName::IsOk() &&
3414 wxFileName::DirExists(dir) &&
3415 !fname.GetFullName().empty());
3421 int seconds =
static_cast<int>(t);
3422 int hh = seconds / 3600;
3423 int mm = seconds % 3600;
3425 return wxString::Format(
"%d:%d:%.3f", hh, mm, t - (hh * 3600 + mm * 60));
3431 int i = evt.GetId() -
ID_Text;
3435 if (wxDynamicCast(evt.GetEventObject(), wxWindow)->GetValidator()->TransferFromWindow())
3439 int pos = (int)floor((ctrl.
val - ctrl.
low) /
3443 slider->SetValue(pos);
3463:
wxDialogWrapper{ parent,
id,
title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER }
3471 S.AddVariableText( prompt,
false, wxALIGN_LEFT | wxLEFT | wxTOP | wxRIGHT );
3476 .Position(wxEXPAND | wxALL)
3477 .MinSize( { 480, 250 } )
3478 .Style(wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH)
3479 .AddTextWindow( message.Translation() );
3483 S.StartHorizontalLay(wxALIGN_CENTRE | wxLEFT | wxBOTTOM | wxRIGHT, 0 );
3486 S.Id(wxID_OK).AddButton(
XXO(
"OK"), wxALIGN_CENTRE,
true );
3488 S.EndHorizontalLay();
3492 SetAutoLayout(
true);
3493 GetSizer()->Fit(
this);
3494 GetSizer()->SetSizeHints(
this);
3507#include "../../../lib-src/libnyquist/nyquist/xlisp/xlisp.h"
3511 auto string =
UTF8CTOWX(getstring(xlgastring()));
3512#if !HAS_I18N_CONTEXTS
3523#if HAS_I18N_CONTEXTS
3524 auto string =
UTF8CTOWX(getstring(xlgastring()));
3525 auto context =
UTF8CTOWX(getstring(xlgastring()));
3527 return cvstring(wxGetTranslation(
string,
"", 0,
"", context )
3528 .mb_str(wxConvUTF8));
3536 auto string1 =
UTF8CTOWX(getstring(xlgastring()));
3537 auto string2 =
UTF8CTOWX(getstring(xlgastring()));
3538 auto number = getfixnum(xlgafixnum());
3539#if !HAS_I18N_CONTEXTS
3546 wxGetTranslation(string1, string2, number).mb_str(wxConvUTF8));
3551#if HAS_I18N_CONTEXTS
3552 auto string1 =
UTF8CTOWX(getstring(xlgastring()));
3553 auto string2 =
UTF8CTOWX(getstring(xlgastring()));
3554 auto number = getfixnum(xlgafixnum());
3555 auto context =
UTF8CTOWX(getstring(xlgastring()));
3557 return cvstring(wxGetTranslation( string1, string2, number,
"", context )
3558 .mb_str(wxConvUTF8));
3566 unsigned char * dstp;
3567 dst = new_string((
int)(
size+2));
3568 dstp = getstring(dst);
3582 wxString Left = Str.BeforeLast(
'\n').BeforeLast(
'\n').ToAscii();
3583 wxString Right = Str.BeforeLast(
'\n').AfterLast(
'\n').ToAscii();
3584 message = cvstring(Left);
3585 success = Right.EndsWith(
"OK") ? s_true :
nullptr;
3586 dst = cons(message, success);
3590#include "../../commands/ScriptCommandRelay.h"
3598 unsigned char *leftp;
3606 leftp = getstring(src);
3620 static bool firstTime =
true;
3625 static const FUNDEF functions[] = {
3633 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)
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
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)
Mutative access to attachment even if the track argument is const.
std::shared_ptr< EffectInstance > MakeInstance() const override
Make an object maintaining short-term state of an Effect.
static bool IsSyncLockSelected(const Track *pTrack)
static TrackIterRange< Track > Group(Track *pTrack)
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 * Find(WaveChannel *pChannel)
A Track that contains audio waveform data.
WaveClipPointers SortedClipArray()
size_t NChannels() const override
May report more than one only when this is a leader track.
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)
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
FILES_API wxString TempDir()
wxString GetClipBoundaries(const Track *t)
static RegisteredToolbarFactory factory
__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)
std::shared_ptr< TrackList > mOutputTracks
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
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)