1
/**********************************************************************
3
Audacity: A Digital Audio Editor
11
*******************************************************************//*!
14
\brief Based on LoadLadspa, this code loads pluggable Audacity
15
extension modules. It also has the code to (a) invoke a script
16
server and (b) invoke a function returning a replacement window,
17
i.e. an alternative to the usual interface, for Audacity.
19
*//*******************************************************************/
21
#include <wx/dynlib.h>
24
#include <wx/string.h>
27
#include "AudacityApp.h"
29
#include "BatchCommands.h"
30
#include "../lib-src/lib-widget-extra/NonGuiThread.h"
32
#define initFnName "ExtensionModuleInit"
33
#define scriptFnName "RegScriptServerFunc"
34
#define mainPanelFnName "MainPanelFunc"
36
typedef _declspec( dllimport) int (*tModuleInit)(int);
37
typedef _declspec( dllimport) wxWindow * (*tPanelFn)(int);
39
// This variable will hold the address of a subroutine in
40
// a DLL that can hijack the normal panel.
41
tPanelFn pPanelHijack=NULL;
43
// Next two commented out lines are handy when investigating
44
// strange DLL behaviour. Instead of dynamic linking,
45
// link the library which has the replacement panel statically.
46
// Give the address of the routine here.
47
// This is a great help in identifying missing
48
// symbols which otherwise cause a dll to unload after loading
49
// without an explanation as to why!
50
//extern wxWindow * MainPanelFunc( int i );
51
//tPanelFn pPanelHijack=&MainPanelFunc;
53
/// IF pPanelHijack has been found in a module DLL
54
/// THEN when this function is called we'll go and
55
/// create that window instead of the normal one.
56
wxWindow * MakeHijackPanel()
58
if( pPanelHijack == NULL )
60
return pPanelHijack(0);
63
//------- Start of stuff related to invoking a batch command ----
64
// Our DLL may call commands back in Audacity.
65
// It will do that through the ExecCommand function.
68
typedef __declspec( dllexport) int (*tpExecScriptServerFunc)( wxString * pOut, wxString * pIn);
69
typedef __declspec( dllimport) int (*tpRegScriptServerFunc)(tpExecScriptServerFunc pFn);
71
// This is the function which actually obeys one command.
72
__declspec( dllexport) int ExecCommand( wxString * pOut, wxString * pIn )
74
// Create a Batch that will have just one command in it...
78
// Find the command name terminator...ingore line if not found
79
int splitAt = pIn->Find(wxT(':'));
81
*pOut= wxT("BAD - Missing ':'?");
86
wxString cmd = pIn->Left(splitAt).Strip(wxString::both);
87
wxString parm = pIn->Mid(splitAt + 1).Strip(wxString::trailing);
89
rc = Batch.ApplyCommand( cmd, parm );
95
*pOut = wxT("FAILED to Execute");
100
// This variable will hold the address of a subroutine in
101
// a DLL that starts a thread and reads script commands.
102
tpRegScriptServerFunc scriptFn = NULL;
104
// We pass the ExecFunction to any scripting DLL that needs it
106
void RegisterAndRun( )
108
wxASSERT( scriptFn != NULL );
110
scriptFn(&ExecCommand);
113
//------- End of stuff related to invoking a batch command ----
115
void LoadModule(wxString fname)
117
wxLogDebug(wxT("About to load %s"), fname );
119
tModuleInit mainFn = NULL;
121
// As a courtesy to some modules that might be bridges to
122
// open other modules, we set the current working
123
// directory to be the module's directory.
125
wxString saveOldCWD = ::wxGetCwd();
126
wxString prefix = ::wxPathOnly(fname);
127
::wxSetWorkingDirectory(prefix);
129
wxDynamicLibrary* pDLL = new wxDynamicLibrary();
130
if (pDLL && pDLL->Load(fname, wxDL_LAZY))
133
mainFn = (tModuleInit)(pDLL->GetSymbol(wxT(initFnName)));
136
result = mainFn( 0 );
138
if(( scriptFn == NULL ) &&(result>=0 ))
139
scriptFn = (tpRegScriptServerFunc)(pDLL->GetSymbol(wxT(scriptFnName)));
141
if((pPanelHijack==NULL ) && (result>=0))
142
pPanelHijack = (tPanelFn)(pDLL->GetSymbol(wxT(mainPanelFnName)));
145
::wxSetWorkingDirectory(saveOldCWD);
150
wxArrayString audacityPathList = wxGetApp().audacityPathList;
151
wxArrayString pathList;
157
// Code from LoadLadspa that might be useful in load modules.
158
pathVar = wxGetenv(wxT("AUDACITY_MODULES_PATH"));
159
if (pathVar != wxT(""))
160
wxGetApp().AddMultiPathsToPathList(pathVar, pathList);
163
wxGetApp().AddUniquePathToPathList(INSTALL_PREFIX wxT("/modules"), pathList);
164
wxGetApp().AddUniquePathToPathList(wxT("/usr/local/lib/modules"), pathList);
165
wxGetApp().AddUniquePathToPathList(wxT("/usr/lib/modules"), pathList);
169
for(i=0; i<audacityPathList.GetCount(); i++) {
170
wxString prefix = audacityPathList[i] + wxFILE_SEP_PATH;
171
wxGetApp().AddUniquePathToPathList(prefix + wxT("modules"),
176
wxGetApp().FindFilesInPathList(wxT("*.dll"), pathList, wxFILE, files);
178
wxGetApp().FindFilesInPathList(wxT("*.so"), pathList, wxFILE, files);
181
for(i=0; i<files.GetCount(); i++)
182
LoadModule(files[i]);
183
// After loading all the modules, we may have a registered scripting function.
186
NonGuiThread::StartChild( &RegisterAndRun );
190
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
191
// version control system. Please do not modify past this point.
195
// indent-tabs-mode: nil
198
// vim: et sts=3 sw=3