446 lines · 15.2 KB · C++
RawDownload
/*----------------------------------------------------------------------------  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, compiling it and spork it as a child shred of the current 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:...\", compiling it and spork it as a child shred of the current 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:...\", compiling it and sporking 'count' instances as a child shreds of the current 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;}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t