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_CoreAudio.h"
25 #include "SC_UnitDef.h"
26 #include "SC_BufGen.h"
28 #include "SC_StringParser.h"
29 #include "SC_InterfaceTable.h"
30 #include "SC_DirUtils.h"
41 #include "SC_Win32Utils.h"
46 // Plugin directory in resource directory
47 #if defined(_WIN32) && defined(_DEBUG)
48 # define SC_PLUGIN_DIR_NAME "plugins_debug"
50 # define SC_PLUGIN_DIR_NAME "plugins"
53 // Extension for binary plugins
55 # define SC_PLUGIN_EXT ".scx"
60 # include <sys/param.h>
65 #include <mach-o/dyld.h>
66 #include <mach-o/getsect.h>
72 HashTable
<SC_LibCmd
, Malloc
> *gCmdLib
;
73 HashTable
<struct UnitDef
, Malloc
> *gUnitDefLib
= 0;
74 HashTable
<struct BufGen
, Malloc
> *gBufGenLib
= 0;
75 HashTable
<struct PlugInCmd
, Malloc
> *gPlugInCmds
= 0;
76 extern struct InterfaceTable gInterfaceTable
;
77 SC_LibCmd
* gCmdArray
[NUMBER_OF_COMMANDS
];
79 void initMiscCommands();
80 static bool PlugIn_LoadDir(const char *dirname
, bool reportError
);
83 void read_section(const struct mach_header
*mhp
, unsigned long slide
, const char *segname
, const char *sectname
)
86 char *sect
= getsectdatafromheader(mhp
, segname
, sectname
, &size
);
89 char *start
= sect
+ slide
;
90 char *end
= start
+ size
;
93 gTempVal
+= *(char *)start
;
99 extern void IO_Load(InterfaceTable
*table
);
100 extern void Osc_Load(InterfaceTable
*table
);
101 extern void Delay_Load(InterfaceTable
*table
);
102 extern void BinaryOp_Load(InterfaceTable
*table
);
103 extern void Filter_Load(InterfaceTable
*table
);
104 extern void Gendyn_Load(InterfaceTable
*table
);
105 extern void LF_Load(InterfaceTable
*table
);
106 extern void Noise_Load(InterfaceTable
*table
);
107 extern void MulAdd_Load(InterfaceTable
*table
);
108 extern void Grain_Load(InterfaceTable
*table
);
109 extern void Pan_Load(InterfaceTable
*table
);
110 extern void Reverb_Load(InterfaceTable
*table
);
111 extern void Trigger_Load(InterfaceTable
*table
);
112 extern void UnaryOp_Load(InterfaceTable
*table
);
113 extern void DiskIO_Load(InterfaceTable
*table
);
114 extern void Test_Load(InterfaceTable
*table
);
115 extern void PhysicalModeling_Load(InterfaceTable
*table
);
116 extern void Demand_Load(InterfaceTable
*table
);
117 extern void DynNoise_Load(InterfaceTable
*table
);
118 extern void FFT_UGens_Load(InterfaceTable
*table
);
119 extern void iPhone_Load(InterfaceTable
*table
);
121 void initialize_library(const char *uGensPluginPath
)
123 gCmdLib
= new HashTable
<SC_LibCmd
, Malloc
>(&gMalloc
, 64, true);
124 gUnitDefLib
= new HashTable
<UnitDef
, Malloc
>(&gMalloc
, 512, true);
125 gBufGenLib
= new HashTable
<BufGen
, Malloc
>(&gMalloc
, 512, true);
126 gPlugInCmds
= new HashTable
<PlugInCmd
, Malloc
>(&gMalloc
, 64, true);
130 #ifdef STATIC_PLUGINS
131 IO_Load(&gInterfaceTable
);
132 Osc_Load(&gInterfaceTable
);
133 Delay_Load(&gInterfaceTable
);
134 BinaryOp_Load(&gInterfaceTable
);
135 Filter_Load(&gInterfaceTable
);
136 Gendyn_Load(&gInterfaceTable
);
137 LF_Load(&gInterfaceTable
);
138 Noise_Load(&gInterfaceTable
);
139 MulAdd_Load(&gInterfaceTable
);
140 Grain_Load(&gInterfaceTable
);
141 Pan_Load(&gInterfaceTable
);
142 Reverb_Load(&gInterfaceTable
);
143 Trigger_Load(&gInterfaceTable
);
144 UnaryOp_Load(&gInterfaceTable
);
145 DiskIO_Load(&gInterfaceTable
);
146 PhysicalModeling_Load(&gInterfaceTable
);
147 Test_Load(&gInterfaceTable
);
148 Demand_Load(&gInterfaceTable
);
149 DynNoise_Load(&gInterfaceTable
);
150 #if defined(SC_IPHONE) && !TARGET_IPHONE_SIMULATOR
151 iPhone_Load(&gInterfaceTable
);
153 FFT_UGens_Load(&gInterfaceTable
);
157 // If uGensPluginPath is supplied, it is exclusive.
158 bool loadUGensExtDirs
= true;
160 loadUGensExtDirs
= false;
161 SC_StringParser
sp(uGensPluginPath
, SC_STRPARSE_PATHDELIMITER
);
162 while (!sp
.AtEnd()) {
163 PlugIn_LoadDir(const_cast<char *>(sp
.NextToken()), true);
167 if(loadUGensExtDirs
) {
169 // load globally installed plugins
170 if (sc_DirectoryExists(SC_PLUGIN_DIR
)) {
171 PlugIn_LoadDir(SC_PLUGIN_DIR
, true);
174 // load default plugin directory
175 char pluginDir
[MAXPATHLEN
];
176 sc_GetResourceDirectory(pluginDir
, MAXPATHLEN
);
177 sc_AppendToPath(pluginDir
, MAXPATHLEN
, SC_PLUGIN_DIR_NAME
);
179 if (sc_DirectoryExists(pluginDir
)) {
180 PlugIn_LoadDir(pluginDir
, true);
184 // get extension directories
185 char extensionDir
[MAXPATHLEN
];
186 if (!sc_IsStandAlone() && loadUGensExtDirs
) {
187 // load system extension plugins
188 sc_GetSystemExtensionDirectory(extensionDir
, MAXPATHLEN
);
189 PlugIn_LoadDir(extensionDir
, false);
191 // load user extension plugins
192 sc_GetUserExtensionDirectory(extensionDir
, MAXPATHLEN
);
193 PlugIn_LoadDir(extensionDir
, false);
195 // load user plugin directories
196 SC_StringParser
sp(getenv("SC_PLUGIN_PATH"), SC_STRPARSE_PATHDELIMITER
);
197 while (!sp
.AtEnd()) {
198 PlugIn_LoadDir(const_cast<char *>(sp
.NextToken()), true);
202 /* on darwin plugins are lazily loaded (dlopen uses mmap internally), which can produce audible
203 glitches when UGens have to be paged-in. to work around this we preload all the plugins by
204 iterating through their memory space. */
207 /* seems to cause a stack corruption on llvm-gcc-4.2, sdk 10.5 on 10.6 */
209 unsigned long images
= _dyld_image_count();
210 for(unsigned long i
= 0; i
< images
; i
++) {
211 const mach_header
*hdr
= _dyld_get_image_header(i
);
212 unsigned long slide
= _dyld_get_image_vmaddr_slide(i
);
213 const char *name
= _dyld_get_image_name(i
);
217 if(!strcmp(name
+ (strlen(name
) - 4), ".scx")) {
218 read_section(hdr
, slide
, "__TEXT", "__text");
219 read_section(hdr
, slide
, "__TEXT", "__const");
220 read_section(hdr
, slide
, "__TEXT", "__cstring");
221 read_section(hdr
, slide
, "__TEXT", "__picsymbol_stub");
222 read_section(hdr
, slide
, "__TEXT", "__symbol_stub");
223 read_section(hdr
, slide
, "__TEXT", "__const");
224 read_section(hdr
, slide
, "__TEXT", "__literal4");
225 read_section(hdr
, slide
, "__TEXT", "__literal8");
227 read_section(hdr
, slide
, "__DATA", "__data");
228 read_section(hdr
, slide
, "__DATA", "__la_symbol_ptr");
229 read_section(hdr
, slide
, "__DATA", "__nl_symbol_ptr");
230 read_section(hdr
, slide
, "__DATA", "__dyld");
231 read_section(hdr
, slide
, "__DATA", "__const");
232 read_section(hdr
, slide
, "__DATA", "__mod_init_func");
233 read_section(hdr
, slide
, "__DATA", "__bss");
234 read_section(hdr
, slide
, "__DATA", "__common");
236 read_section(hdr
, slide
, "__IMPORT", "__jump_table");
237 read_section(hdr
, slide
, "__IMPORT", "__pointers");
245 typedef int (*InfoFunction
)();
247 bool checkAPIVersion(void * f
, const char * filename
)
250 InfoFunction fn
= (InfoFunction
)f
;
251 if ((*fn
)() == sc_api_version
)
254 scprintf("*** ERROR: API Version Mismatch: %s\n", filename
);
258 static bool PlugIn_Load(const char *filename
)
262 HINSTANCE hinstance
= LoadLibrary( filename
);
265 DWORD lastErr
= GetLastError();
266 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
267 0, lastErr
, 0, (char*)&s
, 1, 0 );
268 scprintf("*** ERROR: LoadLibrary '%s' err '%s'\n", filename
, s
);
273 void *apiVersionPtr
= (void *)GetProcAddress( hinstance
, "api_version" );
274 if (!checkAPIVersion(apiVersionPtr
, filename
)) {
275 FreeLibrary(hinstance
);
279 void *ptr
= (void *)GetProcAddress( hinstance
, "load" );
282 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
283 0, GetLastError(), 0, (char*)&s
, 1, 0 );
284 scprintf("*** ERROR: GetProcAddress err '%s'\n", s
);
287 FreeLibrary(hinstance
);
291 LoadPlugInFunc loadFunc
= (LoadPlugInFunc
)ptr
;
292 (*loadFunc
)(&gInterfaceTable
);
294 // FIXME: at the moment we never call FreeLibrary() on a loaded plugin
300 void* handle
= dlopen(filename
, RTLD_NOW
);
303 scprintf("*** ERROR: dlopen '%s' err '%s'\n", filename
, dlerror());
308 void *apiVersionPtr
= (void *)dlsym( handle
, "api_version" );
309 if (!checkAPIVersion(apiVersionPtr
, filename
)) {
314 void *ptr
= dlsym(handle
, "load");
316 scprintf("*** ERROR: dlsym load err '%s'\n", dlerror());
321 LoadPlugInFunc loadFunc
= (LoadPlugInFunc
)ptr
;
322 (*loadFunc
)(&gInterfaceTable
);
329 static bool PlugIn_LoadDir(const char *dirname
, bool reportError
)
333 SC_DirHandle
*dir
= sc_OpenDir(dirname
);
336 scprintf("*** ERROR: open directory failed '%s'\n", dirname
); fflush(stdout
);
341 int firstCharOffset
= strlen(dirname
)+1;
344 char diritem
[MAXPATHLEN
];
345 bool skipItem
= true;
346 bool validItem
= sc_ReadDir(dir
, dirname
, diritem
, skipItem
);
347 if (!validItem
) break;
348 if (skipItem
|| (*(diritem
+firstCharOffset
) == '.')) continue; // skip files+folders whose first char is a dot
350 if (sc_DirectoryExists(diritem
)) {
351 success
= PlugIn_LoadDir(diritem
, reportError
);
353 int dnamelen
= strlen(diritem
);
354 int extlen
= strlen(SC_PLUGIN_EXT
);
355 char *extptr
= diritem
+dnamelen
-extlen
;
356 if (strncmp(extptr
, SC_PLUGIN_EXT
, extlen
) == 0) {
357 success
= PlugIn_Load(diritem
);
361 if (!success
) continue;