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"
61 # include <sys/param.h>
66 #include <mach-o/dyld.h>
67 #include <mach-o/getsect.h>
73 HashTable
<SC_LibCmd
, Malloc
> *gCmdLib
;
74 HashTable
<struct UnitDef
, Malloc
> *gUnitDefLib
= 0;
75 HashTable
<struct BufGen
, Malloc
> *gBufGenLib
= 0;
76 HashTable
<struct PlugInCmd
, Malloc
> *gPlugInCmds
= 0;
77 extern struct InterfaceTable gInterfaceTable
;
78 SC_LibCmd
* gCmdArray
[NUMBER_OF_COMMANDS
];
80 void initMiscCommands();
81 static bool PlugIn_LoadDir(const char *dirname
, bool reportError
);
84 void read_section(const struct mach_header
*mhp
, unsigned long slide
, const char *segname
, const char *sectname
)
87 char *sect
= getsectdatafromheader(mhp
, segname
, sectname
, &size
);
90 char *start
= sect
+ slide
;
91 char *end
= start
+ size
;
94 gTempVal
+= *(char *)start
;
100 extern void IO_Load(InterfaceTable
*table
);
101 extern void Osc_Load(InterfaceTable
*table
);
102 extern void Delay_Load(InterfaceTable
*table
);
103 extern void BinaryOp_Load(InterfaceTable
*table
);
104 extern void Filter_Load(InterfaceTable
*table
);
105 extern void Gendyn_Load(InterfaceTable
*table
);
106 extern void LF_Load(InterfaceTable
*table
);
107 extern void Noise_Load(InterfaceTable
*table
);
108 extern void MulAdd_Load(InterfaceTable
*table
);
109 extern void Grain_Load(InterfaceTable
*table
);
110 extern void Pan_Load(InterfaceTable
*table
);
111 extern void Reverb_Load(InterfaceTable
*table
);
112 extern void Trigger_Load(InterfaceTable
*table
);
113 extern void UnaryOp_Load(InterfaceTable
*table
);
114 extern void DiskIO_Load(InterfaceTable
*table
);
115 extern void Test_Load(InterfaceTable
*table
);
116 extern void PhysicalModeling_Load(InterfaceTable
*table
);
117 extern void Demand_Load(InterfaceTable
*table
);
118 extern void DynNoise_Load(InterfaceTable
*table
);
119 extern void FFT_UGens_Load(InterfaceTable
*table
);
120 extern void iPhone_Load(InterfaceTable
*table
);
122 void initialize_library(const char *uGensPluginPath
)
124 gCmdLib
= new HashTable
<SC_LibCmd
, Malloc
>(&gMalloc
, 64, true);
125 gUnitDefLib
= new HashTable
<UnitDef
, Malloc
>(&gMalloc
, 512, true);
126 gBufGenLib
= new HashTable
<BufGen
, Malloc
>(&gMalloc
, 512, true);
127 gPlugInCmds
= new HashTable
<PlugInCmd
, Malloc
>(&gMalloc
, 64, true);
131 #ifdef STATIC_PLUGINS
132 IO_Load(&gInterfaceTable
);
133 Osc_Load(&gInterfaceTable
);
134 Delay_Load(&gInterfaceTable
);
135 BinaryOp_Load(&gInterfaceTable
);
136 Filter_Load(&gInterfaceTable
);
137 Gendyn_Load(&gInterfaceTable
);
138 LF_Load(&gInterfaceTable
);
139 Noise_Load(&gInterfaceTable
);
140 MulAdd_Load(&gInterfaceTable
);
141 Grain_Load(&gInterfaceTable
);
142 Pan_Load(&gInterfaceTable
);
143 Reverb_Load(&gInterfaceTable
);
144 Trigger_Load(&gInterfaceTable
);
145 UnaryOp_Load(&gInterfaceTable
);
146 DiskIO_Load(&gInterfaceTable
);
147 PhysicalModeling_Load(&gInterfaceTable
);
148 Test_Load(&gInterfaceTable
);
149 Demand_Load(&gInterfaceTable
);
150 DynNoise_Load(&gInterfaceTable
);
151 #if defined(SC_IPHONE) && !TARGET_IPHONE_SIMULATOR
152 iPhone_Load(&gInterfaceTable
);
154 FFT_UGens_Load(&gInterfaceTable
);
158 // If uGensPluginPath is supplied, it is exclusive.
159 bool loadUGensExtDirs
= true;
161 loadUGensExtDirs
= false;
162 SC_StringParser
sp(uGensPluginPath
, SC_STRPARSE_PATHDELIMITER
);
163 while (!sp
.AtEnd()) {
164 PlugIn_LoadDir(const_cast<char *>(sp
.NextToken()), true);
168 if(loadUGensExtDirs
) {
170 // load globally installed plugins
171 if (sc_DirectoryExists(SC_PLUGIN_DIR
)) {
172 PlugIn_LoadDir(SC_PLUGIN_DIR
, true);
175 // load default plugin directory
176 char pluginDir
[MAXPATHLEN
];
177 sc_GetResourceDirectory(pluginDir
, MAXPATHLEN
);
178 sc_AppendToPath(pluginDir
, MAXPATHLEN
, SC_PLUGIN_DIR_NAME
);
180 if (sc_DirectoryExists(pluginDir
)) {
181 PlugIn_LoadDir(pluginDir
, true);
185 // get extension directories
186 char extensionDir
[MAXPATHLEN
];
187 if (!sc_IsStandAlone() && loadUGensExtDirs
) {
188 // load system extension plugins
189 sc_GetSystemExtensionDirectory(extensionDir
, MAXPATHLEN
);
190 PlugIn_LoadDir(extensionDir
, false);
192 // load user extension plugins
193 sc_GetUserExtensionDirectory(extensionDir
, MAXPATHLEN
);
194 PlugIn_LoadDir(extensionDir
, false);
196 // load user plugin directories
197 SC_StringParser
sp(getenv("SC_PLUGIN_PATH"), SC_STRPARSE_PATHDELIMITER
);
198 while (!sp
.AtEnd()) {
199 PlugIn_LoadDir(const_cast<char *>(sp
.NextToken()), true);
203 /* on darwin plugins are lazily loaded (dlopen uses mmap internally), which can produce audible
204 glitches when UGens have to be paged-in. to work around this we preload all the plugins by
205 iterating through their memory space. */
208 /* seems to cause a stack corruption on llvm-gcc-4.2, sdk 10.5 on 10.6 */
210 unsigned long images
= _dyld_image_count();
211 for(unsigned long i
= 0; i
< images
; i
++) {
212 const mach_header
*hdr
= _dyld_get_image_header(i
);
213 unsigned long slide
= _dyld_get_image_vmaddr_slide(i
);
214 const char *name
= _dyld_get_image_name(i
);
218 if(!strcmp(name
+ (strlen(name
) - 4), ".scx")) {
219 read_section(hdr
, slide
, "__TEXT", "__text");
220 read_section(hdr
, slide
, "__TEXT", "__const");
221 read_section(hdr
, slide
, "__TEXT", "__cstring");
222 read_section(hdr
, slide
, "__TEXT", "__picsymbol_stub");
223 read_section(hdr
, slide
, "__TEXT", "__symbol_stub");
224 read_section(hdr
, slide
, "__TEXT", "__const");
225 read_section(hdr
, slide
, "__TEXT", "__literal4");
226 read_section(hdr
, slide
, "__TEXT", "__literal8");
228 read_section(hdr
, slide
, "__DATA", "__data");
229 read_section(hdr
, slide
, "__DATA", "__la_symbol_ptr");
230 read_section(hdr
, slide
, "__DATA", "__nl_symbol_ptr");
231 read_section(hdr
, slide
, "__DATA", "__dyld");
232 read_section(hdr
, slide
, "__DATA", "__const");
233 read_section(hdr
, slide
, "__DATA", "__mod_init_func");
234 read_section(hdr
, slide
, "__DATA", "__bss");
235 read_section(hdr
, slide
, "__DATA", "__common");
237 read_section(hdr
, slide
, "__IMPORT", "__jump_table");
238 read_section(hdr
, slide
, "__IMPORT", "__pointers");
246 typedef int (*InfoFunction
)();
248 bool checkAPIVersion(void * f
, const char * filename
)
253 InfoFunction fn
= (InfoFunction
)f
;
254 if ((*fn
)() == sc_api_version
)
256 scprintf("*** ERROR: API Version Mismatch: %s\n", filename
);
260 static bool PlugIn_Load(const char *filename
)
264 HINSTANCE hinstance
= LoadLibrary( filename
);
267 DWORD lastErr
= GetLastError();
268 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
269 0, lastErr
, 0, (char*)&s
, 1, 0 );
270 scprintf("*** ERROR: LoadLibrary '%s' err '%s'\n", filename
, s
);
275 void *apiVersionPtr
= (void *)GetProcAddress( hinstance
, "api_version" );
276 if (!checkAPIVersion(apiVersionPtr
, filename
)) {
277 FreeLibrary(hinstance
);
281 void *ptr
= (void *)GetProcAddress( hinstance
, "load" );
284 FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
285 0, GetLastError(), 0, (char*)&s
, 1, 0 );
286 scprintf("*** ERROR: GetProcAddress err '%s'\n", s
);
289 FreeLibrary(hinstance
);
293 LoadPlugInFunc loadFunc
= (LoadPlugInFunc
)ptr
;
294 (*loadFunc
)(&gInterfaceTable
);
296 // FIXME: at the moment we never call FreeLibrary() on a loaded plugin
302 void* handle
= dlopen(filename
, RTLD_NOW
);
305 scprintf("*** ERROR: dlopen '%s' err '%s'\n", filename
, dlerror());
310 void *apiVersionPtr
= (void *)dlsym( handle
, "api_version" );
311 if (!checkAPIVersion(apiVersionPtr
, filename
)) {
316 void *ptr
= dlsym(handle
, "load");
318 scprintf("*** ERROR: dlsym load err '%s'\n", dlerror());
323 LoadPlugInFunc loadFunc
= (LoadPlugInFunc
)ptr
;
324 (*loadFunc
)(&gInterfaceTable
);
331 static bool PlugIn_LoadDir(const char *dirname
, bool reportError
)
335 SC_DirHandle
*dir
= sc_OpenDir(dirname
);
338 scprintf("*** ERROR: open directory failed '%s'\n", dirname
); fflush(stdout
);
343 int firstCharOffset
= strlen(dirname
)+1;
346 char diritem
[MAXPATHLEN
];
347 bool skipItem
= true;
348 bool validItem
= sc_ReadDir(dir
, dirname
, diritem
, skipItem
);
349 if (!validItem
) break;
350 if (skipItem
|| (*(diritem
+firstCharOffset
) == '.')) continue; // skip files+folders whose first char is a dot
352 if (sc_DirectoryExists(diritem
)) {
353 success
= PlugIn_LoadDir(diritem
, reportError
);
355 int dnamelen
= strlen(diritem
);
356 int extlen
= strlen(SC_PLUGIN_EXT
);
357 char *extptr
= diritem
+dnamelen
-extlen
;
358 if (strncmp(extptr
, SC_PLUGIN_EXT
, extlen
) == 0) {
359 success
= PlugIn_Load(diritem
);
363 if (!success
) continue;