mirror of
https://github.com/cookiengineer/audacity
synced 2025-09-19 17:40:51 +02:00
Merge branch 'scripting-with-nyquist'
This commit is contained in:
commit
703bf2b647
@ -103,7 +103,10 @@ class AUDACITY_DLL_API EffectDefinitionInterface /* not final */ : public Ident
|
|||||||
public:
|
public:
|
||||||
virtual ~EffectDefinitionInterface() {};
|
virtual ~EffectDefinitionInterface() {};
|
||||||
|
|
||||||
|
// Type determines how it behaves.
|
||||||
virtual EffectType GetType() = 0;
|
virtual EffectType GetType() = 0;
|
||||||
|
// Classification determines which menu it appears in.
|
||||||
|
virtual EffectType GetClassification() { return GetType();};
|
||||||
|
|
||||||
virtual IdentInterfaceSymbol GetFamilyId() = 0;
|
virtual IdentInterfaceSymbol GetFamilyId() = 0;
|
||||||
|
|
||||||
|
1
lib-src/libnyquist/nyquist/nyqsrc/audacityfnintdefs.h
Normal file
1
lib-src/libnyquist/nyquist/nyqsrc/audacityfnintdefs.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
extern LVAL xlc_aud_do(void);
|
1
lib-src/libnyquist/nyquist/nyqsrc/audacityfnintptrs.h
Normal file
1
lib-src/libnyquist/nyquist/nyqsrc/audacityfnintptrs.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ "AUD-DO", S, xlc_aud_do},
|
@ -3,6 +3,7 @@
|
|||||||
/* CHANGE LOG
|
/* CHANGE LOG
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
* 28Apr03 dm changes for portability and fix compiler warnings
|
* 28Apr03 dm changes for portability and fix compiler warnings
|
||||||
|
* 12Feb18 jkc added aud-do function, that is only available in Audacity.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "xlisp.h"
|
#include "xlisp.h"
|
||||||
@ -53,3 +54,50 @@ void print_local_gc_info(void)
|
|||||||
max_sample_block_len) / 1024);
|
max_sample_block_len) / 1024);
|
||||||
stdputstr(buf);
|
stdputstr(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------Audacity Automation -------------------------*/
|
||||||
|
/* These functions may later move to their own source file. */
|
||||||
|
extern void * ExecForLisp( char * pIn );
|
||||||
|
extern void * nyq_make_opaque_string( int size, unsigned char *src );
|
||||||
|
|
||||||
|
|
||||||
|
void * nyq_make_opaque_string( int size, unsigned char *src ){
|
||||||
|
LVAL dst;
|
||||||
|
unsigned char * dstp;
|
||||||
|
dst = new_string((int)(size+2));
|
||||||
|
dstp = getstring(dst);
|
||||||
|
|
||||||
|
/* copy the source to the destination */
|
||||||
|
while (size-- > 0)
|
||||||
|
*dstp++ = *src++;
|
||||||
|
*dstp = '\0';
|
||||||
|
|
||||||
|
return (void*)dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* xlc_aud_do -- interface to C routine aud_do */
|
||||||
|
/**/
|
||||||
|
LVAL xlc_aud_do(void)
|
||||||
|
{
|
||||||
|
// Based on string-trim...
|
||||||
|
unsigned char *leftp,*rightp;
|
||||||
|
LVAL src,dst;
|
||||||
|
|
||||||
|
/* get the string */
|
||||||
|
src = xlgastring();
|
||||||
|
xllastarg();
|
||||||
|
|
||||||
|
/* setup the string pointers */
|
||||||
|
leftp = getstring(src);
|
||||||
|
rightp = leftp + getslength(src) - 2;
|
||||||
|
|
||||||
|
// Go call my real function here...
|
||||||
|
dst = (LVAL)ExecForLisp( leftp );
|
||||||
|
|
||||||
|
/* return the new string */
|
||||||
|
return (dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
/* include actual local file headers: */
|
/* include actual local file headers: */
|
||||||
#include "sndfnintdefs.h"
|
#include "sndfnintdefs.h"
|
||||||
#include "seqfnintdefs.h"
|
#include "seqfnintdefs.h"
|
||||||
|
#include "audacityfnintdefs.h"
|
||||||
|
@ -2,8 +2,11 @@
|
|||||||
*
|
*
|
||||||
* CHANGE LOG
|
* CHANGE LOG
|
||||||
* 28-Apr-03 rbd Removed "include switches.h" -- already included
|
* 28-Apr-03 rbd Removed "include switches.h" -- already included
|
||||||
|
* 12-Feb-18 jkc Added "include audacityfnintptrs.h" -- for internal Audacity commands
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* extension to xlisp */
|
/* extension to xlisp */
|
||||||
#include "sndfnintptrs.h"
|
#include "sndfnintptrs.h"
|
||||||
#include "seqfnintptrs.h"
|
#include "seqfnintptrs.h"
|
||||||
|
#include "audacityfnintptrs.h"
|
||||||
|
|
||||||
|
@ -1435,7 +1435,7 @@ const PluginID & PluginManager::RegisterPlugin(ModuleInterface *provider, Effect
|
|||||||
|
|
||||||
plug.SetProviderID(PluginManager::GetID(provider));
|
plug.SetProviderID(PluginManager::GetID(provider));
|
||||||
|
|
||||||
plug.SetEffectType(effect->GetType());
|
plug.SetEffectType(effect->GetClassification());
|
||||||
plug.SetEffectFamilyId(effect->GetFamilyId().Internal());
|
plug.SetEffectFamilyId(effect->GetFamilyId().Internal());
|
||||||
plug.SetEffectInteractive(effect->IsInteractive());
|
plug.SetEffectInteractive(effect->IsInteractive());
|
||||||
plug.SetEffectDefault(effect->IsDefault());
|
plug.SetEffectDefault(effect->IsDefault());
|
||||||
|
@ -97,6 +97,72 @@ int ExecCommand(wxString *pIn, wxString *pOut)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is the function which actually obeys one command. Rather than applying
|
||||||
|
/// the command directly, an event containing a reference to the command is sent
|
||||||
|
/// to the main (GUI) thread. This is because having more than one thread access
|
||||||
|
/// the GUI at a time causes problems with wxwidgets.
|
||||||
|
int ExecCommand2(wxString *pIn, wxString *pOut)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
CommandBuilder builder(*pIn);
|
||||||
|
if (builder.WasValid())
|
||||||
|
{
|
||||||
|
AudacityProject *project = GetActiveProject();
|
||||||
|
OldStyleCommandPointer cmd = builder.GetCommand();
|
||||||
|
AppCommandEvent ev;
|
||||||
|
ev.SetCommand(cmd);
|
||||||
|
AudacityApp & App = wxGetApp();
|
||||||
|
App.OnReceiveCommand(ev);
|
||||||
|
|
||||||
|
*pOut = wxEmptyString;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*pOut = wxT("Syntax error!\n");
|
||||||
|
*pOut += builder.GetErrorMessage() + wxT("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait until all responses from the command have been received.
|
||||||
|
// The last response is signalled by an empty line.
|
||||||
|
wxString msg = ScriptCommandRelay::ReceiveResponse().GetMessage();
|
||||||
|
while (msg != wxT("\n"))
|
||||||
|
{
|
||||||
|
//wxLogDebug( "Msg: %s", msg );
|
||||||
|
*pOut += msg + wxT("\n");
|
||||||
|
msg = ScriptCommandRelay::ReceiveResponse().GetMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
// The void * return is actually a Lisp LVAL and will be cast to such as needed.
|
||||||
|
extern void * ExecForLisp( char * pIn );
|
||||||
|
extern void * nyq_make_opaque_string( int size, unsigned char *src );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void * ExecForLisp( char * pIn ){
|
||||||
|
wxString Str1( pIn );
|
||||||
|
wxString Str2;
|
||||||
|
ExecCommand2( &Str1, &Str2 );
|
||||||
|
|
||||||
|
// wxString provides a const char *
|
||||||
|
const char * pStr = static_cast<const char*>(Str2);
|
||||||
|
|
||||||
|
// We'll be passing it as a non-const unsigned char *
|
||||||
|
// That 'unsafe' cast is actually safe. nyq_make_opaque_string is just copying the string.
|
||||||
|
void * pResult = nyq_make_opaque_string( Str2.Length(), (unsigned char *)pStr );
|
||||||
|
return pResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Adds a response to the queue to be sent back to the script
|
/// Adds a response to the queue to be sent back to the script
|
||||||
void ScriptCommandRelay::SendResponse(const wxString &response)
|
void ScriptCommandRelay::SendResponse(const wxString &response)
|
||||||
{
|
{
|
||||||
|
@ -207,6 +207,10 @@ void SelectTracksCommand::PopulateOrExchange(ShuttleGui & S)
|
|||||||
|
|
||||||
bool SelectTracksCommand::Apply(const CommandContext &context)
|
bool SelectTracksCommand::Apply(const CommandContext &context)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Count selection as a do-nothing effect.
|
||||||
|
// Used to invalidate cached selection and tracks.
|
||||||
|
Effect::IncEffectCounter();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
TrackList *tracks = context.GetProject()->GetTracks();
|
TrackList *tracks = context.GetProject()->GetTracks();
|
||||||
|
|
||||||
|
@ -70,6 +70,9 @@ greater use in future.
|
|||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
// Effect application counter
|
||||||
|
int Effect::nEffectsDone=0;
|
||||||
|
|
||||||
static const int kDummyID = 20000;
|
static const int kDummyID = 20000;
|
||||||
static const int kSaveAsID = 20001;
|
static const int kSaveAsID = 20001;
|
||||||
static const int kImportID = 20002;
|
static const int kImportID = 20002;
|
||||||
@ -1074,8 +1077,9 @@ bool Effect::SetAutomationParameters(const wxString & parms)
|
|||||||
preset
|
preset
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
// We are using defualt settings and we still wish to continue.
|
||||||
return false;
|
return true;
|
||||||
|
//return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mUIDialog)
|
if (!mUIDialog)
|
||||||
@ -1246,7 +1250,7 @@ bool Effect::DoEffect(wxWindow *parent,
|
|||||||
returnVal = Process();
|
returnVal = Process();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnVal)
|
if (returnVal && (mT1 >= mT0 ))
|
||||||
{
|
{
|
||||||
selectedRegion->setTimes(mT0, mT1);
|
selectedRegion->setTimes(mT0, mT1);
|
||||||
}
|
}
|
||||||
@ -2246,6 +2250,7 @@ void Effect::ReplaceProcessedTracks(const bool bGoodResult)
|
|||||||
// The output list is no longer needed
|
// The output list is no longer needed
|
||||||
mOutputTracks.reset();
|
mOutputTracks.reset();
|
||||||
mOutputTracksType = Track::None;
|
mOutputTracksType = Track::None;
|
||||||
|
nEffectsDone++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Effect::CountWaveTracks()
|
void Effect::CountWaveTracks()
|
||||||
@ -3245,7 +3250,11 @@ void EffectUIHost::OnApply(wxCommandEvent & evt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Honor the "select all if none" preference...a little hackish, but whatcha gonna do...
|
// Honor the "select all if none" preference...a little hackish, but whatcha gonna do...
|
||||||
if (!mIsBatch && mEffect && mEffect->GetType() != EffectTypeGenerate && mProject->mViewInfo.selectedRegion.isPoint())
|
if (!mIsBatch &&
|
||||||
|
mEffect &&
|
||||||
|
mEffect->GetType() != EffectTypeGenerate &&
|
||||||
|
mEffect->GetType() != EffectTypeTool &&
|
||||||
|
mProject->mViewInfo.selectedRegion.isPoint())
|
||||||
{
|
{
|
||||||
auto flags = AlwaysEnabledFlag;
|
auto flags = AlwaysEnabledFlag;
|
||||||
bool allowed = mProject->ReportIfActionNotAllowed(
|
bool allowed = mProject->ReportIfActionNotAllowed(
|
||||||
|
@ -270,6 +270,8 @@ class AUDACITY_DLL_API Effect /* not final */ : public wxEvtHandler,
|
|||||||
long style = DefaultMessageBoxStyle,
|
long style = DefaultMessageBoxStyle,
|
||||||
const wxString& titleStr = wxString{});
|
const wxString& titleStr = wxString{});
|
||||||
|
|
||||||
|
static void IncEffectCounter(){ nEffectsDone++;};
|
||||||
|
|
||||||
//
|
//
|
||||||
// protected virtual methods
|
// protected virtual methods
|
||||||
//
|
//
|
||||||
@ -341,7 +343,6 @@ protected:
|
|||||||
bool TrackGroupProgress(int whichGroup, double frac, const wxString & = wxEmptyString);
|
bool TrackGroupProgress(int whichGroup, double frac, const wxString & = wxEmptyString);
|
||||||
|
|
||||||
int GetNumWaveTracks() { return mNumTracks; }
|
int GetNumWaveTracks() { return mNumTracks; }
|
||||||
|
|
||||||
int GetNumWaveGroups() { return mNumGroups; }
|
int GetNumWaveGroups() { return mNumGroups; }
|
||||||
|
|
||||||
// Calculates the start time and selection length in samples
|
// Calculates the start time and selection length in samples
|
||||||
@ -370,6 +371,9 @@ protected:
|
|||||||
void CopyInputTracks(); // trackType = Track::Wave
|
void CopyInputTracks(); // trackType = Track::Wave
|
||||||
void CopyInputTracks(int trackType);
|
void CopyInputTracks(int trackType);
|
||||||
|
|
||||||
|
// A global counter of all the successful Effect invocations.
|
||||||
|
static int nEffectsDone;
|
||||||
|
|
||||||
// For the use of analyzers, which don't need to make output wave tracks,
|
// For the use of analyzers, which don't need to make output wave tracks,
|
||||||
// but may need to add label tracks.
|
// but may need to add label tracks.
|
||||||
class AddedAnalysisTrack {
|
class AddedAnalysisTrack {
|
||||||
|
@ -75,6 +75,8 @@ effects from this one class.
|
|||||||
|
|
||||||
#include "../../Experimental.h"
|
#include "../../Experimental.h"
|
||||||
|
|
||||||
|
int NyquistEffect::mReentryCount = 0;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ID_Editor = 10000,
|
ID_Editor = 10000,
|
||||||
@ -147,6 +149,7 @@ NyquistEffect::NyquistEffect(const wxString &fName)
|
|||||||
mStop = false;
|
mStop = false;
|
||||||
mBreak = false;
|
mBreak = false;
|
||||||
mCont = false;
|
mCont = false;
|
||||||
|
mIsTool = false;
|
||||||
|
|
||||||
mMaxLen = NYQ_MAX_LEN;
|
mMaxLen = NYQ_MAX_LEN;
|
||||||
|
|
||||||
@ -165,6 +168,7 @@ NyquistEffect::NyquistEffect(const wxString &fName)
|
|||||||
if (fName == NYQUIST_TOOLS_PROMPT_ID) {
|
if (fName == NYQUIST_TOOLS_PROMPT_ID) {
|
||||||
mName = XO("Nyquist Tools Prompt");
|
mName = XO("Nyquist Tools Prompt");
|
||||||
mType = EffectTypeTool;
|
mType = EffectTypeTool;
|
||||||
|
mIsTool = true;
|
||||||
mPromptName = mName;
|
mPromptName = mName;
|
||||||
mPromptType = mType;
|
mPromptType = mType;
|
||||||
mOK = true;
|
mOK = true;
|
||||||
@ -263,6 +267,13 @@ EffectType NyquistEffect::GetType()
|
|||||||
return mType;
|
return mType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EffectType NyquistEffect::GetClassification()
|
||||||
|
{
|
||||||
|
if (mIsTool)
|
||||||
|
return EffectTypeTool;
|
||||||
|
return mType;
|
||||||
|
}
|
||||||
|
|
||||||
IdentInterfaceSymbol NyquistEffect::GetFamilyId()
|
IdentInterfaceSymbol NyquistEffect::GetFamilyId()
|
||||||
{
|
{
|
||||||
return NYQUISTEFFECTS_FAMILY;
|
return NYQUISTEFFECTS_FAMILY;
|
||||||
@ -582,12 +593,25 @@ bool NyquistEffect::CheckWhetherSkipEffect()
|
|||||||
|
|
||||||
static void RegisterFunctions();
|
static void RegisterFunctions();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool NyquistEffect::Process()
|
bool NyquistEffect::Process()
|
||||||
{
|
{
|
||||||
|
// Check for reentrant Nyquist commands.
|
||||||
|
// I'm choosing to mark skipped Nyquist commands as successful even though
|
||||||
|
// they are skipped. The reason is that when Nyquist calls out to a chain,
|
||||||
|
// and that chain contains Nyquist, it will be clearer if the chain completes
|
||||||
|
// skipping Nyquist, rather than doing nothing at all.
|
||||||
|
if( mReentryCount > 0 )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Restore the reentry counter (to zero) when we exit.
|
||||||
|
auto cleanup = valueRestorer( mReentryCount);
|
||||||
|
mReentryCount++;
|
||||||
RegisterFunctions();
|
RegisterFunctions();
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
int nEffectsSoFar = nEffectsDone;
|
||||||
mProjectChanged = false;
|
mProjectChanged = false;
|
||||||
EffectManager & em = EffectManager::Get();
|
EffectManager & em = EffectManager::Get();
|
||||||
em.SetSkipStateFlag(false);
|
em.SetSkipStateFlag(false);
|
||||||
@ -596,12 +620,7 @@ bool NyquistEffect::Process()
|
|||||||
mProgress->Hide();
|
mProgress->Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must copy all the tracks, because Paste needs label tracks to ensure
|
|
||||||
// correct sync-lock group behavior when the timeline is affected; then we just want
|
|
||||||
// to operate on the selected wave tracks
|
|
||||||
CopyInputTracks(Track::All);
|
|
||||||
SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks.get());
|
|
||||||
mCurTrack[0] = (WaveTrack *) iter.First();
|
|
||||||
mOutputTime = 0;
|
mOutputTime = 0;
|
||||||
mCount = 0;
|
mCount = 0;
|
||||||
mProgressIn = 0;
|
mProgressIn = 0;
|
||||||
@ -752,52 +771,67 @@ bool NyquistEffect::Process()
|
|||||||
mProps += wxString::Format(wxT("(putprop '*SELECTION* %d 'CHANNELS)\n"), mNumSelectedChannels);
|
mProps += wxString::Format(wxT("(putprop '*SELECTION* %d 'CHANNELS)\n"), mNumSelectedChannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If in tool mode, then we don't do anything with the track and selection.
|
||||||
|
bool bOnePassTool = (GetType() == EffectTypeTool);
|
||||||
|
|
||||||
|
|
||||||
|
// We must copy all the tracks, because Paste needs label tracks to ensure
|
||||||
|
// correct sync-lock group behavior when the timeline is affected; then we just want
|
||||||
|
// to operate on the selected wave tracks
|
||||||
|
if( !bOnePassTool )
|
||||||
|
CopyInputTracks(Track::All);
|
||||||
|
SelectedTrackListOfKindIterator iter(Track::Wave, mOutputTracks.get());
|
||||||
|
mCurTrack[0] = (WaveTrack *)iter.First();
|
||||||
|
|
||||||
// Keep track of whether the current track is first selected in its sync-lock group
|
// Keep track of whether the current track is first selected in its sync-lock group
|
||||||
// (we have no idea what the length of the returned audio will be, so we have
|
// (we have no idea what the length of the returned audio will be, so we have
|
||||||
// to handle sync-lock group behavior the "old" way).
|
// to handle sync-lock group behavior the "old" way).
|
||||||
mFirstInGroup = true;
|
mFirstInGroup = true;
|
||||||
Track *gtLast = NULL;
|
Track *gtLast = NULL;
|
||||||
|
|
||||||
while (mCurTrack[0]) {
|
while (mCurTrack[0] || bOnePassTool) {
|
||||||
mCurNumChannels = 1;
|
mCurNumChannels = 1;
|
||||||
if (mT1 >= mT0) {
|
if ((mT1 >= mT0)||bOnePassTool) {
|
||||||
if (mCurTrack[0]->GetLinked()) {
|
if (bOnePassTool) {
|
||||||
mCurNumChannels = 2;
|
|
||||||
|
|
||||||
mCurTrack[1] = (WaveTrack *)iter.Next();
|
} else {
|
||||||
if (mCurTrack[1]->GetRate() != mCurTrack[0]->GetRate()) {
|
if (mCurTrack[0]->GetLinked()) {
|
||||||
Effect::MessageBox(_("Sorry, cannot apply effect on stereo tracks where the tracks don't match."),
|
mCurNumChannels = 2;
|
||||||
wxOK | wxCENTRE);
|
|
||||||
success = false;
|
mCurTrack[1] = (WaveTrack *)iter.Next();
|
||||||
goto finish;
|
if (mCurTrack[1]->GetRate() != mCurTrack[0]->GetRate()) {
|
||||||
|
Effect::MessageBox(_("Sorry, cannot apply effect on stereo tracks where the tracks don't match."),
|
||||||
|
wxOK | wxCENTRE);
|
||||||
|
success = false;
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
mCurStart[1] = mCurTrack[1]->TimeToLongSamples(mT0);
|
||||||
}
|
}
|
||||||
mCurStart[1] = mCurTrack[1]->TimeToLongSamples(mT0);
|
|
||||||
|
// Check whether we're in the same group as the last selected track
|
||||||
|
SyncLockedTracksIterator gIter(mOutputTracks.get());
|
||||||
|
Track *gt = gIter.StartWith(mCurTrack[0]);
|
||||||
|
mFirstInGroup = !gtLast || (gtLast != gt);
|
||||||
|
gtLast = gt;
|
||||||
|
|
||||||
|
mCurStart[0] = mCurTrack[0]->TimeToLongSamples(mT0);
|
||||||
|
auto end = mCurTrack[0]->TimeToLongSamples(mT1);
|
||||||
|
mCurLen = end - mCurStart[0];
|
||||||
|
|
||||||
|
if (mCurLen > NYQ_MAX_LEN) {
|
||||||
|
float hours = (float)NYQ_MAX_LEN / (44100 * 60 * 60);
|
||||||
|
const auto message = wxString::Format(
|
||||||
|
_("Selection too long for Nyquist code.\nMaximum allowed selection is %ld samples\n(about %.1f hours at 44100 Hz sample rate)."),
|
||||||
|
(long)NYQ_MAX_LEN, hours
|
||||||
|
);
|
||||||
|
Effect::MessageBox(message, wxOK | wxCENTRE, _("Nyquist Error"));
|
||||||
|
if (!mProjectChanged)
|
||||||
|
em.SetSkipStateFlag(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurLen = std::min(mCurLen, mMaxLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether we're in the same group as the last selected track
|
|
||||||
SyncLockedTracksIterator gIter(mOutputTracks.get());
|
|
||||||
Track *gt = gIter.StartWith(mCurTrack[0]);
|
|
||||||
mFirstInGroup = !gtLast || (gtLast != gt);
|
|
||||||
gtLast = gt;
|
|
||||||
|
|
||||||
mCurStart[0] = mCurTrack[0]->TimeToLongSamples(mT0);
|
|
||||||
auto end = mCurTrack[0]->TimeToLongSamples(mT1);
|
|
||||||
mCurLen = end - mCurStart[0];
|
|
||||||
|
|
||||||
if (mCurLen > NYQ_MAX_LEN) {
|
|
||||||
float hours = (float)NYQ_MAX_LEN / (44100 * 60 * 60);
|
|
||||||
const auto message = wxString::Format(
|
|
||||||
_("Selection too long for Nyquist code.\nMaximum allowed selection is %ld samples\n(about %.1f hours at 44100 Hz sample rate)."),
|
|
||||||
(long)NYQ_MAX_LEN, hours
|
|
||||||
);
|
|
||||||
Effect::MessageBox(message, wxOK | wxCENTRE, _("Nyquist Error"));
|
|
||||||
if (!mProjectChanged)
|
|
||||||
em.SetSkipStateFlag(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mCurLen = std::min(mCurLen, mMaxLen);
|
|
||||||
|
|
||||||
mProgressIn = 0.0;
|
mProgressIn = 0.0;
|
||||||
mProgressOut = 0.0;
|
mProgressOut = 0.0;
|
||||||
|
|
||||||
@ -866,7 +900,7 @@ _("Selection too long for Nyquist code.\nMaximum allowed selection is %ld sample
|
|||||||
// Reset previous locale
|
// Reset previous locale
|
||||||
wxSetlocale(LC_NUMERIC, prevlocale);
|
wxSetlocale(LC_NUMERIC, prevlocale);
|
||||||
|
|
||||||
if (!success) {
|
if (!success || bOnePassTool) {
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
mProgressTot += mProgressIn + mProgressOut;
|
mProgressTot += mProgressIn + mProgressOut;
|
||||||
@ -894,7 +928,13 @@ finish:
|
|||||||
dlog.ShowModal();
|
dlog.ShowModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReplaceProcessedTracks(success);
|
// Has rug been pulled from under us by some effect done within Nyquist??
|
||||||
|
if( !bOnePassTool && ( nEffectsSoFar == nEffectsDone ))
|
||||||
|
ReplaceProcessedTracks(success);
|
||||||
|
else{
|
||||||
|
ReplaceProcessedTracks(false); // Do not use the results.
|
||||||
|
mT1 = mT0 - 1.0;// And don't use the times either, in resetting the selection (make them bogus).
|
||||||
|
}
|
||||||
|
|
||||||
if (!mProjectChanged)
|
if (!mProjectChanged)
|
||||||
em.SetSkipStateFlag(true);
|
em.SetSkipStateFlag(true);
|
||||||
@ -987,7 +1027,11 @@ bool NyquistEffect::ProcessOne()
|
|||||||
wxString cmd;
|
wxString cmd;
|
||||||
cmd += wxT("(snd-set-latency 0.1)");
|
cmd += wxT("(snd-set-latency 0.1)");
|
||||||
|
|
||||||
if (mVersion >= 4) {
|
// A tool may be using AUD-DO which will potentially invalidate *TRACK*
|
||||||
|
// so tools do not get *TRACK*.
|
||||||
|
if (GetType() == EffectTypeTool)
|
||||||
|
; // No Track.
|
||||||
|
else if (mVersion >= 4) {
|
||||||
nyx_set_audio_name("*TRACK*");
|
nyx_set_audio_name("*TRACK*");
|
||||||
cmd += wxT("(setf S 0.25)\n");
|
cmd += wxT("(setf S 0.25)\n");
|
||||||
}
|
}
|
||||||
@ -996,7 +1040,7 @@ bool NyquistEffect::ProcessOne()
|
|||||||
cmd += wxT("(setf *TRACK* '*unbound*)\n");
|
cmd += wxT("(setf *TRACK* '*unbound*)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mVersion >= 4) {
|
if( (mVersion >= 4) && (GetType() != EffectTypeTool) ) {
|
||||||
cmd += mProps;
|
cmd += mProps;
|
||||||
cmd += mPerTrackProps;
|
cmd += mPerTrackProps;
|
||||||
|
|
||||||
@ -1147,7 +1191,11 @@ bool NyquistEffect::ProcessOne()
|
|||||||
cmd += wxString::Format(wxT("(putprop '*SELECTION* %s 'RMS)\n"), rmsString);
|
cmd += wxString::Format(wxT("(putprop '*SELECTION* %s 'RMS)\n"), rmsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetType() == EffectTypeGenerate) {
|
// If in tool mode, then we don't do anything with the track and selection.
|
||||||
|
if (GetType() == EffectTypeTool) {
|
||||||
|
nyx_set_audio_params(44100, 0);
|
||||||
|
}
|
||||||
|
else if (GetType() == EffectTypeGenerate) {
|
||||||
nyx_set_audio_params(mCurTrack[0]->GetRate(), 0);
|
nyx_set_audio_params(mCurTrack[0]->GetRate(), 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1308,7 +1356,7 @@ bool NyquistEffect::ProcessOne()
|
|||||||
|
|
||||||
// True if not process type.
|
// True if not process type.
|
||||||
// If not returning audio from process effect,
|
// If not returning audio from process effect,
|
||||||
// return first reult then stop (disables preview)
|
// return first result then stop (disables preview)
|
||||||
// but allow all output from Nyquist Prompt.
|
// but allow all output from Nyquist Prompt.
|
||||||
return (GetType() != EffectTypeProcess || mIsPrompt);
|
return (GetType() != EffectTypeProcess || mIsPrompt);
|
||||||
}
|
}
|
||||||
@ -1728,18 +1776,32 @@ bool NyquistEffect::Parse(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (len >= 2 && tokens[0] == wxT("type")) {
|
if (len >= 2 && tokens[0] == wxT("type")) {
|
||||||
if (tokens[1] == wxT("process")) {
|
wxString tok = tokens[1];
|
||||||
|
mIsTool = false;
|
||||||
|
if (tok == wxT("tool")) {
|
||||||
|
mIsTool = true;
|
||||||
|
mType = EffectTypeTool;
|
||||||
|
// we allow
|
||||||
|
// ;type tool
|
||||||
|
// ;type tool process
|
||||||
|
// ;type tool generate
|
||||||
|
// ;type tool analyze
|
||||||
|
// The last three are placed in the tool menu, but are processed as
|
||||||
|
// process, generate or analyze.
|
||||||
|
if (len >= 3)
|
||||||
|
tok = tokens[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tok == wxT("process")) {
|
||||||
mType = EffectTypeProcess;
|
mType = EffectTypeProcess;
|
||||||
}
|
}
|
||||||
else if (tokens[1] == wxT("generate")) {
|
else if (tok == wxT("generate")) {
|
||||||
mType = EffectTypeGenerate;
|
mType = EffectTypeGenerate;
|
||||||
}
|
}
|
||||||
else if (tokens[1] == wxT("analyze")) {
|
else if (tok == wxT("analyze")) {
|
||||||
mType = EffectTypeAnalyze;
|
mType = EffectTypeAnalyze;
|
||||||
}
|
}
|
||||||
else if (tokens[1] == wxT("tool")) {
|
|
||||||
mType = EffectTypeTool;
|
|
||||||
}
|
|
||||||
if (len >= 3 && tokens[2] == wxT("spectral")) {;
|
if (len >= 3 && tokens[2] == wxT("spectral")) {;
|
||||||
mIsSpectral = true;
|
mIsSpectral = true;
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,7 @@ public:
|
|||||||
// EffectDefinitionInterface implementation
|
// EffectDefinitionInterface implementation
|
||||||
|
|
||||||
EffectType GetType() override;
|
EffectType GetType() override;
|
||||||
|
EffectType GetClassification() override;
|
||||||
IdentInterfaceSymbol GetFamilyId() override;
|
IdentInterfaceSymbol GetFamilyId() override;
|
||||||
bool IsInteractive() override;
|
bool IsInteractive() override;
|
||||||
bool IsDefault() override;
|
bool IsDefault() override;
|
||||||
@ -120,7 +121,6 @@ public:
|
|||||||
bool TransferDataFromWindow() override;
|
bool TransferDataFromWindow() override;
|
||||||
|
|
||||||
// NyquistEffect implementation
|
// NyquistEffect implementation
|
||||||
|
|
||||||
// For Nyquist Workbench support
|
// For Nyquist Workbench support
|
||||||
void RedirectOutput();
|
void RedirectOutput();
|
||||||
void SetCommand(const wxString &cmd);
|
void SetCommand(const wxString &cmd);
|
||||||
@ -129,6 +129,7 @@ public:
|
|||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static int mReentryCount;
|
||||||
// NyquistEffect implementation
|
// NyquistEffect implementation
|
||||||
|
|
||||||
bool ProcessOne();
|
bool ProcessOne();
|
||||||
@ -218,6 +219,7 @@ private:
|
|||||||
bool mIsSal;
|
bool mIsSal;
|
||||||
bool mExternal;
|
bool mExternal;
|
||||||
bool mIsSpectral;
|
bool mIsSpectral;
|
||||||
|
bool mIsTool;
|
||||||
/** True if the code to execute is obtained interactively from the user via
|
/** True if the code to execute is obtained interactively from the user via
|
||||||
* the "Nyquist Effect Prompt", or "Nyquist Tools Prompt", false for all other effects (lisp code read from
|
* the "Nyquist Effect Prompt", or "Nyquist Tools Prompt", false for all other effects (lisp code read from
|
||||||
* files)
|
* files)
|
||||||
@ -241,7 +243,7 @@ private:
|
|||||||
wxString mHelpFile;
|
wxString mHelpFile;
|
||||||
bool mHelpFileExists;
|
bool mHelpFileExists;
|
||||||
EffectType mType;
|
EffectType mType;
|
||||||
EffectType mPromptType; // If a prompt, need ot remember original type.
|
EffectType mPromptType; // If a prompt, need to remember original type.
|
||||||
|
|
||||||
bool mEnablePreview;
|
bool mEnablePreview;
|
||||||
bool mDebugButton; // Set to false to disable Debug button.
|
bool mDebugButton; // Set to false to disable Debug button.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user