*** empty log message ***
[chuck-blob.git] / exile / v1 / src / chuck_main.cpp
blob194e7d2911c1ff66f13fa29edfd97d974e2948ac
1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 U.S.A.
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: chuck_main.cpp
27 // desc: ...
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // date: Autumn 2002
32 //-----------------------------------------------------------------------------
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/types.h>
38 #include <sys/stat.h>
40 #include <fstream>
41 using namespace std;
43 extern "C" int yyparse( void );
45 #include "chuck_type.h"
46 #include "chuck_emit.h"
47 #include "chuck_instr.h"
48 #include "chuck_vm.h"
49 #include "chuck_bbq.h"
50 #include "chuck_utils.h"
51 #include "chuck_errmsg.h"
52 #include "util_network.h"
54 #include <signal.h>
55 #ifndef __PLATFORM_WIN32__
56 #define CHUCK_THREAD pthread_t
57 #include <pthread.h>
58 #include <unistd.h>
59 #include <netinet/in.h>
60 #include <arpa/inet.h>
61 #else
62 #define CHUCK_THREAD HANDLE
63 #endif
65 #include "ugen_osc.h"
66 #include "ugen_xxx.h"
67 #include "ugen_filter.h"
68 #include "ugen_stk.h"
69 #include "ulib_machine.h"
70 #include "ulib_math.h"
71 #include "ulib_net.h"
72 #include "ulib_std.h"
74 // current version
75 #define CK_VERSION "1.1.5.6d"
78 #ifdef __PLATFORM_WIN32__
79 // 'C' specification necessary for windows to link properly
80 extern "C" a_Program g_program;
81 #else
82 extern a_Program g_program;
83 #endif
85 ck_socket g_sock;
86 Chuck_VM * g_vm = NULL;
87 t_Env g_env = NULL;
88 t_CKBOOL g_error = FALSE;
89 CHUCK_THREAD g_tid = 0;
90 char g_host[256] = "127.0.0.1";
91 int g_port = 8888;
92 #if defined(__MACOSX_CORE__)
93 t_CKINT g_priority = 95;
94 #elif defined(__WINDOWS_DS__)
95 t_CKINT g_priority = 0;
96 #else
97 t_CKINT g_priority = 0x7fffffff;
98 #endif
103 //-----------------------------------------------------------------------------
104 // name: signal_int()
105 // desc: ...
106 //-----------------------------------------------------------------------------
107 void signal_int( int sig_num )
109 if( g_vm )
111 Chuck_VM * vm = g_vm;
112 g_vm = NULL;
113 fprintf( stderr, "[chuck]: cleaning up...\n" );
114 vm->stop();
115 stk_detach( 0, NULL );
116 #ifndef __PLATFORM_WIN32__
117 // pthread_kill( g_tid, 2 );
118 if( g_tid ) pthread_cancel( g_tid );
119 if( g_tid ) usleep( 50000 );
120 delete( vm );
121 #else
122 CloseHandle( g_tid );
123 #endif
124 ck_close( g_sock );
127 #ifndef __PLATFORM_WIN32__
128 // pthread_join( g_tid, NULL );
129 #endif
131 exit(2);
137 t_CKUINT g_sigpipe_mode = 0;
138 //-----------------------------------------------------------------------------
139 // name: signal_pipe()
140 // desc: ...
141 //-----------------------------------------------------------------------------
142 void signal_pipe( int sig_num )
144 fprintf( stderr, "[chuck]: sigpipe handled - broken pipe (no connection)...\n" );
145 if( g_sigpipe_mode ) exit( 1 );
151 //-----------------------------------------------------------------------------
152 // name: open_cat()
153 // desc: ...
154 //-----------------------------------------------------------------------------
155 FILE * open_cat( c_str fname )
157 FILE * fd = NULL;
158 if( !(fd = fopen( fname, "rb" )) )
159 if( !strstr( fname, ".ck" ) && !strstr( fname, ".CK" ) )
161 strcat( fname, ".ck" );
162 fd = fopen( fname, "rb" );
164 return fd;
170 char filename[1024] = "";
171 //-----------------------------------------------------------------------------
172 // name: parse()
173 // desc: ...
174 //-----------------------------------------------------------------------------
175 t_CKBOOL parse( c_str fname, FILE * fd = NULL )
177 t_CKBOOL ret = FALSE;
178 strcpy( filename, fname );
180 // test it
181 if( !fd )
183 fd = open_cat( filename );
184 if( !fd ) strcpy( filename, fname );
187 // parse
188 ret = EM_reset( filename, fd );
189 if( ret == FALSE ) return FALSE;
190 // TODO: clean g_program
191 g_program = NULL;
192 ret = (yyparse( ) == 0);
194 return ret;
200 //-----------------------------------------------------------------------------
201 // name: type_check()
202 // desc: ...
203 //-----------------------------------------------------------------------------
204 t_CKBOOL type_check( t_Env env, a_Program prog )
206 t_CKBOOL ret = FALSE;
208 type_engine_begin( env );
209 ret = type_engine_check_prog( env, g_program );
211 return ret;
217 //-----------------------------------------------------------------------------
218 // name: emit()
219 // desc: ...
220 //-----------------------------------------------------------------------------
221 t_CKBOOL emit_code( Chuck_Emmission * emit, t_Env env, a_Program prog )
223 t_CKBOOL ret = FALSE;
225 ret = emit_engine_emit_prog( emit, g_program );
226 type_engine_end( env );
228 return ret;
234 //-----------------------------------------------------------------------------
235 // name: dump_instr()
236 // desc: ...
237 //-----------------------------------------------------------------------------
238 t_CKBOOL dump_instr( Chuck_VM_Code * code )
240 fprintf( stderr, "[chuck]: dumping src/shred '%s'...\n", code->name.c_str() );
241 fprintf( stderr, "...\n" );
243 for( unsigned int i = 0; i < code->num_instr; i++ )
244 fprintf( stderr, "'%i' %s( %s )\n", i,
245 code->instr[i]->name(), code->instr[i]->params() );
247 fprintf( stderr, "...\n\n" );
249 return TRUE;
255 //-----------------------------------------------------------------------------
256 // name: load_module()
257 // desc: ...
258 //-----------------------------------------------------------------------------
259 t_CKBOOL load_module( t_Env env, f_ck_query query, const char * name, const char * nspc )
261 Chuck_DLL * dll = NULL;
263 // load osc
264 dll = new Chuck_DLL( name );
265 dll->load( query );
266 if( !dll->query() || !type_engine_add_dll( env, dll, nspc ) )
268 fprintf( stderr,
269 "[chuck]: internal error loading internal module '%s.%s'...\n",
270 nspc, name );
271 if( !dll->query() )
272 fprintf( stderr, " %s\n", dll->last_error() );
273 g_error = TRUE;
274 exit(1);
277 return TRUE;
283 //-----------------------------------------------------------------------------
284 // name: usage()
285 // desc: ...
286 //-----------------------------------------------------------------------------
287 void usage()
289 fprintf( stderr, "usage: chuck --[options|commands] [+-=^] file1 file2 file3 ...\n" );
290 fprintf( stderr, " [options] = halt|loop|audio|silent|dump|nodump|about|\n" );
291 fprintf( stderr, " srate<N>|bufsize<N>|bufnum<N>|dac<N>|adc<N>|\n" );
292 fprintf( stderr, " remote<hostname>|port<N>\n" );
293 fprintf( stderr, " [commands] = add|remove|replace|status|time|kill\n" );
294 fprintf( stderr, " [+-=^] = shortcuts for add, remove, replace, status\n\n" );
295 fprintf( stderr, "chuck version: %s\n", CK_VERSION );
296 fprintf( stderr, " http://chuck.cs.princeton.edu/\n\n" );
302 //-----------------------------------------------------------------------------
303 // name: send_file()
304 // desc: ...
305 //-----------------------------------------------------------------------------
306 int send_file( const char * filename, Net_Msg & msg, const char * op )
308 FILE * fd = NULL;
309 struct stat fs;
311 strcpy( msg.buffer, "" );
312 //if( filename[0] != '/' )
313 //{
314 // strcpy( msg.buffer, getenv("PWD") ? getenv("PWD") : "" );
315 // strcat( msg.buffer, getenv("PWD") ? "/" : "" );
317 strcat( msg.buffer, filename );
319 // test it
320 fd = open_cat( (char *)msg.buffer );
321 if( !fd )
323 fprintf( stderr, "[chuck]: cannot open file '%s' for [%s]...\n", filename, op );
324 return FALSE;
327 if( !parse( (char *)msg.buffer, fd ) )
329 fprintf( stderr, "[chuck]: skipping file '%s' for [%s]...\n", filename, op );
330 fclose( fd );
331 return FALSE;
334 // stat it
335 stat( msg.buffer, &fs );
336 fseek( fd, 0, SEEK_SET );
338 //fprintf(stderr, "sending TCP file %s\n", msg.buffer );
339 // send the first packet
340 msg.param2 = (t_CKUINT)fs.st_size;
341 msg.length = 0;
342 otf_hton( &msg );
343 ck_send( g_sock, (char *)&msg, sizeof(msg) );
345 // send the whole thing
346 t_CKUINT left = (t_CKUINT)fs.st_size;
347 while( left )
349 //fprintf(stderr,"file %03d bytes left ... ", left);
350 // amount to send
351 msg.length = left > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : left;
352 // read
353 msg.param3 = fread( msg.buffer, sizeof(char), msg.length, fd );
354 // amount left
355 left -= msg.param3 ? msg.param3 : 0;
356 msg.param2 = left;
357 //fprintf(stderr, "sending fread %03d length %03d...\n", msg.param3, msg.length );
358 // send it
359 otf_hton( &msg );
360 ck_send( g_sock, (char *)&msg, sizeof(msg) );
363 // close
364 fclose( fd );
365 //fprintf(stderr, "done.\n", msg.buffer );
366 return TRUE;
372 //-----------------------------------------------------------------------------
373 // name: recv_file()
374 // desc: ...
375 //-----------------------------------------------------------------------------
376 FILE * recv_file( const Net_Msg & msg, ck_socket sock )
378 Net_Msg buf;
380 // what is left
381 t_CKUINT left = msg.param2;
382 // make a temp file
383 FILE * fd = tmpfile();
385 do {
386 // msg
387 if( !ck_recv( sock, (char *)&buf, sizeof(buf) ) )
388 goto error;
389 otf_ntoh( &buf );
390 // write
391 fwrite( buf.buffer, sizeof(char), buf.length, fd );
392 }while( buf.param2 );
394 return fd;
396 error:
397 fclose( fd );
398 fd = NULL;
399 return NULL;
405 //-----------------------------------------------------------------------------
406 // name: process_msg()
407 // desc: ...
408 //-----------------------------------------------------------------------------
409 extern "C" t_CKUINT process_msg( Net_Msg * msg, t_CKBOOL immediate, void * data )
411 Chuck_Msg * cmd = new Chuck_Msg;
412 FILE * fd = NULL;
414 // fprintf( stderr, "UDP message recv...\n" );
415 if( msg->type == MSG_REPLACE || msg->type == MSG_ADD )
417 // see if entire file is on the way
418 if( msg->param2 )
420 fd = recv_file( *msg, (ck_socket)data );
421 if( !fd )
423 fprintf( stderr, "[chuck]: incoming source transfer '%s' failed...\n",
424 mini(msg->buffer) );
425 return 0;
429 // parse
430 if( !parse( msg->buffer, fd ) )
431 return 0;
433 // type check
434 if( !type_check( g_env, g_program ) )
435 return 0;
437 // emit
438 Chuck_Emmission * emit = emit_engine_init( g_env );
439 if( !emit_code( emit, g_env, g_program ) )
440 return 0;
442 // transform the code
443 Chuck_VM_Code * code = emit_to_code( emit );
444 code->name = msg->buffer;
445 cmd->shred = new Chuck_VM_Shred;
446 cmd->shred->initialize( code );
447 cmd->shred->name = code->name;
448 emit_engine_addr_map( emit, cmd->shred );
449 emit_engine_resolve();
450 emit_engine_shutdown( emit );
452 // set the flags for the command
453 cmd->type = msg->type;
454 cmd->code = code;
455 if( msg->type == MSG_REPLACE )
456 cmd->param = msg->param;
458 else if( msg->type == MSG_STATUS || msg->type == MSG_REMOVE || msg->type == MSG_REMOVEALL
459 || msg->type == MSG_KILL || msg->type == MSG_TIME )
461 cmd->type = msg->type;
462 cmd->param = msg->param;
464 else
466 fprintf( stderr, "[chuck]: unrecognized incoming command from network: '%i'\n", cmd->type );
467 SAFE_DELETE(cmd);
468 return 0;
471 // immediate
472 if( immediate )
473 return g_vm->process_msg( cmd );
475 g_vm->queue_msg( cmd, 1 );
477 return 1;
483 //-----------------------------------------------------------------------------
484 // name: load_internal_modules()
485 // desc: ...
486 //-----------------------------------------------------------------------------
487 t_CKBOOL load_internal_modules( t_Env env )
489 // load
490 load_module( env, osc_query, "osc", "global" );
491 load_module( env, xxx_query, "xxx", "global" );
492 load_module( env, filter_query, "filter", "global" );
493 load_module( env, stk_query, "stk", "global" );
495 // load
496 load_module( env, machine_query, "machine", "machine" );
497 machine_init( g_vm, process_msg );
498 load_module( env, libstd_query, "std", "std" );
499 load_module( env, libmath_query, "math", "math" );
500 load_module( env, net_query, "net", "net" );
502 return TRUE;
508 //-----------------------------------------------------------------------------
509 // name: timer()
510 // desc: ...
511 //-----------------------------------------------------------------------------
512 void * timer( void * p )
514 if ( p ) {
515 t_CKUINT t = *(t_CKUINT *)p;
516 usleep( t );
518 fprintf( stderr, "[chuck]: operation timed out...\n" );
519 exit(1);
525 //-----------------------------------------------------------------------------
526 // name: cb()
527 // desc: ...
528 //-----------------------------------------------------------------------------
529 void * cb( void * p )
531 Net_Msg msg;
532 Net_Msg ret;
533 ck_socket client;
534 int n;
536 #ifndef __PLATFORM_WIN32__
537 // catch SIGPIPE
538 signal( SIGPIPE, signal_pipe );
539 #endif
541 while( true )
543 client = ck_accept( g_sock );
544 if( !client )
546 if( g_vm ) fprintf( stderr, "[chuck]: socket error during accept()...\n" );
547 usleep( 40000 );
548 ck_close( client );
549 continue;
551 msg.clear();
552 // set time out
553 ck_recv_timeout( client, 0, 5000000 );
554 n = ck_recv( client, (char *)&msg, sizeof(msg) );
555 otf_ntoh( &msg );
556 if( n != sizeof(msg) )
558 fprintf( stderr, "[chuck]: 0-length packet...\n", (int)client );
559 usleep( 40000 );
560 ck_close( client );
561 continue;
564 if( msg.header != NET_HEADER )
566 fprintf( stderr, "[chuck]: header mismatch - possible endian lunacy...\n" );
567 ck_close( client );
568 continue;
571 while( msg.type != MSG_DONE )
573 if( g_vm )
575 if( !process_msg( &msg, FALSE, client ) )
577 ret.param = FALSE;
578 strcpy( (char *)ret.buffer, EM_lasterror() );
579 while( msg.type != MSG_DONE && n )
581 n = ck_recv( client, (char *)&msg, sizeof(msg) );
582 otf_ntoh( &msg );
584 break;
586 else
588 ret.param = TRUE;
589 strcpy( (char *)ret.buffer, "success" );
590 n = ck_recv( client, (char *)&msg, sizeof(msg) );
591 otf_ntoh( &msg );
596 otf_hton( &ret );
597 ck_send( client, (char *)&ret, sizeof(ret) );
598 ck_close( client );
601 return NULL;
607 //-----------------------------------------------------------------------------
608 // name: send_connect()
609 // desc: ...
610 //-----------------------------------------------------------------------------
611 int send_connect()
613 g_sock = ck_tcp_create( 0 );
614 if( !g_sock )
616 fprintf( stderr, "[chuck]: cannot open socket to send command...\n" );
617 return FALSE;
620 if( strcmp( g_host, "127.0.0.1" ) )
621 fprintf( stderr, "[chuck]: connecting to %s on port %i via TCP...\n", g_host, g_port );
623 if( !ck_connect( g_sock, g_host, g_port ) )
625 fprintf( stderr, "[chuck]: cannot open TCP socket on %s:%i...\n", g_host, g_port );
626 return FALSE;
629 ck_send_timeout( g_sock, 0, 2000000 );
631 return TRUE;
637 //-----------------------------------------------------------------------------
638 // name: send_cmd()
639 // desc: ...
640 //-----------------------------------------------------------------------------
641 int send_cmd( int argc, char ** argv, int & i )
643 Net_Msg msg;
644 g_sigpipe_mode = 1;
645 int ret = 0;
646 int tasks_total = 0, tasks_done = 0;
648 if( !strcmp( argv[i], "--add" ) || !strcmp( argv[i], "+" ) )
650 if( ++i >= argc )
652 fprintf( stderr, "[chuck]: not enough arguments following [add]...\n" );
653 goto error;
656 if( !send_connect() ) return 0;
657 do {
658 msg.type = MSG_ADD;
659 msg.param = 1;
660 tasks_done += send_file( argv[i], msg, "add" );
661 tasks_total++;
662 } while( ++i < argc );
664 if( !tasks_done )
665 goto error;
667 else if( !strcmp( argv[i], "--remove" ) || !strcmp( argv[i], "-" ) )
669 if( ++i >= argc )
671 fprintf( stderr, "[chuck]: not enough arguments following [remove]...\n" );
672 goto error;
675 if( !send_connect() ) return 0;
676 do {
677 msg.param = atoi( argv[i] );
678 msg.type = MSG_REMOVE;
679 otf_hton( &msg );
680 ck_send( g_sock, (char *)&msg, sizeof(msg) );
681 } while( ++i < argc );
683 else if( !strcmp( argv[i], "--" ) )
685 if( !send_connect() ) return 0;
686 msg.param = 0xffffffff;
687 msg.type = MSG_REMOVE;
688 otf_hton( &msg );
689 ck_send( g_sock, (char *)&msg, sizeof(msg) );
691 else if( !strcmp( argv[i], "--replace" ) || !strcmp( argv[i], "=" ) )
693 if( ++i >= argc )
695 fprintf( stderr, "[chuck]: not enough arguments following [replace]...\n" );
696 goto error;
699 if( i <= 0 )
700 msg.param = 0xffffffff;
701 else
702 msg.param = atoi( argv[i] );
704 if( ++i >= argc )
706 fprintf( stderr, "[chuck]: not enough arguments following [replace]...\n" );
707 goto error;
710 if( !send_connect() ) return 0;
711 msg.type = MSG_REPLACE;
712 if( !send_file( argv[i], msg, "replace" ) )
713 goto error;
715 else if( !strcmp( argv[i], "--removeall" ) || !strcmp( argv[i], "--remall" ) )
717 if( !send_connect() ) return 0;
718 msg.type = MSG_REMOVEALL;
719 msg.param = 0;
720 otf_hton( &msg );
721 ck_send( g_sock, (char *)&msg, sizeof(msg) );
723 else if( !strcmp( argv[i], "--kill" ) )
725 if( !send_connect() ) return 0;
726 msg.type = MSG_REMOVEALL;
727 msg.param = 0;
728 otf_hton( &msg );
729 ck_send( g_sock, (char *)&msg, sizeof(msg) );
730 msg.type = MSG_KILL;
731 msg.param = (i+1)<argc ? atoi(argv[++i]) : 0;
732 otf_hton( &msg );
733 ck_send( g_sock, (char *)&msg, sizeof(msg) );
735 else if( !strcmp( argv[i], "--time" ) )
737 if( !send_connect() ) return 0;
738 msg.type = MSG_TIME;
739 msg.param = 0;
740 otf_hton( &msg );
741 ck_send( g_sock, (char *)&msg, sizeof(msg) );
743 else if( !strcmp( argv[i], "--status" ) || !strcmp( argv[i], "^" ) )
745 if( !send_connect() ) return 0;
746 msg.type = MSG_STATUS;
747 msg.param = 0;
748 otf_hton( &msg );
749 ck_send( g_sock, (char *)&msg, sizeof(msg) );
751 else
752 return 0;
754 // send
755 msg.type = MSG_DONE;
756 otf_hton( &msg );
757 ck_send( g_sock, (char *)&msg, sizeof(msg) );
759 // set timeout
760 ck_recv_timeout( g_sock, 0, 2000000 );
761 // reply
762 if( ck_recv( g_sock, (char *)&msg, sizeof(msg) ) )
764 otf_ntoh( &msg );
765 fprintf( stderr, "[chuck(remote)]: operation %s\n", ( msg.param ? "successful" : "failed (sorry)" ) );
766 if( !msg.param )
767 fprintf( stderr, "(reason): %s\n",
768 ( strstr( (char *)msg.buffer, ":" ) ? strstr( (char *)msg.buffer, ":" ) + 1 : (char *)msg.buffer ) ) ;
770 else
772 fprintf( stderr, "[chuck]: remote operation timed out...\n" );
774 // close the sock
775 ck_close( g_sock );
777 // exit
778 exit( msg.param );
780 return 1;
782 error:
783 msg.type = MSG_DONE;
784 otf_hton( &msg );
785 ck_send( g_sock, (char *)&msg, sizeof(msg) );
786 ck_close( g_sock );
788 exit( 1 );
790 return 0;
795 //-----------------------------------------------------------------------------
796 // name: next_power_2()
797 // desc: ...
798 // thanks: to Niklas Werner / music-dsp
799 //-----------------------------------------------------------------------------
800 t_CKUINT next_power_2( t_CKUINT n )
802 t_CKUINT nn = n;
803 for( ; n &= n-1; nn = n );
804 return nn * 2;
810 //-----------------------------------------------------------------------------
811 // name: main()
812 // desc: ...
813 //-----------------------------------------------------------------------------
814 int main( int argc, char ** argv )
816 int i, a, files = 0;
817 t_CKBOOL enable_audio = TRUE;
818 t_CKBOOL vm_halt = TRUE;
819 t_CKUINT srate = SAMPLING_RATE_DEFAULT;
820 t_CKUINT buffer_size = BUFFER_SIZE_DEFAULT;
821 t_CKUINT num_buffers = 8;
822 t_CKUINT dac = 0;
823 t_CKUINT adc = 0;
824 t_CKBOOL set_priority = FALSE;
826 // catch SIGINT
827 signal( SIGINT, signal_int );
828 #ifndef __PLATFORM_WIN32__
829 // catch SIGPIPE
830 signal( SIGPIPE, signal_pipe );
831 #endif
833 for( i = 1; i < argc; i++ )
835 if( argv[i][0] == '-' || argv[i][0] == '+' ||
836 argv[i][0] == '=' || argv[i][0] == '^' || argv[i][0] == '@' )
838 if( !strcmp(argv[i], "--dump") || !strcmp(argv[i], "+d")
839 || !strcmp(argv[i], "--nodump") || !strcmp(argv[i], "-d") )
840 continue;
841 else if( !strcmp(argv[i], "--audio") || !strcmp(argv[i], "-a") )
842 enable_audio = TRUE;
843 else if( !strcmp(argv[i], "--silent") || !strcmp(argv[i], "-s") )
844 enable_audio = FALSE;
845 else if( !strcmp(argv[i], "--halt") || !strcmp(argv[i], "-t") )
846 vm_halt = TRUE;
847 else if( !strcmp(argv[i], "--loop") || !strcmp(argv[i], "-l") )
848 vm_halt = FALSE;
849 else if( !strncmp(argv[i], "--srate", 7) )
850 srate = atoi( argv[i]+7 ) > 0 ? atoi( argv[i]+7 ) : srate;
851 else if( !strncmp(argv[i], "-r", 2) )
852 srate = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : srate;
853 else if( !strncmp(argv[i], "--bufsize", 9) )
854 buffer_size = atoi( argv[i]+9 ) > 0 ? atoi( argv[i]+9 ) : buffer_size;
855 else if( !strncmp(argv[i], "-b", 2) )
856 buffer_size = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : buffer_size;
857 else if( !strncmp(argv[i], "--bufnum", 8) )
858 num_buffers = atoi( argv[i]+8 ) > 0 ? atoi( argv[i]+8 ) : num_buffers;
859 else if( !strncmp(argv[i], "-n", 2) )
860 num_buffers = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : num_buffers;
861 else if( !strncmp(argv[i], "--dac", 5) )
862 dac = atoi( argv[i]+5 ) > 0 ? atoi( argv[i]+5 ) : 0;
863 else if( !strncmp(argv[i], "--adc", 5) )
864 adc = atoi( argv[i]+5 ) > 0 ? atoi( argv[i]+5 ) : 0;
865 else if( !strncmp(argv[i], "--level", 7) )
866 { g_priority = atoi( argv[i]+7 ); set_priority = TRUE; }
867 else if( !strncmp(argv[i], "--remote", 8) )
868 strcpy( g_host, argv[i]+8 );
869 else if( !strncmp(argv[i], "@", 1) )
870 strcpy( g_host, argv[i]+1 );
871 else if( !strncmp(argv[i], "--port", 6) )
872 g_port = atoi( argv[i]+6 );
873 else if( !strncmp(argv[i], "-p", 2) )
874 g_port = atoi( argv[i]+2 );
875 else if( !strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")
876 || !strcmp(argv[i], "--about") )
878 usage();
879 exit( 2 );
881 else if( a = send_cmd( argc, argv, i ) )
882 exit( 0 );
883 else
885 fprintf( stderr, "[chuck]: invalid flag '%s'\n", argv[i] );
886 usage();
887 exit( 1 );
890 else
891 files++;
894 // check buffer size
895 buffer_size = next_power_2( buffer_size-1 );
896 // if audio then boost priority
897 if( !set_priority && !enable_audio ) g_priority = 0x7fffffff;
898 // set priority
899 Chuck_VM::our_priority = g_priority;
901 if ( !files && vm_halt )
903 fprintf( stderr, "[chuck]: no input files... (try --help)\n" );
904 exit( 1 );
907 // allocate the vm
908 Chuck_VM * vm = g_vm = new Chuck_VM;
909 if( !vm->initialize( enable_audio, vm_halt, srate, buffer_size,
910 num_buffers, dac, adc, g_priority ) )
912 fprintf( stderr, "[chuck]: %s\n", vm->last_error() );
913 exit( 1 );
916 // allocate the type system
917 g_env = type_engine_init( vm );
918 // set the env
919 vm->set_env( g_env );
920 // load modules
921 if( !load_internal_modules( g_env ) || g_error )
922 exit( 1 );
924 Chuck_VM_Code * code = NULL;
925 Chuck_VM_Shred * shred = NULL;
926 t_CKBOOL dump = FALSE;
927 for( i = 1; i < argc; i++ )
929 if( argv[i][0] == '-' || argv[i][0] == '+' )
931 if( !strcmp(argv[i], "--dump") || !strcmp(argv[i], "+d" ) )
932 dump = TRUE;
933 else if( !strcmp(argv[i], "--nodump") || !strcmp(argv[i], "-d" ) )
934 dump = FALSE;
936 continue;
939 // parse
940 if( !parse( argv[i] ) )
941 return 1;
943 // type check
944 if( !type_check( g_env, g_program ) )
945 return 1;
947 // emit
948 Chuck_Emmission * emit = emit_engine_init( g_env );
949 if( !emit_code( emit, g_env, g_program ) )
950 return 1;
952 // transform the code
953 code = emit_to_code( emit, dump );
954 code->name = argv[i];
956 // dump
957 if( dump ) dump_instr( code );
959 // spork it
960 shred = vm->spork( code, NULL );
962 // mem map it
963 emit_engine_addr_map( emit, shred );
965 // link local
966 emit_engine_resolve( );
968 // cleanup the emitter
969 emit_engine_shutdown( emit );
972 // link
973 // emit_engine_resolve_globals();
975 // start tcp server
976 g_sock = ck_tcp_create( 1 );
977 if( !g_sock || !ck_bind( g_sock, g_port ) || !ck_listen( g_sock, 10 ) )
979 fprintf( stderr, "[chuck]: cannot bind to tcp port %i...\n", g_port );
980 ck_close( g_sock );
981 g_sock = NULL;
983 else
985 #ifndef __PLATFORM_WIN32__
986 pthread_create( &g_tid, NULL, cb, NULL );
987 #else
988 g_tid = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)cb, NULL, 0, 0);
989 #endif
992 // run the vm
993 vm->run();
995 // done - clean up
996 vm->shutdown();
997 usleep( 50000 );
998 delete( vm );
999 g_vm = NULL;
1000 #ifndef __PLATFORM_WIN32__
1001 pthread_kill( g_tid, 2 );
1002 #else
1003 CloseHandle( g_tid );
1004 #endif
1005 usleep( 100000 );
1006 ck_close( g_sock );
1008 return 0;