/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// file: ulib_machine.cpp// desc: class library for 'Machine'//// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)// date: Spring 2004//-----------------------------------------------------------------------------#include "ulib_machine.h"#include "chuck_type.h"#include "chuck_vm.h"#include "chuck_compile.h"#include "chuck_errmsg.h"#include "chuck_instr.h"#include "chuck.h"#include "util_string.h" #include <string>#include <algorithm>using namespace std; // exportsCK_DLL_SFUN( machine_crash_impl );CK_DLL_SFUN( machine_add_impl );CK_DLL_SFUN( machine_spork_impl );CK_DLL_SFUN( machine_remove_impl );CK_DLL_SFUN( machine_replace_impl );CK_DLL_SFUN( machine_status_impl );CK_DLL_SFUN( machine_intsize_impl );CK_DLL_SFUN( machine_shreds_impl );CK_DLL_SFUN( machine_realtime_impl );CK_DLL_SFUN( machine_silent_impl );CK_DLL_SFUN( machine_eval_impl );CK_DLL_SFUN( machine_eval2_impl );CK_DLL_SFUN( machine_eval3_impl );CK_DLL_SFUN( machine_version_impl );CK_DLL_SFUN( machine_setloglevel_impl );CK_DLL_SFUN( machine_getloglevel_impl );CK_DLL_SFUN( machine_refcount_impl); //-----------------------------------------------------------------------------// name: machine_query()// desc: query entry point//-----------------------------------------------------------------------------DLL_QUERY machine_query( Chuck_DL_Query * QUERY ){ // get global env instance Chuck_Env * env = QUERY->env(); // set name of this query QUERY->setname( QUERY, "Machine" ); /*! \nameinfo ChucK runtime interface to the virtual machine. this interface can be used to manage shreds. They are similar to the <a href="otfp.html"> On-the-fly Programming Commands</a>, except these are invoked from within a ChucK program, and are accessible to the timing mechanism. */ // register deprecate type_engine_register_deprecate( env, "machine", "Machine" ); // class QUERY->begin_class( QUERY, "Machine", "Object" ); // documentation QUERY->doc_class( QUERY, "Machine is ChucK runtime interface to the virtual machine. This interface can be used to manage shreds, evalute code, set log levels, etc. Machine's shred commands are similar to the On-the-fly Programming Commands, except these are invoked from within a ChucK program, and are subject to the timing mechanism." ); #ifndef __DISABLE_OTF_SERVER__ // add add //! compile and spork a new shred from file at 'path' into the VM now //! returns the shred ID //! (see example/machine.ck) QUERY->add_sfun( QUERY, machine_add_impl, "int", "add" ); QUERY->doc_func( QUERY, "add/run a new shred from file at 'path'." ); QUERY->add_arg( QUERY, "string", "path" ); QUERY->doc_func( QUERY, "Compile and spork a new shred from file at 'path' into the VM now, returns the shred ID."); // add spork //! same as add // QUERY->add_sfun( QUERY, machine_add_impl, "int", "spork" ); // QUERY->add_arg( QUERY, "string", "path" ); // add remove //! remove shred from VM by shred ID (returned by add/spork) QUERY->add_sfun( QUERY, machine_remove_impl, "int", "remove" ); QUERY->doc_func( QUERY, "remove a running shred by 'id'." ); QUERY->add_arg( QUERY, "int", "id" ); QUERY->doc_func( QUERY, "Remove shred from VM by shred ID (returned by Machine.add)."); // add replace //! replace shred with new shred from file //! returns shred ID , or 0 on error QUERY->add_sfun( QUERY, machine_replace_impl, "int", "replace" ); QUERY->doc_func( QUERY, "replace running shred by 'id' with new shred at 'path'." ); QUERY->add_arg( QUERY, "int", "id" ); QUERY->add_arg( QUERY, "string", "path" ); QUERY->doc_func( QUERY, "Replace shred with new shred from file. Returns shred ID , or 0 on error."); // add status //! display current status of VM //! (see example/status.ck) QUERY->add_sfun( QUERY, machine_status_impl, "int", "status" ); QUERY->doc_func( QUERY, "display current status of virtual machine." ); QUERY->doc_func( QUERY, "Display the current status of VM."); #endif // __DISABLE_OTF_SERVER__ // add crash //! explicitly crash the virtual machine QUERY->add_sfun( QUERY, machine_crash_impl, "void", "crash" ); QUERY->doc_func( QUERY, "explicitly crash the virtual machine. The very last resort; or an emphatic gesture. Use with care." ); // add shreds //! get list of active shreds by id QUERY->add_sfun( QUERY, machine_shreds_impl, "int[]", "shreds" ); QUERY->doc_func( QUERY, "Retrieve an array of active shred ids." ); // add eval //! evaluate a string as ChucK code, compiling it and adding it to the the virtual machine QUERY->add_sfun( QUERY, machine_eval_impl, "int", "eval" ); QUERY->doc_func( QUERY, "evaluate a string as ChucK code, compile it and spork it as an independent shred." ); QUERY->add_arg( QUERY, "string", "code" ); // add eval //! evaluate a string as ChucK code, compiling it and adding it to the the virtual machine QUERY->add_sfun( QUERY, machine_eval2_impl, "int", "eval" ); QUERY->doc_func( QUERY, "evaluate a string as ChucK code, with optional arguments (bundled in 'args' as \"ARG1:ARG2:...\", compile it and spork it as an independent shred." ); QUERY->add_arg( QUERY, "string", "code" ); QUERY->add_arg( QUERY, "string", "args" ); // add eval //! evaluate a string as ChucK code, compiling it and adding it to the the virtual machine QUERY->add_sfun( QUERY, machine_eval3_impl, "int", "eval" ); QUERY->doc_func( QUERY, "evaluate a string as ChucK code, with optional arguments (bundled in 'args' as \"ARG1:ARG2:...\", compile it and sporking 'count' instances, each as an independent shred." ); QUERY->add_arg( QUERY, "string", "code" ); QUERY->add_arg( QUERY, "string", "args" ); QUERY->add_arg( QUERY, "int", "count" ); // add get intsize (width) //! get the intsize in bits (e.g., 32 or 64) QUERY->add_sfun( QUERY, machine_intsize_impl, "int", "intsize" ); QUERY->doc_func( QUERY, "Return the bit size of an integer."); // add check for silent (or realtime audio) | adapted from nshaheed PR #230 QUERY->add_sfun( QUERY, machine_silent_impl, "int", "silent" ); QUERY->doc_func( QUERY, "return false if the shred is in realtime mode, true if it's in silent mode (i.e. --silent is enabled)" ); // add check for realtime (always opposite of silent()) | adapted from nshaheed PR #230 QUERY->add_sfun( QUERY, machine_realtime_impl, "int", "realtime" ); QUERY->doc_func( QUERY, "return true if the shred is in realtime mode, false if it's in silent mode (i.e. --silent is enabled)" ); // get version string QUERY->add_sfun( QUERY, machine_version_impl, "string", "version" ); QUERY->doc_func( QUERY, "return version string" ); // get set loglevel QUERY->add_sfun( QUERY, machine_setloglevel_impl, "int", "loglevel" ); QUERY->add_arg( QUERY, "int", "level" ); QUERY->doc_func( QUERY, "set log level\n" " |- 0: NONE\n" " |- 1: CORE\n" " |- 2: SYSTEM\n" " |- 3: SEVERE\n" " |- 4: WARNING\n" " |- 5: INFO\n" " |- 6: CONFIG\n" " |- 7: FINE\n" " |- 8: FINER\n" " |- 9: FINEST\n" " |- 10: ALL" ); // get log level QUERY->add_sfun( QUERY, machine_getloglevel_impl, "int", "loglevel" ); QUERY->doc_func( QUERY, "get log level." ); // get reference count for any object QUERY->add_sfun( QUERY, machine_refcount_impl, "int", "refcount" ); QUERY->add_arg( QUERY, "Object", "obj" ); QUERY->doc_func( QUERY, "get an object's current internal reference count; this is intended for testing or curiosity; NOTE: this function intentionally does not take into account any reference counting related to the calling of this function (normally all functions increments the reference count for objects passed as arguments and decrements upon returning)" ); // add examples QUERY->add_ex( QUERY, "machine/eval.ck" ); QUERY->add_ex( QUERY, "machine/intsize.ck" ); QUERY->add_ex( QUERY, "machine/is-realtime.ck" ); QUERY->add_ex( QUERY, "machine/machine-shred.ck" ); QUERY->add_ex( QUERY, "book/digital-artists/chapter9/DrumMachine" ); QUERY->add_ex( QUERY, "book/digital-artists/chapter9/SmartMandolin/initialize.ck" ); // end class QUERY->end_class( QUERY ); return TRUE;} //-----------------------------------------------------------------------------// name: machine_intsize()// desc: integer size in bits//-----------------------------------------------------------------------------t_CKUINT machine_intsize(){ return sizeof(t_CKINT) * 8;} //-----------------------------------------------------------------------------// name: machine_realtime()// desc: return whether chuck is in realtime mode, or silent mode (--silent is enabled)//-----------------------------------------------------------------------------t_CKUINT machine_realtime( Chuck_VM * vm ){ return vm->carrier()->hintIsRealtimeAudio();} //-----------------------------------------------------------------------------// name: machine_eval()// desc: evaluate a string as ChucK code, compiling it and adding it to the the virtual machine//-----------------------------------------------------------------------------t_CKUINT machine_eval( Chuck_String * codeStr, Chuck_String * argsTogether, t_CKINT count, Chuck_VM * vm ){ // check if null if( codeStr == NULL ) return FALSE; // get ChucK instance ChucK * chuck = vm->carrier()->chuck; // get code as string string code = codeStr->str(); // get args, if there string args = argsTogether ? argsTogether->str() : ""; return chuck->compileCode( code, args, count );} #ifndef __DISABLE_OTF_SERVER__ // OTF server stuffstatic Chuck_Compiler * the_compiler = NULL;static proc_msg_func the_func = NULL;//-----------------------------------------------------------------------------// name: machine_init()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL machine_init( Chuck_Compiler * compiler, proc_msg_func proc_msg ){ the_compiler = compiler; the_func = proc_msg; return TRUE;} // addCK_DLL_SFUN( machine_add_impl ){ const char * v = GET_CK_STRING(ARGS)->str().c_str(); Net_Msg msg; msg.type = MSG_ADD; strcpy( msg.buffer, v ); RETURN->v_int = (int)the_func( SHRED->vm_ref, the_compiler, &msg, TRUE, NULL );} // removeCK_DLL_SFUN( machine_remove_impl ){ t_CKINT v = GET_CK_INT(ARGS); Net_Msg msg; msg.type = MSG_REMOVE; msg.param = v; RETURN->v_int = (int)the_func( SHRED->vm_ref, the_compiler, &msg, TRUE, NULL );} // replaceCK_DLL_SFUN( machine_replace_impl ){ t_CKINT v = GET_NEXT_INT(ARGS); const char * v2 = GET_NEXT_STRING(ARGS)->str().c_str(); Net_Msg msg; msg.type = MSG_REPLACE; msg.param = v; strcpy( msg.buffer, v2 ); RETURN->v_int = (int)the_func( SHRED->vm_ref, the_compiler, &msg, TRUE, NULL );} // statusCK_DLL_SFUN( machine_status_impl ){ Net_Msg msg; msg.type = MSG_STATUS; RETURN->v_int = (int)the_func( SHRED->vm_ref, the_compiler, &msg, TRUE, NULL );} #endif // __DISABLE_OTF_SERVER__ // intsizeCK_DLL_SFUN( machine_intsize_impl ){ RETURN->v_int = machine_intsize();} // realtimeCK_DLL_SFUN( machine_realtime_impl ){ RETURN->v_int = machine_realtime( SHRED->vm_ref );} // silentCK_DLL_SFUN( machine_silent_impl ){ RETURN->v_int = !machine_realtime( SHRED->vm_ref );} CK_DLL_SFUN( machine_shreds_impl ){ Chuck_Array4 *array = new Chuck_Array4(FALSE); initialize_object(array, SHRED->vm_ref->env()->t_array); array->clear(); Chuck_VM_Status status; SHRED->vm_ref->shreduler()->status(&status); for(int i = 0; i < status.list.size(); i++) array->push_back(status.list[i]->xid); status.clear(); RETURN->v_object = array;} CK_DLL_SFUN( machine_eval_impl ){ // get arguments Chuck_String * code = GET_NEXT_STRING(ARGS); RETURN->v_int = machine_eval( code, NULL, 1, VM );} CK_DLL_SFUN( machine_eval2_impl ){ // get arguments Chuck_String * code = GET_NEXT_STRING(ARGS); Chuck_String * argsTogether = GET_NEXT_STRING(ARGS); RETURN->v_int = machine_eval( code, argsTogether, 1, VM );} CK_DLL_SFUN( machine_eval3_impl ){ // get arguments Chuck_String * code = GET_NEXT_STRING(ARGS); Chuck_String * argsTogether = GET_NEXT_STRING(ARGS); t_CKINT count = GET_NEXT_INT(ARGS); RETURN->v_int = machine_eval( code, argsTogether, count, VM );} CK_DLL_SFUN( machine_version_impl ){ // get version string string vs = VM->carrier()->chuck->version(); // make chuck string Chuck_String * s = new Chuck_String( vs ); // initialize initialize_object(s, VM->carrier()->env->t_string ); // return RETURN->v_string = s;} CK_DLL_SFUN( machine_setloglevel_impl ){ // arg t_CKINT level = GET_NEXT_INT(ARGS); // get current log t_CKINT current = VM->carrier()->chuck->getLogLevel(); // clamp compare if( level < CK_LOG_NONE ) level = CK_LOG_NONE; else if( level > CK_LOG_ALL ) level = CK_LOG_ALL; // compare if( level != current ) { EM_log( CK_LOG_NONE, "updating log level from %d to %d...", current, level ); VM->carrier()->chuck->setLogLevel( level ); } // return RETURN->v_int = level;} CK_DLL_SFUN( machine_getloglevel_impl ){ // return RETURN->v_int = VM->carrier()->chuck->getLogLevel();} CK_DLL_SFUN( machine_refcount_impl ){ // get the argument Chuck_Object * obj = (Chuck_Object *)GET_NEXT_OBJECT(ARGS); // return (-1 to account for the extra refcount as part of calling this function!) RETURN->v_int = obj != NULL ? obj->m_ref_count-1 : 0;} // addCK_DLL_SFUN( machine_crash_impl ){ CK_FPRINTF_STDERR( "[chuck]: crashing...\n" ); *(volatile int *)0 = 0;}
/*----------------------------------------------------------------------------
ChucK Concurrent, On-the-fly Audio Programming Language
Compiler and Virtual Machine
Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
http://chuck.stanford.edu/
http://chuck.cs.princeton.edu/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
U.S.A.
-----------------------------------------------------------------------------*/
//-----------------------------------------------------------------------------
// file: ulib_machine.cpp
// desc: class library for 'Machine'
//
// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
// date: Spring 2004
//-----------------------------------------------------------------------------
#include "ulib_machine.h"
#include "chuck_type.h"
#include "chuck_vm.h"
#include "chuck_compile.h"
#include "chuck_errmsg.h"
#include "chuck_instr.h"
#include "chuck.h"
#include "util_string.h"
#include <string>
#include <algorithm>
using namespace std;
// exports
CK_DLL_SFUN( machine_crash_impl );
CK_DLL_SFUN( machine_add_impl );
CK_DLL_SFUN( machine_spork_impl );
CK_DLL_SFUN( machine_remove_impl );
CK_DLL_SFUN( machine_replace_impl );
CK_DLL_SFUN( machine_status_impl );
CK_DLL_SFUN( machine_intsize_impl );
CK_DLL_SFUN( machine_shreds_impl );
CK_DLL_SFUN( machine_realtime_impl );
CK_DLL_SFUN( machine_silent_impl );
CK_DLL_SFUN( machine_eval_impl );
CK_DLL_SFUN( machine_eval2_impl );
CK_DLL_SFUN( machine_eval3_impl );
CK_DLL_SFUN( machine_version_impl );
CK_DLL_SFUN( machine_setloglevel_impl );
CK_DLL_SFUN( machine_getloglevel_impl );
CK_DLL_SFUN( machine_refcount_impl);
//-----------------------------------------------------------------------------
// name: machine_query()
// desc: query entry point
//-----------------------------------------------------------------------------
DLL_QUERY machine_query( Chuck_DL_Query * QUERY )
{
// get global env instance
Chuck_Env * env = QUERY->env();
// set name of this query
QUERY->setname( QUERY, "Machine" );
/*! \nameinfo
ChucK runtime interface to the virtual machine.
this interface can be used to manage shreds.
They are similar to the <a href="otfp.html">
On-the-fly Programming Commands</a>, except these are
invoked from within a ChucK program, and are accessible
to the timing mechanism.
*/
// register deprecate
type_engine_register_deprecate( env, "machine", "Machine" );
// class
QUERY->begin_class( QUERY, "Machine", "Object" );
// documentation
QUERY->doc_class( QUERY, "Machine is ChucK runtime interface to the virtual machine. This interface can be used to manage shreds, evalute code, set log levels, etc. Machine's shred commands are similar to the On-the-fly Programming Commands, except these are invoked from within a ChucK program, and are subject to the timing mechanism." );
#ifndef __DISABLE_OTF_SERVER__
// add add
//! compile and spork a new shred from file at 'path' into the VM now
//! returns the shred ID
//! (see example/machine.ck)
QUERY->add_sfun( QUERY, machine_add_impl, "int", "add" );
QUERY->doc_func( QUERY, "add/run a new shred from file at 'path'." );
QUERY->add_arg( QUERY, "string", "path" );
QUERY->doc_func( QUERY, "Compile and spork a new shred from file at 'path' into the VM now, returns the shred ID.");
// add spork
//! same as add
// QUERY->add_sfun( QUERY, machine_add_impl, "int", "spork" );
// QUERY->add_arg( QUERY, "string", "path" );
// add remove
//! remove shred from VM by shred ID (returned by add/spork)
QUERY->add_sfun( QUERY, machine_remove_impl, "int", "remove" );
QUERY->doc_func( QUERY, "remove a running shred by 'id'." );
QUERY->add_arg( QUERY, "int", "id" );
QUERY->doc_func( QUERY, "Remove shred from VM by shred ID (returned by Machine.add).");
// add replace
//! replace shred with new shred from file
//! returns shred ID , or 0 on error
QUERY->add_sfun( QUERY, machine_replace_impl, "int", "replace" );
QUERY->doc_func( QUERY, "replace running shred by 'id' with new shred at 'path'." );
QUERY->add_arg( QUERY, "int", "id" );
QUERY->add_arg( QUERY, "string", "path" );
QUERY->doc_func( QUERY, "Replace shred with new shred from file. Returns shred ID , or 0 on error.");
// add status
//! display current status of VM
//! (see example/status.ck)
QUERY->add_sfun( QUERY, machine_status_impl, "int", "status" );
QUERY->doc_func( QUERY, "display current status of virtual machine." );
QUERY->doc_func( QUERY, "Display the current status of VM.");
#endif // __DISABLE_OTF_SERVER__
// add crash
//! explicitly crash the virtual machine
QUERY->add_sfun( QUERY, machine_crash_impl, "void", "crash" );
QUERY->doc_func( QUERY, "explicitly crash the virtual machine. The very last resort; or an emphatic gesture. Use with care." );
// add shreds
//! get list of active shreds by id
QUERY->add_sfun( QUERY, machine_shreds_impl, "int[]", "shreds" );
QUERY->doc_func( QUERY, "Retrieve an array of active shred ids." );
// add eval
//! evaluate a string as ChucK code, compiling it and adding it to the the virtual machine
QUERY->add_sfun( QUERY, machine_eval_impl, "int", "eval" );
QUERY->doc_func( QUERY, "evaluate a string as ChucK code, compile it and spork it as an independent shred." );
QUERY->add_arg( QUERY, "string", "code" );
// add eval
//! evaluate a string as ChucK code, compiling it and adding it to the the virtual machine
QUERY->add_sfun( QUERY, machine_eval2_impl, "int", "eval" );
QUERY->doc_func( QUERY, "evaluate a string as ChucK code, with optional arguments (bundled in 'args' as \"ARG1:ARG2:...\", compile it and spork it as an independent shred." );
QUERY->add_arg( QUERY, "string", "code" );
QUERY->add_arg( QUERY, "string", "args" );
// add eval
//! evaluate a string as ChucK code, compiling it and adding it to the the virtual machine
QUERY->add_sfun( QUERY, machine_eval3_impl, "int", "eval" );
QUERY->doc_func( QUERY, "evaluate a string as ChucK code, with optional arguments (bundled in 'args' as \"ARG1:ARG2:...\", compile it and sporking 'count' instances, each as an independent shred." );
QUERY->add_arg( QUERY, "string", "code" );
QUERY->add_arg( QUERY, "string", "args" );
QUERY->add_arg( QUERY, "int", "count" );
// add get intsize (width)
//! get the intsize in bits (e.g., 32 or 64)
QUERY->add_sfun( QUERY, machine_intsize_impl, "int", "intsize" );
QUERY->doc_func( QUERY, "Return the bit size of an integer.");
// add check for silent (or realtime audio) | adapted from nshaheed PR #230
QUERY->add_sfun( QUERY, machine_silent_impl, "int", "silent" );
QUERY->doc_func( QUERY, "return false if the shred is in realtime mode, true if it's in silent mode (i.e. --silent is enabled)" );
// add check for realtime (always opposite of silent()) | adapted from nshaheed PR #230
QUERY->add_sfun( QUERY, machine_realtime_impl, "int", "realtime" );
QUERY->doc_func( QUERY, "return true if the shred is in realtime mode, false if it's in silent mode (i.e. --silent is enabled)" );
// get version string
QUERY->add_sfun( QUERY, machine_version_impl, "string", "version" );
QUERY->doc_func( QUERY, "return version string" );
// get set loglevel
QUERY->add_sfun( QUERY, machine_setloglevel_impl, "int", "loglevel" );
QUERY->add_arg( QUERY, "int", "level" );
QUERY->doc_func( QUERY, "set log level\n"
" |- 0: NONE\n"
" |- 1: CORE\n"
" |- 2: SYSTEM\n"
" |- 3: SEVERE\n"
" |- 4: WARNING\n"
" |- 5: INFO\n"
" |- 6: CONFIG\n"
" |- 7: FINE\n"
" |- 8: FINER\n"
" |- 9: FINEST\n"
" |- 10: ALL" );
// get log level
QUERY->add_sfun( QUERY, machine_getloglevel_impl, "int", "loglevel" );
QUERY->doc_func( QUERY, "get log level." );
// get reference count for any object
QUERY->add_sfun( QUERY, machine_refcount_impl, "int", "refcount" );
QUERY->add_arg( QUERY, "Object", "obj" );
QUERY->doc_func( QUERY, "get an object's current internal reference count; this is intended for testing or curiosity; NOTE: this function intentionally does not take into account any reference counting related to the calling of this function (normally all functions increments the reference count for objects passed as arguments and decrements upon returning)" );
// add examples
QUERY->add_ex( QUERY, "machine/eval.ck" );
QUERY->add_ex( QUERY, "machine/intsize.ck" );
QUERY->add_ex( QUERY, "machine/is-realtime.ck" );
QUERY->add_ex( QUERY, "machine/machine-shred.ck" );
QUERY->add_ex( QUERY, "book/digital-artists/chapter9/DrumMachine" );
QUERY->add_ex( QUERY, "book/digital-artists/chapter9/SmartMandolin/initialize.ck" );
// end class
QUERY->end_class( QUERY );
return TRUE;
}
//-----------------------------------------------------------------------------
// name: machine_intsize()
// desc: integer size in bits
//-----------------------------------------------------------------------------
t_CKUINT machine_intsize()
{
return sizeof(t_CKINT) * 8;
}
//-----------------------------------------------------------------------------
// name: machine_realtime()
// desc: return whether chuck is in realtime mode, or silent mode (--silent is enabled)
//-----------------------------------------------------------------------------
t_CKUINT machine_realtime( Chuck_VM * vm )
{
return vm->carrier()->hintIsRealtimeAudio();
}
//-----------------------------------------------------------------------------
// name: machine_eval()
// desc: evaluate a string as ChucK code, compiling it and adding it to the the virtual machine
//-----------------------------------------------------------------------------
t_CKUINT machine_eval( Chuck_String * codeStr, Chuck_String * argsTogether,
t_CKINT count, Chuck_VM * vm )
{
// check if null
if( codeStr == NULL ) return FALSE;
// get ChucK instance
ChucK * chuck = vm->carrier()->chuck;
// get code as string
string code = codeStr->str();
// get args, if there
string args = argsTogether ? argsTogether->str() : "";
return chuck->compileCode( code, args, count );
}
#ifndef __DISABLE_OTF_SERVER__
// OTF server stuff
static Chuck_Compiler * the_compiler = NULL;
static proc_msg_func the_func = NULL;
//-----------------------------------------------------------------------------
// name: machine_init()
// desc: ...
//-----------------------------------------------------------------------------
t_CKBOOL machine_init( Chuck_Compiler * compiler, proc_msg_func proc_msg )
{
the_compiler = compiler;
the_func = proc_msg;
return TRUE;
}
// add
CK_DLL_SFUN( machine_add_impl )
{
const char * v = GET_CK_STRING(ARGS)->str().c_str();
Net_Msg msg;
msg.type = MSG_ADD;
strcpy( msg.buffer, v );
RETURN->v_int = (int)the_func( SHRED->vm_ref, the_compiler, &msg, TRUE, NULL );
}
// remove
CK_DLL_SFUN( machine_remove_impl )
{
t_CKINT v = GET_CK_INT(ARGS);
Net_Msg msg;
msg.type = MSG_REMOVE;
msg.param = v;
RETURN->v_int = (int)the_func( SHRED->vm_ref, the_compiler, &msg, TRUE, NULL );
}
// replace
CK_DLL_SFUN( machine_replace_impl )
{
t_CKINT v = GET_NEXT_INT(ARGS);
const char * v2 = GET_NEXT_STRING(ARGS)->str().c_str();
Net_Msg msg;
msg.type = MSG_REPLACE;
msg.param = v;
strcpy( msg.buffer, v2 );
RETURN->v_int = (int)the_func( SHRED->vm_ref, the_compiler, &msg, TRUE, NULL );
}
// status
CK_DLL_SFUN( machine_status_impl )
{
Net_Msg msg;
msg.type = MSG_STATUS;
RETURN->v_int = (int)the_func( SHRED->vm_ref, the_compiler, &msg, TRUE, NULL );
}
#endif // __DISABLE_OTF_SERVER__
// intsize
CK_DLL_SFUN( machine_intsize_impl )
{
RETURN->v_int = machine_intsize();
}
// realtime
CK_DLL_SFUN( machine_realtime_impl )
{
RETURN->v_int = machine_realtime( SHRED->vm_ref );
}
// silent
CK_DLL_SFUN( machine_silent_impl )
{
RETURN->v_int = !machine_realtime( SHRED->vm_ref );
}
CK_DLL_SFUN( machine_shreds_impl )
{
Chuck_Array4 *array = new Chuck_Array4(FALSE);
initialize_object(array, SHRED->vm_ref->env()->t_array);
array->clear();
Chuck_VM_Status status;
SHRED->vm_ref->shreduler()->status(&status);
for(int i = 0; i < status.list.size(); i++)
array->push_back(status.list[i]->xid);
status.clear();
RETURN->v_object = array;
}
CK_DLL_SFUN( machine_eval_impl )
{
// get arguments
Chuck_String * code = GET_NEXT_STRING(ARGS);
RETURN->v_int = machine_eval( code, NULL, 1, VM );
}
CK_DLL_SFUN( machine_eval2_impl )
{
// get arguments
Chuck_String * code = GET_NEXT_STRING(ARGS);
Chuck_String * argsTogether = GET_NEXT_STRING(ARGS);
RETURN->v_int = machine_eval( code, argsTogether, 1, VM );
}
CK_DLL_SFUN( machine_eval3_impl )
{
// get arguments
Chuck_String * code = GET_NEXT_STRING(ARGS);
Chuck_String * argsTogether = GET_NEXT_STRING(ARGS);
t_CKINT count = GET_NEXT_INT(ARGS);
RETURN->v_int = machine_eval( code, argsTogether, count, VM );
}
CK_DLL_SFUN( machine_version_impl )
{
// get version string
string vs = VM->carrier()->chuck->version();
// make chuck string
Chuck_String * s = new Chuck_String( vs );
// initialize
initialize_object(s, VM->carrier()->env->t_string );
// return
RETURN->v_string = s;
}
CK_DLL_SFUN( machine_setloglevel_impl )
{
// arg
t_CKINT level = GET_NEXT_INT(ARGS);
// get current log
t_CKINT current = VM->carrier()->chuck->getLogLevel();
// clamp compare
if( level < CK_LOG_NONE ) level = CK_LOG_NONE;
else if( level > CK_LOG_ALL ) level = CK_LOG_ALL;
// compare
if( level != current )
{
EM_log( CK_LOG_NONE, "updating log level from %d to %d...", current, level );
VM->carrier()->chuck->setLogLevel( level );
}
// return
RETURN->v_int = level;
}
CK_DLL_SFUN( machine_getloglevel_impl )
{
// return
RETURN->v_int = VM->carrier()->chuck->getLogLevel();
}
CK_DLL_SFUN( machine_refcount_impl )
{
// get the argument
Chuck_Object * obj = (Chuck_Object *)GET_NEXT_OBJECT(ARGS);
// return (-1 to account for the extra refcount as part of calling this function!)
RETURN->v_int = obj != NULL ? obj->m_ref_count-1 : 0;
}
// add
CK_DLL_SFUN( machine_crash_impl )
{
CK_FPRINTF_STDERR( "[chuck]: crashing...\n" );
*(volatile int *)0 = 0;
}