2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "SC_Lib_Cintf.h"
24 #include "SC_ComPort.h"
25 #include "SC_CoreAudio.h"
26 #include "SC_UnitDef.h"
27 #include "SC_BufGen.h"
29 #include "SC_StringParser.h"
30 #include "SC_InterfaceTable.h"
31 #include "SC_DirUtils.h"
42 #include "SC_Win32Utils.h"
47 // Plugin directory in resource directory
48 #if defined(_WIN32) && defined(_DEBUG)
49 # define SC_PLUGIN_DIR_NAME "plugins_debug"
51 # define SC_PLUGIN_DIR_NAME "plugins"
54 // Extension for binary plugins
56 # define SC_PLUGIN_EXT ".scx"
59 // Symbol of initialization routine when loading plugins
60 #ifndef SC_PLUGIN_LOAD_SYM
61 #define SC_PLUGIN_LOAD_SYM "load"
65 # include <sys/param.h>
70 #include <mach-o/dyld.h>
71 #include <mach-o/getsect.h>
77 HashTable
<SC_LibCmd
, Malloc
> *gCmdLib
;
78 HashTable
<struct UnitDef
, Malloc
> *gUnitDefLib
= 0;
79 HashTable
<struct BufGen
, Malloc
> *gBufGenLib
= 0;
80 HashTable
<struct PlugInCmd
, Malloc
> *gPlugInCmds
= 0;
81 extern struct InterfaceTable gInterfaceTable
;
82 SC_LibCmd
* gCmdArray
[NUMBER_OF_COMMANDS
];
84 void initMiscCommands();
85 static bool PlugIn_LoadDir(const char *dirname
, bool reportError
);
88 void read_section(const struct mach_header
*mhp
, unsigned long slide
, const char *segname
, const char *sectname
)
91 char *sect
= getsectdatafromheader(mhp
, segname
, sectname
, &size
);
94 char *start
= sect
+ slide
;
95 char *end
= start
+ size
;
98 gTempVal
+= *(char *)start
;
104 extern void IO_Load(InterfaceTable
*table
);
105 extern void Osc_Load(InterfaceTable
*table
);
106 extern void Delay_Load(InterfaceTable
*table
);
107 extern void BinaryOp_Load(InterfaceTable
*table
);
108 extern void Filter_Load(InterfaceTable
*table
);
109 extern void Gendyn_Load(InterfaceTable
*table
);
110 extern void LF_Load(InterfaceTable
*table
);
111 extern void Noise_Load(InterfaceTable
*table
);
112 extern void MulAdd_Load(InterfaceTable
*table
);
113 extern void Grain_Load(InterfaceTable
*table
);
114 extern void Pan_Load(InterfaceTable
*table
);
115 extern void Reverb_Load(InterfaceTable
*table
);
116 extern void Trigger_Load(InterfaceTable
*table
);
117 extern void UnaryOp_Load(InterfaceTable
*table
);
118 extern void DiskIO_Load(InterfaceTable
*table
);
119 extern void Test_Load(InterfaceTable
*table
);
120 extern void PhysicalModeling_Load(InterfaceTable
*table
);
121 extern void Demand_Load(InterfaceTable
*table
);
122 extern void DynNoise_Load(InterfaceTable
*table
);
123 extern void FFT_UGens_Load(InterfaceTable
*table
);
124 extern void iPhone_Load(InterfaceTable
*table
);
126 void initialize_library(const char *uGensPluginPath
)
128 gCmdLib
= new HashTable
<SC_LibCmd
, Malloc
>(&gMalloc
, 64, true);
129 gUnitDefLib
= new HashTable
<UnitDef
, Malloc
>(&gMalloc
, 512, true);
130 gBufGenLib
= new HashTable
<BufGen
, Malloc
>(&gMalloc
, 512, true);
131 gPlugInCmds
= new HashTable
<PlugInCmd
, Malloc
>(&gMalloc
, 64, true);
135 #ifdef STATIC_PLUGINS
136 IO_Load(&gInterfaceTable
);
137 Osc_Load(&gInterfaceTable
);
138 Delay_Load(&gInterfaceTable
);
139 BinaryOp_Load(&gInterfaceTable
);
140 Filter_Load(&gInterfaceTable
);
141 Gendyn_Load(&gInterfaceTable
);
142 LF_Load(&gInterfaceTable
);
143 Noise_Load(&gInterfaceTable
);
144 MulAdd_Load(&gInterfaceTable
);
145 Grain_Load(&gInterfaceTable
);
146 Pan_Load(&gInterfaceTable
);
147 Reverb_Load(&gInterfaceTable
);
148 Trigger_Load(&gInterfaceTable
);
149 UnaryOp_Load(&gInterfaceTable
);
150 DiskIO_Load(&gInterfaceTable
);
151 PhysicalModeling_Load(&gInterfaceTable
);
152 Test_Load(&gInterfaceTable
);
153 Demand_Load(&gInterfaceTable
);
154 DynNoise_Load(&gInterfaceTable
);
155 #if defined(SC_IPHONE) && !TARGET_IPHONE_SIMULATOR
156 iPhone_Load(&gInterfaceTable
);
158 FFT_UGens_Load(&gInterfaceTable
);
162 // If uGensPluginPath is supplied, it is exclusive.
163 bool loadUGensExtDirs
= true;
165 loadUGensExtDirs
= false;
166 SC_StringParser
sp(uGensPluginPath
, SC_STRPARSE_PATHDELIMITER
);
167 while (!sp
.AtEnd()) {
168 PlugIn_LoadDir(const_cast<char *>(sp
.NextToken()), true);
172 if(loadUGensExtDirs
) {
174 // load globally installed plugins
175 if (sc_DirectoryExists(SC_PLUGIN_DIR
)) {
176 PlugIn_LoadDir(SC_PLUGIN_DIR
, true);
179 // load default plugin directory
180 char pluginDir
[MAXPATHLEN
];
181 sc_GetResourceDirectory(pluginDir
, MAXPATHLEN
);
182 sc_AppendToPath(pluginDir
, MAXPATHLEN
, SC_PLUGIN_DIR_NAME
);
184 if (sc_DirectoryExists(pluginDir
)) {
185 PlugIn_LoadDir(pluginDir
, true);
189 // get extension directories
190 char extensionDir
[MAXPATHLEN
];
191 if (!sc_IsStandAlone() && loadUGensExtDirs
) {
192 // load system extension plugins
193 sc_GetSystemExtensionDirectory(extensionDir
, MAXPATHLEN
);
194 PlugIn_LoadDir(extensionDir
, false);
196 // load user extension plugins
197 sc_GetUserExtensionDirectory(extensionDir
, MAXPATHLEN
);
198 PlugIn_LoadDir(extensionDir
, false);
200 // load user plugin directories
201 SC_StringParser
sp(getenv("SC_PLUGIN_PATH"), SC_STRPARSE_PATHDELIMITER
);
202 while (!sp
.AtEnd()) {
203 PlugIn_LoadDir(const_cast<char *>(sp
.NextToken()), true);
207 /* on darwin plugins are lazily loaded (dlopen uses mmap internally), which can produce audible
208 glitches when UGens have to be paged-in. to work around this we preload all the plugins by
209 iterating through their memory space. */
211 unsigned long images
= _dyld_image_count();
212 for(unsigned long i
= 0; i
< images
; i
++) {
213 const mach_header
*hdr
= _dyld_get_image_header(i
);
214 unsigned long slide
= _dyld_get_image_vmaddr_slide(i
);
215 const char *name
= _dyld_get_image_name(i
);
219 if(!strcmp(name
+ (strlen(name
) - 4), ".scx")) {
220 read_section(hdr
, slide
, "__TEXT", "__text");
221 read_section(hdr
, slide
, "__TEXT", "__const");
222 read_section(hdr
, slide
, "__TEXT", "__cstring");
223 read_section(hdr
, slide
, "__TEXT", "__picsymbol_stub");
224 read_section(hdr
, slide
, "__TEXT", "__symbol_stub");
225 read_section(hdr
, slide
, "__TEXT", "__const");
226 read_section(hdr
, slide
, "__TEXT", "__literal4");
227 read_section(hdr
, slide
, "__TEXT", "__literal8");
229 read_section(hdr
, slide
, "__DATA", "__data");
230 read_section(hdr
, slide
, "__DATA", "__la_symbol_ptr");
231 read_section(hdr
, slide
, "__DATA", "__nl_symbol_ptr");
232 read_section(hdr
, slide
, "__DATA", "__dyld");
233 read_section(hdr
, slide
, "__DATA", "__const");
234 read_section(hdr
, slide
, "__DATA", "__mod_init_func");
235 read_section(hdr
, slide
, "__DATA", "__bss");
236 read_section(hdr
, slide
, "__DATA", "__common");
238 read_section(hdr
, slide
, "__IMPORT", "__jump_table");
239 read_section(hdr
, slide
, "__IMPORT", "__pointers");
245 static bool PlugIn_Load(const char *filename
)
249 HINSTANCE hinstance
= LoadLibrary( filename
);
252 DWORD lastErr
= GetLastError();
253 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
254 0, lastErr
, 0, (char*)&s
, 1, 0 );
255 scprintf("*** ERROR: LoadLibrary '%s' err '%s'\n", filename
, s
);
260 void *ptr
= (void *)GetProcAddress( hinstance
, SC_PLUGIN_LOAD_SYM
);
263 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
264 0, GetLastError(), 0, (char*)&s
, 1, 0 );
265 scprintf("*** ERROR: GetProcAddress %s err '%s'\n", SC_PLUGIN_LOAD_SYM
, s
);
268 FreeLibrary(hinstance
);
272 LoadPlugInFunc loadFunc
= (LoadPlugInFunc
)ptr
;
273 (*loadFunc
)(&gInterfaceTable
);
275 // FIXME: at the moment we never call FreeLibrary() on a loaded plugin
281 void* handle
= dlopen(filename
, RTLD_NOW
);
284 scprintf("*** ERROR: dlopen '%s' err '%s'\n", filename
, dlerror());
291 ptr
= dlsym(handle
, SC_PLUGIN_LOAD_SYM
);
293 scprintf("*** ERROR: dlsym %s err '%s'\n", SC_PLUGIN_LOAD_SYM
, dlerror());
298 LoadPlugInFunc loadFunc
= (LoadPlugInFunc
)ptr
;
299 (*loadFunc
)(&gInterfaceTable
);
306 static bool PlugIn_LoadDir(const char *dirname
, bool reportError
)
310 SC_DirHandle
*dir
= sc_OpenDir(dirname
);
313 scprintf("*** ERROR: open directory failed '%s'\n", dirname
); fflush(stdout
);
318 int firstCharOffset
= strlen(dirname
)+1;
321 char diritem
[MAXPATHLEN
];
322 bool skipItem
= true;
323 bool validItem
= sc_ReadDir(dir
, dirname
, diritem
, skipItem
);
324 if (!validItem
) break;
325 if (skipItem
|| (*(diritem
+firstCharOffset
) == '.')) continue; // skip files+folders whose first char is a dot
327 if (sc_DirectoryExists(diritem
)) {
328 success
= PlugIn_LoadDir(diritem
, reportError
);
330 int dnamelen
= strlen(diritem
);
331 int extlen
= strlen(SC_PLUGIN_EXT
);
332 char *extptr
= diritem
+dnamelen
-extlen
;
333 if (strncmp(extptr
, SC_PLUGIN_EXT
, extlen
) == 0) {
334 success
= PlugIn_Load(diritem
);
338 if (!success
) continue;