2 Abstract interpreter interface.
3 Copyright (c) 2003 2004 stefan kersten.
5 ====================================================================
7 SuperCollider real time audio synthesis system
8 Copyright (c) 2002 James McCartney. All rights reserved.
9 http://www.audiosynth.com
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "SC_LanguageClient.h"
27 #include "SC_LibraryConfig.h"
35 # define snprintf _snprintf
37 # define PATH_MAX _MAX_PATH
43 #include "PyrObject.h"
44 #include "PyrKernel.h"
45 #include "PyrPrimitive.h"
47 #include "VMGlobals.h"
48 #include "SC_DirUtils.h"
51 void closeAllGUIScreens();
53 void initGUIPrimitives();
55 extern PyrString
* newPyrStringN(class PyrGC
*gc
, long length
, long flags
, long collect
);
57 // =====================================================================
59 // =====================================================================
61 SC_LanguageClient
* SC_LanguageClient::gInstance
= 0;
62 SC_Lock
SC_LanguageClient::gInstanceMutex
;
64 PyrSymbol
* SC_LanguageClient::s_interpretCmdLine
= 0;
65 PyrSymbol
* SC_LanguageClient::s_interpretPrintCmdLine
= 0;
66 PyrSymbol
* SC_LanguageClient::s_run
= 0;
67 PyrSymbol
* SC_LanguageClient::s_stop
= 0;
68 static PyrSymbol
* s_tick
= 0;
70 SC_LanguageClient::SC_LanguageClient(const char* name
)
80 fprintf(stderr
, "SC_LanguageClient already running\n");
90 SC_LanguageClient::~SC_LanguageClient()
98 void SC_LanguageClient::initRuntime(const Options
& opt
)
100 // start virtual machine
103 char deprecatedSupportDirectory
[PATH_MAX
];
104 sc_GetUserHomeDirectory(deprecatedSupportDirectory
, PATH_MAX
);
105 sc_AppendToPath(deprecatedSupportDirectory
, PATH_MAX
, "share/SuperCollider");
107 if (sc_DirectoryExists(deprecatedSupportDirectory
)) {
108 char supportDirectory
[PATH_MAX
];
109 sc_GetUserAppSupportDirectory(supportDirectory
, PATH_MAX
);
110 postfl("WARNING: Deprecated support directory detected: %s\n"
111 "Extensions and other contents in this directory will not be available until you move them to the new support directory:\n"
113 "Quarks will need to be reinstalled due to broken symbolic links.\n\n", deprecatedSupportDirectory
, supportDirectory
);
118 if (opt
.mRuntimeDir
) {
119 int err
= chdir(opt
.mRuntimeDir
);
121 error("Cannot change to runtime directory: %s", strerror(errno
));
123 pyr_init_mem_pools(opt
.mMemSpace
, opt
.mMemGrow
);
130 void SC_LanguageClient::shutdownRuntime()
135 void SC_LanguageClient::compileLibrary()
140 extern void shutdownLibrary();
141 void SC_LanguageClient::shutdownLibrary()
147 void SC_LanguageClient::recompileLibrary()
152 void SC_LanguageClient::setCmdLine(const char* buf
, size_t size
)
154 if (isLibraryCompiled()) {
156 if (isLibraryCompiled()) {
157 VMGlobals
*g
= gMainVMGlobals
;
159 PyrString
* strobj
= newPyrStringN(g
->gc
, size
, 0, true);
160 memcpy(strobj
->s
, buf
, size
);
162 SetObject(&slotRawInterpreter(&g
->process
->interpreter
)->cmdLine
, strobj
);
163 g
->gc
->GCWrite(slotRawObject(&g
->process
->interpreter
), strobj
);
169 void SC_LanguageClient::setCmdLine(const char* str
)
171 setCmdLine(str
, strlen(str
));
174 void SC_LanguageClient::setCmdLine(const SC_StringBuffer
& strBuf
)
176 setCmdLine(strBuf
.getData(), strBuf
.getSize());
179 void SC_LanguageClient::setCmdLinef(const char* fmt
, ...)
184 mScratch
.vappendf(fmt
, ap
);
186 setCmdLine(mScratch
);
189 void SC_LanguageClient::runLibrary(PyrSymbol
* symbol
)
192 ::runLibrary(symbol
);
196 void SC_LanguageClient::runLibrary(const char* methodName
)
199 ::runLibrary(getsym(methodName
));
203 void SC_LanguageClient::executeFile(const char* fileName
)
205 setCmdLinef("thisProcess.interpreter.executeFile(\"%s\")", fileName
);
206 runLibrary(s_interpretCmdLine
);
209 void SC_LanguageClient::snprintMemArg(char* dst
, size_t size
, int arg
)
213 const char* modstr
= "";
215 while (((rem
% 1024) == 0) && (mod
< 4)) {
221 case 0: modstr
= ""; break;
222 case 1: modstr
= "k"; break;
223 case 2: modstr
= "m"; break;
224 case 3: modstr
= "g"; break;
225 default: rem
= arg
; modstr
= ""; break;
228 snprintf(dst
, size
, "%d%s", rem
, modstr
);
231 bool SC_LanguageClient::parseMemArg(const char* arg
, int* res
)
233 long value
, factor
= 1;
236 if (*arg
== '\0') return false;
238 value
= strtol(arg
, &endPtr
, 0);
240 char spec
= *endPtr
++;
243 // trailing characters
251 factor
= 1024 * 1024;
259 *res
= value
* factor
;
264 bool SC_LanguageClient::parsePortArg(const char* arg
, int* res
)
269 if (*arg
== '\0') return false;
271 value
= strtol(arg
, &endPtr
, 0);
273 if ((*endPtr
!= '\0') || (value
< 0) || (value
> 65535))
281 void SC_LanguageClient::tick()
284 if (isLibraryCompiled()) {
285 ::runLibrary(s_tick
);
292 bool SC_LanguageClient::tickLocked( double * nextTime
)
294 if (isLibraryCompiled()) {
295 ::runLibrary(s_tick
);
298 return slotDoubleVal( &gMainVMGlobals
->result
, nextTime
) == errNone
;
301 void SC_LanguageClient::onInitRuntime()
305 void SC_LanguageClient::onLibraryStartup()
309 void SC_LanguageClient::onLibraryShutdown()
313 void SC_LanguageClient::onInterpStartup()
317 // =====================================================================
319 // =====================================================================
321 // this is defined in PySCLang
323 void setPostFile(FILE* file
)
325 SC_LanguageClient::instance()->setPostFile(file
);
328 int vpost(const char *fmt
, va_list ap
)
331 int n
= vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
333 SC_LanguageClient
*client
= SC_LanguageClient::lockedInstance();
334 if (client
) client
->postText(buf
, sc_min(n
, sizeof(buf
) - 1));
335 SC_LanguageClient::unlockInstance();
340 void post(const char *fmt
, ...)
347 void postfl(const char *fmt
, ...)
352 int n
= vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
354 SC_LanguageClient
*client
= SC_LanguageClient::lockedInstance();
355 if (client
) client
->postFlush(buf
, sc_min(n
, sizeof(buf
) - 1));
356 SC_LanguageClient::unlockInstance();
360 void postText(const char *str
, long len
)
362 SC_LanguageClient
*client
= SC_LanguageClient::lockedInstance();
363 if (client
) client
->postFlush(str
, len
);
364 SC_LanguageClient::unlockInstance();
367 void postChar(char c
)
369 SC_LanguageClient
*client
= SC_LanguageClient::lockedInstance();
370 if (client
) client
->postFlush(&c
, sizeof(char));
371 SC_LanguageClient::unlockInstance();
374 void error(const char *fmt
, ...)
379 int n
= vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
381 SC_LanguageClient
*client
= SC_LanguageClient::lockedInstance();
382 if (client
) client
->postError(buf
, sc_min(n
, sizeof(buf
) - 1));
383 SC_LanguageClient::unlockInstance();
387 void flushPostBuf(void)
389 SC_LanguageClient::instance()->flush();
392 void closeAllGUIScreens()
394 SC_LanguageClient::instance()->onLibraryShutdown();
399 SC_LanguageClient::instance()->onInterpStartup();
402 void initGUIPrimitives()
404 SC_LanguageClient::s_interpretCmdLine
= getsym("interpretCmdLine");
405 SC_LanguageClient::s_interpretPrintCmdLine
= getsym("interpretPrintCmdLine");
406 SC_LanguageClient::s_run
= getsym("run");
407 SC_LanguageClient::s_stop
= getsym("stop");
408 s_tick
= getsym("tick");
409 SC_LanguageClient::instance()->onLibraryStartup();
412 void initSCViewPrimitives();
413 void initSCViewPrimitives()
417 void initCocoaFilePrimitives();
418 void initCocoaFilePrimitives()
422 void initCocoaBridgePrimitives();
423 void initCocoaBridgePrimitives()
427 void initRendezvousPrimitives();
428 void initRendezvousPrimitives()
432 #if !defined(HAVE_SPEECH)
433 void initSpeechPrimitives();
434 void initSpeechPrimitives()
437 #endif // HAVE_SPEECH
439 long scMIDIout(int port
, int len
, int statushi
, int chan
, int data1
, int data2
);
440 long scMIDIout(int port
, int len
, int statushi
, int chan
, int data1
, int data2
)