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

Generated on Tue Dec 18 15:59:49 2007 for Julius by  doxygen 1.5.4