Julius 4.1.5
|
00001 #include "app.h" 00002 00003 #include <stdarg.h> 00004 00005 #define DEFAULT_MODULEPORT 10500 00006 00007 static int module_mode = FALSE; 00008 static int module_port = DEFAULT_MODULEPORT; 00009 int module_sd = -1; 00010 static FILE *module_fp; 00011 static RecogProcess *cur = NULL; 00012 00013 #define MAXBUFLEN 4096 ///< Maximum line length of a message sent from a client 00014 static char mbuf[MAXBUFLEN]; 00015 static char buf[MAXBUFLEN]; 00016 static char inbuf[MAXBUFLEN]; 00017 #ifdef CHARACTER_CONVERSION 00018 static char outbuf[MAXBUFLEN]; 00019 #endif 00020 00030 int 00031 module_send(int sd, char *fmt, ...) 00032 { 00033 va_list ap; 00034 int ret; 00035 char *buf; 00036 00037 va_start(ap,fmt); 00038 ret = vsnprintf(inbuf, MAXBUFLEN, fmt, ap); 00039 va_end(ap); 00040 if (ret > 0) { /* success */ 00041 00042 #ifdef CHARACTER_CONVERSION 00043 buf = charconv(inbuf, outbuf, MAXBUFLEN); 00044 #else 00045 buf = inbuf; 00046 #endif 00047 if ( 00048 #ifdef WINSOCK 00049 send(sd, buf, strlen(buf), 0) 00050 #else 00051 write(sd, buf, strlen(buf)) 00052 #endif 00053 < 0) { 00054 perror("Error: module_send:"); 00055 } 00056 } 00057 return(ret); 00058 } 00059 00060 static char * 00061 myfgets(char *buf, int maxlen, FILE *fp) 00062 { 00063 char *ret; 00064 int len; 00065 00066 if ((ret = fgets(buf, maxlen, fp)) != NULL) { 00067 len = strlen(buf); 00068 if (buf[len-1] == '\n') { 00069 buf[len-1] = '\0'; 00070 if (len >= 2 && buf[len-2] == '\r') { 00071 buf[len-2] = '\0'; 00072 } 00073 } 00074 } 00075 return ret; 00076 } 00077 00090 static boolean 00091 read_grammar(FILE *fp, DFA_INFO **ret_dfa, WORD_INFO **ret_winfo, HTK_HMM_INFO *hmminfo, RecogProcess *r) 00092 { 00093 DFA_INFO *dfa = NULL; 00094 WORD_INFO *winfo; 00095 JCONF_LM *lmconf; 00096 00097 /* load grammar: dfa and dict in turn */ 00098 if (r->lmvar != LM_DFA_WORD) { 00099 dfa = dfa_info_new(); 00100 if (!rddfa_fp(fp, dfa)) { 00101 return FALSE; 00102 } 00103 } 00104 winfo = word_info_new(); 00105 if (r->lmvar == LM_DFA_WORD) { 00106 lmconf = r->lm->config; 00107 if (!voca_load_wordlist_fp(fp, winfo, hmminfo, lmconf->wordrecog_head_silence_model_name, lmconf->wordrecog_tail_silence_model_name, (lmconf->wordrecog_silence_context_name[0] == '\0') ? NULL : lmconf->wordrecog_silence_context_name)) { 00108 return FALSE; 00109 } 00110 } else { 00111 if (!voca_load_htkdict_fp(fp, winfo, hmminfo, FALSE)) { 00112 dfa_info_free(dfa); 00113 return FALSE; 00114 } 00115 } 00116 *ret_dfa = dfa; 00117 *ret_winfo = winfo; 00118 return TRUE; 00119 } 00120 00121 00122 static void 00123 send_process_stat(RecogProcess *r) 00124 { 00125 module_send(module_sd, "<SR ID=\"%d\" NAME=\"%s\"", r->config->id, r->config->name); 00126 switch(r->lmtype) { 00127 case LM_PROB: module_send(module_sd, " LMTYPE=\"PROB\""); break; 00128 case LM_DFA: module_send(module_sd, " LMTYPE=\"DFA\""); break; 00129 } 00130 switch(r->lmvar) { 00131 case LM_NGRAM: module_send(module_sd, " LMVAR=\"NGRAM\""); break; 00132 case LM_DFA_GRAMMAR: module_send(module_sd, " LMVAR=\"GRAMMAR\""); break; 00133 case LM_DFA_WORD: module_send(module_sd, " LMVAR=\"WORD\""); break; 00134 case LM_NGRAM_USER: module_send(module_sd, " LMVAR=\"USER\""); break; 00135 } 00136 if (r->live) { 00137 module_send(module_sd, " LIVE=\"ACTIVE\""); 00138 } else { 00139 module_send(module_sd, " LIVE=\"INACTIVE\""); 00140 } 00141 module_send(module_sd, "/>\n.\n"); 00142 } 00143 00144 static void 00145 send_current_process(RecogProcess *r) 00146 { 00147 module_send(module_sd, "<RECOGPROCESS INFO=\"CURRENT\">\n"); 00148 send_process_stat(r); 00149 module_send(module_sd, "</RECOGPROCESS>\n.\n"); 00150 } 00151 00179 static void 00180 msock_exec_command(char *command, Recog *recog) 00181 { 00182 DFA_INFO *new_dfa; 00183 WORD_INFO *new_winfo; 00184 static char *p, *q; 00185 int gid; 00186 int ret; 00187 RecogProcess *r; 00188 00189 /* prompt the received command string */ 00190 printf("[[%s]]\n",command); 00191 00192 if (cur == NULL) { 00193 cur = recog->process_list; 00194 } 00195 00196 if (strmatch(command, "STATUS")) { 00197 /* return status */ 00198 if (recog->process_active) { 00199 module_send(module_sd, "<SYSINFO PROCESS=\"ACTIVE\"/>\n.\n"); 00200 } else { 00201 module_send(module_sd, "<SYSINFO PROCESS=\"SLEEP\"/>\n.\n"); 00202 } 00203 } else if (strmatch(command, "DIE")) { 00204 /* disconnect */ 00205 close_socket(module_sd); 00206 module_sd = -1; 00207 #if defined(_WIN32) && !defined(__CYGWIN32__) 00208 /* this is single process and has not forked, so 00209 we just disconnect the connection here. */ 00210 #else 00211 /* this is a forked process, so exit here. */ 00212 00213 #endif 00214 } else if (strmatch(command, "VERSION")) { 00215 /* return version */ 00216 module_send(module_sd, "<ENGINEINFO TYPE=\"%s\" VERSION=\"%s\" CONF=\"%s\"/>\n.\n", 00217 JULIUS_PRODUCTNAME, JULIUS_VERSION, JULIUS_SETUP); 00218 } else if (strmatch(command, "PAUSE")) { 00219 /* pause recognition: will stop when the current input ends */ 00220 j_request_pause(recog); 00221 } else if (strmatch(command, "TERMINATE")) { 00222 j_request_terminate(recog); 00223 } else if (strmatch(command, "RESUME")) { 00224 j_request_resume(recog); 00225 } else if (strmatch(command, "INPUTONCHANGE")) { 00226 /* change grammar switching timing policy */ 00227 if ( 00228 myfgets(buf, MAXBUFLEN, module_fp) 00229 == NULL) { 00230 fprintf(stderr, "Error: msock(INPUTONCHANGE): no argument\n"); 00231 return; 00232 } 00233 if (strmatch(buf, "TERMINATE")) { 00234 recog->gram_switch_input_method = SM_TERMINATE; 00235 } else if (strmatch(buf, "PAUSE")) { 00236 recog->gram_switch_input_method = SM_PAUSE; 00237 } else if (strmatch(buf, "WAIT")) { 00238 recog->gram_switch_input_method = SM_WAIT; 00239 } else { 00240 fprintf(stderr, "Error: msock(INPUTONCHANGE): unknown method [%s]\n", buf); exit(-1); 00241 } 00242 } else if (strnmatch(command, "GRAMINFO", strlen("GRAMINFO"))) { 00243 send_gram_info(cur); 00244 } else if (strnmatch(command, "CHANGEGRAM", strlen("CHANGEGRAM"))) { 00245 /* receive grammar (DFA + DICT) from the socket, and swap the whole grammar */ 00246 /* read grammar name if any */ 00247 p = &(command[strlen("CHANGEGRAM")]); 00248 while (*p == ' ' && *p != '\r' && *p != '\n' && *p != '\0') p++; 00249 if (*p != '\r' && *p != '\n' && *p != '\0') { 00250 q = buf; 00251 while (*p != ' ' && *p != '\r' && *p != '\n' && *p != '\0') *q++ = *p++; 00252 *q = '\0'; 00253 p = buf; 00254 } else { 00255 p = NULL; 00256 } 00257 /* read a new grammar via socket */ 00258 if (read_grammar(module_fp, &new_dfa, &new_winfo, cur->am->hmminfo, cur) == FALSE) { 00259 module_send(module_sd, "<GRAMMAR STATUS=\"ERROR\" REASON=\"WRONG DATA\"/>\n.\n"); 00260 } else { 00261 if (cur->lmtype == LM_DFA) { 00262 /* delete all existing grammars */ 00263 multigram_delete_all(cur->lm); 00264 /* register the new grammar to multi-gram tree */ 00265 multigram_add(new_dfa, new_winfo, p, cur->lm); 00266 /* need to rebuild the global lexicon */ 00267 /* tell engine to update at requested timing */ 00268 schedule_grammar_update(recog); 00269 /* make sure this process will be activated */ 00270 cur->active = 1; 00271 /* tell module client */ 00272 module_send(module_sd, "<GRAMMAR STATUS=\"RECEIVED\"/>\n.\n"); 00273 send_gram_info(cur); 00274 } else { 00275 module_send(module_sd, "<GRAMMAR STATUS=\"ERROR\" REASON=\"NOT A GRAMMAR-BASED LM\"/>\n.\n"); 00276 } 00277 } 00278 } else if (strnmatch(command, "ADDGRAM", strlen("ADDGRAM"))) { 00279 /* receive grammar and add it to the current grammars */ 00280 /* read grammar name if any */ 00281 p = &(command[strlen("ADDGRAM")]); 00282 while (*p == ' ' && *p != '\r' && *p != '\n' && *p != '\0') p++; 00283 if (*p != '\r' && *p != '\n' && *p != '\0') { 00284 q = buf; 00285 while (*p != ' ' && *p != '\r' && *p != '\n' && *p != '\0') *q++ = *p++; 00286 *q = '\0'; 00287 p = buf; 00288 } else { 00289 p = NULL; 00290 } 00291 /* read a new grammar via socket */ 00292 if (read_grammar(module_fp, &new_dfa, &new_winfo, cur->am->hmminfo, cur) == FALSE) { 00293 module_send(module_sd, "<GRAMMAR STATUS=\"ERROR\" REASON=\"WRONG DATA\"/>\n.\n"); 00294 } else { 00295 if (cur->lmtype == LM_DFA) { 00296 /* add it to multi-gram tree */ 00297 multigram_add(new_dfa, new_winfo, p, cur->lm); 00298 /* need to rebuild the global lexicon */ 00299 /* make sure this process will be activated */ 00300 cur->active = 1; 00301 /* tell engine to update at requested timing */ 00302 schedule_grammar_update(recog); 00303 /* tell module client */ 00304 module_send(module_sd, "<GRAMMAR STATUS=\"RECEIVED\"/>\n.\n"); 00305 send_gram_info(cur); 00306 } else { 00307 module_send(module_sd, "<GRAMMAR STATUS=\"ERROR\" REASON=\"NOT A GRAMMAR-BASED LM\"/>\n.\n"); 00308 } 00309 } 00310 } else if (strmatch(command, "DELGRAM")) { 00311 /* remove the grammar specified by ID or name */ 00312 /* read a list of grammar IDs to be deleted */ 00313 if ( 00314 myfgets(buf, MAXBUFLEN, module_fp) 00315 == NULL) { 00316 fprintf(stderr, "Error: msock(DELGRAM): no argument\n"); 00317 return; 00318 } 00319 /* extract IDs and mark them as delete 00320 (actual deletion will be performed on the next 00321 */ 00322 if (cur->lmtype == LM_DFA) { 00323 for(p=strtok(buf," ");p;p=strtok(NULL," ")) { 00324 q = p; 00325 while(*q != '\0' && *q != '\r' && *q != '\n') { 00326 if (*q < '0' || *q > '9') break; 00327 q++; 00328 } 00329 if (*q == '\0' || *q == '\r' || *q == '\n') { /* numeric */ 00330 gid = atoi(p); 00331 } else { /* string */ 00332 gid = multigram_get_id_by_name(cur->lm, p); 00333 if (gid == -1) continue; 00334 } 00335 if (multigram_delete(gid, cur->lm) == FALSE) { /* deletion marking failed */ 00336 fprintf(stderr, "Warning: msock(DELGRAM): gram #%d failed to delete, ignored\n", gid); 00337 /* tell module */ 00338 module_send(module_sd, "<GRAMMAR STATUS=\"ERROR\" REASON=\"Gram #%d not found\"/>\n.\n", gid); 00339 } 00340 } 00341 /* need to rebuild the global lexicon */ 00342 /* tell engine to update at requested timing */ 00343 schedule_grammar_update(recog); 00344 } else { 00345 module_send(module_sd, "<GRAMMAR STATUS=\"ERROR\" REASON=\"NOT A GRAMMAR-BASED LM\"/>\n.\n"); 00346 } 00347 } else if (strmatch(command, "ACTIVATEGRAM")) { 00348 /* activate grammar in this engine */ 00349 /* read a list of grammar IDs or names to be activated */ 00350 if ( 00351 myfgets(buf, MAXBUFLEN, module_fp) 00352 == NULL) { 00353 fprintf(stderr, "Error: msock(ACTIVATEGRAM): no argument\n"); 00354 return; 00355 } 00356 /* mark them as active */ 00357 if (cur->lmtype == LM_DFA) { 00358 for(p=strtok(buf," ");p;p=strtok(NULL," ")) { 00359 q = p; 00360 while(*q != '\0' && *q != '\r' && *q != '\n') { 00361 if (*q < '0' || *q > '9') break; 00362 q++; 00363 } 00364 if (*q == '\0' || *q == '\r' || *q == '\n') { /* numeric */ 00365 gid = atoi(p); 00366 } else { /* string */ 00367 gid = multigram_get_id_by_name(cur->lm, p); 00368 if (gid == -1) continue; 00369 } 00370 ret = multigram_activate(gid, cur->lm); 00371 if (ret == 1) { 00372 /* already active */ 00373 module_send(module_sd, "<WARN MESSAGE=\"Gram #%d already active\"/>\n.\n", gid); 00374 } else if (ret == -1) { 00375 /* not found */ 00376 module_send(module_sd, "<WARN MESSAGE=\"Gram #%d not found\"/>\n.\n", gid); 00377 } /* else success */ 00378 } 00379 /* tell engine to update at requested timing */ 00380 schedule_grammar_update(recog); 00381 } else { 00382 module_send(module_sd, "<GRAMMAR STATUS=\"ERROR\" REASON=\"NOT A GRAMMAR-BASED LM\"/>\n.\n"); 00383 } 00384 } else if (strmatch(command, "DEACTIVATEGRAM")) { 00385 /* deactivate grammar in this engine */ 00386 /* read a list of grammar IDs or names to be de-activated */ 00387 if ( 00388 myfgets(buf, MAXBUFLEN, module_fp) 00389 == NULL) { 00390 fprintf(stderr, "Error: msock(DEACTIVATEGRAM): no argument\n"); 00391 return; 00392 } 00393 if (cur->lmtype == LM_DFA) { 00394 /* mark them as not active */ 00395 for(p=strtok(buf," ");p;p=strtok(NULL," ")) { 00396 q = p; 00397 while(*q != '\0' && *q != '\r' && *q != '\n') { 00398 if (*q < '0' || *q > '9') break; 00399 q++; 00400 } 00401 if (*q == '\0' || *q == '\r' || *q == '\n') { /* numeric */ 00402 gid = atoi(p); 00403 } else { /* string */ 00404 gid = multigram_get_id_by_name(cur->lm, p); 00405 if (gid == -1) continue; 00406 } 00407 ret = multigram_deactivate(gid, cur->lm); 00408 if (ret == 1) { 00409 /* already inactive */ 00410 module_send(module_sd, "<WARN MESSAGE=\"Gram #%d already inactive\"/>\n.\n", gid); 00411 } else if (ret == -1) { 00412 /* not found */ 00413 module_send(module_sd, "<WARN MESSAGE=\"Gram #%d not found\"/>\n.\n", gid); 00414 } /* else success */ 00415 } 00416 schedule_grammar_update(recog); 00417 } else { 00418 module_send(module_sd, "<GRAMMAR STATUS=\"ERROR\" REASON=\"NOT A GRAMMAR-BASED LM\"/>\n.\n"); 00419 } 00420 } else if (strmatch(command, "SYNCGRAM")) { 00421 /* update grammar if necessary */ 00422 if (cur->lmtype == LM_DFA) { 00423 multigram_update(cur->lm); /* some modification occured if return TRUE */ 00424 for(r=recog->process_list;r;r=r->next) { 00425 if (r->lmtype == LM_DFA && r->lm->global_modified) { 00426 multigram_build(r); 00427 } 00428 } 00429 cur->lm->global_modified = FALSE; 00430 module_send(module_sd, "<GRAMMAR STATUS=\"READY\"/>\n.\n"); 00431 } else { 00432 module_send(module_sd, "<GRAMMAR STATUS=\"ERROR\" REASON=\"NOT A GRAMMAR-BASED LM\"/>\n.\n"); 00433 } 00434 } else if (strmatch(command, "CURRENTPROCESS")) { 00435 JCONF_SEARCH *sconf; 00436 RecogProcess *r; 00437 if ( 00438 myfgets(buf, MAXBUFLEN, module_fp) 00439 == NULL) { 00440 /* when no argument, just return current process */ 00441 send_current_process(cur); 00442 return; 00443 } 00444 if (buf[0] == '\0') { 00445 /* when no argument, just return current process */ 00446 send_current_process(cur); 00447 return; 00448 } 00449 sconf = j_get_searchconf_by_name(recog->jconf, buf); 00450 if (sconf == NULL) { 00451 fprintf(stderr, "Error: msock(CURRENTPROCESS): no such process \"%s\"\n", buf); 00452 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO SUCH PROCESS\"/>\n.\n"); 00453 return; 00454 } 00455 for(r=recog->process_list;r;r=r->next) { 00456 if (r->config == sconf) { 00457 cur = r; 00458 break; 00459 } 00460 } 00461 if (!r) { 00462 fprintf(stderr, "Error: msock(CURRENTPROCESS): no process assigned to searchconf \"%s\"??\n", buf); 00463 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO SUCH PROCESS\"/>\n.\n"); 00464 return; 00465 } 00466 send_current_process(cur); 00467 } 00468 00469 else if (strmatch(command, "SHIFTPROCESS")) { 00470 cur = cur->next; 00471 if (cur == NULL) { 00472 fprintf(stderr, "SHIFTPROCESS: reached end, rotated to first\n"); 00473 cur = recog->process_list; 00474 } 00475 send_process_stat(cur); 00476 } 00477 00478 else if (strmatch(command, "ADDPROCESS")) { 00479 Jconf *jconf; 00480 JCONF_LM *lmconf; 00481 JCONF_AM *amconf; 00482 JCONF_SEARCH *sconf; 00483 RecogProcess *r; 00484 00485 if ( 00486 myfgets(buf, MAXBUFLEN, module_fp) 00487 == NULL) { 00488 fprintf(stderr, "Error: msock(ADDPROCESS): no argument\n"); 00489 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO ARGUMENT\"/>\n.\n"); 00490 return; 00491 } 00492 /* load specified jconf file and use its last LM conf as new */ 00493 jconf = j_jconf_new(); 00494 j_config_load_file(jconf, buf); 00495 lmconf = jconf->lmnow; 00496 00497 /* create a search instance */ 00498 sconf = j_jconf_search_new(); 00499 /* all the parameters are defaults */ 00500 00501 /* create process instance with new LM and SR */ 00502 if (j_process_add_lm(recog, lmconf, sconf, buf) == FALSE) { 00503 fprintf(stderr, "Error: failed to regist new process \"%s\"\n", buf); 00504 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"FAILED TO REGISTER\"/>\n.\n"); 00505 j_jconf_search_free(sconf); 00506 return; 00507 } 00508 printf("added process: SR%02d %s\n", sconf->id, sconf->name); 00509 module_send(module_sd, "<RECOGPROCESS INFO=\"ADDED\">\n"); 00510 for(r=recog->process_list;r;r=r->next) { 00511 if (r->config == sconf) { 00512 send_process_stat(r); 00513 } 00514 } 00515 module_send(module_sd, "</RECOGPROCESS>\n.\n"); 00516 } 00517 00518 else if (strmatch(command, "DELPROCESS")) { 00519 JCONF_SEARCH *sconf; 00520 JCONF_LM *lmconf; 00521 RecogProcess *r; 00522 00523 if ( 00524 myfgets(buf, MAXBUFLEN, module_fp) 00525 == NULL) { 00526 fprintf(stderr, "Error: msock(DELPROCESS): no argument\n"); 00527 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO ARGUMENT\"/>\n.\n"); 00528 return; 00529 } 00530 00531 sconf = j_get_searchconf_by_name(recog->jconf, buf); 00532 if (sconf == NULL) { 00533 fprintf(stderr, "Error: msock(DELPROCESS): no searchconf named %s\n", buf); 00534 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO RECOGPROCESS OF THE NAME\"/>\n.\n"); 00535 return; 00536 } 00537 00538 lmconf = sconf->lmconf; 00539 printf("remove process: SR%02d %s, LM%02d %s\n", sconf->id, sconf->name, lmconf->id, lmconf->name); 00540 module_send(module_sd, "<RECOGPROCESS INFO=\"DELETE\">\n"); 00541 for(r=recog->process_list;r;r=r->next) { 00542 if (r->config == sconf) send_process_stat(r); 00543 } 00544 module_send(module_sd, "</RECOGPROCESS>\n.\n"); 00545 j_process_remove(recog, sconf); 00546 j_process_lm_remove(recog, lmconf); 00547 /* change current */ 00548 for(r=recog->process_list;r;r=r->next) { 00549 if (r == cur) break; 00550 } 00551 if (!r) { 00552 cur = recog->process_list; 00553 printf("now current moved to SR%02d %s\n", cur->config->id, cur->config->name); 00554 send_current_process(cur); 00555 } 00556 00557 } 00558 00559 else if (strmatch(command, "LISTPROCESS")) { 00560 RecogProcess *r; 00561 00562 module_send(module_sd, "<RECOGPROCESS INFO=\"STATUS\">\n"); 00563 for(r=recog->process_list;r;r=r->next) { 00564 send_process_stat(r); 00565 } 00566 module_send(module_sd, "</RECOGPROCESS>\n.\n"); 00567 } 00568 00569 else if (strmatch(command, "ACTIVATEPROCESS")) { 00570 if ( 00571 myfgets(buf, MAXBUFLEN, module_fp) 00572 == NULL) { 00573 fprintf(stderr, "Error: msock(ACTIVATEPROCESS): no argument\n"); 00574 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO ARGUMENT\"/>\n.\n"); 00575 return; 00576 } 00577 if (j_process_activate(recog, buf) == FALSE) { 00578 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"ACTIVATION FAILED\"/>\n.\n"); 00579 } else { 00580 module_send(module_sd, "<RECOGPROCESS INFO=\"ACTIVATED\" NAME=\"%s\"/>\n.\n", buf); 00581 } 00582 } 00583 else if (strmatch(command, "DEACTIVATEPROCESS")) { 00584 if ( 00585 myfgets(buf, MAXBUFLEN, module_fp) 00586 == NULL) { 00587 fprintf(stderr, "Error: msock(DEACTIVATEPROCESS): no argument\n"); 00588 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO ARGUMENT\"/>\n.\n"); 00589 return; 00590 } 00591 if (j_process_deactivate(recog, buf) == FALSE) { 00592 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"DEACTIVATION FAILED\"/>\n.\n"); 00593 } else { 00594 module_send(module_sd, "<RECOGPROCESS INFO=\"DEACTIVATED\" NAME=\"%s\"/>\n.\n", buf); 00595 } 00596 module_send(module_sd, ".\n"); 00597 } 00598 else if (strmatch(command, "ADDWORD")) { 00599 WORD_INFO *words; 00600 boolean ret; 00601 int id; 00602 00603 /* get gramamr ID to add */ 00604 if ( 00605 myfgets(buf, MAXBUFLEN, module_fp) 00606 == NULL) { 00607 fprintf(stderr, "Error: msock(DEACTIVATEPROCESS): no argument\n"); 00608 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO ARGUMENT\"/>\n.\n"); 00609 return; 00610 } 00611 id = atoi(buf); 00612 00613 /* read list of word entries, will stop by "DICEND" */ 00614 words = word_info_new(); 00615 voca_load_start(words, cur->am->hmminfo, FALSE); 00616 while ( 00617 myfgets(buf, MAXBUFLEN, module_fp) 00618 != NULL) { 00619 if (cur->lmvar == LM_DFA_WORD) { 00620 ret = voca_load_word_line(buf, words, cur->am->hmminfo, 00621 cur->lm->config->wordrecog_head_silence_model_name, 00622 cur->lm->config->wordrecog_tail_silence_model_name, 00623 (cur->lm->config->wordrecog_silence_context_name[0] == '\0') ? NULL : cur->lm->config->wordrecog_silence_context_name); 00624 } else { 00625 ret = voca_load_line(buf, words, cur->am->hmminfo); 00626 } 00627 if (ret == FALSE) break; 00628 } 00629 ret = voca_load_end(words); 00630 if (ret == FALSE) { 00631 fprintf(stderr, "Error: msock(ADDWORD): error in reading word entries\n"); 00632 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"ERROR IN READING WORD ENTRIES\"/>\n.\n"); 00633 word_info_free(words); 00634 return; 00635 } 00636 if (words->num == 0) { 00637 fprintf(stderr, "Error: msock(ADDWORD): no word specified\n"); 00638 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO WORD SPECIFIED\"/>\n.\n"); 00639 word_info_free(words); 00640 return; 00641 } 00642 printf("%d words read\n", words->num); 00643 /* add the words to the grammar */ 00644 if (multigram_add_words_to_grammar_by_id(cur->lm, id, words) == FALSE) { 00645 fprintf(stderr, "Error: msock(ADDWORD): failed to add words to grammar #%d\n", id); 00646 module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"FAILED\"/>\n.\n"); 00647 word_info_free(words); 00648 return; 00649 } 00650 /* book for update */ 00651 schedule_grammar_update(recog); 00652 module_send(module_sd, "%d words added to grammar #%d\n.\n", words->num, id); 00653 module_send(module_sd, "<RECOGPROCESS INFO=\"ADDEDWORD\" GRAMMARID=\"%d\" NUM=\"%d\"/>\n.\n", id, words->num); 00654 00655 word_info_free(words); 00656 } 00657 } 00658 00671 static void 00672 msock_check_and_process_command(Recog *recog, void *dummy) 00673 { 00674 fd_set rfds; 00675 int ret; 00676 struct timeval tv; 00677 00678 /* check if some commands are waiting in queue */ 00679 FD_ZERO(&rfds); 00680 FD_SET(module_sd, &rfds); 00681 tv.tv_sec = 0; 00682 tv.tv_usec = 0; /* 0 msec timeout: return immediately */ 00683 ret = select(module_sd+1, &rfds, NULL, NULL, &tv); 00684 if (ret < 0) { 00685 perror("msock_check_and_process_command: cannot poll\n"); 00686 } 00687 if (ret > 0) { 00688 /* there is data to read */ 00689 /* process command and change status if necessaty */ 00690 while(select(module_sd+1, &rfds, NULL, NULL, &tv) > 0 && 00691 myfgets(mbuf, MAXBUFLEN, module_fp) 00692 != NULL) { 00693 msock_exec_command(mbuf, recog); 00694 } 00695 } 00696 } 00697 00713 static void 00714 msock_process_command(Recog *recog, void *dummy) 00715 { 00716 00717 while(!recog->process_active) { 00718 if ( 00719 myfgets(mbuf, MAXBUFLEN, module_fp) 00720 != NULL) { 00721 msock_exec_command(mbuf, recog); 00722 } 00723 } 00724 } 00725 00726 static void 00727 module_regist_callback(Recog *recog, void *data) 00728 { 00729 callback_add(recog, CALLBACK_POLL, msock_check_and_process_command, data); 00730 callback_add(recog, CALLBACK_PAUSE_FUNCTION, msock_process_command, data); 00731 } 00732 00733 /************************************************************************/ 00734 static boolean 00735 opt_module(Jconf *jconf, char *arg[], int argnum) 00736 { 00737 module_mode = TRUE; 00738 if (argnum > 0) { 00739 module_port = atoi(arg[0]); 00740 } 00741 return TRUE; 00742 } 00743 00744 static boolean 00745 opt_outcode(Jconf *jconf, char *arg[], int argnum) 00746 { 00747 decode_output_selection(arg[0]); 00748 return TRUE; 00749 } 00750 00751 void 00752 module_add_option() 00753 { 00754 j_add_option("-module", 1, 0, "run as a server module", opt_module); 00755 j_add_option("-outcode", 1, 1, "select info to output to the module: WLPSCwlps", opt_outcode); 00756 } 00757 00758 boolean 00759 is_module_mode() 00760 { 00761 return module_mode; 00762 } 00763 00764 void 00765 module_setup(Recog *recog, void *data) 00766 { 00767 /* register result output callback functions */ 00768 module_regist_callback(recog, data); 00769 setup_output_msock(recog, data); 00770 } 00771 00772 void 00773 module_server() 00774 { 00775 int listen_sd; 00776 #if defined(_WIN32) && !defined(__CYGWIN32__) 00777 int sd; 00778 #endif 00779 00780 /* prepare socket to listen */ 00781 if ((listen_sd = ready_as_server(module_port)) < 0) { 00782 fprintf(stderr, "Error: failed to bind socket\n"); 00783 return; 00784 } 00785 00786 printf ("///////////////////////////////\n"); 00787 printf ("/// Module mode ready\n"); 00788 printf ("/// waiting client at %5d\n", module_port); 00789 printf ("///////////////////////////////\n"); 00790 printf ("/// "); 00791 00792 /* no fork, just wait for one connection and proceed */ 00793 if ((module_sd = accept_from(listen_sd)) < 0) { 00794 fprintf(stderr, "Error: failed to accept connection\n"); 00795 return; 00796 } 00797 #if defined(_WIN32) && !defined(__CYGWIN32__) 00798 /* call winsock function to make the socket capable of reading/writing */ 00799 if ((sd = _open_osfhandle(module_sd, O_RDWR|O_BINARY)) < 0) { 00800 fprintf(stderr, "Error: failed to open_osfhandle\n"); 00801 return; 00802 } 00803 if ((module_fp = fdopen(sd, "rb+")) == NULL) { 00804 fprintf(stderr, "Error: failed to fdopen socket\n"); 00805 return; 00806 } 00807 #else 00808 if ((module_fp = fdopen(module_sd, "r+")) == NULL) { 00809 fprintf(stderr, "Error; failed to fdopen socket\n"); 00810 return; 00811 } 00812 #endif 00813 } 00814 00815 void 00816 module_disconnect() 00817 { 00818 /* disconnect control module */ 00819 if (module_sd >= 0) { /* connected now */ 00820 module_send(module_sd, "<SYSINFO PROCESS=\"ERREXIT\"/>\n.\n"); 00821 close_socket(module_sd); 00822 module_sd = -1; 00823 } 00824 }