00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <unistd.h>
00025 #include <errno.h>
00026 #include <string>
00027
00028 #include <tbt.h>
00029 #include <jutils.h>
00030 #include <string.h>
00031 #include <errno.h>
00032
00033 #include <slw/keycodes.h>
00034
00035 #ifdef linux
00036 #include <rtclock.h>
00037 #endif
00038
00039
00040 TBTEntry::TBTEntry()
00041 : Entry() {
00042 key = 0;
00043 msec = 0;
00044
00045 set_name("char64,msec64");
00046 }
00047
00048 TBTEntry::~TBTEntry() { }
00049
00050 bool TBTEntry::parse_uint64(void *buf) {
00051
00052 uint64_t *p = (uint64_t*)buf;
00053
00054 key = *p;
00055 msec = *(p+1);
00056
00057 return true;
00058 }
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 bool TBTEntry::parse_ascii(char *buf) {
00075
00076 unsigned char k = 0;
00077 unsigned long int m = 0;
00078
00079 sscanf(buf, "%c:%lu\n", &k, &m);
00080 key = (uint64_t)k;
00081 msec = (uint64_t)m;
00082
00083 return true;
00084 }
00085
00086
00087 int TBTEntry::render_uint64(void *buf) {
00088 int len;
00089 uint64_t tmp[2];
00090
00091 tmp[0] = key;
00092 tmp[1] = msec;
00093
00094 len = 16;
00095
00096 memcpy(buf, (void*)tmp, len);
00097
00098 return len;
00099 }
00100
00101 int TBTEntry::render_ascii(void *buf) {
00102 int len;
00103 char tmp[512];
00104
00105 len = snprintf(tmp,511,"%c:%lu\n",(int)key, (unsigned long)msec);
00106 if(len<0) {
00107 error("error rendering in ascii: %s", strerror(errno));
00108 return 0;
00109 }
00110
00111 memcpy(buf,tmp,len*sizeof(char));
00112 return len;
00113 }
00114
00115 int TBTEntry::render_html(void *buf) {
00116 int len;
00117 char tmp[512];
00118
00119 len = snprintf(tmp,511,"[%lu,%lu]", (unsigned long)key, (unsigned long)msec);
00120 if(len<0) {
00121 error("error rendering in javascript array: %s", strerror(errno));
00122 return 0;
00123 }
00124
00125 memcpy(buf, tmp, len*sizeof(char));
00126 return len;
00127 }
00128
00129
00130
00131
00132
00133 TBT::TBT() {
00134
00135
00136 now = 0;
00137 past = 0;
00138
00139 position = 1;
00140
00141 rtc = false;
00142 quit = false;
00143
00144
00145 gettime.tv_sec = 0;
00146 gettime.tv_usec = 0;
00147 psleep.tv_sec = 0;
00148 psleep.tv_nsec = 0;
00149
00150 buffer = new Linklist;
00151
00152 clock = NULL;
00153
00154 }
00155
00156 TBT::~TBT() {
00157
00158 clear();
00159
00160 delete buffer;
00161 }
00162
00163 int TBT::init() {
00164
00165 #ifdef linux
00166 if(rtc) {
00167 rtc = false;
00168
00169
00170 clock = new RTClock();
00171 if( clock->init() ) {
00172 notice("real time clock device is present");
00173
00174
00175
00176
00177
00178
00179
00180 clock->set_freq( 1024 );
00181
00182
00183 if( ! clock->start() ) {
00184 error("no permission to run real time clock at 1024HZ");
00185 delete clock;
00186 clock = NULL;
00187 } else
00188 rtc = true;
00189 }
00190 }
00191 #endif
00192
00193 if(!rtc) {
00194
00195 if( gettimeofday(&gettime, NULL) <0 ) {
00196 error("error getting (posix) time: %s",strerror(errno));
00197 error("no timing source available, impossible to go further");
00198 return 0;
00199 }
00200
00201 past = (gettime.tv_sec * 1000) + (gettime.tv_usec / 1000);
00202
00203 }
00204
00205 return 1;
00206 }
00207
00208
00209 void TBT::clear() {
00210
00211
00212 TBTEntry *ent;
00213 ent = (TBTEntry*)buffer->begin();
00214
00215
00216
00217 while(ent) {
00218 delete ent;
00219 ent = (TBTEntry*) buffer->begin();
00220 }
00221
00222 }
00223
00224 void TBT::append(uint64_t key) {
00225 TBTEntry *ent;
00226 ent = new TBTEntry();
00227
00228
00229
00230 compute_delta( ent );
00231
00232
00233 switch( key ) {
00234
00235 case KEY_BACKSPACE_ASCII:
00236 case KEY_BACKSPACE:
00237 case KEY_BACKSPACE_APPLE:
00238 case KEY_BACKSPACE_SOMETIMES:
00239 ent->key = (uint64_t)KEY_BACKSPACE_ASCII;
00240 break;
00241
00242 case KEY_NEWLINE:
00243 case KEY_ENTER:
00244 ent->key = (uint64_t)KEY_ENTER;
00245 break;
00246
00247 default:
00248 ent->key = (uint64_t)key;
00249
00250 }
00251
00252 buffer->append(ent);
00253 }
00254
00255
00256
00257
00258 uint64_t TBT::getkey() {
00259 TBTEntry *ent;
00260 ent = (TBTEntry*) buffer->pick(position);
00261
00262 if(!ent) {
00263 func("NULL entry at position %u", position);
00264 return 0;
00265 }
00266
00267 position++;
00268
00269
00270
00271 if(!rtc) {
00272
00273 psleep.tv_sec = ent->msec / 1000;
00274 psleep.tv_nsec = (ent->msec % 1000) * 1000000;
00275 nanosleep(&psleep, NULL);
00276
00277 }
00278 #ifdef linux
00279 else clock->sleep(ent->msec);
00280 #endif
00281
00282 return ent->key;
00283 }
00284
00285 int TBT::load(char *filename) {
00286
00287 int c, len;
00288
00289 void *buf;
00290
00291 FILE *fd;
00292
00293 fd = fopen(filename, "r");
00294 if(!fd) {
00295 error("can't open file: %s", strerror(errno));
00296 return false;
00297 }
00298
00299 clear();
00300
00301
00302 buf = malloc(64);
00303
00304 TBTEntry *ent;
00305
00306 c = 0;
00307
00308 act("loading file %s", filename);
00309
00310 while( ! feof(fd) ) {
00311
00312 len = fread(buf, 4, 4, fd);
00313 if(!len) break;
00314 else if(len != 4) {
00315 warning("truncated entry, %u elements read", len);
00316 continue;
00317 }
00318
00319 ent = new TBTEntry();
00320
00321 if( ! ent->parse_uint64(buf) ) {
00322 error("error in TBTEntry::parse_uint64");
00323 continue;
00324 }
00325
00326 buffer->append( ent );
00327 c++;
00328
00329 }
00330
00331 free(buf);
00332
00333 position = 1;
00334
00335 return c;
00336 }
00337
00338
00339
00340
00341
00342 int TBT::load_ascii(char *filename) {
00343
00344 int c;
00345
00346 char ascii_line[512];
00347
00348 FILE *fd;
00349
00350 fd = fopen(filename, "r");
00351 if(!fd) {
00352 error("can't open ascii file: %s", strerror(errno));
00353 return false;
00354 }
00355
00356 clear();
00357
00358 TBTEntry *ent;
00359
00360 c = 0;
00361
00362 act("loading ascii file %s", filename);
00363
00364 while( ! feof(fd) ) {
00365
00366 fgets(ascii_line, 512, fd);
00367
00368 ent = new TBTEntry();
00369
00370 if( ! ent->parse_ascii(ascii_line) ) {
00371 error("error in TBTEntry::parse_ascii");
00372 continue;
00373 }
00374
00375 buffer->append( ent );
00376 c++;
00377
00378 }
00379
00380 position = 1;
00381
00382 return c;
00383 }
00384
00385 int TBT::save_bin(char *filename) {
00386
00387 int c, len;
00388
00389 void *buf;
00390
00391 FILE *fd;
00392
00393 fd = fopen(filename, "w");
00394 if(!fd) {
00395 error("can't oper file %s for writing: %s", filename, strerror(errno));
00396 return false;
00397 }
00398
00399
00400 buf = malloc(512);
00401
00402
00403 TBTEntry *ent;
00404 ent = (TBTEntry*) buffer->begin();
00405
00406
00407 c = 0;
00408 while( ent ) {
00409
00410 len = ent->render_uint64(buf);
00411
00412 fwrite(buf, len, 1, fd);
00413
00414 c++;
00415
00416 ent = (TBTEntry*) ent->next;
00417
00418 }
00419
00420
00421 fflush(fd);
00422 fclose(fd);
00423
00424 free(buf);
00425
00426 return c;
00427 }
00428
00429 int TBT::save_ascii(char *filename) {
00430
00431 int c, len;
00432
00433 void *buf;
00434
00435 FILE *fd;
00436
00437 fd = fopen(filename, "w");
00438 if(!fd) return false;
00439
00440
00441 buf = malloc(512);
00442
00443 TBTEntry *ent;
00444 ent = (TBTEntry*)buffer->begin();
00445
00446
00447 c = 0;
00448 while( ent ) {
00449
00450 len = ent->render_ascii(buf);
00451
00452 fwrite(buf, len, 1, fd);
00453
00454 c++;
00455
00456 ent = (TBTEntry*) ent->next;
00457 }
00458
00459 fflush(fd);
00460 fclose(fd);
00461
00462 free(buf);
00463
00464 return c;
00465 }
00466
00467 int TBT::save_doku(char *filename) {
00468
00469 int c, len;
00470
00471 void *buf;
00472
00473 FILE *fd;
00474
00475 fd = fopen(filename, "w");
00476 if(!fd) return false;
00477
00478 fputs("{{tbt>[", fd);
00479
00480 buf = malloc(512);
00481 TBTEntry *ent;
00482 ent = (TBTEntry*) buffer->begin();
00483
00484 c = 0;
00485 while( ent ) {
00486
00487 if(c>0)
00488 fwrite(",",sizeof(char),1,fd);
00489
00490 len = ent->render_html(buf);
00491
00492 fwrite(buf, len, 1, fd);
00493
00494 c++;
00495
00496 ent = (TBTEntry*) ent->next;
00497 }
00498
00499 fputs("]}}\n", fd);
00500 fflush(fd);
00501 fclose(fd);
00502
00503 free(buf);
00504
00505 return c;
00506 }
00507
00508 int TBT::save_html(char *filename) {
00509
00510 int c, len;
00511
00512 void *buf;
00513
00514 FILE *fd;
00515
00516 fd = fopen(filename, "w");
00517 if(!fd) return false;
00518
00519 fputs("<html><head>\n"
00520 "<script language=\"JavaScript\" src=\"tbt-typewriter.js\"></script>\n"
00521 "<title>Time Based Text - recorded with tbt.dyne.org</title></head>\n"
00522 "<body text=\"#FFFFFF\" bgcolor=\"#000000\">\n"
00523 "<div id=\"textDestination\">\n"
00524 "</div>\n"
00525 "<script language=\"JavaScript\">\n"
00526 "<!--\n", fd);
00527
00528
00529 fwrite("var TimeBasedText=[",sizeof(char),19,fd);
00530
00531
00532 buf = malloc(512);
00533
00534 TBTEntry *ent;
00535 ent = (TBTEntry*) buffer->begin();
00536
00537
00538 c = 0;
00539 while( ent ) {
00540
00541 if(c>0)
00542 fwrite(",",sizeof(char),1,fd);
00543
00544 len = ent->render_html(buf);
00545
00546 fwrite(buf, len, 1, fd);
00547
00548 c++;
00549
00550 ent = (TBTEntry*) ent->next;
00551 }
00552
00553
00554
00555 fwrite("]\n",sizeof(char),2,fd);
00556
00557 fputs("\n"
00558 "var tbt = new TBT();\n"
00559 "tbt.startTyping(\"textDestination\", TimeBasedText);\n"
00560 "//--></script>\n"
00561 "</body></html>\n\n", fd);
00562 fflush(fd);
00563 fclose(fd);
00564
00565 free(buf);
00566
00567 return c;
00568 }
00569
00570 void TBT::compute_delta(TBTEntry *tbt) {
00571
00572
00573
00574 if(!rtc) {
00575
00576
00577 if( gettimeofday(&gettime, NULL) <0)
00578 error("error getting time: %s",strerror(errno));
00579 now = (gettime.tv_sec * 1000) + (gettime.tv_usec / 1000);
00580
00581 }
00582 #ifdef linux
00583 else now = clock->msec;
00584 #endif
00585
00586 tbt->msec = now - past;
00587
00588
00589 past = now;
00590
00591 }