/*---------------------------------------------------------------------------- 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: chuck_vm.cpp// desc: chuck virtual machine//// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)// date: Autumn 2002//-----------------------------------------------------------------------------#include "chuck_vm.h"#include "chuck_instr.h"#include "chuck_lang.h"#include "chuck_type.h"#include "chuck_dl.h"#include "chuck_globals.h" // added 1.4.1.0 (jack)#include "chuck_errmsg.h" #ifndef __DISABLE_SERIAL__#include "chuck_io.h"#endif #include "ugen_xxx.h"#include "util_buffers.h" #ifndef __DISABLE_HID__#include "hidio_sdl.h" // 1.4.0.0#endif #ifndef __DISABLE_MIDI__#include "midiio_rtmidi.h" // 1.4.1.0#endif #include <algorithm>using namespace std; #if defined(__PLATFORM_WIN32__) #ifndef __CHUNREAL_ENGINE__ #include <windows.h> #else // 1.5.0.0 (ge) | #chunreal #include "Windows/MinWindows.h" #endif // #ifndef __CHUNREAL_ENGINE__#else #include <unistd.h> #include <pthread.h>#endif // #if defined(__PLATFORM_WIN32__) // uncomment to compile VM debug messages#define CK_VM_DEBUG_ENABLE (0) #if CK_VM_DEBUG_ENABLE#define CK_VM_DEBUG(x) x#include <typeinfo>#else#define CK_VM_DEBUG(x)#endif // CK_VM_DEBUG_ENABLE //-----------------------------------------------------------------------------// name: struct Chuck_VM_Frame// desc: func frame//-----------------------------------------------------------------------------struct Chuck_VM_Frame{public: t_CKUINT size; public: Chuck_VM_Frame() { size = 0; } ~Chuck_VM_Frame() { }}; //-----------------------------------------------------------------------------// name: struct Chuck_VM_Func// desc: vm function//-----------------------------------------------------------------------------struct Chuck_VM_Func{public: Chuck_VM_Code * code; Chuck_VM_Frame * frame; t_CKUINT index; public: Chuck_VM_Func() { code = NULL; frame = NULL; index = 0; } ~Chuck_VM_Func() { }}; //-----------------------------------------------------------------------------// name: struct Chuck_VM_FTable// desc: function table//-----------------------------------------------------------------------------struct Chuck_VM_FTable{public: Chuck_VM_FTable(); ~Chuck_VM_FTable(); public: Chuck_VM_Func * get_func( t_CKUINT index ); t_CKUINT append( Chuck_VM_Func * f ); t_CKBOOL remove( t_CKUINT index ); public: vector<Chuck_VM_Func *> func_table;}; //-----------------------------------------------------------------------------// name: Chuck_VM()// desc: ...//-----------------------------------------------------------------------------Chuck_VM::Chuck_VM(){ // REFACTOR-2017: refs m_carrier = NULL; // data m_shreds = NULL; m_num_shreds = 0; m_shreduler = NULL; m_num_dumped_shreds = 0; m_globals_manager = NULL; // 1.4.1.0 (jack) m_msg_buffer = NULL; m_reply_buffer = NULL; m_event_buffer = NULL; m_shred_id = 0; m_halt = TRUE; m_dac = NULL; m_adc = NULL; m_bunghole = NULL; m_srate = 0; m_num_dac_channels = 0; m_num_adc_channels = 0; m_init = FALSE; m_input_ref = NULL; m_output_ref = NULL; m_current_buffer_frames = 0;} //-----------------------------------------------------------------------------// name: ~Chuck_VM()// desc: ...//-----------------------------------------------------------------------------Chuck_VM::~Chuck_VM(){ // check if init if( m_init ) { // cleanup shutdown(); }} //-----------------------------------------------------------------------------// name: initialize()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL Chuck_VM::initialize( t_CKUINT srate, t_CKUINT dac_chan, t_CKUINT adc_chan, t_CKUINT adaptive, t_CKBOOL halt ){ if( m_init ) { m_last_error = "VM already initialized!"; return FALSE; } // log EM_log( CK_LOG_SYSTEM, "initializing virtual machine..." ); EM_pushlog(); // push stack m_halt = halt; m_num_adc_channels = adc_chan; m_num_dac_channels = dac_chan; m_srate = srate; // lockdown Chuck_VM_Object::lock_all(); // log EM_log( CK_LOG_SYSTEM, "allocating shreduler..." ); // allocate shreduler m_shreduler = new Chuck_VM_Shreduler; m_shreduler->vm_ref = this; m_shreduler->set_adaptive( adaptive > 0 ? adaptive : 0 ); // log EM_log( CK_LOG_SYSTEM, "allocating messaging buffers..." ); // allocate msg buffer m_msg_buffer = new CBufferSimple; m_msg_buffer->initialize( 1024, sizeof(Chuck_Msg *) ); //m_msg_buffer->join(); // this should return 0 m_reply_buffer = new CBufferSimple; m_reply_buffer->initialize( 1024, sizeof(Chuck_Msg *) ); //m_reply_buffer->join(); // this should return 0 too m_event_buffer = new CBufferSimple; m_event_buffer->initialize( 1024, sizeof(Chuck_Event *) ); //m_event_buffer->join(); // this should also return 0 // 1.4.1.0 (jack): added globals manager EM_log( CK_LOG_SYSTEM, "allocating globals manager..." ); m_globals_manager = new Chuck_Globals_Manager( this ); // pop log EM_poplog(); // TODO: clean up all the dynamic objects here on failure // and in the shutdown function! return m_init = TRUE;} //-----------------------------------------------------------------------------// name: initialize_synthesis()// desc: requires type system//-----------------------------------------------------------------------------t_CKBOOL Chuck_VM::initialize_synthesis( ){ if( !m_init ) { m_last_error = "VM initialize_synthesis() called on raw VM"; return FALSE; } if( !env()->t_dac || !env()->t_adc ) { m_last_error = "VM initialize_synthesis() called before type system initialized"; return FALSE; } if( m_dac != NULL ) { m_last_error = "VM synthesis already initialized"; return FALSE; } // log EM_log( CK_LOG_SEVERE, "initializing 'dac'..." ); // allocate dac and adc (REFACTOR-2017: g_t_dac changed to env()->t_dac) env()->t_dac->ugen_info->num_outs = env()->t_dac->ugen_info->num_ins = m_num_dac_channels; m_dac = (Chuck_UGen *)instantiate_and_initialize_object( env()->t_dac, this ); // Chuck_DL_Api::Api::instance() added 1.3.0.0 object_ctor( m_dac, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); // TODO: this can't be the place to do this stereo_ctor( m_dac, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); // TODO: is the NULL shred a problem? multi_ctor( m_dac, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); // TODO: remove and let type system do this m_dac->add_ref(); // lock it m_dac->lock(); // log EM_log( CK_LOG_SEVERE, "initializing 'adc'..." ); // (REFACTOR-2017: g_t_adc changed to env()->t_adc) env()->t_adc->ugen_info->num_ins = env()->t_adc->ugen_info->num_outs = m_num_adc_channels; m_adc = (Chuck_UGen *)instantiate_and_initialize_object( env()->t_adc, this ); // Chuck_DL_Api::Api::instance() added 1.3.0.0 object_ctor( m_adc, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); // TODO: this can't be the place to do this stereo_ctor( m_adc, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); multi_ctor( m_adc, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); // TODO: remove and let type system do this m_adc->add_ref(); // lock it m_adc->lock(); // log EM_log( CK_LOG_SEVERE, "initializing 'blackhole'..." ); m_bunghole = new Chuck_UGen; m_bunghole->add_ref(); m_bunghole->lock(); initialize_object( m_bunghole, env()->t_ugen ); m_bunghole->tick = NULL; m_bunghole->alloc_v( m_shreduler->m_max_block_size ); m_shreduler->m_dac = m_dac; m_shreduler->m_adc = m_adc; m_shreduler->m_bunghole = m_bunghole; m_shreduler->m_num_dac_channels = m_num_dac_channels; m_shreduler->m_num_adc_channels = m_num_adc_channels; return TRUE;} //-----------------------------------------------------------------------------// name: shutdown()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL Chuck_VM::shutdown(){ // make sure we are in the initialized state if( !m_init ) return FALSE; // log EM_log( CK_LOG_SYSTEM, "shutting down virtual machine..." ); // push indent EM_pushlog(); // unlockdown // REFACTOR-2017: TODO: don't unlock all objects for all VMs? see relockdown below Chuck_VM_Object::unlock_all(); // REFACTOR-2017: clean up after my global variables m_globals_manager->cleanup_global_variables(); SAFE_DELETE( m_globals_manager ); // log EM_log( CK_LOG_SYSTEM, "freeing shreduler..." ); // free the shreduler SAFE_DELETE( m_shreduler ); #ifndef __DISABLE_HID__ // log EM_log( CK_LOG_SYSTEM, "unregistering VM from HID manager..." ); // clean up this vm HidInManager::cleanup_buffer( this ); #endif #ifndef __DISABLE_MIDI__ EM_log( CK_LOG_SYSTEM, "unregistering VM from MIDI manager..." ); MidiInManager::cleanup_buffer( this ); #endif // log EM_log( CK_LOG_SYSTEM, "freeing msg/reply/event buffers..." ); // free the msg buffer SAFE_DELETE( m_msg_buffer ); // free the reply buffer SAFE_DELETE( m_reply_buffer ); // free the event buffer SAFE_DELETE( m_event_buffer ); // log EM_log( CK_LOG_SEVERE, "clearing shreds..." ); // terminate shreds Chuck_VM_Shred * curr = m_shreds, * prev = NULL; while( curr ) { prev = curr; curr = curr->next; // release shred prev->release(); } m_shreds = NULL; m_num_shreds = 0; // log EM_pushlog(); EM_log( CK_LOG_SEVERE, "freeing dumped shreds..." ); // do it this->release_dump(); EM_poplog(); // log EM_log( CK_LOG_SYSTEM, "freeing special ugens..." ); // go SAFE_RELEASE( m_dac ); SAFE_RELEASE( m_adc ); SAFE_RELEASE( m_bunghole ); // set state m_init = FALSE; // relockdown (added 1.3.6.0) // REFACTOR-2017: TODO -- remove once made per-VM Chuck_VM_Object::lock_all(); // log EM_log( CK_LOG_SYSTEM, "virtual machine shutdown complete." ); // pop indent EM_poplog(); return TRUE;} //-----------------------------------------------------------------------------// name: start()// desc: run start (can be called before or after init)//-----------------------------------------------------------------------------t_CKBOOL Chuck_VM::start(){ // already running? if( m_is_running) return FALSE; // set state m_is_running = TRUE; // done return TRUE;} //-----------------------------------------------------------------------------// name: running()// desc: get run state//-----------------------------------------------------------------------------t_CKBOOL Chuck_VM::running(){ return m_is_running;} //-----------------------------------------------------------------------------// name: stop()// desc: run stop//-----------------------------------------------------------------------------t_CKBOOL Chuck_VM::stop(){ // running? if( !m_is_running ) return FALSE; // set state m_is_running = FALSE; // done return TRUE;} //-----------------------------------------------------------------------------// name: compute()// desc: compute all shreds at one instance in ChucK time//-----------------------------------------------------------------------------t_CKBOOL Chuck_VM::compute(){ Chuck_VM_Shred *& shred = m_shreduler->m_current_shred; Chuck_Msg * msg = NULL; Chuck_Event * event = NULL; t_CKBOOL iterate = TRUE; // REFACTOR-2017: spork queued shreds, handle global messages // this is called once per chuck time / sample / "tick" // global manager added 1.4.1.0 (jack) m_globals_manager->handle_global_queue_messages(); // iterate until no more shreds/events/messages while( iterate ) { // get the shreds queued for 'now' shred = m_shreduler->get(); // run all shreds waiting to run 'now' while( shred != NULL ) { // set the current time of the shred shred->now = shred->wake_time; // track shred activation CK_TRACK( Chuck_Stats::instance()->activate_shred( shred ) ); // run the shred // 1.5.0.0 (ge) add check for shred->is_done, which flags a shred to exit if( shred->is_done || !shred->run( this ) ) {Lines 1–500 of 2473. Load more
/*---------------------------------------------------------------------------- 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: chuck_vm.cpp // desc: chuck virtual machine // // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #include "chuck_vm.h" #include "chuck_instr.h" #include "chuck_lang.h" #include "chuck_type.h" #include "chuck_dl.h" #include "chuck_globals.h" // added 1.4.1.0 (jack) #include "chuck_errmsg.h" #ifndef __DISABLE_SERIAL__ #include "chuck_io.h" #endif #include "ugen_xxx.h" #include "util_buffers.h" #ifndef __DISABLE_HID__ #include "hidio_sdl.h" // 1.4.0.0 #endif #ifndef __DISABLE_MIDI__ #include "midiio_rtmidi.h" // 1.4.1.0 #endif #include <algorithm> using namespace std; #if defined(__PLATFORM_WIN32__) #ifndef __CHUNREAL_ENGINE__ #include <windows.h> #else // 1.5.0.0 (ge) | #chunreal #include "Windows/MinWindows.h" #endif // #ifndef __CHUNREAL_ENGINE__ #else #include <unistd.h> #include <pthread.h> #endif // #if defined(__PLATFORM_WIN32__) // uncomment to compile VM debug messages #define CK_VM_DEBUG_ENABLE (0) #if CK_VM_DEBUG_ENABLE #define CK_VM_DEBUG(x) x #include <typeinfo> #else #define CK_VM_DEBUG(x) #endif // CK_VM_DEBUG_ENABLE //----------------------------------------------------------------------------- // name: struct Chuck_VM_Frame // desc: func frame //----------------------------------------------------------------------------- struct Chuck_VM_Frame { public: t_CKUINT size; public: Chuck_VM_Frame() { size = 0; } ~Chuck_VM_Frame() { } }; //----------------------------------------------------------------------------- // name: struct Chuck_VM_Func // desc: vm function //----------------------------------------------------------------------------- struct Chuck_VM_Func { public: Chuck_VM_Code * code; Chuck_VM_Frame * frame; t_CKUINT index; public: Chuck_VM_Func() { code = NULL; frame = NULL; index = 0; } ~Chuck_VM_Func() { } }; //----------------------------------------------------------------------------- // name: struct Chuck_VM_FTable // desc: function table //----------------------------------------------------------------------------- struct Chuck_VM_FTable { public: Chuck_VM_FTable(); ~Chuck_VM_FTable(); public: Chuck_VM_Func * get_func( t_CKUINT index ); t_CKUINT append( Chuck_VM_Func * f ); t_CKBOOL remove( t_CKUINT index ); public: vector<Chuck_VM_Func *> func_table; }; //----------------------------------------------------------------------------- // name: Chuck_VM() // desc: ... //----------------------------------------------------------------------------- Chuck_VM::Chuck_VM() { // REFACTOR-2017: refs m_carrier = NULL; // data m_shreds = NULL; m_num_shreds = 0; m_shreduler = NULL; m_num_dumped_shreds = 0; m_globals_manager = NULL; // 1.4.1.0 (jack) m_msg_buffer = NULL; m_reply_buffer = NULL; m_event_buffer = NULL; m_shred_id = 0; m_halt = TRUE; m_dac = NULL; m_adc = NULL; m_bunghole = NULL; m_srate = 0; m_num_dac_channels = 0; m_num_adc_channels = 0; m_init = FALSE; m_input_ref = NULL; m_output_ref = NULL; m_current_buffer_frames = 0; } //----------------------------------------------------------------------------- // name: ~Chuck_VM() // desc: ... //----------------------------------------------------------------------------- Chuck_VM::~Chuck_VM() { // check if init if( m_init ) { // cleanup shutdown(); } } //----------------------------------------------------------------------------- // name: initialize() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::initialize( t_CKUINT srate, t_CKUINT dac_chan, t_CKUINT adc_chan, t_CKUINT adaptive, t_CKBOOL halt ) { if( m_init ) { m_last_error = "VM already initialized!"; return FALSE; } // log EM_log( CK_LOG_SYSTEM, "initializing virtual machine..." ); EM_pushlog(); // push stack m_halt = halt; m_num_adc_channels = adc_chan; m_num_dac_channels = dac_chan; m_srate = srate; // lockdown Chuck_VM_Object::lock_all(); // log EM_log( CK_LOG_SYSTEM, "allocating shreduler..." ); // allocate shreduler m_shreduler = new Chuck_VM_Shreduler; m_shreduler->vm_ref = this; m_shreduler->set_adaptive( adaptive > 0 ? adaptive : 0 ); // log EM_log( CK_LOG_SYSTEM, "allocating messaging buffers..." ); // allocate msg buffer m_msg_buffer = new CBufferSimple; m_msg_buffer->initialize( 1024, sizeof(Chuck_Msg *) ); //m_msg_buffer->join(); // this should return 0 m_reply_buffer = new CBufferSimple; m_reply_buffer->initialize( 1024, sizeof(Chuck_Msg *) ); //m_reply_buffer->join(); // this should return 0 too m_event_buffer = new CBufferSimple; m_event_buffer->initialize( 1024, sizeof(Chuck_Event *) ); //m_event_buffer->join(); // this should also return 0 // 1.4.1.0 (jack): added globals manager EM_log( CK_LOG_SYSTEM, "allocating globals manager..." ); m_globals_manager = new Chuck_Globals_Manager( this ); // pop log EM_poplog(); // TODO: clean up all the dynamic objects here on failure // and in the shutdown function! return m_init = TRUE; } //----------------------------------------------------------------------------- // name: initialize_synthesis() // desc: requires type system //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::initialize_synthesis( ) { if( !m_init ) { m_last_error = "VM initialize_synthesis() called on raw VM"; return FALSE; } if( !env()->t_dac || !env()->t_adc ) { m_last_error = "VM initialize_synthesis() called before type system initialized"; return FALSE; } if( m_dac != NULL ) { m_last_error = "VM synthesis already initialized"; return FALSE; } // log EM_log( CK_LOG_SEVERE, "initializing 'dac'..." ); // allocate dac and adc (REFACTOR-2017: g_t_dac changed to env()->t_dac) env()->t_dac->ugen_info->num_outs = env()->t_dac->ugen_info->num_ins = m_num_dac_channels; m_dac = (Chuck_UGen *)instantiate_and_initialize_object( env()->t_dac, this ); // Chuck_DL_Api::Api::instance() added 1.3.0.0 object_ctor( m_dac, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); // TODO: this can't be the place to do this stereo_ctor( m_dac, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); // TODO: is the NULL shred a problem? multi_ctor( m_dac, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); // TODO: remove and let type system do this m_dac->add_ref(); // lock it m_dac->lock(); // log EM_log( CK_LOG_SEVERE, "initializing 'adc'..." ); // (REFACTOR-2017: g_t_adc changed to env()->t_adc) env()->t_adc->ugen_info->num_ins = env()->t_adc->ugen_info->num_outs = m_num_adc_channels; m_adc = (Chuck_UGen *)instantiate_and_initialize_object( env()->t_adc, this ); // Chuck_DL_Api::Api::instance() added 1.3.0.0 object_ctor( m_adc, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); // TODO: this can't be the place to do this stereo_ctor( m_adc, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); multi_ctor( m_adc, NULL, this, NULL, Chuck_DL_Api::Api::instance() ); // TODO: remove and let type system do this m_adc->add_ref(); // lock it m_adc->lock(); // log EM_log( CK_LOG_SEVERE, "initializing 'blackhole'..." ); m_bunghole = new Chuck_UGen; m_bunghole->add_ref(); m_bunghole->lock(); initialize_object( m_bunghole, env()->t_ugen ); m_bunghole->tick = NULL; m_bunghole->alloc_v( m_shreduler->m_max_block_size ); m_shreduler->m_dac = m_dac; m_shreduler->m_adc = m_adc; m_shreduler->m_bunghole = m_bunghole; m_shreduler->m_num_dac_channels = m_num_dac_channels; m_shreduler->m_num_adc_channels = m_num_adc_channels; return TRUE; } //----------------------------------------------------------------------------- // name: shutdown() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::shutdown() { // make sure we are in the initialized state if( !m_init ) return FALSE; // log EM_log( CK_LOG_SYSTEM, "shutting down virtual machine..." ); // push indent EM_pushlog(); // unlockdown // REFACTOR-2017: TODO: don't unlock all objects for all VMs? see relockdown below Chuck_VM_Object::unlock_all(); // REFACTOR-2017: clean up after my global variables m_globals_manager->cleanup_global_variables(); SAFE_DELETE( m_globals_manager ); // log EM_log( CK_LOG_SYSTEM, "freeing shreduler..." ); // free the shreduler SAFE_DELETE( m_shreduler ); #ifndef __DISABLE_HID__ // log EM_log( CK_LOG_SYSTEM, "unregistering VM from HID manager..." ); // clean up this vm HidInManager::cleanup_buffer( this ); #endif #ifndef __DISABLE_MIDI__ EM_log( CK_LOG_SYSTEM, "unregistering VM from MIDI manager..." ); MidiInManager::cleanup_buffer( this ); #endif // log EM_log( CK_LOG_SYSTEM, "freeing msg/reply/event buffers..." ); // free the msg buffer SAFE_DELETE( m_msg_buffer ); // free the reply buffer SAFE_DELETE( m_reply_buffer ); // free the event buffer SAFE_DELETE( m_event_buffer ); // log EM_log( CK_LOG_SEVERE, "clearing shreds..." ); // terminate shreds Chuck_VM_Shred * curr = m_shreds, * prev = NULL; while( curr ) { prev = curr; curr = curr->next; // release shred prev->release(); } m_shreds = NULL; m_num_shreds = 0; // log EM_pushlog(); EM_log( CK_LOG_SEVERE, "freeing dumped shreds..." ); // do it this->release_dump(); EM_poplog(); // log EM_log( CK_LOG_SYSTEM, "freeing special ugens..." ); // go SAFE_RELEASE( m_dac ); SAFE_RELEASE( m_adc ); SAFE_RELEASE( m_bunghole ); // set state m_init = FALSE; // relockdown (added 1.3.6.0) // REFACTOR-2017: TODO -- remove once made per-VM Chuck_VM_Object::lock_all(); // log EM_log( CK_LOG_SYSTEM, "virtual machine shutdown complete." ); // pop indent EM_poplog(); return TRUE; } //----------------------------------------------------------------------------- // name: start() // desc: run start (can be called before or after init) //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::start() { // already running? if( m_is_running) return FALSE; // set state m_is_running = TRUE; // done return TRUE; } //----------------------------------------------------------------------------- // name: running() // desc: get run state //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::running() { return m_is_running; } //----------------------------------------------------------------------------- // name: stop() // desc: run stop //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::stop() { // running? if( !m_is_running ) return FALSE; // set state m_is_running = FALSE; // done return TRUE; } //----------------------------------------------------------------------------- // name: compute() // desc: compute all shreds at one instance in ChucK time //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::compute() { Chuck_VM_Shred *& shred = m_shreduler->m_current_shred; Chuck_Msg * msg = NULL; Chuck_Event * event = NULL; t_CKBOOL iterate = TRUE; // REFACTOR-2017: spork queued shreds, handle global messages // this is called once per chuck time / sample / "tick" // global manager added 1.4.1.0 (jack) m_globals_manager->handle_global_queue_messages(); // iterate until no more shreds/events/messages while( iterate ) { // get the shreds queued for 'now' shred = m_shreduler->get(); // run all shreds waiting to run 'now' while( shred != NULL ) { // set the current time of the shred shred->now = shred->wake_time; // track shred activation CK_TRACK( Chuck_Stats::instance()->activate_shred( shred ) ); // run the shred // 1.5.0.0 (ge) add check for shred->is_done, which flags a shred to exit if( shred->is_done || !shred->run( this ) ) {