*** empty log message ***
[chuck-blob.git] / v2 / ulib_std.cpp
blobe6e8cc90474cfa79f2f843e129340f397209230e
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 // KBHit
69 CK_DLL_CTOR( KBHit_ctor );
70 CK_DLL_DTOR( KBHit_dtor );
71 CK_DLL_MFUN( KBHit_on );
72 CK_DLL_MFUN( KBHit_off );
73 CK_DLL_MFUN( KBHit_state );
74 CK_DLL_MFUN( KBHit_hit );
75 CK_DLL_MFUN( KBHit_more );
76 CK_DLL_MFUN( KBHit_getchar );
77 CK_DLL_MFUN( KBHit_can_wait );
79 static t_CKUINT KBHit_offset_data = 0;
81 // Skot functions
82 CK_DLL_CTOR( Skot_ctor );
83 CK_DLL_DTOR( Skot_dtor );
84 CK_DLL_MFUN( Skot_prompt );
85 CK_DLL_MFUN( Skot_prompt2 );
86 CK_DLL_MFUN( Skot_more );
87 CK_DLL_MFUN( Skot_getLine );
88 CK_DLL_MFUN( Skot_can_wait );
90 static t_CKUINT Skot_offset_data = 0;
92 // StrTok functions
93 CK_DLL_CTOR( StrTok_ctor );
94 CK_DLL_DTOR( StrTok_dtor );
95 CK_DLL_MFUN( StrTok_set );
96 CK_DLL_MFUN( StrTok_reset );
97 CK_DLL_MFUN( StrTok_more );
98 CK_DLL_MFUN( StrTok_next );
99 CK_DLL_MFUN( StrTok_next2 );
100 CK_DLL_MFUN( StrTok_get );
101 CK_DLL_MFUN( StrTok_get2 );
102 CK_DLL_MFUN( StrTok_size );
104 static t_CKUINT StrTok_offset_data = 0;
106 #ifdef AJAY
108 #include <fstream>
110 // VCR functions
111 CK_DLL_CTOR( VCR_ctor );
112 CK_DLL_MFUN( VCR_load );
113 CK_DLL_MFUN( VCR_reset );
114 CK_DLL_MFUN( VCR_seek );
115 CK_DLL_MFUN( VCR_more );
116 CK_DLL_MFUN( VCR_curr );
117 CK_DLL_MFUN( VCR_next );
118 CK_DLL_MFUN( VCR_pos );
119 CK_DLL_MFUN( VCR_size );
120 CK_DLL_MFUN( VCR_name );
122 static t_CKUINT VCR_offset_data = 0;
124 // Cereal functions
125 CK_DLL_CTOR( Cereal_ctor );
126 CK_DLL_MFUN( Cereal_open );
127 CK_DLL_MFUN( Cereal_close );
128 CK_DLL_MFUN( Cereal_send );
129 CK_DLL_MFUN( Cereal_recv );
130 CK_DLL_MFUN( Cereal_more );
132 static t_CKUINT Cereal_offset_data = 0;
134 #endif
139 //-----------------------------------------------------------------------------
140 // name: libstd_query()
141 // desc: query entry point
142 //-----------------------------------------------------------------------------
143 DLL_QUERY libstd_query( Chuck_DL_Query * QUERY )
145 // get global
146 Chuck_Env * env = Chuck_Env::instance();
147 // set name
148 QUERY->setname( QUERY, "Std" );
150 /*! \example
151 std.rand2f( 100.0, 1000.0 ) => stdout;
154 // register deprecate
155 type_engine_register_deprecate( env, "std", "Std" );
157 // begin class
158 QUERY->begin_class( QUERY, "Std", "Object" );
160 // add abs
161 QUERY->add_sfun( QUERY, abs_impl, "int", "abs" );
162 QUERY->add_arg( QUERY, "int", "value" );
164 // add fabs
165 QUERY->add_sfun( QUERY, fabs_impl, "float", "fabs" );
166 QUERY->add_arg( QUERY, "float", "value" );
168 // add rand
169 QUERY->add_sfun( QUERY, rand_impl, "int", "rand"); //! return int between 0 and RAND_MAX
171 // add rand2
172 QUERY->add_sfun( QUERY, rand2_impl, "int", "rand2" ); //! integer between [min,max]
173 QUERY->add_arg( QUERY, "int", "min" );
174 QUERY->add_arg( QUERY, "int", "max" );
176 // add rand
177 QUERY->add_sfun( QUERY, randf_impl, "float", "randf" ); //! rand between -1.0,1.0
179 // add rand2
180 QUERY->add_sfun( QUERY, rand2f_impl, "float", "rand2f" ); //! rand between min and max
181 QUERY->add_arg( QUERY, "float", "min" );
182 QUERY->add_arg( QUERY, "float", "max" );
184 // add srand
185 QUERY->add_sfun( QUERY, srand_impl, "void", "srand" );
186 QUERY->add_arg( QUERY, "int", "seed" );
188 // add sgn
189 QUERY->add_sfun( QUERY, sgn_impl, "float", "sgn" ); //! return sign of value (-1, 0, 1)
190 QUERY->add_arg( QUERY, "float", "value" );
192 // add system
193 //! see \example std.ck
194 QUERY->add_sfun( QUERY, system_impl, "int", "system" ); //! issue system command
195 QUERY->add_arg( QUERY, "string", "cmd" );
197 // add atoi
198 QUERY->add_sfun( QUERY, atoi_impl, "int", "atoi" ); //! string to integer
199 QUERY->add_arg( QUERY, "string", "value" );
201 // add atof
202 QUERY->add_sfun( QUERY, atof_impl, "float", "atof" ); //! string to float
203 QUERY->add_arg( QUERY, "string", "value" );
205 // add itoa
206 QUERY->add_sfun( QUERY, itoa_impl, "string", "itoa" ); //! int to string
207 QUERY->add_arg( QUERY, "int", "i" );
209 // add ftoa
210 QUERY->add_sfun( QUERY, ftoa_impl, "string", "ftoa" ); //! float to string
211 QUERY->add_arg( QUERY, "float", "f" );
212 QUERY->add_arg( QUERY, "int", "precision" );
214 // add getenv
215 QUERY->add_sfun( QUERY, getenv_impl, "string", "getenv" ); //! fetch environment variable
216 QUERY->add_arg( QUERY, "string", "value" );
218 // add setenv
219 QUERY->add_sfun( QUERY, setenv_impl, "int", "setenv" ); //! set environment variable
220 QUERY->add_arg( QUERY, "string", "key" );
221 QUERY->add_arg( QUERY, "string", "value" );
223 // add mtof
224 //! see \example mand-o-matic.ck
225 QUERY->add_sfun( QUERY, mtof_impl, "float", "mtof" ); //! midi note to frequency
226 QUERY->add_arg( QUERY, "float", "value" );
228 // add ftom
229 QUERY->add_sfun( QUERY, ftom_impl, "float", "ftom" ); //! frequency to midi note
230 QUERY->add_arg( QUERY, "float", "value" );
232 // add powtodb
233 QUERY->add_sfun( QUERY, powtodb_impl, "float", "powtodb" ); //! linear power to decibel
234 QUERY->add_arg( QUERY, "float", "value" );
236 // add rmstodb
237 QUERY->add_sfun( QUERY, rmstodb_impl, "float", "rmstodb" ); //! rms to decibel
238 QUERY->add_arg( QUERY, "float", "value" );
240 // add dbtopow
241 QUERY->add_sfun( QUERY, dbtopow_impl, "float", "dbtopow" ); //! decibel to linear
242 QUERY->add_arg( QUERY, "float", "value" );
244 // add dbtorms
245 QUERY->add_sfun( QUERY, dbtorms_impl, "float", "dbtorms" ); //! decibel to rms
246 QUERY->add_arg( QUERY, "float", "value" );
248 // finish class
249 QUERY->end_class( QUERY );
251 // seed the rand
252 srand( time( NULL ) );
254 Chuck_DL_Func * func = NULL;
256 // KBHit
257 // begin class (KBHit)
258 if( !type_engine_import_class_begin( env, "KBHit", "Event",
259 env->global(), KBHit_ctor,
260 KBHit_dtor ) )
261 return FALSE;
263 // add member variable
264 KBHit_offset_data = type_engine_import_mvar( env, "int", "@KBHit_data", FALSE );
265 if( KBHit_offset_data == CK_INVALID_OFFSET ) goto error;
267 // add on()
268 func = make_new_mfun( "void", "on", KBHit_on );
269 if( !type_engine_import_mfun( env, func ) ) goto error;
271 // add off()
272 func = make_new_mfun( "void", "off", KBHit_off );
273 if( !type_engine_import_mfun( env, func ) ) goto error;
275 // add state()
276 func = make_new_mfun( "void", "state", KBHit_state );
277 if( !type_engine_import_mfun( env, func ) ) goto error;
279 // add hit()
280 func = make_new_mfun( "Event", "hit", KBHit_hit );
281 if( !type_engine_import_mfun( env, func ) ) goto error;
283 // add more()
284 func = make_new_mfun( "int", "more", KBHit_more );
285 if( !type_engine_import_mfun( env, func ) ) goto error;
287 // add getchar()
288 func = make_new_mfun( "int", "getchar", KBHit_getchar );
289 if( !type_engine_import_mfun( env, func ) ) goto error;
291 // add can_wait()
292 func = make_new_mfun( "int", "can_wait", KBHit_can_wait );
293 if( !type_engine_import_mfun( env, func ) ) goto error;
295 // end class
296 type_engine_import_class_end( env );
298 // start it
299 KBHitManager::init();
302 // register deprecate
303 type_engine_register_deprecate( env, "Skot", "ConsoleInput" );
305 // begin class (Skot)
306 if( !type_engine_import_class_begin( env, "ConsoleInput", "Event",
307 env->global(), Skot_ctor,
308 Skot_dtor ) )
309 return FALSE;
311 // add member variable
312 Skot_offset_data = type_engine_import_mvar( env, "int", "@Skot_data", FALSE );
313 if( Skot_offset_data == CK_INVALID_OFFSET ) goto error;
315 // add prompt()
316 func = make_new_mfun( "Event", "prompt", Skot_prompt );
317 if( !type_engine_import_mfun( env, func ) ) goto error;
319 // add prompt()
320 func = make_new_mfun( "Event", "prompt", Skot_prompt2 );
321 func->add_arg( "string", "what" );
322 if( !type_engine_import_mfun( env, func ) ) goto error;
324 // add ready()
325 func = make_new_mfun( "int", "more", Skot_more );
326 if( !type_engine_import_mfun( env, func ) ) goto error;
328 // add getString()
329 func = make_new_mfun( "string", "getLine", Skot_getLine );
330 if( !type_engine_import_mfun( env, func ) ) goto error;
332 // add can_wait()
333 func = make_new_mfun( "int", "can_wait", Skot_can_wait );
334 if( !type_engine_import_mfun( env, func ) ) goto error;
336 // end class
337 type_engine_import_class_end( env );
340 // register deprecate
341 type_engine_register_deprecate( env, "PRC", "StringTokenizer" );
343 // begin class (StrTok)
344 if( !type_engine_import_class_begin( env, "StringTokenizer", "Object",
345 env->global(), StrTok_ctor,
346 StrTok_dtor ) )
347 return FALSE;
349 // add member variable
350 StrTok_offset_data = type_engine_import_mvar( env, "int", "@StrTok_data", FALSE );
351 if( StrTok_offset_data == CK_INVALID_OFFSET ) goto error;
353 // add set()
354 func = make_new_mfun( "void", "set", StrTok_set );
355 func->add_arg( "string", "line" );
356 if( !type_engine_import_mfun( env, func ) ) goto error;
358 // add reset()
359 func = make_new_mfun( "void", "reset", StrTok_reset );
360 if( !type_engine_import_mfun( env, func ) ) goto error;
362 // add more()
363 func = make_new_mfun( "int", "more", StrTok_more );
364 if( !type_engine_import_mfun( env, func ) ) goto error;
366 // add next()
367 func = make_new_mfun( "string", "next", StrTok_next );
368 if( !type_engine_import_mfun( env, func ) ) goto error;
370 // add get()
371 func = make_new_mfun( "string", "next", StrTok_next2 );
372 func->add_arg( "string", "out" );
373 if( !type_engine_import_mfun( env, func ) ) goto error;
375 // add get()
376 func = make_new_mfun( "string", "get", StrTok_get );
377 func->add_arg( "int", "index" );
378 if( !type_engine_import_mfun( env, func ) ) goto error;
380 // add get()
381 func = make_new_mfun( "string", "get", StrTok_get2 );
382 func->add_arg( "int", "index" );
383 func->add_arg( "string", "out" );
384 if( !type_engine_import_mfun( env, func ) ) goto error;
386 // add size()
387 func = make_new_mfun( "int", "size", StrTok_size );
388 if( !type_engine_import_mfun( env, func ) ) goto error;
390 // end class
391 type_engine_import_class_end( env );
394 #ifdef AJAY
396 // begin class
397 // init base class
398 if( !type_engine_import_class_begin( env, "VCR", "Object",
399 env->global(), VCR_ctor ) )
400 return FALSE;
402 // add member variable
403 VCR_offset_data = type_engine_import_mvar( env, "int", "@me", FALSE );
404 if( VCR_offset_data == CK_INVALID_OFFSET ) goto error;
406 // add load()
407 func = make_new_mfun( "int", "load", VCR_load );
408 func->add_arg( "string", "filename" );
409 func->add_arg( "int", "column" );
410 if( !type_engine_import_mfun( env, func ) ) goto error;
412 // add reset()
413 func = make_new_mfun( "int", "reset", VCR_reset );
414 if( !type_engine_import_mfun( env, func ) ) goto error;
416 // add seek()
417 func = make_new_mfun( "int", "seek", VCR_seek );
418 func->add_arg( "int", "where" );
419 if( !type_engine_import_mfun( env, func ) ) goto error;
421 // add more()
422 func = make_new_mfun( "int", "more", VCR_more );
423 if( !type_engine_import_mfun( env, func ) ) goto error;
425 // add curr()
426 func = make_new_mfun( "float", "curr", VCR_curr );
427 if( !type_engine_import_mfun( env, func ) ) goto error;
429 // add next()
430 func = make_new_mfun( "int", "next", VCR_next );
431 if( !type_engine_import_mfun( env, func ) ) goto error;
433 // add pos()
434 func = make_new_mfun( "int", "pos", VCR_pos );
435 if( !type_engine_import_mfun( env, func ) ) goto error;
437 // add size()
438 func = make_new_mfun( "int", "size", VCR_size );
439 if( !type_engine_import_mfun( env, func ) ) goto error;
441 // add name()
442 func = make_new_mfun( "string", "name", VCR_name );
443 if( !type_engine_import_mfun( env, func ) ) goto error;
445 // end the class import
446 type_engine_import_class_end( env );
449 #if defined(__PLATFORM_WIN32__)
450 // begin class (Cereal)
451 if( !type_engine_import_class_begin( env, "Cereal", "Object",
452 env->global(), Cereal_ctor ) )
453 return FALSE;
455 // add member
456 Cereal_offset_data = type_engine_import_mvar( env, "int", "@Cereal_data", FALSE );
457 if( Cereal_offset_data == CK_INVALID_OFFSET ) goto error;
459 // add open()
460 func = make_new_mfun( "int", "open", Cereal_open );
461 func->add_arg( "string", "name" );
462 func->add_arg( "int", "baudrate" );
463 if( !type_engine_import_mfun( env, func ) ) goto error;
465 // add close()
466 func = make_new_mfun( "void", "close", Cereal_close );
467 if( !type_engine_import_mfun( env, func ) ) goto error;
469 // add more()
470 func = make_new_mfun( "int", "more", Cereal_more );
471 if( !type_engine_import_mfun( env, func ) ) goto error;
473 // add send()
474 func = make_new_mfun( "int", "send", Cereal_send );
475 func->add_arg( "int", "bite" );
476 if( !type_engine_import_mfun( env, func ) ) goto error;
478 // add recv()
479 func = make_new_mfun( "int", "recv", Cereal_recv );
480 if( !type_engine_import_mfun( env, func ) ) goto error;
482 // end class
483 type_engine_import_class_end( env );
484 #endif
486 return TRUE;
488 #else
490 return TRUE;
492 #endif
494 error:
496 // end the class import
497 type_engine_import_class_end( env );
499 return FALSE;
503 #define RAND_INV_RANGE(r) (RAND_MAX / (r))
505 int irand_exclusive ( int max ) {
506 int x = ::rand();
508 while (x >= max * RAND_INV_RANGE (max))
509 x = ::rand();
511 x /= RAND_INV_RANGE (max);
512 return x;
516 // abs
517 CK_DLL_SFUN( abs_impl )
519 t_CKINT v = GET_CK_INT(ARGS);
520 RETURN->v_int = v >= 0 ? v : -v;
523 // fabs
524 CK_DLL_SFUN( fabs_impl )
526 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
527 RETURN->v_float = v >= 0.0 ? v : -v;
528 //RETURN->v_float = ::fabs( GET_CK_FLOAT(ARGS) );
531 // rand
532 CK_DLL_SFUN( rand_impl )
534 RETURN->v_int = ::rand();
537 // randf
538 CK_DLL_SFUN( randf_impl )
540 RETURN->v_float = ( 2.0 * ::rand() / (t_CKFLOAT)RAND_MAX - 1.0 );
543 // randf
544 CK_DLL_SFUN( rand2f_impl )
546 t_CKFLOAT min = GET_CK_FLOAT(ARGS), max = *((t_CKFLOAT *)ARGS + 1);
547 RETURN->v_float = min + (max-min)*(::rand()/(t_CKFLOAT)RAND_MAX);
550 // randi
551 CK_DLL_SFUN( rand2_impl ) // inclusive.
553 int min = *(int *)ARGS, max = *((int *)ARGS + 1);
554 int range = max - min;
555 if ( range == 0 )
557 RETURN->v_int = min;
559 //else if ( range < RAND_MAX / 2 ) {
560 // RETURN->v_int = ( range > 0 ) ? min + irand_exclusive(1 + range) : max + irand_exclusive ( -range + 1 ) ;
562 else
564 if( range > 0 )
566 RETURN->v_int = min + (int) ( (1.0 + range) * ( ::rand()/(RAND_MAX+1.0) ) );
568 else
570 RETURN->v_int = min - (int) ( (-range + 1.0) * ( ::rand()/(RAND_MAX+1.0) ) );
575 // srand
576 CK_DLL_SFUN( srand_impl )
578 t_CKINT seed = GET_CK_INT(ARGS);
579 ::srand( seed );
582 // sgn
583 CK_DLL_SFUN( sgn_impl )
585 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
586 RETURN->v_float = v == 0.0f ? 0.0f : ( v > 0.0f ? 1.0f : -1.0f );
589 // system
590 CK_DLL_SFUN( system_impl )
592 const char * cmd = GET_CK_STRING(ARGS)->str.c_str();
594 // check globals for permission
595 if( !g_enable_system_cmd )
597 fprintf( stderr, "[chuck]:error: VM not authorized to call Std.system( string )...\n" );
598 fprintf( stderr, "[chuck]: (command string was: \"%s\")\n", cmd );
599 fprintf( stderr, "[chuck]: (note: enable via --caution-to-the-wind flag or other means)\n" );
600 RETURN->v_int = 0;
602 else
604 // log
605 EM_log( CK_LOG_SEVERE, "invoking system( CMD )..." );
606 EM_pushlog();
607 EM_log( CK_LOG_SEVERE, "CMD: \"%s\"", cmd );
608 EM_poplog();
609 RETURN->v_int = system( cmd );
613 // aoti
614 CK_DLL_SFUN( atoi_impl )
616 Chuck_String * str = GET_CK_STRING(ARGS);
617 if( str )
619 const char * v = str->str.c_str();
620 RETURN->v_int = atoi( v );
622 else
624 RETURN->v_int = 0;
628 // atof
629 CK_DLL_SFUN( atof_impl )
631 Chuck_String * str = GET_CK_STRING(ARGS);
632 if( str )
634 const char * v = GET_CK_STRING(ARGS)->str.c_str();
635 RETURN->v_float = atof( v );
637 else
639 RETURN->v_float = 0.0;
643 // itoa
644 CK_DLL_SFUN( itoa_impl )
646 t_CKINT i = GET_CK_INT(ARGS);
647 // TODO: memory leak, please fix. Thanks.
648 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
649 a->str = itoa( i );
650 RETURN->v_string = a;
653 // ftoa
654 CK_DLL_SFUN( ftoa_impl )
656 t_CKFLOAT f = GET_NEXT_FLOAT(ARGS);
657 t_CKINT p = GET_NEXT_INT(ARGS);
658 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
659 a->str = ftoa( f, (t_CKUINT)p );
660 RETURN->v_string = a;
663 // getenv
664 static Chuck_String g_str; // PROBLEM: not thread friendly
665 CK_DLL_SFUN( getenv_impl )
667 const char * v = GET_CK_STRING(ARGS)->str.c_str();
668 const char * s = getenv( v );
669 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
670 a->str = s ? s : "";
671 RETURN->v_string = a;
674 // setenv
675 CK_DLL_SFUN( setenv_impl )
677 const char * v1 = GET_NEXT_STRING(ARGS)->str.c_str();
678 const char * v2 = GET_NEXT_STRING(ARGS)->str.c_str();
679 RETURN->v_int = setenv( v1, v2, 1 );
683 // mtof
684 CK_DLL_SFUN( mtof_impl )
686 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
687 RETURN->v_float = mtof(v);
690 // ftom
691 CK_DLL_SFUN( ftom_impl )
693 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
694 RETURN->v_float = ftom(v);
697 // powtodb
698 CK_DLL_SFUN( powtodb_impl )
700 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
701 RETURN->v_float = powtodb(v);
704 // rmstodb
705 CK_DLL_SFUN( rmstodb_impl )
707 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
708 RETURN->v_float = rmstodb(v);
711 // dbtopow
712 CK_DLL_SFUN( dbtopow_impl )
714 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
715 RETURN->v_float = dbtopow(v);
718 // dbtorms
719 CK_DLL_SFUN( dbtorms_impl )
721 t_CKFLOAT v = GET_CK_FLOAT(ARGS);
722 RETURN->v_float = dbtorms(v);
728 // static
729 CBufferAdvance * KBHitManager::the_buf = NULL;
730 t_CKINT KBHitManager::the_onoff = 0;
731 t_CKBOOL KBHitManager::the_init = FALSE;
732 XThread * KBHitManager::the_thread;
733 #define BUFFER_SIZE 1024
736 #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
737 static void * kb_loop( void * )
738 #else
739 static unsigned int __stdcall kb_loop( void * )
740 #endif
742 t_CKINT c;
743 EM_log( CK_LOG_INFO, "starting kb loop..." );
745 // go
746 while( KBHitManager::the_init )
748 // if on
749 if( KBHitManager::the_onoff )
751 // see if we have kb hit
752 while( kb_hit() )
754 // get the next char
755 c = kb_getch();
756 // queue it
757 KBHitManager::the_buf->put( &c, 1 );
761 // wait
762 usleep( 5000 );
765 return 0;
769 // init
770 t_CKBOOL KBHitManager::init()
772 // sanity check
773 if( the_buf ) return FALSE;
775 EM_log( CK_LOG_INFO, "initializing KBHitManager..." );
776 the_buf = new CBufferAdvance;
777 if( !the_buf->initialize( BUFFER_SIZE, sizeof(t_CKINT) ) )
779 EM_log( CK_LOG_SEVERE, "KBHitManager: couldn't allocate central KB buffer..." );
780 SAFE_DELETE( the_buf );
781 return FALSE;
784 the_onoff = 0;
785 the_init = TRUE;
786 the_thread = new XThread;
787 the_thread->start( kb_loop, NULL );
789 return TRUE;
793 // shutdown
794 void KBHitManager::shutdown()
796 EM_log( CK_LOG_INFO, "shutting down KBHitManager..." );
797 SAFE_DELETE( the_buf );
798 kb_endwin();
800 the_onoff = 0;
801 the_init = FALSE;
805 // on()
806 void KBHitManager::on()
808 the_onoff++;
809 if( !kb_ready() )
810 kb_initscr();
814 // off()
815 void KBHitManager::off()
817 the_onoff--;
818 if( kb_ready() && the_onoff == 0 )
819 kb_endwin();
823 // open()
824 t_CKBOOL KBHitManager::open( KBHit * kb )
826 if( the_buf == NULL ) return FALSE;
827 if( kb->m_buffer != NULL ) return FALSE;
829 EM_log( CK_LOG_INFO, "adding KBHit..." );
830 // init the kb
831 kb->m_buffer = the_buf;
832 // read index
833 kb->m_read_index = kb->m_buffer->join( (Chuck_Event *)kb->SELF );
835 return TRUE;
839 // close()
840 t_CKBOOL KBHitManager::close( KBHit * kb )
842 if( the_buf == NULL ) return FALSE;
843 if( kb->m_buffer == NULL ) return FALSE;
845 EM_log( CK_LOG_INFO, "removing KBHit..." );
846 // unjoin
847 kb->m_buffer->resign( kb->m_read_index );
848 // done
849 kb->m_read_index = 0;
851 return TRUE;
855 // KBHit
856 KBHit::KBHit()
858 m_buffer = NULL;
859 m_read_index = 0;
860 m_valid = FALSE;
861 m_onoff = FALSE;
862 m_echo = FALSE;
863 SELF = NULL;
867 // ~KBHit()
868 KBHit::~KBHit()
870 this->close();
874 // open()
875 t_CKBOOL KBHit::open()
877 return KBHitManager::open( this );
881 // close()
882 t_CKBOOL KBHit::close()
884 return KBHitManager::close( this );
888 // on()
889 void KBHit::on()
891 if( m_onoff == FALSE )
893 KBHitManager::on();
894 open();
895 m_onoff = TRUE;
900 // off()
901 void KBHit::off()
903 if( m_onoff == TRUE )
905 KBHitManager::off();
906 open();
907 m_onoff = FALSE;
912 // empty
913 t_CKBOOL KBHit::empty()
915 if( m_buffer == NULL ) return TRUE;
916 if( m_onoff == FALSE ) return TRUE;
917 // if( m_read_index == 0 ) return TRUE;
918 return m_buffer->empty( m_read_index );
922 // getch
923 t_CKINT KBHit::getch()
925 t_CKINT c;
926 if( empty() ) return 0;
927 m_buffer->get( &c, 1, m_read_index );
928 return c;
932 // ctor
933 CK_DLL_CTOR( KBHit_ctor )
935 KBHit * kb = new KBHit;
936 OBJ_MEMBER_INT(SELF, KBHit_offset_data) = (t_CKINT)kb;
937 kb->SELF = SELF;
938 kb->on();
942 // dtor
943 CK_DLL_DTOR( KBHit_dtor )
945 delete (KBHit *)OBJ_MEMBER_INT(SELF, KBHit_offset_data);
946 OBJ_MEMBER_INT(SELF, KBHit_offset_data) = 0;
949 // on
950 CK_DLL_MFUN( KBHit_on )
952 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
953 kb->on();
957 // off
958 CK_DLL_MFUN( KBHit_off )
960 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
961 kb->off();
965 // state
966 CK_DLL_MFUN( KBHit_state )
968 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
969 RETURN->v_int = kb->state();
973 // hit
974 CK_DLL_MFUN( KBHit_hit )
976 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
977 RETURN->v_object = SELF;
981 // more
982 CK_DLL_MFUN( KBHit_more )
984 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
985 RETURN->v_int = (kb->empty() == FALSE);
989 // getchar
990 CK_DLL_MFUN( KBHit_getchar )
992 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
993 RETURN->v_int = kb->getch();
997 // can wait
998 CK_DLL_MFUN( KBHit_can_wait )
1000 KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data));
1001 RETURN->v_int = kb->empty();
1007 class LineEvent : public Chuck_Event
1009 public:
1010 LineEvent( Chuck_Event * SELF );
1011 ~LineEvent();
1013 public:
1014 void prompt( const string & what = "" );
1015 t_CKBOOL more();
1016 string getLine();
1017 t_CKBOOL can_wait();
1018 void enqueue( const string & line )
1019 { m_q.push( line ); }
1021 Chuck_Event * SELF;
1023 protected:
1024 queue<string> m_q;
1027 // global variables
1028 t_CKBOOL g_le_launched = FALSE;
1029 t_CKBOOL g_le_wait = TRUE;
1030 // CHUCK_THREAD g_tid_le = 0;
1031 extern CHUCK_THREAD g_tid_whatever;
1032 map<LineEvent *, LineEvent *> g_le_map;
1033 XMutex g_le_mutex;
1034 string g_le_what;
1035 extern Chuck_VM * g_vm;
1037 void * le_cb( void * p )
1039 char line[2048];
1040 map<LineEvent *, LineEvent *>::iterator iter;
1041 LineEvent * le = NULL;
1043 // loop
1044 while( true )
1046 // wait
1047 while( g_le_wait )
1048 usleep( 10000 );
1050 // check
1051 if( !g_vm ) break;
1053 // do the prompt
1054 cout << g_le_what;
1055 cout.flush();
1056 if( !cin.getline( line, 2048 ) ) break;
1058 // lock
1059 g_le_mutex.acquire();
1060 // go through
1061 for( iter = g_le_map.begin(); iter != g_le_map.end(); iter++ )
1063 // get the line event
1064 le = (*iter).first;
1065 // add to its queue
1066 le->enqueue( line );
1067 // broadcast it
1068 le->SELF->queue_broadcast();
1070 // unlock
1071 g_le_mutex.release();
1073 // reset wait
1074 g_le_wait = TRUE;
1077 return NULL;
1081 LineEvent::LineEvent( Chuck_Event * SELF )
1083 // launch the cb
1084 if( !g_le_launched )
1086 #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__)
1087 pthread_create( &g_tid_whatever, NULL, le_cb, NULL );
1088 #else
1089 g_tid_whatever = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)le_cb, NULL, 0, 0 );
1090 #endif
1091 g_le_launched = TRUE;
1094 // lock
1095 g_le_mutex.acquire();
1096 // add
1097 g_le_map[this] = this;
1098 this->SELF = SELF;
1099 // unlock
1100 g_le_mutex.release();
1103 LineEvent::~LineEvent()
1105 // do nothing
1108 void LineEvent::prompt( const string & what )
1110 // set what
1111 g_le_what = what;
1112 if( g_le_what != "" ) g_le_what += " ";
1113 // signal
1114 g_le_wait = FALSE;
1117 t_CKBOOL LineEvent::more()
1119 // more
1120 return m_q.size() > 0;
1123 string LineEvent::getLine()
1125 string ret;
1127 // lock
1128 g_le_mutex.acquire();
1129 // get next line
1130 if( m_q.size() )
1132 // get it
1133 ret = m_q.front();
1134 // dequeue it
1135 m_q.pop();
1137 else
1139 ret = "[ERROR -> getLine() called on empty Skot]";
1141 // unlock
1142 g_le_mutex.release();
1144 return ret;
1147 t_CKBOOL LineEvent::can_wait()
1149 return !more();
1153 // Skot
1154 CK_DLL_CTOR( Skot_ctor )
1156 LineEvent * le = new LineEvent((Chuck_Event *)SELF);
1157 OBJ_MEMBER_INT(SELF, Skot_offset_data) = (t_CKINT)le;
1160 CK_DLL_DTOR( Skot_dtor )
1162 delete (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1163 OBJ_MEMBER_INT(SELF, Skot_offset_data) = 0;
1166 CK_DLL_MFUN( Skot_prompt )
1168 LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1169 le->prompt();
1170 RETURN->v_int = (t_CKINT)(SELF);
1173 CK_DLL_MFUN( Skot_prompt2 )
1175 LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1176 const char * v = GET_CK_STRING(ARGS)->str.c_str();
1177 le->prompt( v );
1178 RETURN->v_int = (t_CKINT)(SELF);
1181 CK_DLL_MFUN( Skot_more )
1183 LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1184 RETURN->v_int = le->more();
1187 CK_DLL_MFUN( Skot_getLine )
1189 LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1190 // TODO: memory leak
1191 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
1192 a->str = le->getLine();
1193 RETURN->v_string = a;
1196 CK_DLL_MFUN( Skot_can_wait )
1198 LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data);
1199 RETURN->v_int = le->can_wait();
1203 // StrTok
1204 class StrTok
1206 public:
1207 StrTok();
1208 ~StrTok();
1210 public:
1211 void set( const string & line );
1212 void reset();
1213 t_CKBOOL more();
1214 string next();
1215 string get( t_CKINT index );
1216 t_CKINT size();
1218 protected:
1219 istringstream * m_ss;
1220 string m_next;
1221 vector<string> m_tokens;
1222 vector<string>::size_type m_index;
1225 StrTok::StrTok()
1227 m_ss = NULL;
1228 m_index = 0;
1231 StrTok::~StrTok()
1233 SAFE_DELETE( m_ss );
1236 void StrTok::set( const string & line )
1238 string s;
1240 // delete
1241 SAFE_DELETE( m_ss );
1242 // alloc
1243 m_ss = new istringstream( line );
1244 // read
1245 reset();
1246 m_tokens.clear();
1247 while( (*m_ss) >> s )
1248 m_tokens.push_back( s );
1251 void StrTok::reset()
1253 m_index = 0;
1256 t_CKBOOL StrTok::more()
1258 return m_index < m_tokens.size();
1261 string StrTok::next()
1263 if( !more() ) return "";
1264 return m_tokens[m_index++];
1267 string StrTok::get( t_CKINT index )
1269 if( index >= (t_CKINT)m_tokens.size() ) return "";
1270 return m_tokens[index];
1273 t_CKINT StrTok::size()
1275 return (t_CKINT)m_tokens.size();
1278 CK_DLL_CTOR( StrTok_ctor )
1280 StrTok * tokens = new StrTok;
1281 OBJ_MEMBER_INT(SELF, StrTok_offset_data) = (t_CKINT)tokens;
1284 CK_DLL_DTOR( StrTok_dtor )
1286 delete (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1287 OBJ_MEMBER_INT(SELF, StrTok_offset_data) = 0;
1290 CK_DLL_MFUN( StrTok_set )
1292 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1293 Chuck_String * s = GET_CK_STRING(ARGS);
1294 if( s ) tokens->set( s->str );
1295 else tokens->set( "" );
1298 CK_DLL_MFUN( StrTok_reset )
1300 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1301 tokens->reset();
1304 CK_DLL_MFUN( StrTok_more )
1306 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1307 RETURN->v_int = (t_CKINT)tokens->more();
1310 CK_DLL_MFUN( StrTok_next )
1312 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1313 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
1314 a->str = tokens->next();
1315 RETURN->v_string = a;
1318 CK_DLL_MFUN( StrTok_next2 )
1320 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1321 Chuck_String * a = GET_CK_STRING(ARGS);
1322 string s = tokens->next();
1323 if( a ) a->str = s;
1324 RETURN->v_string = a;
1327 CK_DLL_MFUN( StrTok_get )
1329 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1330 t_CKINT index = GET_NEXT_INT(ARGS);
1331 Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL );
1332 string s = tokens->get( index );
1333 a->str = s;
1334 RETURN->v_string = a;
1337 CK_DLL_MFUN( StrTok_get2 )
1339 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1340 t_CKINT index = GET_NEXT_INT(ARGS);
1341 Chuck_String * a = GET_NEXT_STRING(ARGS);
1342 string s = tokens->get( index );
1343 if( a ) a->str = s;
1344 RETURN->v_string = a;
1347 CK_DLL_MFUN( StrTok_size )
1349 StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data);
1350 RETURN->v_int = tokens->size();
1356 #ifdef AJAY
1359 class ColumnReader
1361 public:
1362 ColumnReader();
1363 virtual ~ColumnReader();
1365 bool init( const string & filename, long col );
1367 bool reset() { if( !fin.good() ) return false; where = 0; return true; }
1368 bool seek( long pos ) { if( pos < 0 || pos >= values.size() ) return false; where = pos; return true; }
1369 bool more() { return where < values.size(); }
1370 double curr();
1371 bool next() { if( where < values.size() ) where++; return more(); }
1372 long pos() { return where; }
1373 long size() { return values.size(); }
1374 string name() { return n; }
1376 Chuck_String s;
1378 protected:
1379 bool get_str( string & out );
1380 bool get_double( double & out );
1382 protected:
1383 ifstream fin;
1384 string n;
1385 long column;
1386 long where;
1387 char line[0x1000];
1388 long len;
1390 vector<double> values;
1394 ColumnReader::ColumnReader()
1396 n = "[NONE]";
1397 column = -1;
1398 where = -1;
1399 len = 0x1000;
1403 ColumnReader::~ColumnReader()
1405 // close file
1406 if( fin.good() )
1407 fin.close();
1410 bool ColumnReader::init( const string & filename, long col )
1412 // hmm
1413 if( col < 1 )
1415 cerr << "column must be greater than 0!!!" << endl;
1416 return false;
1419 // open file
1420 fin.open( filename.c_str(), ios::in );
1421 // yes
1422 if( !fin.good() )
1424 cerr << "ColumnReader: cannot open file: '" << filename << "'..." << endl;
1425 return false;
1428 // set column
1429 column = col;
1431 // read first line
1432 if( !fin.getline( line, len ) )
1434 cerr << "ColumnReader: cannot read first line: '" << filename << "'..." << endl;
1435 return false;
1438 // get the name
1439 if( !get_str( n ) )
1441 cerr << "ColumnReader: cannot seek to column " << col << ": " << filename << "..." << endl;
1442 return false;
1445 double v;
1446 long i = 1;
1447 // read values
1448 while( fin.getline( line, len ) )
1450 v = 0.0;
1451 // get value
1452 if( !get_double( v ) )
1454 cerr << "ColumnReader: cannot read column " << v << " on line i: " << n << "..." << endl;
1455 return false;
1458 values.push_back( v );
1461 // well
1462 if( values.size() == 0 )
1464 cerr << "ColumnReader: file doesn't not contain data after first line: " << n << "..." << endl;
1465 return false;
1468 // set location
1469 where = 0;
1471 s.str = n;
1473 return true;
1476 double ColumnReader::curr()
1478 if( where >= values.size() )
1480 cerr << "ColumnReader: trying to read beyond end of file: " << n << "..." << endl;
1481 return 0.0;
1484 return values[where];
1487 bool ColumnReader::get_double( double & out )
1489 assert( column > 0 );
1490 long c = 1;
1492 char * start = line;
1493 char * curr = start;
1495 while( c < column )
1497 // move past value
1498 while( *curr && *curr != ',' ) curr++;
1499 // move past ,
1500 while( *curr && *curr == ',' ) curr++;
1501 // check
1502 if( *curr == '\0' )
1504 cerr << "ColumnReader: cannot find column " << column << ": " << n << endl;
1505 return false;
1508 // increment
1509 c++;
1510 // set start
1511 start = curr;
1514 // move past value
1515 while( *curr && *curr != ',' ) curr++;
1516 // end
1517 *curr = '\0';
1519 out = atof( start );
1521 return true;
1525 bool ColumnReader::get_str( string & out )
1527 assert( column > 0 );
1528 long c = 1;
1530 char * start = line;
1531 char * curr = start;
1533 while( c < column )
1535 // move past value
1536 while( *curr && *curr != ',' ) curr++;
1537 // move past ,
1538 while( *curr && *curr == ',' ) curr++;
1539 // check
1540 if( *curr == '\0' )
1542 cerr << "ColumnReader: cannot find column " << column << ": " << n << endl;
1543 return false;
1546 // increment
1547 c++;
1548 // set start
1549 start = curr;
1552 // move past value
1553 while( *curr && *curr != ',' ) curr++;
1554 // end
1555 *curr = '\0';
1557 out = start;
1559 return true;
1563 CK_DLL_CTOR( VCR_ctor )
1565 OBJ_MEMBER_INT(SELF, VCR_offset_data) = (t_CKUINT)new ColumnReader;
1568 CK_DLL_MFUN( VCR_load )
1570 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1571 const char * filename = GET_NEXT_STRING(ARGS)->str.c_str();
1572 t_CKINT column = GET_NEXT_INT(ARGS);
1573 RETURN->v_int = vcr->init( filename, column );
1576 CK_DLL_MFUN( VCR_reset )
1578 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1579 RETURN->v_int = vcr->reset();
1582 CK_DLL_MFUN( VCR_seek )
1584 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1585 t_CKINT where = GET_CK_INT(ARGS);
1586 RETURN->v_int = vcr->seek( where );
1589 CK_DLL_MFUN( VCR_more )
1591 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1592 RETURN->v_int = vcr->more();
1595 CK_DLL_MFUN( VCR_curr )
1597 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1598 RETURN->v_float = vcr->curr();
1601 CK_DLL_MFUN( VCR_next )
1603 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1604 RETURN->v_int = vcr->next();
1607 CK_DLL_MFUN( VCR_pos )
1609 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1610 RETURN->v_int = vcr->pos();
1613 CK_DLL_MFUN( VCR_size )
1615 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1616 RETURN->v_int = vcr->size();
1619 CK_DLL_MFUN( VCR_name )
1621 ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data);
1622 RETURN->v_string = &(vcr->s);
1626 #ifdef __PLATFORM_WIN32__
1629 // jeff's cereal
1630 class Serial
1632 public:
1633 // one stop bit, 8 bits, no parity
1634 Serial();
1635 ~Serial();
1637 unsigned read( char * buffer, unsigned numberOfBytesToRead );
1638 unsigned write( char * buffer, unsigned numberOfBytesToWrite );
1640 void write( char c );
1641 char read();
1643 unsigned available() const;
1645 t_CKBOOL open( char * port, t_CKUINT baudrate );
1646 void close();
1648 private:
1649 HANDLE serialFile;
1653 Serial::Serial( )
1655 serialFile = NULL;
1658 Serial::~Serial( )
1660 close();
1663 t_CKBOOL Serial::open( char * port, t_CKUINT baudrate )
1665 if( serialFile )
1666 close();
1668 // open port
1669 serialFile = CreateFile( port,
1670 GENERIC_READ | GENERIC_WRITE,
1673 OPEN_EXISTING,
1674 FILE_ATTRIBUTE_NORMAL,
1675 0 );
1676 if( serialFile == INVALID_HANDLE_VALUE )
1678 if( GetLastError() == ERROR_FILE_NOT_FOUND )
1680 EM_log( CK_LOG_SYSTEM, "error: cannot open serial port '%s'...", port );
1682 else
1684 EM_log( CK_LOG_SYSTEM, "error opening serial port '%s'...", port );
1687 return FALSE;
1690 // set params
1691 DCB dcbSerialParams = {0};
1692 dcbSerialParams.DCBlength = sizeof( dcbSerialParams );
1693 if( !GetCommState( serialFile, &dcbSerialParams) )
1695 EM_log( CK_LOG_SYSTEM, "error getting serial state..." );
1696 close();
1697 return FALSE;
1700 dcbSerialParams.BaudRate = baudrate;
1701 dcbSerialParams.ByteSize = 8;
1702 dcbSerialParams.StopBits = ONESTOPBIT;
1703 dcbSerialParams.Parity = NOPARITY;
1704 if( !SetCommState( serialFile, &dcbSerialParams ) )
1706 EM_log( CK_LOG_SYSTEM, "error setting serial state..." );
1707 close();
1708 return FALSE;
1711 // SET TIMEOUTS
1713 COMMTIMEOUTS timeouts = {0};
1714 timeouts.ReadIntervalTimeout = 50;
1715 timeouts.ReadTotalTimeoutConstant = 50;
1716 timeouts.ReadTotalTimeoutMultiplier = 10;
1717 timeouts.WriteTotalTimeoutConstant= 50;
1718 timeouts.WriteTotalTimeoutMultiplier = 10;
1719 if( !SetCommTimeouts( serialFile, &timeouts ) )
1721 //error occureed. Inform user
1725 return TRUE;
1728 void Serial::close()
1730 if( serialFile )
1732 CloseHandle( serialFile );
1733 serialFile = NULL;
1737 void Serial::write( char c )
1739 write( &c, 1 );
1742 char Serial::read()
1744 char c = '\0';
1745 read( &c, 1 );
1746 return c;
1749 unsigned Serial::available() const
1751 struct _COMSTAT status;
1752 unsigned long etat;
1753 memset( &status, 0, sizeof(status) );
1755 if( serialFile )
1757 ClearCommError( serialFile, &etat, &status);
1758 return status.cbInQue;
1761 return 0;
1764 // try to read numberOfBytesToRead into buffer, return how many bytes read
1765 unsigned Serial::read( char * buffer, unsigned numberOfBytesToRead )
1767 DWORD bytesRead = 0;
1768 if( serialFile )
1769 ReadFile( serialFile, buffer, numberOfBytesToRead, &bytesRead, NULL );
1770 return bytesRead;
1773 // try to write numberOfBytesToWrite to serial from buffer, return how many bytes written
1774 unsigned Serial::write( char * buffer, unsigned numberOfBytesToWrite )
1776 DWORD bytesWritten = 0;
1777 if( serialFile )
1778 WriteFile( serialFile, buffer, numberOfBytesToWrite, &bytesWritten, NULL );
1779 return bytesWritten;
1783 // ctor
1784 CK_DLL_CTOR( Cereal_ctor )
1786 OBJ_MEMBER_UINT(SELF, Cereal_offset_data) = (t_CKUINT)new Serial;
1789 // open
1790 CK_DLL_MFUN( Cereal_open )
1792 Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data);
1793 Chuck_String * str = GET_NEXT_STRING(ARGS);
1794 t_CKINT i = GET_NEXT_INT(ARGS);
1796 // close
1797 s->close();
1799 if( str )
1800 RETURN->v_int = s->open( (char *)str->str.c_str(), i );
1801 else
1802 RETURN->v_int = 0;
1805 // close
1806 CK_DLL_MFUN( Cereal_close )
1808 Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data);
1809 s->close();
1812 // more
1813 CK_DLL_MFUN( Cereal_more )
1815 Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data);
1816 RETURN->v_int = s->available();
1819 // send
1820 CK_DLL_MFUN( Cereal_send )
1822 Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data);
1823 t_CKINT i = GET_NEXT_INT(ARGS);
1824 s->write( i );
1825 RETURN->v_int = i;
1828 // recv
1829 CK_DLL_MFUN( Cereal_recv )
1831 Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data);
1832 if( s->available() )
1833 RETURN->v_int = (t_CKINT)s->read();
1834 else
1835 RETURN->v_int = 0;
1838 #endif
1841 #endif