From 1bc0f0f4d0c3332e27d4e3eecb735ae60d0785b5 Mon Sep 17 00:00:00 2001 From: James Crook Date: Sat, 24 Feb 2018 10:36:43 +0000 Subject: [PATCH] Make Nyquist support (AUD-DO) Nyquist AUD-DO calls out to a new function that executes script commands, and returns results in a lisp string. --- .../nyquist/nyqsrc/audacityfnintdefs.h | 1 + .../nyquist/nyqsrc/audacityfnintptrs.h | 1 + lib-src/libnyquist/nyquist/nyqsrc/local.c | 48 ++++++++++++++ lib-src/libnyquist/nyquist/nyqsrc/localdefs.h | 1 + lib-src/libnyquist/nyquist/nyqsrc/localptrs.h | 3 + src/commands/ScriptCommandRelay.cpp | 66 +++++++++++++++++++ 6 files changed, 120 insertions(+) create mode 100644 lib-src/libnyquist/nyquist/nyqsrc/audacityfnintdefs.h create mode 100644 lib-src/libnyquist/nyquist/nyqsrc/audacityfnintptrs.h diff --git a/lib-src/libnyquist/nyquist/nyqsrc/audacityfnintdefs.h b/lib-src/libnyquist/nyquist/nyqsrc/audacityfnintdefs.h new file mode 100644 index 000000000..501e428b1 --- /dev/null +++ b/lib-src/libnyquist/nyquist/nyqsrc/audacityfnintdefs.h @@ -0,0 +1 @@ +extern LVAL xlc_aud_do(void); diff --git a/lib-src/libnyquist/nyquist/nyqsrc/audacityfnintptrs.h b/lib-src/libnyquist/nyquist/nyqsrc/audacityfnintptrs.h new file mode 100644 index 000000000..da5246409 --- /dev/null +++ b/lib-src/libnyquist/nyquist/nyqsrc/audacityfnintptrs.h @@ -0,0 +1 @@ + { "AUD-DO", S, xlc_aud_do}, diff --git a/lib-src/libnyquist/nyquist/nyqsrc/local.c b/lib-src/libnyquist/nyquist/nyqsrc/local.c index 1cd3eedae..422ed0af9 100644 --- a/lib-src/libnyquist/nyquist/nyqsrc/local.c +++ b/lib-src/libnyquist/nyquist/nyqsrc/local.c @@ -3,6 +3,7 @@ /* CHANGE LOG * -------------------------------------------------------------------- * 28Apr03 dm changes for portability and fix compiler warnings + * 12Feb18 jkc added aud-do function, that is only available in Audacity. */ #include "xlisp.h" @@ -53,3 +54,50 @@ void print_local_gc_info(void) max_sample_block_len) / 1024); 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); +} + diff --git a/lib-src/libnyquist/nyquist/nyqsrc/localdefs.h b/lib-src/libnyquist/nyquist/nyqsrc/localdefs.h index b227c2fb7..c5c2cc952 100644 --- a/lib-src/libnyquist/nyquist/nyqsrc/localdefs.h +++ b/lib-src/libnyquist/nyquist/nyqsrc/localdefs.h @@ -1,3 +1,4 @@ /* include actual local file headers: */ #include "sndfnintdefs.h" #include "seqfnintdefs.h" +#include "audacityfnintdefs.h" diff --git a/lib-src/libnyquist/nyquist/nyqsrc/localptrs.h b/lib-src/libnyquist/nyquist/nyqsrc/localptrs.h index 8789cfa55..14ef8687c 100644 --- a/lib-src/libnyquist/nyquist/nyqsrc/localptrs.h +++ b/lib-src/libnyquist/nyquist/nyqsrc/localptrs.h @@ -2,8 +2,11 @@ * * CHANGE LOG * 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 */ #include "sndfnintptrs.h" #include "seqfnintptrs.h" +#include "audacityfnintptrs.h" + diff --git a/src/commands/ScriptCommandRelay.cpp b/src/commands/ScriptCommandRelay.cpp index b721a3c90..6b6e3929d 100644 --- a/src/commands/ScriptCommandRelay.cpp +++ b/src/commands/ScriptCommandRelay.cpp @@ -97,6 +97,72 @@ int ExecCommand(wxString *pIn, wxString *pOut) 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(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 void ScriptCommandRelay::SendResponse(const wxString &response) {