/** * @file plugin.c * * * @brief Load plugin * * * * @brief プラグイン読み込み * * * @author Akinobu Lee * @date Sat Aug 2 09:46:09 2008 * * $Revision: 1.7 $ * */ /* * Copyright (c) 1991-2012 Kawahara Lab., Kyoto University * Copyright (c) 2000-2005 Shikano Lab., Nara Institute of Science and Technology * Copyright (c) 2005-2012 Julius project team, Nagoya Institute of Technology * All rights reserved */ #include #ifdef ENABLE_PLUGIN #if defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__MINGW32__) #include #else #include #endif #include /** * Plugin file path suffix * */ static char *plugin_suffix = PLUGIN_SUFFIX; /** * Function names to be loaded * */ static char *plugin_function_namelist[] = PLUGIN_FUNCTION_NAMELIST; /**************************************************************/ #if defined(_WIN32) && !defined(__CYGWIN32__) /** * Return error string. * * @return the error string. */ static const char* dlerror() { static char szMsgBuf[256]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), szMsgBuf, sizeof szMsgBuf, NULL); return szMsgBuf; } #endif /**************************************************************/ static int plugin_namelist_num() { return(sizeof(plugin_function_namelist) / sizeof(char *)); } static void plugin_free_all() { PLUGIN_ENTRY *p, *ptmp; int i, num; num = plugin_namelist_num(); for(i=0;inext; free(p); p = ptmp; } } free(global_plugin_list); } int plugin_get_id(char *name) { int i, num; num = plugin_namelist_num(); for(i=0;i= plugin_suffix && p >= filename && *x == *p) { x--; p--; } if (x < plugin_suffix) { return TRUE; } return FALSE; } /** * Load a plugin file. * * @param file [in] plugin file path * * @return TRUE on success, FALSE on failure. */ boolean plugin_load_file(char *file) { PLUGIN_MODULE handle; FUNC_INT func; FUNC_VOID entfunc; int ret, number, num; char buf[256]; int buflen = 256; PLUGIN_ENTRY *p; int i; if (global_plugin_list == NULL) plugin_init(); /* open file */ handle = dlopen(file, RTLD_LAZY); if (!handle) { jlog("ERROR: plugin_load: failed to open: %s\n", dlerror()); return(FALSE); } /* call initialization function */ func = dlsym(handle, "initialize"); if (func) { ret = (*func)(); if (ret == -1) { jlog("WARNING: plugin_load: %s: initialize() returns no, skip this file\n", file); dlclose(handle); return(FALSE); } } /* call information function */ func = dlsym(handle, "get_plugin_info"); if (func == NULL) { jlog("ERROR: plugin_load: %s: get_plugin_info(): %s\n", file, dlerror()); dlclose(handle); return(FALSE); } number = 0; ret = (*func)(number, buf, buflen); if (ret == -1) { jlog("ERROR: plugin_load: %s: get_plugin_info(0) returns error\n", file); dlclose(handle); return(FALSE); } buf[buflen-1] = '\0'; jlog("#%d [%s]\n", global_plugin_loaded_file_num, buf); /* register plugin functions */ num = plugin_namelist_num(); for(i=0;iid = i; p->source_id = global_plugin_loaded_file_num; p->func = entfunc; p->next = global_plugin_list[i]; global_plugin_list[i] = p; } } /* increment file counter */ global_plugin_loaded_file_num++; return(TRUE); } /** * Search for plugin file in a directory and load them. * * @param dir [in] directory * * @return TRUE on success, FALSE on failure */ boolean plugin_load_dir(char *dir) { #if defined(_WIN32) && !defined(__CYGWIN32__) && !defined(__MINGW32__) WIN32_FIND_DATA FindFileData; HANDLE hFind; static char buf[512]; int cnt; strncpy(buf, dir, 505); strcat(buf, "\\*.dll"); if ((hFind = FindFirstFile(buf, &FindFileData)) == INVALID_HANDLE_VALUE) { jlog("ERROR: plugin_load: cannot open plugins dir \"%s\"\n", dir); return FALSE; } cnt = 0; do { jlog("STAT: file: %-23s ", FindFileData.cFileName); sprintf_s(buf, 512, "%s\\%s", dir, FindFileData.cFileName); if (plugin_load_file(buf)) cnt++; } while (FindNextFile(hFind, &FindFileData)); FindClose(hFind); jlog("STAT: %d files loaded\n", cnt); return TRUE; #else DIR *d; struct dirent *f; static char buf[512]; int cnt; if ((d = opendir(dir)) == NULL) { jlog("ERROR: plugin_load: cannot open plugins dir \"%s\"\n", dir); return FALSE; } cnt = 0; while((f = readdir(d)) != NULL) { if (is_plugin_obj(f->d_name)) { snprintf(buf, 512, "%s/%s", dir, f->d_name); jlog("STAT: file: %-23s ", f->d_name); if (plugin_load_file(buf)) cnt++; } } closedir(d); jlog("STAT: %d files loaded\n", cnt); return TRUE; #endif } /** * read in plugins in multiple directories * * @param dirent [i/o] directory entry in form of * "dir1:dir2:dir3:...". * */ void plugin_load_dirs(char *dirent) { char *p, *s; char c; if (dirent == NULL) return; if (debug2_flag) { jlog("DEBUG: loading dirs: %s\n", dirent); } p = dirent; do { s = p; while(*p != '\0' && *p != ':') p++; c = *p; *p = '\0'; jlog("STAT: loading plugins at \"%s\":\n", dirent); plugin_load_dir(s); if (c != '\0') { *p = c; p++; } } while (*p != '\0'); } /************************************************************************/ int plugin_find_optname(char *optfuncname, char *str) { char buf[64]; int id; PLUGIN_ENTRY *p; FUNC_VOID func; if ((id = plugin_get_id(optfuncname)) < 0) return -1; for(p=global_plugin_list[id];p;p=p->next) { func = (FUNC_VOID) p->func; (*func)(buf, (int)64); if (strmatch(buf, str)) { return p->source_id; } } return -1; } FUNC_VOID plugin_get_func(int sid, char *name) { int id; PLUGIN_ENTRY *p; FUNC_VOID func; if ((id = plugin_get_id(name)) < 0) return NULL; for(p=global_plugin_list[id];p;p=p->next) { if (p->source_id == sid) return p->func; } return NULL; } /************************************************************************/ boolean plugin_exec_engine_startup(Recog *recog) { int id; PLUGIN_ENTRY *p; FUNC_INT func; boolean ok_p; if (global_plugin_list == NULL) return TRUE; if ((id = plugin_get_id("startup")) < 0) return FALSE; ok_p = TRUE; for(p=global_plugin_list[id];p;p=p->next) { func = (FUNC_INT) p->func; if ((*func)(recog) != 0) { jlog("WARNING: plugin #%d: failed in startup()\n", p->source_id); ok_p = FALSE; } } return ok_p; } /************************************************************************/ void plugin_exec_adin_captured(short *buf, int len) { int id; PLUGIN_ENTRY *p; FUNC_VOID adfunc; if (global_plugin_list == NULL) return; if ((id = plugin_get_id("adin_postprocess")) < 0) return; for(p=global_plugin_list[id];p;p=p->next) { adfunc = (FUNC_VOID) p->func; (*adfunc)(buf, len); } } void plugin_exec_adin_triggered(short *buf, int len) { int id; PLUGIN_ENTRY *p; FUNC_VOID adfunc; if (global_plugin_list == NULL) return; if ((id = plugin_get_id("adin_postprocess_triggered")) < 0) return; for(p=global_plugin_list[id];p;p=p->next) { adfunc = (FUNC_VOID) p->func; (*adfunc)(buf, len); } } void plugin_exec_vector_postprocess(VECT *vecbuf, int veclen, int nframe) { int id; PLUGIN_ENTRY *p; FUNC_INT func; if (global_plugin_list == NULL) return; if ((id = plugin_get_id("fvin_postprocess")) < 0) return; for(p=global_plugin_list[id];p;p=p->next) { func = (FUNC_INT) p->func; (*func)(vecbuf, veclen, nframe); } } void plugin_exec_vector_postprocess_all(HTK_Param *param) { int id; PLUGIN_ENTRY *p; FUNC_INT func; int t; if (global_plugin_list == NULL) return; if ((id = plugin_get_id("fvin_postprocess")) < 0) return; for(t=0;tsamplenum;t++) { for(p=global_plugin_list[id];p;p=p->next) { func = (FUNC_INT) p->func; (*func)(param->parvec[t], param->veclen, t); } } } void plugin_exec_process_result(Recog *recog) { int id; PLUGIN_ENTRY *p; FUNC_VOID func; RecogProcess *rtmp, *r; Sentence *s; int i; int len; char *str; if (global_plugin_list == NULL) return; /* for result_str(), return the best sentence string among processes */ s = NULL; for(rtmp=recog->process_list;rtmp;rtmp=rtmp->next) { if (! rtmp->live) continue; if (rtmp->result.status >= 0 && rtmp->result.sentnum > 0) { /* recognition succeeded */ if (s == NULL || rtmp->result.sent[0].score > s->score) { r = rtmp; s = &(r->result.sent[0]); } } } if (s == NULL) { str = NULL; } else { len = 0; for(i=0;iword_num;i++) len += strlen(r->lm->winfo->woutput[s->word[i]]) + 1; str = (char *)mymalloc(len); str[0]='\0'; for(i=0;iword_num;i++) { if (strlen(r->lm->winfo->woutput[s->word[i]]) == 0) continue; if (strlen(str) > 0) strcat(str, " "); strcat(str, r->lm->winfo->woutput[s->word[i]]); } } if ((id = plugin_get_id("result_best_str")) < 0) return; for(p=global_plugin_list[id];p;p=p->next) { func = (FUNC_VOID) p->func; (*func)(str); } if (str != NULL) free(str); } #endif /* ENABLE_PLUGIN */ /************************************************************************/ /* assume only one MFCC module! */ /************************************************************************/ boolean mfc_module_init(MFCCCalc *mfcc, Recog *recog) { #ifdef ENABLE_PLUGIN mfcc->plugin_source = recog->jconf->input.plugin_source; if (mfcc->plugin_source < 0) { jlog("ERROR: SP_MDCMODULE selected but plugin is missing?\n"); return FALSE; } mfcc->func.fv_standby = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_standby"); mfcc->func.fv_begin = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_open"); mfcc->func.fv_read = (int (*)(VECT *, int)) plugin_get_func(mfcc->plugin_source, "fvin_read"); mfcc->func.fv_end = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_close"); mfcc->func.fv_resume = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_resume"); mfcc->func.fv_pause = (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_pause"); mfcc->func.fv_terminate= (boolean (*)()) plugin_get_func(mfcc->plugin_source, "fvin_terminate"); mfcc->func.fv_input_name= (char * (*)()) plugin_get_func(mfcc->plugin_source, "fvin_input_name"); if (mfcc->func.fv_read == NULL) { jlog("ERROR: FEATURE_INPUT plugin: fvin_read() not found!\n"); return FALSE; } #endif return TRUE; } boolean mfc_module_set_header(MFCCCalc *mfcc, Recog *recog) { FUNC_INT func; unsigned int ret; #ifdef ENABLE_PLUGIN func = (FUNC_INT) plugin_get_func(mfcc->plugin_source, "fvin_get_configuration"); if (func == NULL) { jlog("ERROR: feature vector input plugin: fvin_get_configuration() not found\n"); return FALSE; } /* vector length in unit */ mfcc->param->veclen = (*func)(0); mfcc->param->header.sampsize = mfcc->param->veclen * sizeof(VECT); /* frame shift in msec */ mfcc->param->header.wshift = (*func)(1) * 10000.0; /* parameter type for checking (return 0xffff to disable the check) */ ret = (*func)(2); if (ret == 0xffff) { /* disable type checking */ recog->jconf->input.paramtype_check_flag = FALSE; } else { mfcc->param->header.samptype = ret; } #endif return TRUE; } boolean mfc_module_standby(MFCCCalc *mfcc) { #ifdef ENABLE_PLUGIN FUNC_INT func; int ret; if (mfcc->func.fv_standby) ret = mfcc->func.fv_standby(); else ret = TRUE; mfcc->segmented_by_input = FALSE; return ret; #else return TRUE; #endif } boolean mfc_module_begin(MFCCCalc *mfcc) { #ifdef ENABLE_PLUGIN FUNC_INT func; int ret; if (mfcc->segmented_by_input) return TRUE; /* do nothing if last was segmented */ if (mfcc->func.fv_begin) ret = mfcc->func.fv_begin(); else ret = TRUE; return ret; #else return TRUE; #endif } boolean mfc_module_end(MFCCCalc *mfcc) { #ifdef ENABLE_PLUGIN FUNC_INT func; int ret; if (mfcc->segmented_by_input) return TRUE; /* do nothing if last was segmented */ if (mfcc->func.fv_end) ret = mfcc->func.fv_end(); else ret = TRUE; return ret; #else return TRUE; #endif } int mfc_module_read(MFCCCalc *mfcc, int *new_t) { #ifdef ENABLE_PLUGIN FUNC_INT func; int ret; /* expand area if needed */ if (param_alloc(mfcc->param, mfcc->f + 1, mfcc->param->veclen) == FALSE) { jlog("ERROR: FEATURE_INPUT plugin: failed to allocate memory\n"); return -2; } /* get data */ ret = mfcc->func.fv_read(mfcc->param->parvec[mfcc->f], mfcc->param->veclen); if (ret == -3) { /* function requests segmentation of the current recognition */ mfcc->segmented_by_input = TRUE; *new_t = mfcc->f; return -3; } else if (ret == -1) { /* end of input */ mfcc->segmented_by_input = FALSE; *new_t = mfcc->f; return -1; } else if (ret == -2) { /* error */ jlog("ERROR: FEATURE_INPUT plugin: fvin_read() returns error (-2)\n"); return -2; } *new_t = mfcc->f + 1; #endif return 0; } char * mfc_module_input_name(MFCCCalc *mfcc) { #ifdef ENABLE_PLUGIN int ret; if (mfcc->func.fv_input_name) return(mfcc->func.fv_input_name()); #endif return NULL; } /* end of file */