//----------------------------------------------------------------------------- // name: all_detach() // desc: called during cleanup to close all open file handles //----------------------------------------------------------------------------- extern "C" void all_detach() { // log EM_log( CK_LOG_INFO, "detaching all resources..." ); // push EM_pushlog(); // close stk file handles stk_detach( 0, NULL ); #ifndef __DISABLE_MIDI__ // close midi file handles midirw_detach(); #endif // __DISABLE_MIDI__ #ifndef __DISABLE_KBHIT__ // shutdown kb loop KBHitManager::shutdown(); #endif // __DISABLE_KBHIT__ #ifndef __ALTER_HID__ // shutdown HID HidInManager::cleanup(); #endif // __ALTER_HID__ Chuck_IO_Serial::shutdown(); // pop EM_poplog(); }
void ConsoleWindow::addAlert ( std::string mesg, Color4D col , double b , double e ) { // log EM_log( CK_LOG_INFO, "(audicle) add alert box..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "(audicle) text: %s", mesg.c_str() ); EM_log( CK_LOG_INFO, "(audicle) time: %.3f, %.3f", b, e ); EM_poplog(); AlertBox * a = new AlertBox(mesg); a->setColor( col ); a->setTime( b, e ); _alerts.push_back( a ) ; }
//----------------------------------------------------------------------------- // name: render() // desc: ... //----------------------------------------------------------------------------- t_CKUINT AudicleFaceTnT::render( void * d ) { EM_log( CK_LOG_FINEST, "AudicleFaceTNT: rendering objects..." ); EM_pushlog(); int i; map<Shred_Stat *, Shred_Stat *>::iterator iter; Chuck_Stats::instance()->get_shreds( m_shreds, m_done ); Shred_Stat * stat = NULL; m_now = the()->shreduler()->now_system; m_earliest = m_now - m_window; // set a now time for the check_active test // log EM_log( CK_LOG_FINEST, "num shreds: %d", m_shreds.size() ); // get activations m_drawing_active_set = true; //hack for( i = 0; i < m_shreds.size(); i++ ) fetch_shred_activations ( m_shreds[i] ); m_drawing_active_set = false; //hack for( iter = m_done.begin(); iter != m_done.end(); iter++ ) { stat = (*iter).second; fetch_shred_activations ( stat ); } m_now = the()->shreduler()->now_system; m_earliest = m_now - m_window; EM_poplog(); if ( m_show_mode == SHOW_TIMING_HISTORY ) return render_timing_history(); else return render_cycle_heatmap (); return 0; }
t_CKBOOL client_send_update_info( AudicleClient * source, t_CKUINT user ) { AudiclePak packit; // log EM_log( CK_LOG_INFO, "preparing update info packet (follow up to join request)..." ); // push indent EM_pushlog(); // set type //packit.type = ?; // set user to appropriate value packit.user = user; // set server to "" strcpy( packit.server, "" ); // allocate payload packit.alloc( sizeof( t_CKUINT ) ); // log EM_log( CK_LOG_INFO, "user id: %d", packit.user ); // set length packit.length = 0; // log EM_log( CK_LOG_INFO, "packet length: %d", packit.length ); // pop indent EM_poplog(); EM_log( CK_LOG_INFO, "sending update packet..." ); // send the request if( !source->m_update_socket.send( &packit ) ) { EM_error3( "cannot send update packet! oh no!" ); return FALSE; } return TRUE; }
t_CKUINT client_send_join_request( AudicleClient * source, t_CKINT port ) { AudiclePak packit; // log EM_log( CK_LOG_INFO, "preparing JOIN_REQUEST..." ); // push indent EM_pushlog(); // set type packit.type = JOIN_REQUEST; // set user to 0 packit.user = 0; // set server to "" strcpy( packit.server, "" ); // allocate payload packit.alloc( 372); // get the host name of this machine if( gethostname( packit.data, 256 ) ) { EM_error3( "cannot get my own hostname! what kind of a world do we..." ); return FALSE; } // log EM_log( CK_LOG_INFO, "current hostname: %s", packit.data ); // get port? ? ? - use UDP port of audio receiver memcpy( packit.data + 256, &port, 4 ); // log EM_log( CK_LOG_INFO, "copying UDP port: %d", port ); // ip (maximum 16 bytes) strcpy( packit.data + 260, CoAudicle::instance()->the_ip.c_str() ); // log EM_log( CK_LOG_INFO, "copying ip address: %s", CoAudicle::instance()->the_ip.c_str() ); // user name strcpy( packit.data + 276, source->m_session->user()->username().c_str() ); // log EM_log( CK_LOG_INFO, "copying user name: %s", packit.data + 276 ); // server strcpy( packit.data + 308, source->m_session->server()->host().c_str() ); // TODO (later): check size // log EM_log( CK_LOG_INFO, "copying server: %s", packit.data + 308 ); // set length packit.length = 372; // log EM_log( CK_LOG_INFO, "packet length: %d", packit.length ); // pop indent EM_poplog(); EM_log( CK_LOG_INFO, "sending JOIN_REQUEST packet..." ); // send the request if( !source->send_request( &packit ) ) { EM_error3( "cannot send request packet! oh no!" ); return 0; } // get the answer if( !source->recv_answer( &packit ) ) { EM_error3( "cannot recv answer! nothing works!" ); return 0; } // log EM_log( CK_LOG_INFO, "client received packet (hopefully JOIN_ANSWER)..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "response: %s", packit.data ); EM_log( CK_LOG_INFO, "buffer size: %d", *(t_CKINT *)(packit.data + 80) ); EM_poplog(); return packit.user; }
t_CKBOOL server_handle_join_request( AudiclePak * packit ) { // log EM_log( CK_LOG_INFO, "server discarding JOIN_REQUEST..." ); // push indent EM_pushlog(); // log EM_log( CK_LOG_INFO, "return address: %s", packit->data ); EM_log( CK_LOG_INFO, "return UDP port: %d", *(t_CKINT *)(packit->data + 256) ); EM_log( CK_LOG_INFO, "return ip: %s", packit->data + 260 ); // pop indent EM_poplog(); // id static t_CKUINT id = 0; // set answer AudiclePak answer; answer.type = JOIN_ANSWER; answer.user = ++id; // create_new_user(); strcpy( answer.server, "an arbitrary string" ); answer.alloc( 84 ); answer.length = 84; strcpy( answer.data, "accept" ); (*(t_CKUINT *)(answer.data + 80)) = CO_BUFFER_SIZE; // create session CoCoSession * session = new CoCoSession; session->m_request_socket = packit->sender; // check session->m_user_id = answer.user; session->m_ip = packit->data + 260; session->m_user_name = packit->data + 276; session->m_host_name = packit->data + 308; // session->m_wm = ; // session->m_state = ; // session->m_bindle = ; // send join answer packit->sender->send( &answer ); // notify other users of new user AudiclePak new_user; new_user.type = HEY_USER_ADD; new_user.alloc( 100 ); new_user.length = 100; EM_log (CK_LOG_SYSTEM, "BROADCAST new user %d", session->m_user_id ); // copy user id and user name and host name *((t_CKUINT *)new_user.data) = htonl( session->m_user_id ); strcpy( new_user.data + 4, session->m_user_name.c_str() ); strcpy( new_user.data + 36, session->m_host_name.c_str() ); // broadcast packet CoAudicle::instance()->coco_server.broadcast( &new_user ); // add the new session CoAudicle::instance()->coco_server.add( session ); return TRUE; }
extern "C" int chuck_main( int argc, const char ** argv ) #endif { Chuck_Compiler * compiler = NULL; Chuck_VM * vm = NULL; Chuck_VM_Code * code = NULL; Chuck_VM_Shred * shred = NULL; t_CKBOOL enable_audio = TRUE; t_CKBOOL vm_halt = TRUE; t_CKUINT srate = SAMPLING_RATE_DEFAULT; t_CKUINT buffer_size = BUFFER_SIZE_DEFAULT; t_CKUINT num_buffers = NUM_BUFFERS_DEFAULT; t_CKUINT dac = 0; t_CKUINT adc = 0; t_CKUINT dac_chans = 2; t_CKUINT adc_chans = 2; t_CKBOOL dump = FALSE; t_CKBOOL probe = FALSE; t_CKBOOL set_priority = FALSE; t_CKBOOL auto_depend = FALSE; t_CKBOOL block = FALSE; t_CKBOOL enable_shell = FALSE; t_CKBOOL no_vm = FALSE; t_CKBOOL load_hid = FALSE; t_CKBOOL enable_server = TRUE; t_CKBOOL do_watchdog = TRUE; t_CKINT adaptive_size = 0; t_CKINT log_level = CK_LOG_CORE; t_CKINT deprecate_level = 1; // warn string filename = ""; vector<string> args; #if defined(__DISABLE_WATCHDOG__) do_watchdog = FALSE; #elif defined(__MACOSX_CORE__) do_watchdog = TRUE; #elif defined(__PLATFORM_WIN32__) && !defined(__WINDOWS_PTHREAD__) do_watchdog = TRUE; #else do_watchdog = FALSE; #endif t_CKUINT files = 0; t_CKUINT count = 1; t_CKINT i; // set log level EM_setlog( log_level ); // parse command line args for( i = 1; i < argc; i++ ) { if( argv[i][0] == '-' || argv[i][0] == '+' || argv[i][0] == '=' || argv[i][0] == '^' || argv[i][0] == '@' ) { if( !strcmp(argv[i], "--dump") || !strcmp(argv[i], "+d") || !strcmp(argv[i], "--nodump") || !strcmp(argv[i], "-d") ) continue; else if( get_count( argv[i], &count ) ) continue; else if( !strcmp(argv[i], "--audio") || !strcmp(argv[i], "-a") ) enable_audio = TRUE; else if( !strcmp(argv[i], "--silent") || !strcmp(argv[i], "-s") ) enable_audio = FALSE; else if( !strcmp(argv[i], "--halt") || !strcmp(argv[i], "-t") ) vm_halt = TRUE; else if( !strcmp(argv[i], "--loop") || !strcmp(argv[i], "-l") ) { vm_halt = FALSE; enable_server = TRUE; } else if( !strcmp(argv[i], "--server") ) enable_server = TRUE; else if( !strcmp(argv[i], "--standalone") ) enable_server = FALSE; else if( !strcmp(argv[i], "--callback") ) block = FALSE; else if( !strcmp(argv[i], "--blocking") ) block = TRUE; else if( !strcmp(argv[i], "--hid") ) load_hid = TRUE; else if( !strcmp(argv[i], "--shell") || !strcmp( argv[i], "-e" ) ) { enable_shell = TRUE; vm_halt = FALSE; } else if( !strcmp(argv[i], "--empty") ) no_vm = TRUE; else if( !strncmp(argv[i], "--srate", 7) ) srate = atoi( argv[i]+7 ) > 0 ? atoi( argv[i]+7 ) : srate; else if( !strncmp(argv[i], "-r", 2) ) srate = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : srate; else if( !strncmp(argv[i], "--bufsize", 9) ) buffer_size = atoi( argv[i]+9 ) > 0 ? atoi( argv[i]+9 ) : buffer_size; else if( !strncmp(argv[i], "-b", 2) ) buffer_size = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : buffer_size; else if( !strncmp(argv[i], "--bufnum", 8) ) num_buffers = atoi( argv[i]+8 ) > 0 ? atoi( argv[i]+8 ) : num_buffers; else if( !strncmp(argv[i], "-n", 2) ) num_buffers = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : num_buffers; else if( !strncmp(argv[i], "--dac", 5) ) dac = atoi( argv[i]+5 ) > 0 ? atoi( argv[i]+5 ) : 0; else if( !strncmp(argv[i], "--adc", 5) ) adc = atoi( argv[i]+5 ) > 0 ? atoi( argv[i]+5 ) : 0; else if( !strncmp(argv[i], "--channels", 10) ) dac_chans = adc_chans = atoi( argv[i]+10 ) > 0 ? atoi( argv[i]+10 ) : 2; else if( !strncmp(argv[i], "-c", 2) ) dac_chans = adc_chans = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : 2; else if( !strncmp(argv[i], "--out", 5) ) dac_chans = atoi( argv[i]+5 ) > 0 ? atoi( argv[i]+5 ) : 2; else if( !strncmp(argv[i], "-o", 2) ) dac_chans = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : 2; else if( !strncmp(argv[i], "--in", 4) ) adc_chans = atoi( argv[i]+4 ) > 0 ? atoi( argv[i]+4 ) : 2; else if( !strncmp(argv[i], "-i", 2) ) adc_chans = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : 2; else if( !strncmp(argv[i], "--level", 7) ) { g_priority = atoi( argv[i]+7 ); set_priority = TRUE; } else if( !strncmp(argv[i], "--watchdog", 10) ) { g_watchdog_timeout = atof( argv[i]+10 ); if( g_watchdog_timeout <= 0 ) g_watchdog_timeout = 0.5; do_watchdog = TRUE; } else if( !strncmp(argv[i], "--nowatchdog", 12) ) do_watchdog = FALSE; else if( !strncmp(argv[i], "--remote", 8) ) strcpy( g_host, argv[i]+8 ); else if( !strncmp(argv[i], "@", 1) ) strcpy( g_host, argv[i]+1 ); else if( !strncmp(argv[i], "--port", 6) ) g_port = atoi( argv[i]+6 ); else if( !strncmp(argv[i], "-p", 2) ) g_port = atoi( argv[i]+2 ); else if( !strncmp(argv[i], "--auto", 6) ) auto_depend = TRUE; else if( !strncmp(argv[i], "-u", 2) ) auto_depend = TRUE; else if( !strncmp(argv[i], "--log", 5) ) log_level = argv[i][5] ? atoi( argv[i]+5 ) : CK_LOG_INFO; else if( !strncmp(argv[i], "--verbose", 9) ) log_level = argv[i][9] ? atoi( argv[i]+9 ) : CK_LOG_INFO; else if( !strncmp(argv[i], "-v", 2) ) log_level = argv[i][2] ? atoi( argv[i]+2 ) : CK_LOG_INFO; else if( !strncmp(argv[i], "--adaptive", 10) ) adaptive_size = argv[i][10] ? atoi( argv[i]+10 ) : -1; else if( !strncmp(argv[i], "--deprecate", 11) ) { // get the rest string arg = argv[i]+11; if( arg == ":stop" ) deprecate_level = 0; else if( arg == ":warn" ) deprecate_level = 1; else if( arg == ":ignore" ) deprecate_level = 2; else { // error fprintf( stderr, "[chuck]: invalid arguments for '--deprecate'...\n" ); fprintf( stderr, "[chuck]: ... (looking for :stop, :warn, or :ignore)\n" ); exit( 1 ); } } else if( !strcmp( argv[i], "--probe" ) ) probe = TRUE; else if( !strcmp( argv[i], "--poop" ) ) uh(); else if( !strcmp( argv[i], "--caution-to-the-wind" ) ) g_enable_system_cmd = TRUE; else if( !strcmp(argv[i], "--help") || !strcmp(argv[i], "-h") || !strcmp(argv[i], "--about") ) { usage(); exit( 2 ); } else if( !strcmp( argv[i], "--version" ) ) { version(); exit( 2 ); } else { // boost log level g_otf_log = CK_LOG_CORE; // flag int is_otf = FALSE; // log level EM_setlog( log_level ); // do it if( otf_send_cmd( argc, argv, i, g_host, g_port, &is_otf ) ) exit( 0 ); // is otf if( is_otf ) exit( 1 ); // done fprintf( stderr, "[chuck]: invalid flag '%s'\n", argv[i] ); usage(); exit( 1 ); } } else files++; } // log level EM_setlog( log_level ); // probe if( probe ) { Digitalio::probe(); #ifndef __DISABLE_MIDI__ EM_error2b( 0, "" ); probeMidiIn(); EM_error2b( 0, "" ); probeMidiOut(); EM_error2b( 0, "" ); #endif // __DISABLE_MIDI__ // HidInManager::probeHidIn(); // exit exit( 0 ); } // check buffer size buffer_size = ensurepow2( buffer_size ); // check mode and blocking if( !enable_audio && !block ) block = TRUE; // audio, boost if( !set_priority && !block ) g_priority = g_priority_low; if( !set_priority && !enable_audio ) g_priority = 0x7fffffff; // set priority Chuck_VM::our_priority = g_priority; // set watchdog g_do_watchdog = do_watchdog; // set adaptive size if( adaptive_size < 0 ) adaptive_size = buffer_size; if ( !files && vm_halt && !enable_shell ) { fprintf( stderr, "[chuck]: no input files... (try --help)\n" ); exit( 1 ); } // shell initialization without vm if( enable_shell && no_vm ) { // instantiate g_shell = new Chuck_Shell; // initialize if( !init_shell( g_shell, new Chuck_Console, NULL ) ) exit( 1 ); // no vm is needed, just start running the shell now g_shell->run(); // clean up SAFE_DELETE( g_shell ); // done exit( 0 ); } // make sure vm if( no_vm ) { fprintf( stderr, "[chuck]: '--empty' can only be used with shell...\n" ); exit( 1 ); } // allocate the vm - needs the type system vm = g_vm = new Chuck_VM; if( !vm->initialize( enable_audio, vm_halt, srate, buffer_size, num_buffers, dac, adc, dac_chans, adc_chans, block, adaptive_size ) ) { fprintf( stderr, "[chuck]: %s\n", vm->last_error() ); exit( 1 ); } // allocate the compiler compiler = g_compiler = new Chuck_Compiler; // initialize the compiler if( !compiler->initialize( vm ) ) { fprintf( stderr, "[chuck]: error initializing compiler...\n" ); exit( 1 ); } // enable dump compiler->emitter->dump = dump; // set auto depend compiler->set_auto_depend( auto_depend ); // vm synthesis subsystem - needs the type system if( !vm->initialize_synthesis( ) ) { fprintf( stderr, "[chuck]: %s\n", vm->last_error() ); exit( 1 ); } #ifndef __ALTER_HID__ // pre-load hid if( load_hid ) HidInManager::init(); #endif // __ALTER_HID__ // catch SIGINT signal( SIGINT, signal_int ); #ifndef __PLATFORM_WIN32__ // catch SIGPIPE signal( SIGPIPE, signal_pipe ); #endif // shell initialization if( enable_shell ) { // instantiate g_shell = new Chuck_Shell; // initialize if( !init_shell( g_shell, new Chuck_Console, vm ) ) exit( 1 ); } // set deprecate compiler->env->deprecate_level = deprecate_level; // reset count count = 1; // log EM_log( CK_LOG_SEVERE, "starting compilation..." ); // push indent EM_pushlog(); // loop through and process each file for( i = 1; i < argc; i++ ) { // make sure if( argv[i][0] == '-' || argv[i][0] == '+' ) { if( !strcmp(argv[i], "--dump") || !strcmp(argv[i], "+d" ) ) compiler->emitter->dump = TRUE; else if( !strcmp(argv[i], "--nodump") || !strcmp(argv[i], "-d" ) ) compiler->emitter->dump = FALSE; else get_count( argv[i], &count ); continue; } // parse out command line arguments if( !extract_args( argv[i], filename, args ) ) { // error fprintf( stderr, "[chuck]: malformed filename with argument list...\n" ); fprintf( stderr, " --> '%s'", argv[i] ); return 1; } // log EM_log( CK_LOG_FINE, "compiling '%s'...", filename.c_str() ); // push indent EM_pushlog(); // parse, type-check, and emit if( !compiler->go( filename, NULL ) ) return 1; // get the code code = compiler->output(); // name it code->name += string(argv[i]); // log EM_log( CK_LOG_FINE, "sporking %d %s...", count, count == 1 ? "instance" : "instances" ); // spork it while( count-- ) { // spork shred = vm->spork( code, NULL ); // add args shred->args = args; } // pop indent EM_poplog(); // reset count count = 1; } // pop indent EM_poplog(); // reset the parser reset_parse(); // boost priority if( Chuck_VM::our_priority != 0x7fffffff ) { // try if( !Chuck_VM::set_priority( Chuck_VM::our_priority, vm ) ) { // error fprintf( stderr, "[chuck]: %s\n", vm->last_error() ); exit( 1 ); } } // server if( enable_server ) { #ifndef __DISABLE_OTF_SERVER__ // log EM_log( CK_LOG_SYSTEM, "starting listener on port: %d...", g_port ); // start tcp server g_sock = ck_tcp_create( 1 ); if( !g_sock || !ck_bind( g_sock, g_port ) || !ck_listen( g_sock, 10 ) ) { fprintf( stderr, "[chuck]: cannot bind to tcp port %i...\n", g_port ); ck_close( g_sock ); g_sock = NULL; } else { #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) pthread_create( &g_tid_otf, NULL, otf_cb, NULL ); #else g_tid_otf = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)otf_cb, NULL, 0, 0 ); #endif } #endif // __DISABLE_OTF_SERVER__ } else { // log EM_log( CK_LOG_SYSTEM, "OTF server/listener: OFF" ); } // start shell on separate thread if( enable_shell ) { #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) pthread_create( &g_tid_shell, NULL, shell_cb, g_shell ); #else g_tid_shell = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)shell_cb, g_shell, 0, 0 ); #endif } // run the vm vm->run(); // detach all_detach(); // free vm vm = NULL; SAFE_DELETE( g_vm ); // free the compiler compiler = NULL; SAFE_DELETE( g_compiler ); // wait for the shell, if it is running // does the VM reset its priority to normal before exiting? if( enable_shell ) while( g_shell != NULL ) usleep(10000); return 0; }
t_CKBOOL CodeRevision::local_spork( int replace ) { // if ( !compile() ) return 0; // log EM_log( CK_LOG_INFO, "(audicle) performing local spork..." ); // push EM_pushlog(); _status = rev_COMPILED; setVersion(); // log EM_log( CK_LOG_INFO, "(audicle) replace: %s", replace ? "TRUE" : "FALSE" ); Net_Msg msg; // make the message if( replace ) msg.param = replace; // set the type msg.type = replace ? MSG_REPLACE : MSG_ADD; strcpy ( (char*)msg.buffer, "editor->" ); strcat ( (char*)msg.buffer, _buffer->filename().c_str() ); // log EM_log( CK_LOG_INFO, "(audicle) name: %s", (char *)msg.buffer ); // make tmp file #ifdef __PLATFORM_WIN32__ HANDLE hRead, hWrite; int fd_read, fd_write; int code_size = 0, k, code_num_lines = _buffer->nlines(); for( k = 0; k < code_num_lines; k++ ) { code_size += _buffer->line( k ).size(); } code_size += code_num_lines; if( !CreatePipe( &hRead, &hWrite, NULL, code_size ) ) { EM_log( CK_LOG_SEVERE, "(audicle): error in CreatePipe: %d", GetLastError() ); return FALSE; } // WARNING: fails on 64 bit Windows! fd_read = _open_osfhandle( ( long ) hRead, _O_RDONLY ); fd_write = _open_osfhandle( ( long ) hWrite, _O_WRONLY ); FILE * read = _fdopen( fd_read, "r" ); FILE * write = _fdopen( fd_write, "w" ); _buffer->print( write ); fclose( write ); #else if( _tmp_fd ) fclose( _tmp_fd ); _tmp_fd = tmpfile(); _buffer->print( _tmp_fd ); #endif // log EM_log( CK_LOG_INFO, "(audicle) sending SPORK request..." ); // send it #ifdef __PLATFORM_WIN32__ if( !process_msg2( &msg, dothiswhenmsgfinishes, this, read ) ) #else if( !process_msg2( &msg, dothiswhenmsgfinishes, this, _tmp_fd ) ) #endif { // log EM_log( CK_LOG_INFO, "(audicle) return code: failure..." ); // if here, then the message failed already static Color4D errCol( 1.0, 0.8, 0.8, 0.8 ); fprintf( stderr, "[audicle]: error in local spork %s\n", EM_lasterror() ); parseErrorLocation( EM_lasterror() ); WindowManager::addAlert( EM_lasterror(), errCol, 0.0, 10.0 ); // pop EM_poplog(); return FALSE; } // log // EM_log( CK_LOG_INFO, "(audicle) local spork successful..." ); // pop EM_poplog(); return TRUE; }
//----------------------------------------------------------------------------- // name: start_vm() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL miniAudicle::start_vm() { char buffer[1024]; time_t t; // allocate status buffers // allocate alternating buffers for VM status messages num_status_bufs = 4; status_bufs = new Chuck_VM_Status * [num_status_bufs]; for( size_t i = 0; i < num_status_bufs; i++ ) status_bufs[i] = new Chuck_VM_Status; status_bufs_read = 0; status_bufs_write = 0; // clear shred management structures last_result.clear(); while( !otf_docids.empty() ) otf_docids.pop(); map< t_CKUINT, vector< t_CKUINT > * >::iterator iter = documents.begin(), end = documents.end(); for( ; iter != end; iter++ ) iter->second->clear(); shreds.clear(); // clear the class name existence map class_names->clear(); time(&t); strncpy( buffer, ctime(&t), 24 ); buffer[24] = '\0'; // log EM_log( CK_LOG_SYSTEM, "-------( %s )-------", buffer ); EM_log( CK_LOG_SYSTEM, "starting chuck virtual machine..." ); // push log EM_pushlog(); if( m_chuck == NULL ) { // log EM_log( CK_LOG_INFO, "allocating VM..." ); t_CKBOOL enable_audio = vm_options.enable_audio; t_CKBOOL vm_halt = FALSE; t_CKBOOL force_srate = TRUE; t_CKUINT srate = vm_options.srate; t_CKUINT buffer_size = vm_options.buffer_size; t_CKUINT num_buffers = NUM_BUFFERS_DEFAULT; t_CKUINT dac = vm_options.dac; t_CKUINT adc = vm_options.adc; t_CKBOOL set_priority = FALSE; t_CKBOOL block = vm_options.enable_block; t_CKUINT output_channels = vm_options.num_outputs; t_CKUINT input_channels = vm_options.num_inputs; t_CKUINT adaptive_size = 0; // lets make up some magic numbers... vm_sleep_time = vm_options.buffer_size * 1000000 / vm_options.srate; vm_sleep_max = 20; vm_status_timeouts_max = vm_options.buffer_size / 100; vm_status_timeouts = 0; // check buffer size // buffer_size = next_power_2( buffer_size-1 ); // audio, boost if( !set_priority && !block ) priority = priority_low; if( !set_priority && !enable_audio ) priority = 0x7fffffff; // set priority // Chuck_VM::our_priority = priority; // set watchdog #ifdef __MACOSX_CORE__ g_do_watchdog = TRUE; g_watchdog_timeout = .5; #else g_do_watchdog = FALSE; #endif std::list<std::string> library_paths = vm_options.library_paths; std::list<std::string> named_chugins = vm_options.named_chugins; // normalize paths for(std::list<std::string>::iterator i = library_paths.begin(); i != library_paths.end(); i++) *i = expand_filepath(*i); for(std::list<std::string>::iterator j = named_chugins.begin(); j != named_chugins.end(); j++) *j = expand_filepath(*j); m_chuck = new ChucK(); m_chuck->setParam(CHUCK_PARAM_SAMPLE_RATE, srate); m_chuck->setParam(CHUCK_PARAM_INPUT_CHANNELS, input_channels); m_chuck->setParam(CHUCK_PARAM_OUTPUT_CHANNELS, output_channels); m_chuck->setParam(CHUCK_PARAM_VM_ADAPTIVE, adaptive_size); m_chuck->setParam(CHUCK_PARAM_VM_HALT, vm_halt); m_chuck->setParam(CHUCK_PARAM_USER_CHUGINS, named_chugins); m_chuck->setParam(CHUCK_PARAM_USER_CHUGIN_DIRECTORIES, library_paths); if( !m_chuck->init() ) { fprintf( stderr, "[chuck]: failed to init chuck engine\n" ); // pop EM_poplog(); return FALSE; } // allocate the vm - needs the type system vm = m_chuck->vm(); //--------------------------- AUDIO I/O SETUP --------------------------------- // push EM_pushlog(); // log EM_log( CK_LOG_SYSTEM, "probing '%s' audio subsystem...", enable_audio ? "real-time" : "fake-time" ); ChuckAudio::m_dac_n = dac; ChuckAudio::m_adc_n = adc; // probe / init (this shouldn't start audio yet... // moved here 1.3.1.2; to main ge: 1.3.5.3) if( !ChuckAudio::initialize( output_channels, input_channels, srate, buffer_size, num_buffers, audio_cb, m_chuck, force_srate ) ) { EM_log( CK_LOG_SYSTEM, "cannot initialize audio device (use --silent/-s for non-realtime)" ); // pop EM_poplog(); // done return FALSE; } // log EM_log( CK_LOG_SYSTEM, "real-time audio: %s", enable_audio ? "YES" : "NO" ); EM_log( CK_LOG_SYSTEM, "mode: %s", block ? "BLOCKING" : "CALLBACK" ); EM_log( CK_LOG_SYSTEM, "sample rate: %ld", srate ); EM_log( CK_LOG_SYSTEM, "buffer size: %ld", buffer_size ); if( enable_audio ) { EM_log( CK_LOG_SYSTEM, "num buffers: %ld", num_buffers ); EM_log( CK_LOG_SYSTEM, "adc: %ld dac: %d", adc, dac ); EM_log( CK_LOG_SYSTEM, "adaptive block processing: %ld", adaptive_size > 1 ? adaptive_size : 0 ); } EM_log( CK_LOG_SYSTEM, "channels in: %ld out: %ld", input_channels, output_channels ); // pop EM_poplog(); // allocate the compiler compiler = m_chuck->compiler(); #ifdef __MA_IMPORT_MAUI__ // import api init_maui( compiler->env() ); #endif for(list<t_CKBOOL (*)(Chuck_Env *)>::iterator i = vm_options.query_funcs.begin(); i != vm_options.query_funcs.end(); i++) (*i)( compiler->env() ); if(!ChuckAudio::start()) { EM_log( CK_LOG_SYSTEM, "error starting audio (use --silent/-s for non-realtime)" ); // pop EM_poplog(); // done return FALSE; } // pop log EM_poplog(); EM_log( CK_LOG_SYSTEM, "running audio" ); } vm_on = TRUE; // pop EM_poplog(); return vm_on; }
//----------------------------------------------------------------------------- // name: start_vm() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL miniAudicle::start_vm() { char buffer[1024]; time_t t; // allocate status buffers // allocate alternating buffers for VM status messages num_status_bufs = 4; status_bufs = new Chuck_VM_Status * [num_status_bufs]; for( size_t i = 0; i < num_status_bufs; i++ ) status_bufs[i] = new Chuck_VM_Status; status_bufs_read = 0; status_bufs_write = 0; // clear shred management structures last_result.clear(); while( !otf_docids.empty() ) otf_docids.pop(); map< t_CKUINT, vector< t_CKUINT > * >::iterator iter = documents.begin(), end = documents.end(); for( ; iter != end; iter++ ) iter->second->clear(); shreds.clear(); // clear the class name existence map class_names->clear(); time(&t); strncpy( buffer, ctime(&t), 24 ); buffer[24] = '\0'; // log EM_log( CK_LOG_SYSTEM, "-------( %s )-------", buffer ); EM_log( CK_LOG_SYSTEM, "starting chuck virtual machine..." ); // push log EM_pushlog(); if( vm == NULL ) { // log EM_log( CK_LOG_INFO, "allocating VM..." ); t_CKBOOL enable_audio = vm_options.enable_audio; t_CKBOOL vm_halt = FALSE; t_CKUINT srate = vm_options.srate; t_CKUINT buffer_size = vm_options.buffer_size; t_CKUINT num_buffers = NUM_BUFFERS_DEFAULT; t_CKUINT dac = vm_options.dac; t_CKUINT adc = vm_options.adc; t_CKBOOL set_priority = FALSE; t_CKBOOL block = vm_options.enable_block; t_CKUINT output_channels = vm_options.num_outputs; t_CKUINT input_channels = vm_options.num_inputs; // lets make up some magic numbers... vm_sleep_time = vm_options.buffer_size * 1000000 / vm_options.srate; vm_sleep_max = 20; vm_status_timeouts_max = vm_options.buffer_size / 100; vm_status_timeouts = 0; // check buffer size // buffer_size = next_power_2( buffer_size-1 ); // audio, boost if( !set_priority && !block ) priority = priority_low; if( !set_priority && !enable_audio ) priority = 0x7fffffff; // set priority Chuck_VM::our_priority = priority; // set watchdog #ifdef __MACOSX_CORE__ g_do_watchdog = TRUE; g_watchdog_timeout = .5; #else g_do_watchdog = FALSE; #endif // allocate the vm - needs the type system vm = g_vm = new Chuck_VM; if( !vm->initialize( enable_audio, vm_halt, srate, buffer_size, num_buffers, dac, adc, output_channels, input_channels, block ) ) { fprintf( stderr, "[chuck]: %s\n", vm->last_error() ); // pop EM_poplog(); return FALSE; } // log EM_log( CK_LOG_INFO, "allocating compiler..." ); // allocate the compiler g_compiler = compiler = new Chuck_Compiler; std::list<std::string> library_paths = vm_options.library_paths; std::list<std::string> named_chugins = vm_options.named_chugins; // normalize paths for(std::list<std::string>::iterator i = library_paths.begin(); i != library_paths.end(); i++) *i = expand_filepath(*i); for(std::list<std::string>::iterator j = named_chugins.begin(); j != named_chugins.end(); j++) *j = expand_filepath(*j); // initialize the compiler compiler->initialize( vm, library_paths, named_chugins ); // enable dump compiler->emitter->dump = FALSE; // set auto depend compiler->set_auto_depend( FALSE ); // vm synthesis subsystem - needs the type system if( !vm->initialize_synthesis() ) { fprintf( stderr, "[chuck]: %s\n", vm->last_error() ); // pop EM_poplog(); return FALSE; } #ifdef __MA_IMPORT_MAUI__ // import api init_maui( compiler->env ); #endif for(list<t_CKBOOL (*)(Chuck_Env *)>::iterator i = vm_options.query_funcs.begin(); i != vm_options.query_funcs.end(); i++) (*i)( compiler->env ); // reset the parser reset_parse(); Chuck_VM_Code * code = NULL; Chuck_VM_Shred * shred = NULL; // whether or not chug should be enabled (added 1.3.0.0) EM_log( CK_LOG_SEVERE, "pre-loading ChucK libs..." ); EM_pushlog(); // iterate over list of ck files that the compiler found for( std::list<std::string>::iterator fck = compiler->m_cklibs_to_preload.begin(); fck != compiler->m_cklibs_to_preload.end(); fck++) { // the filename std::string filename = *fck; // log EM_log( CK_LOG_SEVERE, "preloading '%s'...", filename.c_str() ); // push indent EM_pushlog(); // SPENCERTODO: what to do for full path std::string full_path = filename; // parse, type-check, and emit if( compiler->go( filename, NULL, NULL, full_path ) ) { // TODO: how to compilation handle? //return 1; // get the code code = compiler->output(); // name it - TODO? // code->name += string(argv[i]); // spork it shred = vm->spork( code, NULL ); } // pop indent EM_poplog(); } // clear the list of chuck files to preload compiler->m_cklibs_to_preload.clear(); // pop log EM_poplog(); // load user namespace compiler->env->load_user_namespace(); // start the vm handler threads #ifndef __PLATFORM_WIN32__ pthread_create( &vm_tid, NULL, vm_cb, NULL ); #else vm_tid = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)vm_cb, NULL, 0, 0 ); #endif } // check it if( !g_forked && vm_options.enable_network ) { // start tcp server g_sock = ck_tcp_create( 1 ); if( !g_sock || !ck_bind( g_sock, g_port ) || !ck_listen( g_sock, 10 ) ) { fprintf( stderr, "[chuck]: cannot bind to tcp port %li...\n", g_port ); ck_close( g_sock ); g_sock = NULL; } else { #ifndef __PLATFORM_WIN32__ pthread_create( &otf_tid, NULL, otf_cb, NULL ); #else otf_tid = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)otf_cb, NULL, 0, 0 ); #endif } g_forked = TRUE; } vm_on = TRUE; // pop EM_poplog(); return vm_on; }
//----------------------------------------------------------------------------- // name: initialize() // desc: ... //----------------------------------------------------------------------------- BOOL__ Digitalio::initialize( DWORD__ num_dac_channels, DWORD__ num_adc_channels, DWORD__ sampling_rate, DWORD__ bps, DWORD__ buffer_size, DWORD__ num_buffers, DWORD__ block, Chuck_VM * vm_ref, BOOL__ rt_audio, void * callback, void * data, BOOL__ force_srate ) { if( m_init ) return FALSE; m_num_channels_out = num_dac_channels; m_num_channels_in = num_adc_channels; m_sampling_rate = sampling_rate; m_bps = bps; m_buffer_size = buffer_size; m_num_buffers = num_buffers; m_start = 0; m_tick_count = 0; m_go = 0; m_end = 0; m_block = block; DWORD__ num_channels; unsigned int bufsize = m_buffer_size; // log EM_log( CK_LOG_FINE, "initializing RtAudio..." ); // push indent EM_pushlog(); // if rt_audio is false, then set block to FALSE to avoid deadlock if( !rt_audio ) m_block = FALSE; #ifndef __DISABLE_RTAUDIO__ // if real-time audio if( rt_audio ) { // allocate RtAudio try { m_rtaudio = new RtAudio( ); } catch( RtError err ) { // problem finding audio devices, most likely EM_error2( 0, "%s", err.getMessage().c_str() ); return m_init = FALSE; } // convert 1-based ordinal to 0-based ordinal (added 1.3.0.0) // note: this is to preserve previous devices numbering after RtAudio change if( m_num_channels_out > 0 ) { // check output device number; 0 used to mean "default" bool useDefault = ( m_dac_n == 0 ); // default (refactor 1.3.1.2) if( useDefault ) { // get the default m_dac_n = m_rtaudio->getDefaultOutputDevice(); } else { m_dac_n -= 1; } // get device info RtAudio::DeviceInfo device_info = m_rtaudio->getDeviceInfo(m_dac_n); // ensure correct channel count if default device is requested if( useDefault ) { // check if( device_info.outputChannels < m_num_channels_out ) { // find first device with at least the requested channel count m_dac_n = -1; int num_devices = m_rtaudio->getDeviceCount(); for( int i = 0; i < num_devices; i++ ) { device_info = m_rtaudio->getDeviceInfo(i); if(device_info.outputChannels >= m_num_channels_out) { m_dac_n = i; break; } } // check for error if( m_dac_n == -1 ) { EM_error2( 0, "no audio output device with requested channel count (%i)...", m_num_channels_out ); return m_init = FALSE; } } } // index of closest sample rate long closestIndex = -1; // difference of closest so far long closestDiff = LONG_MAX; // the next highest long nextHighest = -1; // diff to next highest so far long diffToNextHighest = LONG_MAX; // check if request sample rate in support rates (added 1.3.1.2) for( long i = 0; i < device_info.sampleRates.size(); i++ ) { // difference long diff = device_info.sampleRates[i] - sampling_rate; // check // ge: changed from abs to labs, 2015.11 if( ::labs(diff) < closestDiff ) { // remember index closestIndex = i; // update diff closestDiff = ::labs(diff); } // for next highest if( diff > 0 && diff < diffToNextHighest ) { // remember index nextHighest = i; // update diff diffToNextHighest = diff; } } // see if we found exact match (added 1.3.1.2) if( closestDiff != 0 ) { // check if( force_srate ) { // request sample rate not found, error out EM_error2( 0, "unsupported sample rate (%d) requested...", sampling_rate ); EM_error2( 0, "| (try --probe to enumerate available sample rates)" ); return m_init = FALSE; } // use next highest if available if( nextHighest >= 0 ) { // log EM_log( CK_LOG_SEVERE, "new sample rate (next highest): %d -> %d", sampling_rate, device_info.sampleRates[nextHighest] ); // update sampling rate m_sampling_rate = sampling_rate = device_info.sampleRates[nextHighest]; } else if( closestIndex >= 0 ) // nothing higher { // log EM_log( CK_LOG_SEVERE, "new sample rate (closest): %d -> %d", sampling_rate, device_info.sampleRates[closestIndex] ); // update sampling rate m_sampling_rate = sampling_rate = device_info.sampleRates[closestIndex]; } else { // nothing to do (will fail and throw error message when opening) } } } // convert 1-based ordinal to 0-based ordinal if( m_num_channels_in > 0 ) { if( m_adc_n == 0 ) { m_adc_n = m_rtaudio->getDefaultInputDevice(); // ensure correct channel count if default device is requested RtAudio::DeviceInfo device_info = m_rtaudio->getDeviceInfo(m_adc_n); // check if input channels > 0 if( device_info.inputChannels < m_num_channels_in ) { // find first device with at least the requested channel count m_adc_n = -1; int num_devices = m_rtaudio->getDeviceCount(); for(int i = 0; i < num_devices; i++) { device_info = m_rtaudio->getDeviceInfo(i); if(device_info.inputChannels >= m_num_channels_in) { m_adc_n = i; break; } } // changed 1.3.1.2 (ge): for input, if nothing found, we just gonna try to open half-duplex if( m_adc_n == -1 ) { // set to 0 m_num_channels_in = 0; // problem finding audio devices, most likely // EM_error2( 0, "unable to find audio input device with requested channel count (%i)...", m_num_channels_in); // return m_init = FALSE; } } } else { m_adc_n -= 1; } } // open device try { // log EM_log( CK_LOG_FINE, "trying %d input %d output...", m_num_channels_in, m_num_channels_out ); RtAudio::StreamParameters output_parameters; output_parameters.deviceId = m_dac_n; output_parameters.nChannels = m_num_channels_out; output_parameters.firstChannel = 0; RtAudio::StreamParameters input_parameters; input_parameters.deviceId = m_adc_n; input_parameters.nChannels = m_num_channels_in; input_parameters.firstChannel = 0; RtAudio::StreamOptions stream_options; stream_options.flags = 0; stream_options.numberOfBuffers = num_buffers; stream_options.streamName = "ChucK"; stream_options.priority = 0; // open RtAudio m_rtaudio->openStream( m_num_channels_out > 0 ? &output_parameters : NULL, m_num_channels_in > 0 ? &input_parameters : NULL, CK_RTAUDIO_FORMAT, sampling_rate, &bufsize, m_use_cb ? ( block ? &cb : &cb2 ) : NULL, vm_ref, &stream_options ); } catch( RtError err ) { // log EM_log( CK_LOG_INFO, "exception caught: '%s'...", err.getMessage().c_str() ); EM_error2( 0, "%s", err.getMessage().c_str() ); SAFE_DELETE( m_rtaudio ); return m_init = FALSE; } // check bufsize if( bufsize != (int)m_buffer_size ) { EM_log( CK_LOG_SEVERE, "new buffer size: %d -> %i", m_buffer_size, bufsize ); m_buffer_size = bufsize; } // pop indent EM_poplog(); } #endif // __DISABLE_RTAUDIO__ #if defined(__CHIP_MODE__) if( !MoAudio::init( sampling_rate, buffer_size, 2 ) ) { EM_error2( 0, "%s", "(chuck)error: unable to initialize MoAudio..." ); return m_init = FALSE; } #endif // __CHIP_MODE__ if( m_use_cb ) { num_channels = num_dac_channels > num_adc_channels ? num_dac_channels : num_adc_channels; // log EM_log( CK_LOG_SEVERE, "allocating buffers for %d x %d samples...", m_buffer_size, num_channels ); // allocate buffers m_buffer_in = new SAMPLE[m_buffer_size * num_channels]; m_buffer_out = new SAMPLE[m_buffer_size * num_channels]; memset( m_buffer_in, 0, m_buffer_size * sizeof(SAMPLE) * num_channels ); memset( m_buffer_out, 0, m_buffer_size * sizeof(SAMPLE) * num_channels ); m_read_ptr = NULL; m_write_ptr = NULL; } m_in_ready = FALSE; m_out_ready = FALSE; return m_init = TRUE; }
static unsigned int __stdcall watch_dog( void * ) #endif { t_CKFLOAT time; // boost priority? t_CKUINT priority = Chuck_VM::our_priority; // log EM_log( CK_LOG_SEVERE, "starting real-time watch dog processs..." ); // push log EM_pushlog(); EM_log( CK_LOG_INFO, "watchdog timeout: %f::second", g_watchdog_timeout ); EM_log( CK_LOG_INFO, "watchdog thread priority: %d", priority ); EM_log( CK_LOG_INFO, "watchdog countermeasure priority: %d", g_watchdog_countermeasure_priority ); // pop log EM_poplog(); // boost watchdog by same priority if( Chuck_VM::our_priority != 0x7fffffff ) Chuck_VM::set_priority( priority, NULL ); // while going while( g_do_watchdog ) { // get time = get_current_time( TRUE ); // fprintf( stderr, "last: %f now: %f\n", g_watchdog_time, time ); // resting if( g_watchdog_state == FALSE ) { // check xrun // if( Digitalio::m_xrun > 100 ) if( time - g_watchdog_time > g_watchdog_timeout ) { // log EM_log( CK_LOG_SEVERE, "real-time watchdog counter-measure activating..." ); // lowering priority if( g_tid_synthesis && Chuck_VM::our_priority != 0x7fffffff ) set_priority( g_tid_synthesis, g_watchdog_countermeasure_priority ); // set state g_watchdog_state = TRUE; } } else { // check xrun // if( Digitalio::m_xrun == 0 ) if( time - g_watchdog_time < g_watchdog_timeout ) { // log EM_log( CK_LOG_SEVERE, "real-time watchdog resting..." ); // raise priority if( g_tid_synthesis && Chuck_VM::our_priority != 0x7fffffff ) set_priority( g_tid_synthesis, Chuck_VM::our_priority ); // set state g_watchdog_state = FALSE; } } // advance time usleep( 40000 ); } // log EM_log( CK_LOG_SEVERE, "stopping real-time watch dog process..." ); return 0; }