/**
* @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 */