Julius 4.2
libjulius/src/plugin.c
説明を見る。
00001 
00018 /*
00019  * Copyright (c) 1991-2011 Kawahara Lab., Kyoto University
00020  * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology
00021  * Copyright (c) 2005-2011 Julius project team, Nagoya Institute of Technology
00022  * All rights reserved
00023  */
00024 
00025 #include <julius/julius.h>
00026 
00027 #ifdef ENABLE_PLUGIN
00028 
00029 #if defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__MINGW32__)
00030 #include <windows.h>
00031 #else
00032 #include <dirent.h>
00033 #endif
00034 #include <stdarg.h>
00035 
00040 static char *plugin_suffix = PLUGIN_SUFFIX;
00041 
00046 static char *plugin_function_namelist[] = PLUGIN_FUNCTION_NAMELIST;
00047 
00048 
00049 /**************************************************************/
00050 
00051 #if defined(_WIN32) && !defined(__CYGWIN32__)
00052 
00057 static const char* dlerror()
00058 {
00059   static char szMsgBuf[256];
00060   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
00061                 NULL,
00062                 GetLastError(),
00063                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00064                 szMsgBuf,
00065                 sizeof szMsgBuf,
00066                 NULL);
00067   return szMsgBuf;
00068 }
00069 #endif
00070 
00071 /**************************************************************/
00072 static int
00073 plugin_namelist_num()
00074 {
00075   return(sizeof(plugin_function_namelist) / sizeof(char *));
00076 }
00077 
00078 static void
00079 plugin_free_all()
00080 {
00081   PLUGIN_ENTRY *p, *ptmp;
00082   int i, num;
00083 
00084   num = plugin_namelist_num();
00085   for(i=0;i<num;i++) {
00086     p = global_plugin_list[i];
00087     while(p) {
00088       ptmp = p->next;
00089       free(p);
00090       p = ptmp;
00091     }
00092   }
00093   free(global_plugin_list);
00094 }    
00095 
00096 
00097 int
00098 plugin_get_id(char *name)
00099 {
00100   int i, num;
00101   num = plugin_namelist_num();
00102   for(i=0;i<num;i++) {
00103     if (strmatch(plugin_function_namelist[i], name)) {
00104       return i;
00105     }
00106   }
00107   jlog("InternalError: no plugin entry named %s\n", name);
00108   return -1;
00109 }
00110 
00111 void
00112 plugin_init()
00113 {
00114   int i, num;
00115 
00116   if (global_plugin_list != NULL) {
00117     plugin_free_all();
00118   }
00119   num = plugin_namelist_num();
00120   global_plugin_list = (PLUGIN_ENTRY **)mymalloc(sizeof(PLUGIN_ENTRY *) * num);
00121   for(i=0;i<num;i++) {
00122     global_plugin_list[i] = NULL;
00123   }
00124   global_plugin_loaded_file_num = 0;
00125 }
00126 
00127 /**************************************************************/
00135 static boolean
00136 is_plugin_obj(char *filename)
00137 {
00138   char *p, *x;
00139   x = plugin_suffix + strlen(plugin_suffix) - 1;
00140   p = filename + strlen(filename) - 1;
00141 
00142   while (x >= plugin_suffix && p >= filename && *x == *p) {
00143     x--; p--;
00144   }
00145   if (x < plugin_suffix) {
00146     return TRUE;
00147   }
00148 
00149   return FALSE;
00150 }
00151 
00159 boolean
00160 plugin_load_file(char *file)
00161 {
00162   PLUGIN_MODULE handle;
00163   FUNC_INT func;
00164   FUNC_VOID entfunc;
00165   int ret, number, num;
00166   char buf[256];
00167   int buflen = 256;
00168   PLUGIN_ENTRY *p;
00169   int i;
00170 
00171   if (global_plugin_list == NULL) plugin_init();
00172 
00173   /* open file */
00174   handle = dlopen(file, RTLD_LAZY);
00175   if (!handle) {
00176     jlog("ERROR: plugin_load: failed to open: %s\n", dlerror());
00177     return(FALSE);
00178   }
00179 
00180   /* call initialization function */
00181   func = dlsym(handle, "initialize");
00182   if (func) {
00183     ret = (*func)();
00184     if (ret == -1) {
00185       jlog("WARNING: plugin_load: %s: initialize() returns no, skip this file\n", file);
00186       dlclose(handle);
00187       return(FALSE);
00188     }
00189   }
00190 
00191   /* call information function */
00192   func = dlsym(handle, "get_plugin_info");
00193   if (func == NULL) {
00194     jlog("ERROR: plugin_load: %s: get_plugin_info(): %s\n", file, dlerror());
00195     dlclose(handle);
00196     return(FALSE);
00197   }
00198   number = 0;
00199   ret = (*func)(number, buf, buflen);
00200   if (ret == -1) {
00201     jlog("ERROR: plugin_load: %s: get_plugin_info(0) returns error\n", file);
00202     dlclose(handle);
00203     return(FALSE);
00204   }
00205   buf[buflen-1] = '\0';
00206   jlog("#%d [%s]\n", global_plugin_loaded_file_num, buf);
00207   
00208   /* register plugin functions */
00209   num = plugin_namelist_num();
00210   for(i=0;i<num;i++) {
00211     entfunc = dlsym(handle, plugin_function_namelist[i]);
00212     if (entfunc) {
00213       if (debug2_flag) {
00214         jlog("     (%s)\n", plugin_function_namelist[i]);
00215       }
00216       p = (PLUGIN_ENTRY *)mymalloc(sizeof(PLUGIN_ENTRY));
00217       p->id = i;
00218       p->source_id = global_plugin_loaded_file_num;
00219       p->func = entfunc;
00220       p->next = global_plugin_list[i];
00221       global_plugin_list[i] = p;
00222     }
00223   }
00224 
00225   /* increment file counter */
00226   global_plugin_loaded_file_num++;
00227 
00228   return(TRUE);
00229 }
00230 
00238 boolean
00239 plugin_load_dir(char *dir)
00240 {
00241 #if defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__MINGW32__)
00242 
00243   WIN32_FIND_DATA FindFileData;
00244   HANDLE hFind;
00245   static char buf[512];
00246   int cnt;
00247 
00248   strncpy(buf, dir, 505);
00249   strcat(buf, "\\*.dll");
00250   if ((hFind = FindFirstFile(buf, &FindFileData)) == INVALID_HANDLE_VALUE) {
00251     jlog("ERROR: plugin_load: cannot open plugins dir \"%s\"\n", dir);
00252     return FALSE;
00253   }
00254 
00255   cnt = 0;
00256   do {
00257     jlog("STAT: file: %-23s ", FindFileData.cFileName);
00258     sprintf_s(buf, 512, "%s\\%s", dir, FindFileData.cFileName);
00259     if (plugin_load_file(buf)) cnt++;
00260   } while (FindNextFile(hFind, &FindFileData));
00261 
00262   FindClose(hFind);
00263   jlog("STAT: %d files loaded\n", cnt);
00264 
00265   return TRUE;
00266   
00267 #else
00268   
00269   DIR *d;
00270   struct dirent *f;
00271   static char buf[512];
00272   int cnt;
00273 
00274   if ((d = opendir(dir)) == NULL) {
00275     jlog("ERROR: plugin_load: cannot open plugins dir \"%s\"\n", dir);
00276     return FALSE;
00277   }
00278   cnt = 0;
00279   while((f = readdir(d)) != NULL) {
00280     if (is_plugin_obj(f->d_name)) {
00281       snprintf(buf, 512, "%s/%s", dir, f->d_name);
00282       jlog("STAT: file: %-23s ", f->d_name);
00283       if (plugin_load_file(buf)) cnt++;
00284     }
00285   }
00286   closedir(d);
00287   jlog("STAT: %d files loaded\n", cnt);
00288 
00289   return TRUE;
00290 
00291 #endif
00292 }
00293 
00301 void
00302 plugin_load_dirs(char *dirent)
00303 {
00304   char *p, *s;
00305   char c;
00306 
00307   if (dirent == NULL) return;
00308 
00309   if (debug2_flag) {
00310     jlog("DEBUG: loading dirs: %s\n", dirent);
00311   }
00312 
00313   p = dirent;
00314   do {
00315     s = p;
00316     while(*p != '\0' && *p != ':') p++;
00317     c = *p;
00318     *p = '\0';
00319     jlog("STAT: loading plugins at \"%s\":\n", dirent);
00320     plugin_load_dir(s);
00321     if (c != '\0') {
00322       *p = c;
00323       p++;
00324     }
00325   } while (*p != '\0');
00326 }
00327 
00328 
00329 /************************************************************************/
00330 
00331 int
00332 plugin_find_optname(char *optfuncname, char *str)
00333 {
00334   char buf[64];
00335   int id;
00336   PLUGIN_ENTRY *p;
00337   FUNC_VOID func;
00338 
00339   if ((id = plugin_get_id(optfuncname)) < 0) return -1;
00340 
00341   for(p=global_plugin_list[id];p;p=p->next) {
00342     func = (FUNC_VOID) p->func;
00343     (*func)(buf, (int)64);
00344     if (strmatch(buf, str)) {
00345       return p->source_id;
00346     }
00347   }
00348   return -1;
00349 }
00350 
00351 FUNC_VOID
00352 plugin_get_func(int sid, char *name)
00353 {
00354   int id;
00355   PLUGIN_ENTRY *p;
00356   FUNC_VOID func;
00357 
00358   if ((id = plugin_get_id(name)) < 0) return NULL;
00359 
00360   for(p=global_plugin_list[id];p;p=p->next) {
00361     if (p->source_id == sid) return p->func;
00362   }
00363   return NULL;
00364 }
00365 
00366 /************************************************************************/
00367 boolean
00368 plugin_exec_engine_startup(Recog *recog)
00369 {
00370   int id;
00371   PLUGIN_ENTRY *p;
00372   FUNC_INT func;
00373   boolean ok_p;
00374 
00375   if (global_plugin_list == NULL) return TRUE;
00376 
00377   if ((id = plugin_get_id("startup")) < 0) return FALSE;
00378 
00379   ok_p = TRUE;
00380   for(p=global_plugin_list[id];p;p=p->next) {
00381     func = (FUNC_INT) p->func;
00382     if ((*func)(recog) != 0) {
00383       jlog("WARNING: plugin #%d: failed in startup()\n", p->source_id);
00384       ok_p = FALSE;
00385     }
00386   }
00387 
00388   return ok_p;
00389 }
00390 
00391 
00392 /************************************************************************/
00393 void
00394 plugin_exec_adin_captured(short *buf, int len)
00395 {
00396   int id;
00397   PLUGIN_ENTRY *p;
00398   FUNC_VOID adfunc;
00399 
00400   if (global_plugin_list == NULL) return;
00401 
00402   if ((id = plugin_get_id("adin_postprocess")) < 0) return;
00403   for(p=global_plugin_list[id];p;p=p->next) {
00404     adfunc = (FUNC_VOID) p->func;
00405     (*adfunc)(buf, len);
00406   }
00407 }
00408 
00409 void
00410 plugin_exec_adin_triggered(short *buf, int len)
00411 {
00412   int id;
00413   PLUGIN_ENTRY *p;
00414   FUNC_VOID adfunc;
00415 
00416   if (global_plugin_list == NULL) return;
00417 
00418   if ((id = plugin_get_id("adin_postprocess_triggered")) < 0) return;
00419   for(p=global_plugin_list[id];p;p=p->next) {
00420     adfunc = (FUNC_VOID) p->func;
00421     (*adfunc)(buf, len);
00422   }
00423 }
00424 
00425 void
00426 plugin_exec_vector_postprocess(VECT *vecbuf, int veclen, int nframe)
00427 {
00428   int id;
00429   PLUGIN_ENTRY *p;
00430   FUNC_INT func;
00431 
00432   if (global_plugin_list == NULL) return;
00433 
00434   if ((id = plugin_get_id("fvin_postprocess")) < 0) return;
00435   for(p=global_plugin_list[id];p;p=p->next) {
00436     func = (FUNC_INT) p->func;
00437     (*func)(vecbuf, veclen, nframe);
00438   }
00439 }
00440 void
00441 plugin_exec_vector_postprocess_all(HTK_Param *param)
00442 {
00443   int id;
00444   PLUGIN_ENTRY *p;
00445   FUNC_INT func;
00446   int t;
00447 
00448   if (global_plugin_list == NULL) return;
00449 
00450   if ((id = plugin_get_id("fvin_postprocess")) < 0) return;
00451   for(t=0;t<param->samplenum;t++) {
00452     for(p=global_plugin_list[id];p;p=p->next) {
00453       func = (FUNC_INT) p->func;
00454       (*func)(param->parvec[t], param->veclen, t);
00455     }
00456   }
00457 }
00458 
00459 void
00460 plugin_exec_process_result(Recog *recog)
00461 {
00462   int id;
00463   PLUGIN_ENTRY *p;
00464   FUNC_VOID func;
00465 
00466   RecogProcess *rtmp, *r;
00467   Sentence *s;
00468   int i;
00469   int len;
00470   char *str;
00471 
00472   if (global_plugin_list == NULL) return;
00473 
00474   /* for result_str(), return the best sentence string among processes */
00475   s = NULL;
00476   for(rtmp=recog->process_list;rtmp;rtmp=rtmp->next) {
00477     if (! rtmp->live) continue;
00478     if (rtmp->result.status >= 0 && rtmp->result.sentnum > 0) { /* recognition succeeded */
00479       if (s == NULL || rtmp->result.sent[0].score > s->score) {
00480         r = rtmp;
00481         s = &(r->result.sent[0]);
00482       }
00483     }
00484   }
00485   if (s == NULL) {
00486     str = NULL;
00487   } else {
00488     len = 0;
00489     for(i=0;i<s->word_num;i++) len += strlen(r->lm->winfo->woutput[s->word[i]]) + 1;
00490     str = (char *)mymalloc(len);
00491     str[0]='\0';
00492     for(i=0;i<s->word_num;i++) {
00493       if (strlen(r->lm->winfo->woutput[s->word[i]]) == 0) continue;
00494       if (strlen(str) > 0) strcat(str, " ");
00495       strcat(str, r->lm->winfo->woutput[s->word[i]]);
00496     }
00497   }
00498 
00499   if ((id = plugin_get_id("result_best_str")) < 0) return;
00500   for(p=global_plugin_list[id];p;p=p->next) {
00501     func = (FUNC_VOID) p->func;
00502     (*func)(str);
00503   }
00504 
00505   if (str != NULL) free(str);
00506 }
00507 
00508 
00509 #endif /* ENABLE_PLUGIN */
00510 
00511 /************************************************************************/
00512 /* assume only one MFCC module! */
00513 
00514 /************************************************************************/
00515 
00516 boolean
00517 mfc_module_init(MFCCCalc *mfcc, Recog *recog)
00518 {
00519 #ifdef ENABLE_PLUGIN
00520   mfcc->plugin_source = recog->jconf->input.plugin_source;
00521   if (mfcc->plugin_source < 0) {
00522     jlog("ERROR: SP_MDCMODULE selected but plugin is missing?\n");
00523     return FALSE;
00524   }
00525   mfcc->func.fv_standby  = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_standby");
00526   mfcc->func.fv_begin    = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_open");
00527   mfcc->func.fv_read       = (int (*)(VECT *, int)) plugin_get_func(mfcc->plugin_source, "fvin_read");
00528   mfcc->func.fv_end        = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_close");
00529   mfcc->func.fv_resume   = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_resume");
00530   mfcc->func.fv_pause    = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_pause");
00531   mfcc->func.fv_terminate= (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_terminate");
00532   mfcc->func.fv_input_name= (char * (*)()) plugin_get_func(mfcc->plugin_source, "fvin_input_name");
00533 
00534   if (mfcc->func.fv_read == NULL) {
00535     jlog("ERROR: FEATURE_INPUT plugin: fvin_read() not found!\n");
00536     return FALSE;
00537   }
00538 #endif
00539 
00540   return TRUE;
00541 }
00542 
00543 boolean
00544 mfc_module_set_header(MFCCCalc *mfcc, Recog *recog)
00545 {
00546   FUNC_INT func;
00547   unsigned int ret;
00548 
00549 #ifdef ENABLE_PLUGIN
00550   func = (FUNC_INT) plugin_get_func(mfcc->plugin_source, "fvin_get_configuration");
00551   if (func == NULL) {
00552     jlog("ERROR: feature vector input plugin: fvin_get_configuration() not found\n");
00553     return FALSE;
00554   }
00555 
00556   /* vector length in unit */
00557   mfcc->param->veclen = (*func)(0);
00558   mfcc->param->header.sampsize = mfcc->param->veclen * sizeof(VECT);
00559   /* frame shift in msec */
00560   mfcc->param->header.wshift = (*func)(1) * 10000.0;
00561   /* parameter type for checking (return 0xffff to disable the check) */
00562   ret = (*func)(2);
00563   if (ret == 0xffff) {
00564     /* disable type checking */
00565     recog->jconf->input.paramtype_check_flag = FALSE;
00566   } else {
00567     mfcc->param->header.samptype = ret;
00568   }
00569 #endif
00570 
00571   return TRUE;
00572 }
00573 
00574 boolean
00575 mfc_module_standby(MFCCCalc *mfcc)
00576 {
00577 #ifdef ENABLE_PLUGIN
00578   FUNC_INT func;
00579   int ret;
00580 
00581   if (mfcc->func.fv_standby) ret = mfcc->func.fv_standby();
00582   else ret = TRUE;
00583   mfcc->segmented_by_input = FALSE;
00584   return ret;
00585 #else
00586   return TRUE;
00587 #endif
00588 }
00589 
00590 boolean
00591 mfc_module_begin(MFCCCalc *mfcc)
00592 {
00593 #ifdef ENABLE_PLUGIN
00594   FUNC_INT func;
00595   int ret;
00596 
00597   if (mfcc->segmented_by_input) return TRUE; /* do nothing if last was segmented */
00598 
00599   if (mfcc->func.fv_begin) ret = mfcc->func.fv_begin();
00600   else ret = TRUE;
00601   return ret;
00602 #else
00603   return TRUE;
00604 #endif
00605 }
00606 
00607 boolean
00608 mfc_module_end(MFCCCalc *mfcc)
00609 {
00610 #ifdef ENABLE_PLUGIN
00611   FUNC_INT func;
00612   int ret;
00613 
00614   if (mfcc->segmented_by_input) return TRUE; /* do nothing if last was segmented */
00615 
00616   if (mfcc->func.fv_end) ret = mfcc->func.fv_end();
00617   else ret = TRUE;
00618   return ret;
00619 #else
00620   return TRUE;
00621 #endif
00622 }
00623 
00624 int
00625 mfc_module_read(MFCCCalc *mfcc, int *new_t)
00626 {
00627 #ifdef ENABLE_PLUGIN
00628   FUNC_INT func;
00629   int ret;
00630 
00631   /* expand area if needed */
00632   if (param_alloc(mfcc->param, mfcc->f + 1, mfcc->param->veclen) == FALSE) {
00633     jlog("ERROR: FEATURE_INPUT plugin: failed to allocate memory\n");
00634     return -2;
00635   }
00636   /* get data */
00637   ret = mfcc->func.fv_read(mfcc->param->parvec[mfcc->f], mfcc->param->veclen);
00638   if (ret == -3) {
00639     /* function requests segmentation of the current recognition */
00640     mfcc->segmented_by_input = TRUE;
00641     *new_t = mfcc->f;
00642     return -3;
00643   } else if (ret == -1) {
00644     /* end of input */
00645     mfcc->segmented_by_input = FALSE;
00646     *new_t = mfcc->f;
00647     return -1;
00648   } else if (ret == -2) {
00649     /* error */
00650     jlog("ERROR: FEATURE_INPUT plugin: fvin_read() returns error (-2)\n");
00651     return -2;
00652   }
00653     
00654   *new_t = mfcc->f + 1;
00655 #endif
00656 
00657   return 0;
00658 }  
00659 
00660 char *
00661 mfc_module_input_name(MFCCCalc *mfcc)
00662 {
00663 #ifdef ENABLE_PLUGIN
00664   int ret;
00665 
00666   if (mfcc->func.fv_input_name) return(mfcc->func.fv_input_name());
00667 #endif
00668   return NULL;
00669 }
00670 
00671 /* end of file */