1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
// 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 "commands/ScriptCommandRelay.h"
/*
//#define ModuleDispatchName "ModuleDispatch"
See the example in this file. It has several cases/options in it.
*/
#include "ModuleConstants.h"
extern void PipeServer();
typedef DLL_IMPORT int (*tpExecScriptServerFunc)( wxString * pIn, wxString * pOut);
static tpExecScriptServerFunc pScriptServerFn=NULL;
extern "C" {
// And here is our special registration function.
int DLL_API RegScriptServerFunc( tpExecScriptServerFunc pFn )
{
if( pFn )
{
pScriptServerFn = pFn;
PipeServer();
}
return 4;
}
DEFINE_VERSION_CHECK
extern "C" DLL_API int ModuleDispatch(ModuleDispatchTypes type)
{
switch (type) {
case ModuleInitialize:
ScriptCommandRelay::StartScriptServer(RegScriptServerFunc);
break;
default:
break;
}
return 1;
}
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)
{
wxCharBuffer lineString = aStr[currentLine].ToUTF8();
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.data()[currentPosition]),
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"
|