/** * @file callback.c * * * @brief Regist and execute callback functions. * * This file contains functions for handling callback functions. * User should use callback_add() (and callback_add_adin() for A/D-in * related callbacks) to regist user function to the callback repository. * Then, Julius will call the registered functions at apropriate timimg * while search. * * More than one function can be assigned to a callback, * in which case all functions will be called in turn. * * * * @brief コールバック関数の登録と実行 * * このファイルにはコールバックを扱う関数が含まれています. * ユーザは callback_add() (A/D-in 関連のコールバックでは allback_add_adin()) * を使って,ユーザが作成した関数を,指定のコールバックレポジトリに登録します. * 認識時はJulius は登録された関数を認識処理の各場面で呼び出します. * * あるコールバックについて複数の関数を登録することができます. この場 * 合,コールバック呼出しは,同じコールバックに登録された複数の関数が * 全て呼ばれます. * * * @author Akinobu Lee * @date Fri Oct 26 00:03:18 2007 * * $Revision: 1.3 $ * */ #include /** * * Initialize callback management area. * * * コールバック管理エリアの初期化 * * * @param recog [i/o] engine instance * * @callergraph * @callgraph * */ void callback_init(Recog *recog) { int i; for(i=0;icallback_function_num[i] = 0; recog->callback_num = 0; } /** * * Core function to register a function to a callback registory. * * * 関数をコールバックレジストリに登録するコア関数 * * * @param recog [i/o] engine instance * @param code [in] code in which the function will be registered * @param func [in] function * @param data [in] user-specified argument to be passed when the function is called inside Julius * * @return global callback ID unique for the whole process, or -1 on error. * */ static int callback_add_core(Recog *recog, int code, void (*func)(), void *data) { int i; int num; int newid; num = recog->callback_function_num[code]; if (num >= MAX_CALLBACK_HOOK) { jlog("ERROR: callback_add: failed to add callback for slot %d\n", code); jlog("ERROR: callback_add: maximum number of callback for a slot is limited to %d\n", MAX_CALLBACK_HOOK); jlog("ERROR: callback_add: please increase the value of MAX_CALLBACK_HOOK\n"); return -1; } for(i=0;icallback_function[code][i] == func && recog->callback_user_data[code][i] == data) { jlog("WARNING: callback_add: the same callback already registered at slot %d\n", code); return -1; } } recog->callback_function[code][num] = func; recog->callback_user_data[code][num] = data; recog->callback_function_num[code]++; newid = recog->callback_num; if (newid >= MAX_CALLBACK_HOOK * SIZEOF_CALLBACK_ID) { jlog("ERROR: callback_add: callback registration count reached maximum limit (%d)!\n", MAX_CALLBACK_HOOK * SIZEOF_CALLBACK_ID); return -1; } recog->callback_list_code[newid] = code; recog->callback_list_loc[newid] = num; recog->callback_num++; return newid; } /** * * Register a function to a callback registory. * * * 関数をコールバックレジストリに登録する. * * * @param recog [i/o] engine instance * @param code [in] code in which the function will be registered * @param func [in] function * @param data [in] user-specified argument to be passed when the function is called inside Julius * * @return global callback ID unique for the whole process, or -1 on error. * * @ingroup callback * @callergraph * @callgraph * */ int callback_add(Recog *recog, int code, void (*func)(Recog *recog, void *data), void *data) { return(callback_add_core(recog, code, func, data)); } /** * * Register a function to the A/D-in type callback registory. * * * 関数をA/D-inタイプのコールバックレジストリに登録する. * * * @param recog [i/o] engine instance * @param code [in] code in which the function will be registered * @param func [in] function * @param data [in] user-specified argument to be passed when the function is called inside Julius * * @return global callback ID unique for the whole process, or -1 on error. * * @ingroup callback * @callergraph * @callgraph * */ int callback_add_adin(Recog *recog, int code, void (*func)(Recog *recog, SP16 *buf, int len, void *data), void *data) { return(callback_add_core(recog, code, func, data)); } static void c_out(const char *s, int flag) { if (flag == 0) { jlog("DEBUG: (%s)\n", s); } else { jlog("DEBUG: %s\n", s); } } static void callback_debug_stdout(int code, Recog *recog) { int f = recog->callback_function_num[code]; switch(code) { //case CALLBACK_POLL: c_out("CALLBACK_POLL", f); break; case CALLBACK_EVENT_PROCESS_ONLINE: c_out("CALLBACK_EVENT_PROCESS_ONLINE", f); break; case CALLBACK_EVENT_PROCESS_OFFLINE: c_out("CALLBACK_EVENT_PROCESS_OFFLINE", f); break; case CALLBACK_EVENT_STREAM_BEGIN: c_out("CALLBACK_EVENT_STREAM_BEGIN", f); break; case CALLBACK_EVENT_STREAM_END: c_out("CALLBACK_EVENT_STREAM_END", f); break; case CALLBACK_EVENT_SPEECH_READY: c_out("CALLBACK_EVENT_SPEECH_READY", f); break; case CALLBACK_EVENT_SPEECH_START: c_out("CALLBACK_EVENT_SPEECH_START", f); break; case CALLBACK_EVENT_SPEECH_STOP: c_out("CALLBACK_EVENT_SPEECH_STOP", f); break; case CALLBACK_EVENT_RECOGNITION_BEGIN: c_out("CALLBACK_EVENT_RECOGNITION_BEGIN", f); break; case CALLBACK_EVENT_RECOGNITION_END: c_out("CALLBACK_EVENT_RECOGNITION_END", f); break; case CALLBACK_EVENT_SEGMENT_BEGIN: c_out("CALLBACK_EVENT_SEGMENT_BEGIN", f); break; case CALLBACK_EVENT_SEGMENT_END: c_out("CALLBACK_EVENT_SEGMENT_END", f); break; case CALLBACK_EVENT_PASS1_BEGIN: c_out("CALLBACK_EVENT_PASS1_BEGIN", f); break; //case CALLBACK_EVENT_PASS1_FRAME: c_out("CALLBACK_EVENT_PASS1_FRAME", f); break; case CALLBACK_EVENT_PASS1_END: c_out("CALLBACK_EVENT_PASS1_END", f); break; //case CALLBACK_RESULT_PASS1_INTERIM: c_out("CALLBACK_RESULT_PASS1_INTERIM", f); break; case CALLBACK_RESULT_PASS1: c_out("CALLBACK_RESULT_PASS1", f); break; case CALLBACK_RESULT_PASS1_GRAPH: c_out("CALLBACK_RESULT_PASS1_GRAPH", f); break; case CALLBACK_STATUS_PARAM: c_out("CALLBACK_STATUS_PARAM", f); break; case CALLBACK_EVENT_PASS2_BEGIN: c_out("CALLBACK_EVENT_PASS2_BEGIN", f); break; case CALLBACK_EVENT_PASS2_END: c_out("CALLBACK_EVENT_PASS2_END", f); break; case CALLBACK_RESULT: c_out("CALLBACK_RESULT", f); break; case CALLBACK_RESULT_GMM: c_out("CALLBACK_RESULT_GMM", f); break; case CALLBACK_RESULT_GRAPH: c_out("CALLBACK_RESULT_GRAPH", f); break; case CALLBACK_RESULT_CONFNET: c_out("CALLBACK_RESULT_CONFNET", f); break; //case CALLBACK_ADIN_CAPTURED: c_out("CALLBACK_ADIN_CAPTURED", f); break; //case CALLBACK_ADIN_TRIGGERED: c_out("CALLBACK_ADIN_TRIGGERED", f); break; case CALLBACK_EVENT_PAUSE: c_out("CALLBACK_EVENT_PAUSE", f); break; case CALLBACK_EVENT_RESUME: c_out("CALLBACK_EVENT_RESUME", f); break; case CALLBACK_PAUSE_FUNCTION: c_out("CALLBACK_PAUSE_FUNCTION", f); break; case CALLBACK_DEBUG_PASS2_POP: c_out("CALLBACK_DEBUG_PASS2_POP", f); break; case CALLBACK_DEBUG_PASS2_PUSH: c_out("CALLBACK_DEBUG_PASS2_PUSH", f); break; //case CALLBACK_RESULT_PASS1_DETERMINED: c_out("CALLBACK_RESULT_PASS1_DETERMINED", f); break; } } /** * * Execute all functions assigned to a callback registory. * * * コールバックレジストリに登録されている関数を全て実行する. * * * @param code [in] callback code * @param recog [in] engine instance. * * @callergraph * @callgraph * */ void callback_exec(int code, Recog *recog) { int i; if (code < 0 || code >= SIZEOF_CALLBACK_ID) { jlog("ERROR: callback_exec: failed to exec callback: invalid code number: %d\n", code); return; } if (callback_debug_flag) callback_debug_stdout(code, recog); for(i=0;icallback_function_num[code];i++) { (*(recog->callback_function[code][i]))(recog, recog->callback_user_data[code][i]); } } /** * * Execute all functions assigned to a A/D-in callback. * * * A/D-in タイプのコールバックに登録された関数を全て実行する. * * * @param code [in] callbcak code * @param recog [in] engine instance * @param buf [in] buffer that holds the current input speech which will be passed to the functions * @param len [in] length of @a buf * * @callergraph * @callgraph * */ void callback_exec_adin(int code, Recog *recog, SP16 *buf, int len) { int i; if (code < 0 || code >= SIZEOF_CALLBACK_ID) { jlog("ERROR: callback_exec_adin: failed to exec callback: invalid code number: %d\n", code); return; } if (callback_debug_flag) callback_debug_stdout(code, recog); for(i=0;icallback_function_num[code];i++) { (*(recog->callback_function[code][i]))(recog, buf, len, recog->callback_user_data[code][i]); } } /** * * Check if at least one function has been registered to a callback repository. * * * コールバックレジストリに1つでも関数が登録されたかどうかを返す. * * * @param recog [in] engine instance * @param code [in] callback code * * @return TRUE when at least one is registered, or FALSE if none. * * @ingroup callback * @callergraph * @callgraph * */ boolean callback_exist(Recog *recog, int code) { if (recog->callback_function_num[code] == 0) return FALSE; return TRUE; } /** * * Delete an already registered function from callback. * * * コールバックから関数を削除する. * * * @param recog [i/o] engine instance * @param id [in] global callback ID to delete * * @return TRUE on success, or FALSE on failure. * * @ingroup callback * @callergraph * @callgraph * */ boolean callback_delete(Recog *recog, int id) { int code; int loc; int i; if (id >= recog->callback_num || id < 0) { jlog("ERROR: callback_delete: callback id #%d not exist!\n", id); return FALSE; } code = recog->callback_list_code[id]; loc = recog->callback_list_loc[id]; if (code == -1) { jlog("WARNING: callback_delete: callback #%d already deleted\n", id); return TRUE; } for(i=loc;icallback_function_num[code]-1;i++) { recog->callback_function[code][i] = recog->callback_function[code][i+1]; recog->callback_function[code][i] = recog->callback_function[code][i+1]; recog->callback_user_data[code][i] = recog->callback_user_data[code][i+1]; } recog->callback_function_num[code]--; recog->callback_list_code[id] = -1; recog->callback_list_loc[id] = -1; jlog("STAT: callback #%d deleted\n", id); return TRUE; } /* end of file */