00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <termios.h>
00026 #include <time.h>
00027 #include <errno.h>
00028 #include <string.h>
00029 #include <unistd.h>
00030 #include <inttypes.h>
00031
00032 #include <getopt.h>
00033
00034 #include <sys/types.h>
00035 #include <sys/param.h>
00036 #include <sys/time.h>
00037
00038 #include <assert.h>
00039 #include <signal.h>
00040
00042
00043
00044
00045 #include <tbt.h>
00046
00047
00048
00049
00050 #include <slw_console.h>
00051 #include <slw_text.h>
00052 #include <slw_popup.h>
00053
00054
00055 #include <jutils.h>
00056
00057
00058
00059
00060 TBT tbt;
00061
00062
00063
00065
00066 void set_status(SLangWidget *s);
00067
00068 static const char *help =
00069 "Synopsis: tbt <command> [options] [file]\n"
00070 "Commands:\n"
00071 " -r record\n"
00072 " -p playback\n"
00073 " -x convert\n"
00074 " -v print version\n"
00075 " -h print this help\n"
00076 "Options:\n"
00077 " -C stdin/out commandline mode\n"
00078 " -s save format in [ bin | ascii | html | doku ]\n"
00079 #ifdef linux
00080 " -t timing mode [ posix | rtc ]\n"
00081 #endif
00082 " -D debug verbosity level (1-3)\n";
00083
00084
00085
00086
00087
00088 static const char *short_options = "-hvD:crpxs:t:";
00089
00090 int debug;
00091 char filename[512];
00092 char convert[512];
00093
00094
00095
00096 bool console = true;
00097
00098
00099 #define POSIX 1
00100 #define RTC 2
00101 int timing = POSIX;
00102
00103
00104 int operation = 0x0;
00105 #define REC 1
00106 #define PLAY 2
00107 #define CONV 4
00108
00109
00110
00111 #define BIN 1
00112 #define ASCII 2
00113 #define HTML 3
00114 #define DOKU 4
00115 int render = BIN;
00116
00117
00118 uint64_t key;
00119
00120 int c, len;
00121
00122
00123 void cmdline(int argc, char **argv) {
00124 int res;
00125
00126 debug = 1;
00127 filename[0] = 0x0;
00128
00129 fprintf(stderr, "TBT - Time Based Text - %s\n", VERSION);
00130 fprintf(stderr, "Software by Jaromil @ Dyne.org\n\n");
00131
00133 if ( ! strstr(argv[0], "tbt") )
00134 console = true;
00135 if ( strstr(argv[0],"rectext") )
00136 operation = REC;
00137 else if ( strstr(argv[0],"playtext") )
00138 operation = PLAY;
00139
00140
00141 do {
00142 res = getopt(argc, argv, short_options);
00143 switch(res) {
00144 case 'h':
00145 fprintf(stderr, "%s", help);
00146 exit(0);
00147 break;
00148
00149 case 'v':
00150 fprintf(stderr,"\n");
00151 exit(0);
00152 break;
00153
00154 case 'D':
00155 debug = atoi(optarg);
00156 if(debug>3) {
00157 warning("debug verbosity ranges from 1 to 3\n");
00158 debug = 3;
00159 }
00160 break;
00161
00162 case 'C':
00163 console = false;
00164 break;
00165
00166 case 'c':
00167 console = true;
00168 break;
00169
00170 case 'r':
00171 operation = REC;
00172 break;
00173
00174 case 'p':
00175 operation = PLAY;
00176 break;
00177
00178 case 'x':
00179 operation = CONV;
00180 break;
00181
00182 case 't':
00183 if(strncasecmp(optarg, "rtc", 3) ==0)
00184 timing = RTC;
00185 else
00186 timing = POSIX;
00187 break;
00188
00189 case 's':
00190 if( strcasecmp(optarg, "BIN") ==0)
00191 render = BIN;
00192 else if( strcasecmp(optarg, "ASCII") ==0)
00193 render = ASCII;
00194 else if( strcasecmp(optarg, "HTML") ==0)
00195 render = HTML;
00196 else if( strncasecmp(optarg, "DOKU", 4) ==0)
00197 render = DOKU;
00198 else {
00199 error ("render format not recognized: %s", optarg);
00200 act ("using default binary format render");
00201 render = BIN;
00202 }
00203 break;
00204
00205
00206 case 1: snprintf(filename,511,"%s", optarg);
00207
00208 default: break;
00209
00210 }
00211 } while (res != -1);
00212
00213 for(;optind<argc;optind++)
00214 snprintf(filename, 511, "%s", argv[optind]);
00215
00216 if(!filename[0])
00217 sprintf(filename, "record.tbt");
00218
00219 set_debug(debug);
00220
00221 }
00222
00224
00225
00226
00227
00229
00230
00231 SLangConsole *con;
00232
00233
00234 SLW_Text *txt;
00235 SLW_Text *status;
00236
00237 int record_console() {
00238
00239 assert( con->init() );
00240
00241
00242 SLW_Popup *info;
00243 info = new SLW_Popup();
00244 info->border = false;
00245 info->set_color(1);
00246 info->set_name("welcome popup");
00247 info->set_text("Welcome to Time Based Text\n"
00248 "press [ENTER] to start recording\n"
00249 "press [ESC] when finished.");
00250 con->place(info,
00251 (con->w/2) - 20, (con->h/2) - 5,
00252 (con->w/2) + 20, (con->h/2) + 5);
00253 assert( info->init() );
00254 con->focused = info;
00255 key = 0;
00256 while( con->refresh() ) {
00257 key = con->getkey();
00258 if(key == KEY_ENTER) break;
00259 if(key == KEY_ESC) return 0;
00260 }
00261 delete(info);
00262
00263
00264 status->border = false;
00265 status->set_color(21);
00266 status->set_name("status box");
00267
00268 con->place(status, 0, con->h-1, con->w, con->h);
00269
00270 assert ( status->init() );
00271
00272
00273 set_status(status);
00274
00275
00276 txt->set_name("editor");
00277 txt->cursor = true;
00278
00279 if(! con->place(txt, 0, 0, con->w, con->h-2) ) {
00280 error("error placing the text widget");
00281 return(-1);
00282 }
00283 assert ( txt->init() );
00284
00285
00286 con->focused = txt;
00287 txt->blank();
00288
00289
00290 notice("TBT recording, press [ESC] when finished");
00291
00292 while(!tbt.quit) {
00293
00294 key = con->getkey();
00295
00296 if(key == KEY_ESC) break;
00297
00298 if(key) {
00299
00300
00301 tbt.append(key);
00302
00303
00304 con->feed(key);
00305
00306 }
00307
00308 if( ! con->refresh() ) tbt.quit = true;
00309
00310 jsleep(0,10);
00311
00312 }
00313
00314 return 1;
00315 }
00316
00317
00318 int play_console() {
00319
00320
00321
00322 status->border = false;
00323 status->set_name("status box");
00324 if(! con->place(status, 0, con->h-10, con->w, con->h) ) {
00325 error("error placing the status widget");
00326 return(-1);
00327 }
00328 assert ( status->init() );
00329
00330
00331 set_status(status);
00332
00333
00334 if(! con->place(txt, 0, 0, con->w, con->h-1) ) {
00335 error("error placing the text widget");
00336 return(-1);
00337 }
00338 txt->set_name("player");
00339 assert ( txt->init() );
00340
00341 con->focused = txt;
00342
00343
00344
00345
00346 for(c=0; c<len && !tbt.quit; c++) {
00347
00348
00349
00350 key = tbt.getkey();
00351
00352 con->feed(key);
00353 if( ! con->refresh() ) tbt.quit = true;
00354
00355 }
00356
00357 return 1;
00358 }
00359
00361
00362
00363
00364 void quitproc (int Sig) {
00365 act("interrupt caught, exiting.");
00366 tbt.quit = true;
00367 }
00368
00369
00370
00371 int main(int argc, char** argv)
00372 {
00373
00374 cmdline(argc, argv);
00375
00376 if(!operation) {
00377 error("no operation specified, use -h for help on usage.");
00378 exit(0);
00379 }
00380
00381 if(timing == RTC)
00382 tbt.rtc = true;
00383
00384
00385 if(! tbt.init() ) exit(0);
00386
00387
00388 if (signal (SIGINT, quitproc) == SIG_ERR) {
00389 perror ("Couldn't install SIGINT handler"); exit(0); }
00390
00391
00392 if(operation == PLAY) {
00393 if( ! tbt.load( filename ) ) {
00394 error("no entries found in file %s",filename);
00395 exit(1);
00396 } else
00397 len = tbt.buffer->len();
00398 }
00399
00400 if(console) {
00401
00402 con = new SLangConsole();
00403
00404
00405 if(! con->init() ) {
00406 error("cannot initialize S-Lang console on this terminal.");
00407 exit(0);
00408 }
00409
00410 txt = new SLW_Text();
00411 status = new SLW_Text();
00412
00413 switch(operation) {
00414
00415 case REC:
00416 if( !record_console() ) break;
00417
00418 switch(render) {
00419
00420 case BIN:
00421 tbt.save_bin( filename );
00422 break;
00423
00424 case ASCII:
00425 tbt.save_ascii( filename );
00426 break;
00427
00428 case DOKU:
00429 tbt.save_doku( filename );
00430 break;
00431
00432 case HTML:
00433 tbt.save_html( filename );
00434 break;
00435
00436 }
00437
00438 break;
00439
00440 case PLAY:
00441 play_console();
00442 break;
00443
00444 }
00445
00446
00447 con->refresh();
00448 jsleep(1,0);
00449 con->close();
00450 set_status(NULL);
00451
00452 if(operation == REC)
00453 notice("TBT file %s rendered in %s format", filename,
00454 (render==BIN)?"binary":(render==ASCII)?"ascii":(render==HTML)?"html":"unknown");
00455
00456
00457 } else {
00459
00460 switch(operation){
00461
00462 case REC:
00463
00464 {
00465
00466 struct termios stty;
00467 tcgetattr(0,&stty);
00468 stty.c_lflag ^= ICANON|ECHO;
00469 stty.c_cc[VTIME] = 100;
00470 stty.c_cc[VMIN] = 0;
00471 tcsetattr(0,TCSANOW,&stty);
00472
00473 while(!tbt.quit) {
00474
00475 read(0,(void*)&key,1);
00476
00477 tbt.append((int64_t)key);
00478
00479 write(1, (void*)&key, 1);
00480
00481 }
00482
00483 stty.c_lflag |= ICANON|ECHO;
00484 tcsetattr(0,TCSANOW,&stty);
00485 }
00486
00487 switch(render) {
00488
00489 case BIN:
00490 tbt.save_bin( filename );
00491 break;
00492
00493 case ASCII:
00494 tbt.save_ascii( filename );
00495 break;
00496
00497 case HTML:
00498 tbt.save_html( filename );
00499 break;
00500
00501 case DOKU:
00502 tbt.save_doku( filename );
00503 break;
00504 }
00505
00506 break;
00507
00508 case PLAY:
00509
00510
00511 for(c=0; c<len && !tbt.quit; c++) {
00512
00513
00514 key = tbt.getkey();
00515
00516
00517 write(1, (void*)&key, 1);
00518 }
00519 break;
00520
00521
00522
00523
00524 case CONV:
00525
00526 tbt.load(filename);
00527
00528 switch(render) {
00529
00530 case ASCII:
00531 {
00532
00533 snprintf(convert, 511, "%s.asc",filename);
00534 tbt.save_ascii( convert );
00535
00536 }
00537 break;
00538
00539 case HTML:
00540 {
00541 snprintf(convert, 511,"%s.html",filename);
00542 tbt.save_html( convert );
00543 }
00544 break;
00545 case BIN:
00546 snprintf(convert, 511,"%s.tbt",filename);
00547 tbt.save_bin( convert );
00548 }
00549 }
00550 }
00551
00552 if( (operation==REC) | (operation==CONV) )
00553 notice("TBT file %s %s to %s format",
00554 (operation==REC)?filename:convert,
00555 (operation==REC)?"recorded":
00556 (operation==CONV)?"converted":"***",
00557 (render==BIN)?"binary":
00558 (render==ASCII)?"ascii":
00559 (render==HTML)?"html":
00560 (render==DOKU)?"dokuwiki":"unknown");
00561
00562 act("exiting TBT");
00563 act("%u entries streamed.", tbt.buffer->len());
00564
00565 exit(0);
00566 }