*** empty log message ***
[chuck-blob.git] / v2 / ulib_std.cpp
blobe1767854a0f69cd2f5c344383745c7a27a9faaa0
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: ulib_std.cpp
27 // desc: ...
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // date: Spring 2004
32 //-----------------------------------------------------------------------------
33 #include "ulib_std.h"
34 #include <stdlib.h>
35 #include <time.h>
36 #include <math.h>
37 #include "util_buffers.h"
38 #include "util_console.h"
39 #include "util_math.h"
40 #include "util_string.h"
41 #include "util_thread.h"
42 #include "chuck_type.h"
43 #include "chuck_instr.h"
44 #include "chuck_globals.h"
46 #if defined(__PLATFORM_WIN32__)
48 #include <windows.h>
50 int setenv( const char *n, const char *v, int i )
52 return !SetEnvironmentVariable(n, v);
55 #else
57 #include <unistd.h>
59 #endif
61 // for ConsoleInput and StringTokenizer
62 #include <sstream>
63 #include <iostream>
64 #include "util_thread.h"
65 using namespace std;
68 #ifndef __DISABLE_KBHIT__
69 // KBHit
70 CK_DLL_CTOR( KBHit_ctor );
71 CK_DLL_DTOR( KBHit_dtor );
72 CK_DLL_MFUN( KBHit_on );
73 CK_DLL_MFUN( KBHit_off );
74 CK_DLL_MFUN( KBHit_state );
75 CK_DLL_MFUN( KBHit_hit );
76 CK_DLL_MFUN( KBHit_more );
77 CK_DLL_MFUN( KBHit_getchar );
78 CK_DLL_MFUN( KBHit_can_wait );
80 static t_CKUINT KBHit_offset_data = 0;
81 #endif // __DISABLE_KBHIT__
83 #ifndef __DISABLE_PROMPTER__
84 // Skot functions
85 CK_DLL_CTOR( Skot_ctor );
86 CK_DLL_DTOR( Skot_dtor );
87 CK_DLL_MFUN( Skot_prompt );
88 CK_DLL_MFUN( Skot_prompt2 );
89 CK_DLL_MFUN( Skot_more );
90 CK_DLL_MFUN( Skot_getLine );
91 CK_DLL_MFUN( Skot_can_wait );
93 static t_CKUINT Skot_offset_data = 0;
94 #endif // __DISABLE_PROMPTER__
96 // StrTok functions
97 CK_DLL_CTOR( StrTok_ctor );
98 CK_DLL_DTOR( StrTok_dtor );
99 CK_DLL_MFUN( StrTok_set );
100 CK_DLL_MFUN( StrTok_reset );
101 CK_DLL_MFUN( StrTok_more );
102 CK_DLL_MFUN( StrTok_next );
103 CK_DLL_MFUN( StrTok_next2 );
104 CK_DLL_MFUN( StrTok_get );
105 CK_DLL_MFUN( StrTok_get2 );
106 CK_DLL_MFUN( StrTok_size );
108 static t_CKUINT StrTok_offset_data = 0;
110 #ifdef AJAY
112 #include <fstream>
114 // VCR functions
115 CK_DLL_CTOR( VCR_ctor );
116 CK_DLL_MFUN( VCR_load );
117 CK_DLL_MFUN( VCR_reset );
118 CK_DLL_MFUN( VCR_seek );
119 CK_DLL_MFUN( VCR_more );
120 CK_DLL_MFUN( VCR_curr );
121 CK_DLL_MFUN( VCR_next );
122 CK_DLL_MFUN( VCR_pos );
123 CK_DLL_MFUN( VCR_size );
124 CK_DLL_MFUN( VCR_name );
126 static t_CKUINT VCR_offset_data = 0;
128 // Cereal functions
129 CK_DLL_CTOR( Cereal_ctor );
130 CK_DLL_MFUN( Cereal_open );
131 CK_DLL_MFUN( Cereal_close );
132 CK_DLL_MFUN( Cereal_send );
133 CK_DLL_MFUN( Cereal_recv );
134 CK_DLL_MFUN( Cereal_more );
136 static t_CKUINT Cereal_offset_data = 0;
138 #endif
143 //-----------------------------------------------------------------------------
144 // name: libstd_query()
145 // desc: query entry point
146 //-----------------------------------------------------------------------------
147 DLL_QUERY libstd_query( Chuck_DL_Query * QUERY )
149 // get global
150 Chuck_Env * env = Chuck_Env::instance();
151 // set name
152 QUERY->setname( QUERY, "Std" );
154 /*! \example
155 std.rand2f( 100.0, 1000.0 ) => stdout;
158 // register deprecate
159 type_engine_register_deprecate( env, "std", "Std" );
161 // begin class
162 QUERY->begin_class( QUERY, "Std", "Object" );
164 // add abs
165 QUERY->add_sfun( QUERY, abs_impl, "int", "abs" );
166 QUERY->add_arg( QUERY, "int", "value" );
168 // add fabs
169 QUERY->add_sfun( QUERY, fabs_impl, "float", "fabs" );
170 QUERY->add_arg( QUERY, "float", "value" );
172 // add rand
173 QUERY->add_sfun( QUERY, rand_impl, "int", "rand"); //! return int between 0 and RAND_MAX
175 // add rand2
176 QUERY->add_sfun( QUERY, rand2_impl, "int", "rand2" ); //! integer between [min,max]
177 QUERY->add_arg( QUERY, "int", "min" );
178 QUERY->add_arg( QUERY, "int", "max" );
180 // add rand
181 QUERY->add_sfun( QUERY, randf_impl, "float", "randf" ); //! rand between -1.0,1.0
183 // add rand2
184 QUERY->add_sfun( QUERY, rand2f_impl, "float", "rand2f" ); //! rand between min and max
185 QUERY->add_arg( QUERY, "float", "min" );
186 QUERY->add_arg( QUERY, "float", "max" );
188 // add srand
189 QUERY->add_sfun( QUERY, srand_impl, "void", "srand" );
190 QUERY->add_arg( QUERY, "int", "seed" );
192 // add sgn
193 QUERY->add_sfun( QUERY, sgn_impl, "float", "sgn" ); //! return sign of value (-1, 0, 1)
194 QUERY->add_arg( QUERY, "float", "value" );
196 // add system
197 //! see \example std.ck
198 QUERY->add_sfun( QUERY, system_impl, "int", "system" ); //! issue system command
199 QUERY->add_arg( QUERY, "string", "cmd" );
201 // add atoi
202 QUERY->add_sfun( QUERY, atoi_impl, "int", "atoi" ); //! string to integer
203 QUERY->add_arg( QUERY, "string", "value" );
205 // add atof
206 QUERY->add_sfun( QUERY, atof_impl, "float", "atof" ); //! string to float
207 QUERY->add_arg( QUERY, "string", "value" );
209 // add itoa
210 QUERY->add_sfun( QUERY, itoa_impl, "string", "itoa" ); //! int to string
211 QUERY->add_arg( QUERY, "int", "i" );
213 // add ftoa
214 QUERY->add_sfun( QUERY, ftoa_impl, "string", "ftoa" ); //! float to string
215 QUERY->add_arg( QUERY, "float", "f" );
216 QUERY->add_arg( QUERY, "int", "precision" );
218 // add getenv
219 QUERY->add_sfun( QUERY, getenv_impl, "string", "getenv" ); //! fetch environment variable
220 QUERY->add_arg( QUERY, "string", "value" );
222 // add setenv
223 QUERY->add_sfun( QUERY, setenv_impl, "int", "setenv" ); //! set environment variable
224 QUERY->add_arg( QUERY, "string", "key" );
225 QUERY->add_arg( QUERY, "string", "value" );
227 // add mtof
228 //! see \example mand-o-matic.ck
229 QUERY->add_sfun( QUERY, mtof_impl, "float", "mtof" ); //! midi note to frequency
230 QUERY->add_arg( QUERY, "float", "value" );
232 // add ftom
233 QUERY->add_sfun( QUERY, ftom_impl, "float", "ftom" ); //! frequency to midi note
234 QUERY->add_arg( QUERY, "float", "value" );
236 // add powtodb
237 QUERY->add_sfun( QUERY, powtodb_impl, "float", "powtodb" ); //! linear power to decibel
238 QUERY->add_arg( QUERY, "float", "value" );
240 // add rmstodb
241 QUERY->add_sfun( QUERY, rmstodb_impl, "float", "rmstodb" ); //! rms to decibel
242 QUERY->add_arg( QUERY, "float", "value" );
244 // add dbtopow
245 QUERY->add_sfun( QUERY, dbtopow_impl, "float", "dbtopow" ); //! decibel to linear
246 QUERY->add_arg( QUERY, "float", "value" );
248 // add dbtorms
249 QUERY->add_sfun( QUERY, dbtorms_impl, "float", "dbtorms" ); //! decibel to rms
250 QUERY->add_arg( QUERY, "float", "value" );
252 // finish class
253 QUERY->end_class( QUERY );
255 // seed the rand
256 srand( time( NULL ) );
258 Chuck_DL_Func * func = NULL;
260 #ifndef __DISABLE_KBHIT__
261 // KBHit
262 // begin class (KBHit)
263 if( !type_engine_import_class_begin( env, "KBHit", "Event",
264 env->global(), KBHit_ctor,
265 KBHit_dtor ) )
266 return FALSE;
268 // add member variable
269 KBHit_offset_data = type_engine_import_mvar( env, "int", "@KBHit_data", FALSE );
270 if( KBHit_offset_data == CK_INVALID_OFFSET ) goto error;
272 // add on()
273 func = make_new_mfun( "void", "on", KBHit_on );
274 if( !type_engine_import_mfun( env, func ) ) goto error;
276 // add off()
277 func = make_new_mfun( "void", "off", KBHit_off );
278 if( !type_engine_import_mfun( env, func ) ) goto error;
280 // add state()
281 func = make_new_mfun( "void", "state", KBHit_state );
282 if( !type_engine_import_mfun( env, func ) ) goto error;
284 // add hit()
285 func = make_new_mfun( "Event", "hit", KBHit_hit );
286 if( !type_engine_import_mfun( env, func ) ) goto error;
288 // add more()
289 func = make_new_mfun( "int", "more", KBHit_more );
290 if( !type_engine_import_mfun( env, func ) ) goto error;
292 // add getchar()
293 func = make_new_mfun( "int", "getchar", KBHit_getchar );
294 if( !type_engine_import_mfun( env, func ) ) goto error;
296 // add can_wait()
297 func = make_new_mfun( "int", "can_wait", KBHit_can_wait );
298 if( !type_engine_import_mfun( env, func ) ) goto error;
300 // end class
301 type_engine_import_class_end( env );
303 // start it
304 KBHitManager::init();
305 #endif // __DISABLE_KBHIT__
308 // register deprecate
309 type_engine_register_deprecate( env, "Skot", "ConsoleInput" );
311 #ifndef __DISABLE_PROMPTER__
312 // begin class (Skot)
313 if( !type_engine_import_class_begin( env, "ConsoleInput", "Event",
314 env->global(), Skot_ctor,
315 Skot_dtor ) )
316 return FALSE;
318 // add member variable
319 Skot_offset_data = type_engine_import_mvar( env, "int", "@Skot_data", FALSE );
320 if( Skot_offset_data == CK_INVALID_OFFSET ) goto error;
322 // add prompt()
323 func = make_new_mfun( "Event", "prompt", Skot_prompt );
324 if( !type_engine_import_mfun( env, func ) ) goto error;
326 // add prompt()
327 func = make_new_mfun( "Event", "prompt", Skot_prompt2 );
328 func->add_arg( "string", "what" );
329 if( !type_engine_import_mfun( env, func ) ) goto error;
331 // add ready()
332 func = make_new_mfun( "int", "more", Skot_more );
333 if( !type_engine_import_mfun( env, func ) ) goto error;
335 // add getString()
336 func = make_new_mfun( "string", "getLine", Skot_getLine );
337 if( !type_engine_import_mfun( env, func ) ) goto error;
339 // add can_wait()
340 func = make_new_mfun( "int", "can_wait", Skot_can_wait );
341 if( !type_engine_import_mfun( env, func ) ) goto error;
343 // end class
344 type_engine_import_class_end( env );
345 #endif // __DISABLE_PROMPTER__
348 // register deprecate
349 type_engine_register_deprecate( env, "PRC", "StringTokenizer" );
351 // begin class (StrTok)
352 if( !type_engine_import_class_begin( env, "StringTokenizer", "Object",
353 env->global(), StrTok_ctor,
354 StrTok_dtor ) )
355 return FALSE;
357 // add member variable
358 StrTok_offset_data = type_engine_import_mvar( env, "int", "@StrTok_data", FALSE );
359 if( StrTok_offset_data == CK_INVALID_OFFSET ) goto error;
361 // add set()
362 func = make_new_mfun( "void", "set", StrTok_set );
363 func->add_arg( "string", "line" );
364 if( !type_engine_import_mfun( env, func ) ) goto error;
366 // add reset()
367 func = make_new_mfun( "void", "reset", StrTok_reset );
368 if( !type_engine_import_mfun( env, func ) ) goto error;
370 // add more()
371 func = make_new_mfun( "int", "more", StrTok_more );
372 if( !type_engine_import_mfun( env, func ) ) goto error;
374 // add next()
375 func = make_new_mfun( "string", "next", StrTok_next );
376 if( !type_engine_import_mfun( env, func ) ) goto error;
378 // add get()
379 func = make_new_mfun( "string", "next", StrTok_next2 );
380 func->add_arg( "string", "out" );
381 if( !type_engine_import_mfun( env, func ) ) goto error;
383 // add get()
384 func = make_new_mfun( "string", "get", StrTok_get );
385 func->add_arg( "int", "index" );
386 if( !type_engine_import_mfun( env, func ) ) goto error;
388 // add get()
389 func = make_new_mfun( "string", "get", StrTok_get2 );
390 func->add_arg( "int", "index" );
391 func->add_arg( "string", "out" );
392 if( !type_engine_import_mfun( env, func ) ) goto error;
394 // add size()
395 func = make_new_mfun( "int", "size", StrTok_size );
396 if( !type_engine_import_mfun( env, func ) ) goto error;
398 // end class
399 type_engine_import_class_end( env );
402 #ifdef AJAY
404 // begin class
405 // init base class
406 if( !type_engine_import_class_begin( env, "VCR", "Object",
407 env->global(), VCR_ctor ) )
408 return FALSE;
410 // add member variable
411 VCR_offset_data = type_engine_import_mvar( env, "int", "@me", FALSE );
412 if( VCR_offset_data == CK_INVALID_OFFSET ) goto error;
414 // add load()
415 func = make_new_mfun( "int", "load", VCR_load );
416 func->add_arg( "string", "filename" );
417 func->add_arg( "int", "column" );
418 if( !type_engine_import_mfun( env, func ) ) goto error;
420 // add reset()
421 func = make_new_mfun( "int", "reset", VCR_reset );
422 if( !type_engine_import_mfun( env, func ) ) goto error;
424 // add seek()
425 func = make_new_mfun( "int", "seek", VCR_seek );
426 func->add_arg( "int", "where" );
427 if( !type_engine_import_mfun( env, func ) ) goto error;
429 // add more()
430 func = make_new_mfun( "int", "more", VCR_more );
431 if( !type_engine_import_mfun( env, func ) ) goto error;
433 // add curr()
434 func = make_new_mfun( "float", "curr", VCR_curr );
435 if( !type_engine_import_mfun( env, func ) ) goto error;
437 // add next()
438 func = make_new_mfun( "int", "next", VCR_next );
439 if( !type_engine_import_mfun( env, func ) ) goto error;
441 // add pos()
442 func = make_new_mfun( "int", "pos", VCR_pos );
443 if( !type_engine_import_mfun( env, func ) ) goto error;
445 // add size()
446 func = make_new_mfun( "int", "size", VCR_size );
447 if( !type_engine_import_mfun( env, func ) ) goto error;
449 // add name()
450 func = make_new_mfun( "string", "name", VCR_name );
451 if( !type_engine_import_mfun( env, func ) ) goto error;
453 // end the class import
454 type_engine_import_class_end( env );
457 #if defined(__PLATFORM_WIN32__)
458 // begin class (Cereal)
459 if( !type_engine_import_class_begin( env, "Cereal", "Object",
460 env->global(), Cereal_ctor ) )
461 return FALSE;
463 // add member
464 Cereal_offset_data = type_engine_import_mvar( env, "int", "@Cereal_data", FALSE );
465 if( Cereal_offset_data == CK_INVALID_OFFSET ) goto error;
467 // add open()
468 func = make_new_mfun( "int", "open", Cereal_open );
469 func->add_arg( "string", "name" );
470 func->add_arg( "int", "baudrate" );
471 if( !type_engine_import_mfun( env, func ) ) goto error;
473 // add close()
474 func = make_new_mfun( "void", "close", Cereal_close );
475 if( !type_engine_import_mfun( env, func ) ) goto error;
477 // add more()
478 func = make_new_mfun( "int", "more", Cereal_more );
479 if( !type_engine_import_mfun( env, func ) ) goto error;
481 // add send()
482 func = make_new_mfun( "int", "send", Cereal_send );
483 func->add_arg( "int", "bite" );
484 if( !type_engine_import_mfun( env, func ) ) goto error;
486 // add recv()
487 func = make_new_mfun( "int", "recv", Cereal_recv );
488 if( !type_engine_import_mfun( env, func ) ) goto error;
490 // end class
491 type_engine_import_class_end( env );
492 #endif
494 return TRUE;
496 #else
498 return TRUE;
500 #endif
502 error:
504 // end the class import
505 type_engine_import_class_end( env );
507 return FALSE;
511 #define RAND_INV_RANGE(r) (RAND_MAX / (r))
513 int irand_exclusive ( int max ) {
514 int x = ::rand();
516 while (x >= max * RAND_INV_RANGE (max))
517 x = ::rand();
519 x /= RAND_INV_RANGE (max);
520 return x;
524 // abs
525 CK_DLL_SFUN( abs_impl )
527 t_CKINT v = GET_CK_INT(ARGS);
528 RETURN->v_int = v >= 0 ? v : -v;
531 // fabs
532 CK_DLL_SFUN( fabs_impl )
534 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
535 RETURN->v_float = v >= 0.0 ? v : -v;
536 //RETURN->v_float = ::fabs( GET_CK_FLOAT(ARGS) );
539 // rand
540 CK_DLL_SFUN( rand_impl )
542 RETURN->v_int = ::rand();
545 // randf
546 CK_DLL_SFUN( randf_impl )
548 RETURN->v_float = ( 2.0 * ::rand() / (t_CKFLOAT)RAND_MAX - 1.0 );
551 // randf
552 CK_DLL_SFUN( rand2f_impl )
554 t_CKFLOAT min = GET_CK_FLOAT(ARGS), max = *((t_CKFLOAT *)ARGS + 1);
555 RETURN->v_float = min + (max-min)*(::rand()/(t_CKFLOAT)RAND_MAX);
558 // randi
559 CK_DLL_SFUN( rand2_impl ) // inclusive.
561 int min = *(int *)ARGS, max = *((int *)ARGS + 1);
562 int range = max - min;
563 if ( range == 0 )
565 RETURN->v_int = min;
567 //else if ( range < RAND_MAX / 2 ) {
568 // RETURN->v_int = ( range > 0 ) ? min + irand_exclusive(1 + range) : max + irand_exclusive ( -range + 1 ) ;
570 else
572 if( range > 0 )
574 RETURN->v_int = min + (int) ( (1.0 + range) * ( ::rand()/(RAND_MAX+1.0) ) );
576 else
578 RETURN->v_int = min - (int) ( (-range + 1.0) * ( ::rand()/(RAND_MAX+1.0) ) );
583 // srand
584 CK_DLL_SFUN( srand_impl )
586 t_CKINT seed = GET_CK_INT(ARGS);
587 ::srand( seed );
590 // sgn
591 CK_DLL_SFUN( sgn_impl )
593 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
594 RETURN->v_float = v == 0.0f ? 0.0f : ( v > 0.0f ? 1.0f : -1.0f );
597 // system
598 CK_DLL_SFUN( system_impl )
600 const char * cmd = GET_CK_STRING(ARGS)->str.c_str();
602 // check globals for permission
603 if( !g_enable_system_cmd )
605 fprintf( stderr, "[chuck]:error: VM not authorized to call Std.system( string )...\n" );
606 fprintf( stderr, "[chuck]: (command string was: \"%s\")\n", cmd );
607 fprintf( stderr, "[chuck]: (note: enable via --caution-to-the-wind flag or other means)\n" );
608 RETURN->v_int = 0;
610 else
612 // log
613 EM_log( CK_LOG_SEVERE, "invoking system( CMD )..." );
614 EM_pushlog();
615 EM_log( CK_LOG_SEVERE, "CMD: \"%s\"", cmd );
616 EM_poplog();
617 RETURN->v_int = system( cmd );
621 // aoti
622 CK_DLL_SFUN( atoi_impl )
624 Chuck_String * str = GET_CK_STRING(ARGS);
625 if( str )
627 const char * v = str->str.c_str();
628 RETURN->v_int = atoi( v );
630 else
632 RETURN->v_int = 0;
636 // atof
637 CK_DLL_SFUN( atof_impl )
639 Chuck_String * str = GET_CK_STRING(ARGS);
640 if( str )
642 const char * v = GET_CK_STRING(ARGS)->str.c_str();
643 RETURN->v_float = atof( v );
645 else
647 RETURN->v_float = 0.0;
651 // itoa
652 CK_DLL_SFUN( itoa_impl )
654 t_CKINT i = GET_CK_INT(ARGS);
655 // TODO: memory leak, please fix. Thanks.
656 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
657 a->str = itoa( i );
658 RETURN->v_string = a;
661 // ftoa
662 CK_DLL_SFUN( ftoa_impl )
664 t_CKFLOAT f = GET_NEXT_FLOAT(ARGS);
665 t_CKINT p = GET_NEXT_INT(ARGS);
666 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
667 a->str = ftoa( f, (t_CKUINT)p );
668 RETURN->v_string = a;
671 // getenv
672 static Chuck_String g_str; // PROBLEM: not thread friendly
673 CK_DLL_SFUN( getenv_impl )
675 const char * v = GET_CK_STRING(ARGS)->str.c_str();
676 const char * s = getenv( v );
677 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
678 a->str = s ? s : "";
679 RETURN->v_string = a;
682 // setenv
683 CK_DLL_SFUN( setenv_impl )
685 const char * v1 = GET_NEXT_STRING(ARGS)->str.c_str();
686 const char * v2 = GET_NEXT_STRING(ARGS)->str.c_str();
687 RETURN->v_int = setenv( v1, v2, 1 );
691 // mtof
692 CK_DLL_SFUN( mtof_impl )
694 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
695 RETURN->v_float = mtof(v);
698 // ftom
699 CK_DLL_SFUN( ftom_impl )
701 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
702 RETURN->v_float = ftom(v);
705 // powtodb
706 CK_DLL_SFUN( powtodb_impl )
708 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
709 RETURN->v_float = powtodb(v);
712 // rmstodb
713 CK_DLL_SFUN( rmstodb_impl )
715 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
716 RETURN->v_float = rmstodb(v);
719 // dbtopow
720 CK_DLL_SFUN( dbtopow_impl )
722 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
723 RETURN->v_float = dbtopow(v);
726 // dbtorms
727 CK_DLL_SFUN( dbtorms_impl )
729 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
730 RETURN->v_float = dbtorms(v);
736 #ifndef __DISABLE_KBHIT__
737 // static
738 CBufferAdvance * KBHitManager::the_buf = NULL;
739 t_CKINT KBHitManager::the_onoff = 0;
740 t_CKBOOL KBHitManager::the_init = FALSE;
741 XThread * KBHitManager::the_thread;
742 #define BUFFER_SIZE 1024
745 #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
746 static void * kb_loop( void * )
747 #else
748 static unsigned int __stdcall kb_loop( void * )
749 #endif
751 t_CKINT c;
752 EM_log( CK_LOG_INFO, "starting kb loop..." );
754 // go
755 while( KBHitManager::the_init )
757 // if on
758 if( KBHitManager::the_onoff )
760 // see if we have kb hit
761 while( kb_hit() )
763 // get the next char
764 c = kb_getch();
765 // queue it
766 KBHitManager::the_buf->put( &c, 1 );
770 // wait
771 usleep( 5000 );
774 return 0;
778 // init
779 t_CKBOOL KBHitManager::init()
781 // sanity check
782 if( the_buf ) return FALSE;
784 EM_log( CK_LOG_INFO, "initializing KBHitManager..." );
785 the_buf = new CBufferAdvance;
786 if( !the_buf->initialize( BUFFER_SIZE, sizeof(t_CKINT) ) )
788 EM_log( CK_LOG_SEVERE, "KBHitManager: couldn't allocate central KB buffer..." );
789 SAFE_DELETE( the_buf );
790 return FALSE;
793 the_onoff = 0;
794 the_init = TRUE;
795 the_thread = new XThread;
796 the_thread->start( kb_loop, NULL );
799 return TRUE;
803 // shutdown
804 void KBHitManager::shutdown()
806 EM_log( CK_LOG_INFO, "shutting down KBHitManager..." );
807 SAFE_DELETE( the_buf );
808 kb_endwin();
810 the_onoff = 0;
811 the_init = FALSE;
815 // on()
816 void KBHitManager::on()
818 the_onoff++;
819 if( !kb_ready() )
820 kb_initscr();
824 // off()
825 void KBHitManager::off()
827 the_onoff--;
828 if( kb_ready() && the_onoff == 0 )
829 kb_endwin();
833 // open()
834 t_CKBOOL KBHitManager::open( KBHit * kb )
836 if( the_buf == NULL ) return FALSE;
837 if( kb->m_buffer != NULL ) return FALSE;
839 EM_log( CK_LOG_INFO, "adding KBHit..." );
840 // init the kb
841 kb->m_buffer = the_buf;
842 // read index
843 kb->m_read_index = kb->m_buffer->join( (Chuck_Event *)kb->SELF );
845 return TRUE;
849 // close()
850 t_CKBOOL KBHitManager::close( KBHit * kb )
852 if( the_buf == NULL ) return FALSE;
853 if( kb->m_buffer == NULL ) return FALSE;
855 EM_log( CK_LOG_INFO, "removing KBHit..." );
856 // unjoin
857 kb->m_buffer->resign( kb->m_read_index );
858 // done
859 kb->m_read_index = 0;
861 return TRUE;
865 // KBHit
866 KBHit::KBHit()
868 m_buffer = NULL;
869 m_read_index = 0;
870 m_valid = FALSE;
871 m_onoff = FALSE;
872 m_echo = FALSE;
873 SELF = NULL;
877 // ~KBHit()
878 KBHit::~KBHit()
880 this->close();
884 // open()
885 t_CKBOOL KBHit::open()
887 return KBHitManager::open( this );
891 // close()
892 t_CKBOOL KBHit::close()
894 return KBHitManager::close( this );
898 // on()
899 void KBHit::on()
901 if( m_onoff == FALSE )
903 KBHitManager::on();
904 open();
905 m_onoff = TRUE;
910 // off()
911 void KBHit::off()
913 if( m_onoff == TRUE )
915 KBHitManager::off();
916 open();
917 m_onoff = FALSE;
922 // empty
923 t_CKBOOL KBHit::empty()
925 if( m_buffer == NULL ) return TRUE;
926 if( m_onoff == FALSE ) return TRUE;
927 // if( m_read_index == 0 ) return TRUE;
928 return m_buffer->empty( m_read_index );
932 // getch
933 t_CKINT KBHit::getch()
935 t_CKINT c;
936 if( empty() ) return 0;
937 m_buffer->get( &c, 1, m_read_index );
938 return c;
942 // ctor
943 CK_DLL_CTOR( KBHit_ctor )
945 KBHit * kb = new KBHit;
946 OBJ_MEMBER_INT(SELF, KBHit_offset_data) = (t_CKINT)kb;
947 kb->SELF = SELF;
948 kb->on();
952 // dtor
953 CK_DLL_DTOR( KBHit_dtor )
955 delete (KBHit *)OBJ_MEMBER_INT(SELF, KBHit_offset_data);
956 OBJ_MEMBER_INT(SELF, KBHit_offset_data) = 0;
959 // on
960 CK_DLL_MFUN( KBHit_on )
962 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
963 kb->on();
967 // off
968 CK_DLL_MFUN( KBHit_off )
970 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
971 kb->off();
975 // state
976 CK_DLL_MFUN( KBHit_state )
978 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
979 RETURN->v_int = kb->state();
983 // hit
984 CK_DLL_MFUN( KBHit_hit )
986 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
987 RETURN->v_object = SELF;
991 // more
992 CK_DLL_MFUN( KBHit_more )
994 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
995 RETURN->v_int = (kb->empty() == FALSE);
999 // getchar
1000 CK_DLL_MFUN( KBHit_getchar )
1002 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
1003 RETURN->v_int = kb->getch();
1007 // can wait
1008 CK_DLL_MFUN( KBHit_can_wait )
1010 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
1011 RETURN->v_int = kb->empty();
1013 #endif // __DISABLE_KBHIT__
1018 #ifndef __DISABLE_PROMPTER__
1019 class LineEvent : public Chuck_Event
1021 public:
1022 LineEvent( Chuck_Event * SELF );
1023 ~LineEvent();
1025 public:
1026 void prompt( const string & what = "" );
1027 t_CKBOOL more();
1028 string getLine();
1029 t_CKBOOL can_wait();
1030 void enqueue( const string & line )
1031 { m_q.push( line ); }
1033 Chuck_Event * SELF;
1035 protected:
1036 queue<string> m_q;
1039 // global variables
1040 t_CKBOOL g_le_launched = FALSE;
1041 t_CKBOOL g_le_wait = TRUE;
1042 // CHUCK_THREAD g_tid_le = 0;
1043 extern CHUCK_THREAD g_tid_whatever;
1044 map<LineEvent *, LineEvent *> g_le_map;
1045 XMutex g_le_mutex;
1046 string g_le_what;
1047 extern Chuck_VM * g_vm;
1049 void * le_cb( void * p )
1051 char line[2048];
1052 map<LineEvent *, LineEvent *>::iterator iter;
1053 LineEvent * le = NULL;
1055 // loop
1056 while( true )
1058 // wait
1059 while( g_le_wait )
1060 usleep( 10000 );
1062 // check
1063 if( !g_vm ) break;
1065 // do the prompt
1066 cout << g_le_what;
1067 cout.flush();
1068 if( !cin.getline( line, 2048 ) ) break;
1070 // lock
1071 g_le_mutex.acquire();
1072 // go through
1073 for( iter = g_le_map.begin(); iter != g_le_map.end(); iter++ )
1075 // get the line event
1076 le = (*iter).first;
1077 // add to its queue
1078 le->enqueue( line );
1079 // broadcast it
1080 le->SELF->queue_broadcast();
1082 // unlock
1083 g_le_mutex.release();
1085 // reset wait
1086 g_le_wait = TRUE;
1089 return NULL;
1093 LineEvent::LineEvent( Chuck_Event * SELF )
1095 // launch the cb
1096 if( !g_le_launched )
1098 #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
1099 pthread_create( &g_tid_whatever, NULL, le_cb, NULL );
1100 #else
1101 g_tid_whatever = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)le_cb, NULL, 0, 0 );
1102 #endif
1103 g_le_launched = TRUE;
1106 // lock
1107 g_le_mutex.acquire();
1108 // add
1109 g_le_map[this] = this;
1110 this->SELF = SELF;
1111 // unlock
1112 g_le_mutex.release();
1115 LineEvent::~LineEvent()
1117 // do nothing
1120 void LineEvent::prompt( const string & what )
1122 // set what
1123 g_le_what = what;
1124 if( g_le_what != "" ) g_le_what += " ";
1125 // signal
1126 g_le_wait = FALSE;
1129 t_CKBOOL LineEvent::more()
1131 // more
1132 return m_q.size() > 0;
1135 string LineEvent::getLine()
1137 string ret;
1139 // lock
1140 g_le_mutex.acquire();
1141 // get next line
1142 if( m_q.size() )
1144 // get it
1145 ret = m_q.front();
1146 // dequeue it
1147 m_q.pop();
1149 else
1151 ret = "[ERROR -> getLine() called on empty Skot]";
1153 // unlock
1154 g_le_mutex.release();
1156 return ret;
1159 t_CKBOOL LineEvent::can_wait()
1161 return !more();
1165 // Skot
1166 CK_DLL_CTOR( Skot_ctor )
1168 LineEvent * le = new LineEvent((Chuck_Event *)SELF);
1169 OBJ_MEMBER_INT(SELF, Skot_offset_data) = (t_CKINT)le;
1172 CK_DLL_DTOR( Skot_dtor )
1174 delete (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1175 OBJ_MEMBER_INT(SELF, Skot_offset_data) = 0;
1178 CK_DLL_MFUN( Skot_prompt )
1180 LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1181 le->prompt();
1182 RETURN->v_int = (t_CKINT)(SELF);
1185 CK_DLL_MFUN( Skot_prompt2 )
1187 LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1188 const char * v = GET_CK_STRING(ARGS)->str.c_str();
1189 le->prompt( v );
1190 RETURN->v_int = (t_CKINT)(SELF);
1193 CK_DLL_MFUN( Skot_more )
1195 LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1196 RETURN->v_int = le->more();
1199 CK_DLL_MFUN( Skot_getLine )
1201 LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1202 // TODO: memory leak
1203 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
1204 a->str = le->getLine();
1205 RETURN->v_string = a;
1208 CK_DLL_MFUN( Skot_can_wait )
1210 LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1211 RETURN->v_int = le->can_wait();
1213 #endif // __DISABLE_PROMPTER__
1216 // StrTok
1217 class StrTok
1219 public:
1220 StrTok();
1221 ~StrTok();
1223 public:
1224 void set( const string & line );
1225 void reset();
1226 t_CKBOOL more();
1227 string next();
1228 string get( t_CKINT index );
1229 t_CKINT size();
1231 protected:
1232 istringstream * m_ss;
1233 string m_next;
1234 vector<string> m_tokens;
1235 vector<string>::size_type m_index;
1238 StrTok::StrTok()
1240 m_ss = NULL;
1241 m_index = 0;
1244 StrTok::~StrTok()
1246 SAFE_DELETE( m_ss );
1249 void StrTok::set( const string & line )
1251 string s;
1253 // delete
1254 SAFE_DELETE( m_ss );
1255 // alloc
1256 m_ss = new istringstream( line );
1257 // read
1258 reset();
1259 m_tokens.clear();
1260 while( (*m_ss) >> s )
1261 m_tokens.push_back( s );
1264 void StrTok::reset()
1266 m_index = 0;
1269 t_CKBOOL StrTok::more()
1271 return m_index < m_tokens.size();
1274 string StrTok::next()
1276 if( !more() ) return "";
1277 return m_tokens[m_index++];
1280 string StrTok::get( t_CKINT index )
1282 if( index >= (t_CKINT)m_tokens.size() ) return "";
1283 return m_tokens[index];
1286 t_CKINT StrTok::size()
1288 return (t_CKINT)m_tokens.size();
1291 CK_DLL_CTOR( StrTok_ctor )
1293 StrTok * tokens = new StrTok;
1294 OBJ_MEMBER_INT(SELF, StrTok_offset_data) = (t_CKINT)tokens;
1297 CK_DLL_DTOR( StrTok_dtor )
1299 delete (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1300 OBJ_MEMBER_INT(SELF, StrTok_offset_data) = 0;
1303 CK_DLL_MFUN( StrTok_set )
1305 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1306 Chuck_String * s = GET_CK_STRING(ARGS);
1307 if( s ) tokens->set( s->str );
1308 else tokens->set( "" );
1311 CK_DLL_MFUN( StrTok_reset )
1313 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1314 tokens->reset();
1317 CK_DLL_MFUN( StrTok_more )
1319 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1320 RETURN->v_int = (t_CKINT)tokens->more();
1323 CK_DLL_MFUN( StrTok_next )
1325 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1326 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
1327 a->str = tokens->next();
1328 RETURN->v_string = a;
1331 CK_DLL_MFUN( StrTok_next2 )
1333 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1334 Chuck_String * a = GET_CK_STRING(ARGS);
1335 string s = tokens->next();
1336 if( a ) a->str = s;
1337 RETURN->v_string = a;
1340 CK_DLL_MFUN( StrTok_get )
1342 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1343 t_CKINT index = GET_NEXT_INT(ARGS);
1344 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
1345 string s = tokens->get( index );
1346 a->str = s;
1347 RETURN->v_string = a;
1350 CK_DLL_MFUN( StrTok_get2 )
1352 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1353 t_CKINT index = GET_NEXT_INT(ARGS);
1354 Chuck_String * a = GET_NEXT_STRING(ARGS);
1355 string s = tokens->get( index );
1356 if( a ) a->str = s;
1357 RETURN->v_string = a;
1360 CK_DLL_MFUN( StrTok_size )
1362 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1363 RETURN->v_int = tokens->size();
1369 #ifdef AJAY
1372 class ColumnReader
1374 public:
1375 ColumnReader();
1376 virtual ~ColumnReader();
1378 bool init( const string & filename, long col );
1380 bool reset() { if( !fin.good() ) return false; where = 0; return true; }
1381 bool seek( long pos ) { if( pos < 0 || pos >= values.size() ) return false; where = pos; return true; }
1382 bool more() { return where < values.size(); }
1383 double curr();
1384 bool next() { if( where < values.size() ) where++; return more(); }
1385 long pos() { return where; }
1386 long size() { return values.size(); }
1387 string name() { return n; }
1389 Chuck_String s;
1391 protected:
1392 bool get_str( string & out );
1393 bool get_double( double & out );
1395 protected:
1396 ifstream fin;
1397 string n;
1398 long column;
1399 long where;
1400 char line[0x1000];
1401 long len;
1403 vector<double> values;
1407 ColumnReader::ColumnReader()
1409 n = "[NONE]";
1410 column = -1;
1411 where = -1;
1412 len = 0x1000;
1416 ColumnReader::~ColumnReader()
1418 // close file
1419 if( fin.good() )
1420 fin.close();
1423 bool ColumnReader::init( const string & filename, long col )
1425 // hmm
1426 if( col < 1 )
1428 cerr << "column must be greater than 0!!!" << endl;
1429 return false;
1432 // open file
1433 fin.open( filename.c_str(), ios::in );
1434 // yes
1435 if( !fin.good() )
1437 cerr << "ColumnReader: cannot open file: '" << filename << "'..." << endl;
1438 return false;
1441 // set column
1442 column = col;
1444 // read first line
1445 if( !fin.getline( line, len ) )
1447 cerr << "ColumnReader: cannot read first line: '" << filename << "'..." << endl;
1448 return false;
1451 // get the name
1452 if( !get_str( n ) )
1454 cerr << "ColumnReader: cannot seek to column " << col << ": " << filename << "..." << endl;
1455 return false;
1458 double v;
1459 long i = 1;
1460 // read values
1461 while( fin.getline( line, len ) )
1463 v = 0.0;
1464 // get value
1465 if( !get_double( v ) )
1467 cerr << "ColumnReader: cannot read column " << v << " on line i: " << n << "..." << endl;
1468 return false;
1471 values.push_back( v );
1474 // well
1475 if( values.size() == 0 )
1477 cerr << "ColumnReader: file doesn't not contain data after first line: " << n << "..." << endl;
1478 return false;
1481 // set location
1482 where = 0;
1484 s.str = n;
1486 return true;
1489 double ColumnReader::curr()
1491 if( where >= values.size() )
1493 cerr << "ColumnReader: trying to read beyond end of file: " << n << "..." << endl;
1494 return 0.0;
1497 return values[where];
1500 bool ColumnReader::get_double( double & out )
1502 assert( column > 0 );
1503 long c = 1;
1505 char * start = line;
1506 char * curr = start;
1508 while( c < column )
1510 // move past value
1511 while( *curr && *curr != ',' ) curr++;
1512 // move past ,
1513 while( *curr && *curr == ',' ) curr++;
1514 // check
1515 if( *curr == '\0' )
1517 cerr << "ColumnReader: cannot find column " << column << ": " << n << endl;
1518 return false;
1521 // increment
1522 c++;
1523 // set start
1524 start = curr;
1527 // move past value
1528 while( *curr && *curr != ',' ) curr++;
1529 // end
1530 *curr = '\0';
1532 out = atof( start );
1534 return true;
1538 bool ColumnReader::get_str( string & out )
1540 assert( column > 0 );
1541 long c = 1;
1543 char * start = line;
1544 char * curr = start;
1546 while( c < column )
1548 // move past value
1549 while( *curr && *curr != ',' ) curr++;
1550 // move past ,
1551 while( *curr && *curr == ',' ) curr++;
1552 // check
1553 if( *curr == '\0' )
1555 cerr << "ColumnReader: cannot find column " << column << ": " << n << endl;
1556 return false;
1559 // increment
1560 c++;
1561 // set start
1562 start = curr;
1565 // move past value
1566 while( *curr && *curr != ',' ) curr++;
1567 // end
1568 *curr = '\0';
1570 out = start;
1572 return true;
1576 CK_DLL_CTOR( VCR_ctor )
1578 OBJ_MEMBER_INT(SELF, VCR_offset_data) = (t_CKUINT)new ColumnReader;
1581 CK_DLL_MFUN( VCR_load )
1583 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1584 const char * filename = GET_NEXT_STRING(ARGS)->str.c_str();
1585 t_CKINT column = GET_NEXT_INT(ARGS);
1586 RETURN->v_int = vcr->init( filename, column );
1589 CK_DLL_MFUN( VCR_reset )
1591 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1592 RETURN->v_int = vcr->reset();
1595 CK_DLL_MFUN( VCR_seek )
1597 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1598 t_CKINT where = GET_CK_INT(ARGS);
1599 RETURN->v_int = vcr->seek( where );
1602 CK_DLL_MFUN( VCR_more )
1604 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1605 RETURN->v_int = vcr->more();
1608 CK_DLL_MFUN( VCR_curr )
1610 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1611 RETURN->v_float = vcr->curr();
1614 CK_DLL_MFUN( VCR_next )
1616 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1617 RETURN->v_int = vcr->next();
1620 CK_DLL_MFUN( VCR_pos )
1622 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1623 RETURN->v_int = vcr->pos();
1626 CK_DLL_MFUN( VCR_size )
1628 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1629 RETURN->v_int = vcr->size();
1632 CK_DLL_MFUN( VCR_name )
1634 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1635 RETURN->v_string = &(vcr->s);
1639 #ifdef __PLATFORM_WIN32__
1642 // jeff's cereal
1643 class Serial
1645 public:
1646 // one stop bit, 8 bits, no parity
1647 Serial();
1648 ~Serial();
1650 unsigned read( char * buffer, unsigned numberOfBytesToRead );
1651 unsigned write( char * buffer, unsigned numberOfBytesToWrite );
1653 void write( char c );
1654 char read();
1656 unsigned available() const;
1658 t_CKBOOL open( char * port, t_CKUINT baudrate );
1659 void close();
1661 private:
1662 HANDLE serialFile;
1666 Serial::Serial( )
1668 serialFile = NULL;
1671 Serial::~Serial( )
1673 close();
1676 t_CKBOOL Serial::open( char * port, t_CKUINT baudrate )
1678 if( serialFile )
1679 close();
1681 // open port
1682 serialFile = CreateFile( port,
1683 GENERIC_READ | GENERIC_WRITE,
1686 OPEN_EXISTING,
1687 FILE_ATTRIBUTE_NORMAL,
1688 0 );
1689 if( serialFile == INVALID_HANDLE_VALUE )
1691 if( GetLastError() == ERROR_FILE_NOT_FOUND )
1693 EM_log( CK_LOG_SYSTEM, "error: cannot open serial port '%s'...", port );
1695 else
1697 EM_log( CK_LOG_SYSTEM, "error opening serial port '%s'...", port );
1700 return FALSE;
1703 // set params
1704 DCB dcbSerialParams = {0};
1705 dcbSerialParams.DCBlength = sizeof( dcbSerialParams );
1706 if( !GetCommState( serialFile, &dcbSerialParams) )
1708 EM_log( CK_LOG_SYSTEM, "error getting serial state..." );
1709 close();
1710 return FALSE;
1713 dcbSerialParams.BaudRate = baudrate;
1714 dcbSerialParams.ByteSize = 8;
1715 dcbSerialParams.StopBits = ONESTOPBIT;
1716 dcbSerialParams.Parity = NOPARITY;
1717 if( !SetCommState( serialFile, &dcbSerialParams ) )
1719 EM_log( CK_LOG_SYSTEM, "error setting serial state..." );
1720 close();
1721 return FALSE;
1724 // SET TIMEOUTS
1726 COMMTIMEOUTS timeouts = {0};
1727 timeouts.ReadIntervalTimeout = 50;
1728 timeouts.ReadTotalTimeoutConstant = 50;
1729 timeouts.ReadTotalTimeoutMultiplier = 10;
1730 timeouts.WriteTotalTimeoutConstant= 50;
1731 timeouts.WriteTotalTimeoutMultiplier = 10;
1732 if( !SetCommTimeouts( serialFile, &timeouts ) )
1734 //error occureed. Inform user
1738 return TRUE;
1741 void Serial::close()
1743 if( serialFile )
1745 CloseHandle( serialFile );
1746 serialFile = NULL;
1750 void Serial::write( char c )
1752 write( &c, 1 );
1755 char Serial::read()
1757 char c = '\0';
1758 read( &c, 1 );
1759 return c;
1762 unsigned Serial::available() const
1764 struct _COMSTAT status;
1765 unsigned long etat;
1766 memset( &status, 0, sizeof(status) );
1768 if( serialFile )
1770 ClearCommError( serialFile, &etat, &status);
1771 return status.cbInQue;
1774 return 0;
1777 // try to read numberOfBytesToRead into buffer, return how many bytes read
1778 unsigned Serial::read( char * buffer, unsigned numberOfBytesToRead )
1780 DWORD bytesRead = 0;
1781 if( serialFile )
1782 ReadFile( serialFile, buffer, numberOfBytesToRead, &bytesRead, NULL );
1783 return bytesRead;
1786 // try to write numberOfBytesToWrite to serial from buffer, return how many bytes written
1787 unsigned Serial::write( char * buffer, unsigned numberOfBytesToWrite )
1789 DWORD bytesWritten = 0;
1790 if( serialFile )
1791 WriteFile( serialFile, buffer, numberOfBytesToWrite, &bytesWritten, NULL );
1792 return bytesWritten;
1796 // ctor
1797 CK_DLL_CTOR( Cereal_ctor )
1799 OBJ_MEMBER_UINT(SELF, Cereal_offset_data) = (t_CKUINT)new Serial;
1802 // open
1803 CK_DLL_MFUN( Cereal_open )
1805 Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data);
1806 Chuck_String * str = GET_NEXT_STRING(ARGS);
1807 t_CKINT i = GET_NEXT_INT(ARGS);
1809 // close
1810 s->close();
1812 if( str )
1813 RETURN->v_int = s->open( (char *)str->str.c_str(), i );
1814 else
1815 RETURN->v_int = 0;
1818 // close
1819 CK_DLL_MFUN( Cereal_close )
1821 Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data);
1822 s->close();
1825 // more
1826 CK_DLL_MFUN( Cereal_more )
1828 Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data);
1829 RETURN->v_int = s->available();
1832 // send
1833 CK_DLL_MFUN( Cereal_send )
1835 Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data);
1836 t_CKINT i = GET_NEXT_INT(ARGS);
1837 s->write( i );
1838 RETURN->v_int = i;
1841 // recv
1842 CK_DLL_MFUN( Cereal_recv )
1844 Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data);
1845 if( s->available() )
1846 RETURN->v_int = (t_CKINT)s->read();
1847 else
1848 RETURN->v_int = 0;
1851 #endif
1854 #endif