julius/module.c

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 
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_LM *lmconf;
00520     JCONF_AM *amconf;
00521     JCONF_SEARCH *sconf;
00522     RecogProcess *r;
00523 
00524     if (
00525         myfgets(buf, MAXBUFLEN, module_fp)
00526         == NULL) {
00527       fprintf(stderr, "Error: msock(DELPROCESS): no argument\n");
00528       module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO ARGUMENT\"/>\n.\n");
00529       return;
00530     }
00531 
00532     lmconf = j_get_lmconf_by_name(recog->jconf, buf);
00533     if (lmconf == NULL) {
00534       fprintf(stderr, "Error: msock(DELPROCESS): no lmconf named %s\n", buf);
00535       module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO LM PROCESS OF THE NAME\"/>\n.\n");
00536       return;
00537     }
00538     sconf =  j_get_searchconf_by_name(recog->jconf, buf);
00539     if (sconf == NULL) {
00540       fprintf(stderr, "Error: msock(DELPROCESS): no searchconf named %s\n", buf);
00541       module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO RECOGPROCESS OF THE NAME\"/>\n.\n");
00542       return;
00543     }
00544     printf("remove process: SR%02d %s, LM%02d %s\n", sconf->id, sconf->name, lmconf->id, lmconf->name);
00545     module_send(module_sd, "<RECOGPROCESS INFO=\"DELETE\">\n");
00546     for(r=recog->process_list;r;r=r->next) {
00547       if (r->config == sconf) send_process_stat(r);
00548     }
00549     module_send(module_sd, "</RECOGPROCESS>\n.\n");
00550     j_process_remove(recog, sconf);
00551     j_process_lm_remove(recog, lmconf);
00552     /* change current */
00553     for(r=recog->process_list;r;r=r->next) {
00554       if (r == cur) break;
00555     }
00556     if (!r) {
00557       cur = recog->process_list;
00558       printf("now current moved to SR%02d %s\n", cur->config->id, cur->config->name);
00559       send_current_process(cur);
00560     }
00561     
00562   }
00563 
00564   else if (strmatch(command, "LISTPROCESS")) {
00565     RecogProcess *r;
00566     
00567     module_send(module_sd, "<RECOGPROCESS INFO=\"STATUS\">\n");
00568     for(r=recog->process_list;r;r=r->next) {
00569       send_process_stat(r);
00570     }
00571     module_send(module_sd, "</RECOGPROCESS>\n.\n");
00572   }
00573 
00574   else if (strmatch(command, "ACTIVATEPROCESS")) {
00575     if (
00576         myfgets(buf, MAXBUFLEN, module_fp)
00577         == NULL) {
00578       fprintf(stderr, "Error: msock(ACTIVATEPROCESS): no argument\n");
00579       module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO ARGUMENT\"/>\n.\n");
00580       return;
00581     }
00582     if (j_process_activate(recog, buf) == FALSE) {
00583       module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"ACTIVATION FAILED\"/>\n.\n");
00584     } else {
00585       module_send(module_sd, "<RECOGPROCESS INFO=\"ACTIVATED\" NAME=\"%s\"/>\n.\n", buf);
00586     }
00587   }
00588   else if (strmatch(command, "DEACTIVATEPROCESS")) {
00589     if (
00590         myfgets(buf, MAXBUFLEN, module_fp)
00591         == NULL) {
00592       fprintf(stderr, "Error: msock(DEACTIVATEPROCESS): no argument\n");
00593       module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO ARGUMENT\"/>\n.\n");
00594       return;
00595     }
00596     if (j_process_deactivate(recog, buf) == FALSE) {
00597       module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"DEACTIVATION FAILED\"/>\n.\n");
00598     } else {
00599       module_send(module_sd, "<RECOGPROCESS INFO=\"DEACTIVATED\" NAME=\"%s\"/>\n.\n", buf);
00600     }
00601     module_send(module_sd, ".\n");
00602   }
00603   else if (strmatch(command, "ADDWORD")) {
00604     WORD_INFO *words;
00605     boolean ret;
00606     int id;
00607 
00608     /* get gramamr ID to add */
00609     if (
00610         myfgets(buf, MAXBUFLEN, module_fp)
00611         == NULL) {
00612       fprintf(stderr, "Error: msock(DEACTIVATEPROCESS): no argument\n");
00613       module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO ARGUMENT\"/>\n.\n");
00614       return;
00615     }
00616     id = atoi(buf);
00617 
00618     /* read list of word entries, will stop by "DICEND" */
00619     words = word_info_new();
00620     voca_load_start(words, cur->am->hmminfo, FALSE);
00621     while (
00622         myfgets(buf, MAXBUFLEN, module_fp)
00623         != NULL) {
00624       if (cur->lmvar == LM_DFA_WORD) {
00625         ret = voca_load_word_line(buf, words, cur->am->hmminfo, 
00626                                   cur->lm->config->wordrecog_head_silence_model_name,
00627                                   cur->lm->config->wordrecog_tail_silence_model_name,
00628                                   (cur->lm->config->wordrecog_silence_context_name[0] == '\0') ? NULL : cur->lm->config->wordrecog_silence_context_name);
00629       } else {
00630         ret = voca_load_line(buf, words, cur->am->hmminfo);
00631       }
00632       if (ret == FALSE) break;
00633     }
00634     ret = voca_load_end(words);
00635     if (ret == FALSE) {
00636       fprintf(stderr, "Error: msock(ADDWORD): error in reading word entries\n");
00637       module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"ERROR IN READING WORD ENTRIES\"/>\n.\n");
00638       word_info_free(words);
00639       return;
00640     }
00641     if (words->num == 0) {
00642       fprintf(stderr, "Error: msock(ADDWORD): no word specified\n");
00643       module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"NO WORD SPECIFIED\"/>\n.\n");
00644       word_info_free(words);
00645       return;
00646     }
00647     printf("%d words read\n", words->num);
00648     /* add the words to the grammar */
00649     if (multigram_add_words_to_grammar_by_id(cur->lm, id, words) == FALSE) {
00650       fprintf(stderr, "Error: msock(ADDWORD): failed to add words to grammar #%d\n", id);
00651       module_send(module_sd, "<RECOGPROCESS STATUS=\"ERROR\" REASON=\"FAILED\"/>\n.\n");
00652       word_info_free(words);
00653       return;
00654     }
00655     /* book for update */
00656     schedule_grammar_update(recog);
00657     module_send(module_sd, "%d words added to grammar #%d\n.\n", words->num, id);
00658     module_send(module_sd, "<RECOGPROCESS INFO=\"ADDEDWORD\" GRAMMARID=\"%d\" NUM=\"%d\"/>\n.\n", id, words->num);
00659 
00660     word_info_free(words);
00661   }
00662 }
00663 
00676 static void
00677 msock_check_and_process_command(Recog *recog, void *dummy)
00678 {
00679   fd_set rfds;
00680   int ret;
00681   struct timeval tv;
00682 
00683   /* check if some commands are waiting in queue */
00684   FD_ZERO(&rfds);
00685   FD_SET(module_sd, &rfds);
00686   tv.tv_sec = 0;
00687   tv.tv_usec = 0;             /* 0 msec timeout: return immediately */
00688   ret = select(module_sd+1, &rfds, NULL, NULL, &tv);
00689   if (ret < 0) {
00690     perror("msock_check_and_process_command: cannot poll\n");
00691   }
00692   if (ret > 0) {
00693     /* there is data to read */
00694     /* process command and change status if necessaty */
00695     while(select(module_sd+1, &rfds, NULL, NULL, &tv) > 0 &&
00696           myfgets(mbuf, MAXBUFLEN, module_fp)
00697           != NULL) {
00698       msock_exec_command(mbuf, recog);
00699     }
00700   }
00701 }
00702 
00718 static void
00719 msock_process_command(Recog *recog, void *dummy)
00720 {
00721 
00722   while(!recog->process_active) {
00723     if (
00724         myfgets(mbuf, MAXBUFLEN, module_fp)
00725         != NULL) {
00726       msock_exec_command(mbuf, recog);
00727     }
00728   }
00729 }
00730 
00731 static void
00732 module_regist_callback(Recog *recog, void *data)
00733 {
00734   callback_add(recog, CALLBACK_POLL, msock_check_and_process_command, data);
00735   callback_add(recog, CALLBACK_PAUSE_FUNCTION, msock_process_command, data);
00736 }
00737 
00738 /************************************************************************/
00739 static boolean
00740 opt_module(Jconf *jconf, char *arg[], int argnum)
00741 {
00742   module_mode = TRUE;
00743   if (argnum > 0) {
00744     module_port = atoi(arg[0]);
00745   }
00746   return TRUE;
00747 }
00748 
00749 static boolean
00750 opt_outcode(Jconf *jconf, char *arg[], int argnum)
00751 {
00752   decode_output_selection(arg[0]);
00753   return TRUE;
00754 }
00755 
00756 void
00757 module_add_option()
00758 {
00759   j_add_option("-module", 1, 0, "run as a server module", opt_module);
00760   j_add_option("-outcode", 1, 1, "select info to output to the module: WLPSCwlps", opt_outcode);
00761 }
00762 
00763 boolean
00764 is_module_mode()
00765 {
00766   return module_mode;
00767 }
00768 
00769 void
00770 module_setup(Recog *recog, void *data)
00771 {
00772   /* register result output callback functions */
00773   module_regist_callback(recog, data);
00774   setup_output_msock(recog, data);
00775 }
00776   
00777 void
00778 module_server()
00779 {
00780   int listen_sd;        
00781 #if defined(_WIN32) && !defined(__CYGWIN32__)
00782   int sd;
00783 #endif
00784   
00785   /* prepare socket to listen */
00786   if ((listen_sd = ready_as_server(module_port)) < 0) {
00787     fprintf(stderr, "Error: failed to bind socket\n");
00788     return;
00789   }
00790   
00791   printf  ("///////////////////////////////\n");
00792   printf  ("///  Module mode ready\n");
00793   printf  ("///  waiting client at %5d\n", module_port);
00794   printf  ("///////////////////////////////\n");
00795   printf  ("///  ");
00796   
00797   /* no fork, just wait for one connection and proceed */
00798   if ((module_sd = accept_from(listen_sd)) < 0) {
00799     fprintf(stderr, "Error: failed to accept connection\n");
00800     return;
00801   }
00802 #if defined(_WIN32) && !defined(__CYGWIN32__)
00803   /* call winsock function to make the socket capable of reading/writing */
00804   if ((sd = _open_osfhandle(module_sd, O_RDWR|O_BINARY)) < 0) {
00805     fprintf(stderr, "Error: failed to open_osfhandle\n");
00806     return;
00807   }
00808   if ((module_fp = fdopen(sd, "rb+")) == NULL) {
00809     fprintf(stderr, "Error: failed to fdopen socket\n");
00810     return;
00811   }
00812 #else
00813   if ((module_fp = fdopen(module_sd, "r+")) == NULL) {
00814     fprintf(stderr, "Error; failed to fdopen socket\n");
00815     return;
00816   }
00817 #endif
00818 }
00819 
00820 void
00821 module_disconnect()
00822 {
00823   /* disconnect control module */
00824   if (module_sd >= 0) { /* connected now */
00825     module_send(module_sd, "<SYSINFO PROCESS=\"ERREXIT\"/>\n.\n");
00826     close_socket(module_sd);
00827     module_sd = -1;
00828   }
00829 }

Juliusに対してThu Jul 23 12:16:22 2009に生成されました。  doxygen 1.5.1