1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-13 06:40:24 +02:00
Paul Licameli 56cd24a062 Rewrite insertion of menu items by null and Nyquist modules...
... using the new registration system, and without the fragile hacks making
assumptions about the positions of menus within the menu bar.
2020-01-30 15:09:30 -05:00

228 lines
5.9 KiB
C++

// ScripterCallback.cpp :
//
// A loadable module that connects a windows named pipe
// to a registered service function that is able to
// process a single command at a time.
//
// The service function is provided by the application
// and not by libscript. mod_script_pipe was developed for
// Audacity. Because it forwards commands
// rather than handling them itself it can be used in
// other projects too.
//
// Enabling other programs to connect to Audacity via a pipe is a potential
// security risk. Use at your own risk.
#include <wx/wx.h>
#include "ScripterCallback.h"
#include "../../src/Audacity.h"
#if defined(__WXMSW__)
#include <wx/init.h>
# if defined(__WXDEBUG__)
# define D "d"
# else
# define D ""
# endif
# if wxCHECK_VERSION(3, 1, 0)
# define V "31"
# elif wxCHECK_VERSION(3, 0, 0)
# define V "30"
# else
# define V "28"
# endif
# pragma comment(lib, "wxbase" V "u" D)
# pragma comment(lib, "wxbase" V "u" D "_net")
# pragma comment(lib, "wxmsw" V "u" D "_adv")
# pragma comment(lib, "wxmsw" V "u" D "_core")
# pragma comment(lib, "wxmsw" V "u" D "_html")
# pragma comment(lib, "wxpng" D)
# pragma comment(lib, "wxzlib" D)
# pragma comment(lib, "wxjpeg" D)
# pragma comment(lib, "wxtiff" D)
# undef V
# undef D
#endif //(__WXMSW__)
/*
There are several functions that can be used in a GUI module.
//#define versionFnName "GetVersionString"
If the version is wrong, the module will be rejected.
That is it will be loaded and then unloaded.
//#define ModuleDispatchName "ModuleDispatch"
The most useful function. See the example in this
file. It has several cases/options in it.
//#define scriptFnName "RegScriptServerFunc"
This function is run from a non gui thread. It was originally
created for the benefit of mod-script-pipe.
//#define mainPanelFnName "MainPanelFunc"
This function is the hijacking function, to take over Audacity
and replace the main project window with our own wxFrame.
*/
#ifdef _MSC_VER
#define DLL_API _declspec(dllexport)
#define DLL_IMPORT _declspec(dllimport)
#else
#define DLL_API __attribute__ ((visibility("default")))
#define DLL_IMPORT
#endif
typedef enum
{
ModuleInitialize,
ModuleTerminate,
AppInitialized,
AppQuiting,
ProjectInitialized,
ProjectClosing
} ModuleDispatchTypes;
extern void PipeServer();
typedef DLL_IMPORT int (*tpExecScriptServerFunc)( wxString * pIn, wxString * pOut);
static tpExecScriptServerFunc pScriptServerFn=NULL;
extern "C" {
DLL_API const wxChar * GetVersionString()
{
// Make sure that this version of the module requires the version
// of Audacity it is built with.
// For now the versions must match exactly for Audacity to
// agree to load the module.
return AUDACITY_VERSION_STRING;
}
extern int DLL_API ModuleDispatch(ModuleDispatchTypes type);
// ModuleDispatch
// is called by Audacity to initialize/terminate the module
// We don't (yet) do anything in this, since we have a special function for the scripter
// all we need to do is return 1.
int ModuleDispatch(ModuleDispatchTypes type){
switch (type){
case AppInitialized:{
}
break;
case AppQuiting: {
}
break;
case ProjectInitialized: {
}
break;
default:
break;
}
return 1;
}
// And here is our special registration function.
int DLL_API RegScriptServerFunc( tpExecScriptServerFunc pFn )
{
if( pFn )
{
pScriptServerFn = pFn;
PipeServer();
}
return 4;
}
wxString Str2;
wxArrayString aStr;
unsigned int currentLine;
size_t currentPosition;
// Send the received command to Audacity and build an array of response lines.
// The response lines can be retrieved by calling DoSrvMore repeatedly.
int DoSrv(char *pIn)
{
// Interpret string as unicode.
// wxWidgets (now) uses unicode internally.
// Scripts must send unicode strings (if going beyond 7-bit ASCII).
// Important for filenames in commands.
wxString Str1(pIn, wxConvUTF8);
Str1.Replace( wxT("\r"), wxT(""));
Str1.Replace( wxT("\n"), wxT(""));
Str2 = wxEmptyString;
(*pScriptServerFn)( &Str1 , &Str2);
Str2 += wxT('\n');
size_t outputLength = Str2.Length();
aStr.Clear();
size_t iStart = 0;
size_t i;
for(i = 0; i < outputLength; ++i)
{
if( Str2[i] == wxT('\n') )
{
aStr.Add( Str2.Mid( iStart, i-iStart) + wxT("\n") );
iStart = i+1;
}
}
currentLine = 0;
currentPosition = 0;
return 1;
}
size_t smin(size_t a, size_t b) { return a < b ? a : b; }
// Write up to nMax characters of the prepared (by DoSrv) response lines.
// Returns the number of characters sent, including null.
// Zero returned if and only if there's nothing else to send.
int DoSrvMore(char *pOut, size_t nMax)
{
wxASSERT(currentLine >= 0);
wxASSERT(currentPosition >= 0);
size_t totalLines = aStr.GetCount();
while (currentLine < totalLines)
{
wxString lineString = aStr[currentLine];
size_t lineLength = lineString.Length();
size_t charsLeftInLine = lineLength - currentPosition;
wxASSERT(charsLeftInLine >= 0);
if (charsLeftInLine == 0)
{
// Move to next line
++currentLine;
currentPosition = 0;
}
else
{
// Write as much of the rest of the line as will fit in the buffer
size_t charsToWrite = smin(charsLeftInLine, nMax - 1);
memcpy(pOut,
lineString.Mid(currentPosition,
currentPosition + charsToWrite).mb_str(),
charsToWrite);
pOut[charsToWrite] = '\0';
currentPosition += charsToWrite;
// Need to cast to prevent compiler warnings
int charsWritten = static_cast<int>(charsToWrite + 1);
// (Check cast was safe)
wxASSERT(static_cast<size_t>(charsWritten) == charsToWrite + 1);
return charsWritten;
}
}
return 0;
}
} // End extern "C"