1 /**
2 * @file callback.c
3 *
4 * <EN>
5 * @brief Regist and execute callback functions.
6 *
7 * This file contains functions for handling callback functions.
8 * User should use callback_add() (and callback_add_adin() for A/D-in
9 * related callbacks) to regist user function to the callback repository.
10 * Then, Julius will call the registered functions at apropriate timimg
11 * while search.
12 *
13 * More than one function can be assigned to a callback,
14 * in which case all functions will be called in turn.
15 * </EN>
16 *
17 * <JA>
18 * @brief ������Хå��ؿ�����Ͽ�ȼ¹�
19 *
20 * ���Υե�����ˤϥ�����Хå����ؿ����ޤޤ�Ƥ��ޤ�.
21 * �桼���� callback_add() (A/D-in ��Ϣ�Υ�����Хå��Ǥ� allback_add_adin())
22 * ��Ȥäơ��桼�������������ؿ�����Υ�����Хå���ݥ��ȥ����Ͽ���ޤ�.
23 * ǧ������Julius ����Ͽ���줿�ؿ���ǧ�������γƾ��̤ǸƤӽФ��ޤ�.
24 *
25 * ���륳����Хå��ˤĤ���ʣ���δؿ�����Ͽ���뤳�Ȥ��Ǥ��ޤ�. ���ξ�
26 * �硤������Хå��ƽФ��ϡ�Ʊ��������Хå�����Ͽ���줿ʣ���δؿ���
27 * ���ƸƤФ�ޤ�.
28 * </JA>
29 *
30 * @author Akinobu Lee
31 * @date Fri Oct 26 00:03:18 2007
32 *
33 * $Revision: 1.3 $
34 *
35 */
36 #include <julius/julius.h>
37
38 /**
39 * <EN>
40 * Initialize callback management area.
41 * </EN>
42 * <JA>
43 * ������Хå��������ꥢ�ν����
44 * </JA>
45 *
46 * @param recog [i/o] engine instance
47 *
48 * @callergraph
49 * @callgraph
50 *
51 */
52 void
callback_init(Recog * recog)53 callback_init(Recog *recog)
54 {
55 int i;
56 for(i=0;i<SIZEOF_CALLBACK_ID;i++) recog->callback_function_num[i] = 0;
57 recog->callback_num = 0;
58 }
59
60 /**
61 * <EN>
62 * Core function to register a function to a callback registory.
63 * </EN>
64 * <JA>
65 * �ؿ�����Хå��쥸���ȥ����Ͽ���륳���ؿ�
66 * </JA>
67 *
68 * @param recog [i/o] engine instance
69 * @param code [in] code in which the function will be registered
70 * @param func [in] function
71 * @param data [in] user-specified argument to be passed when the function is called inside Julius
72 *
73 * @return global callback ID unique for the whole process, or -1 on error.
74 *
75 */
76 static int
callback_add_core(Recog * recog,int code,void (* func)(),void * data)77 callback_add_core(Recog *recog, int code, void (*func)(), void *data)
78 {
79 int i;
80 int num;
81 int newid;
82
83 num = recog->callback_function_num[code];
84
85 if (num >= MAX_CALLBACK_HOOK) {
86 jlog("ERROR: callback_add: failed to add callback for slot %d\n", code);
87 jlog("ERROR: callback_add: maximum number of callback for a slot is limited to %d\n", MAX_CALLBACK_HOOK);
88 jlog("ERROR: callback_add: please increase the value of MAX_CALLBACK_HOOK\n");
89 return -1;
90 }
91
92 for(i=0;i<num;i++) {
93 if (recog->callback_function[code][i] == func && recog->callback_user_data[code][i] == data) {
94 jlog("WARNING: callback_add: the same callback already registered at slot %d\n", code);
95 return -1;
96 }
97 }
98 recog->callback_function[code][num] = func;
99 recog->callback_user_data[code][num] = data;
100 recog->callback_function_num[code]++;
101
102 newid = recog->callback_num;
103 if (newid >= MAX_CALLBACK_HOOK * SIZEOF_CALLBACK_ID) {
104 jlog("ERROR: callback_add: callback registration count reached maximum limit (%d)!\n", MAX_CALLBACK_HOOK * SIZEOF_CALLBACK_ID);
105 return -1;
106 }
107 recog->callback_list_code[newid] = code;
108 recog->callback_list_loc[newid] = num;
109 recog->callback_num++;
110
111 return newid;
112 }
113
114 /**
115 * <EN>
116 * Register a function to a callback registory.
117 * </EN>
118 * <JA>
119 * �ؿ�����Хå��쥸���ȥ����Ͽ����.
120 * </JA>
121 *
122 * @param recog [i/o] engine instance
123 * @param code [in] code in which the function will be registered
124 * @param func [in] function
125 * @param data [in] user-specified argument to be passed when the function is called inside Julius
126 *
127 * @return global callback ID unique for the whole process, or -1 on error.
128 *
129 * @ingroup callback
130 * @callergraph
131 * @callgraph
132 *
133 */
134 int
callback_add(Recog * recog,int code,void (* func)(Recog * recog,void * data),void * data)135 callback_add(Recog *recog, int code, void (*func)(Recog *recog, void *data), void *data)
136 {
137 return(callback_add_core(recog, code, func, data));
138 }
139
140 /**
141 * <EN>
142 * Register a function to the A/D-in type callback registory.
143 * </EN>
144 * <JA>
145 * �ؿ���A/D-in�����פΥ�����Хå��쥸���ȥ����Ͽ����.
146 * </JA>
147 *
148 * @param recog [i/o] engine instance
149 * @param code [in] code in which the function will be registered
150 * @param func [in] function
151 * @param data [in] user-specified argument to be passed when the function is called inside Julius
152 *
153 * @return global callback ID unique for the whole process, or -1 on error.
154 *
155 * @ingroup callback
156 * @callergraph
157 * @callgraph
158 *
159 */
160 int
callback_add_adin(Recog * recog,int code,void (* func)(Recog * recog,SP16 * buf,int len,void * data),void * data)161 callback_add_adin(Recog *recog, int code, void (*func)(Recog *recog, SP16 *buf, int len, void *data), void *data)
162 {
163 return(callback_add_core(recog, code, func, data));
164 }
165
166 static void
c_out(const char * s,int flag)167 c_out(const char *s, int flag)
168 {
169 if (flag == 0) {
170 jlog("DEBUG: (%s)\n", s);
171 } else {
172 jlog("DEBUG: %s\n", s);
173 }
174 }
175
176 static void
callback_debug_stdout(int code,Recog * recog)177 callback_debug_stdout(int code, Recog *recog)
178 {
179 int f = recog->callback_function_num[code];
180 switch(code) {
181 //case CALLBACK_POLL: c_out("CALLBACK_POLL", f); break;
182 case CALLBACK_EVENT_PROCESS_ONLINE: c_out("CALLBACK_EVENT_PROCESS_ONLINE", f); break;
183 case CALLBACK_EVENT_PROCESS_OFFLINE: c_out("CALLBACK_EVENT_PROCESS_OFFLINE", f); break;
184 case CALLBACK_EVENT_STREAM_BEGIN: c_out("CALLBACK_EVENT_STREAM_BEGIN", f); break;
185 case CALLBACK_EVENT_STREAM_END: c_out("CALLBACK_EVENT_STREAM_END", f); break;
186 case CALLBACK_EVENT_SPEECH_READY: c_out("CALLBACK_EVENT_SPEECH_READY", f); break;
187 case CALLBACK_EVENT_SPEECH_START: c_out("CALLBACK_EVENT_SPEECH_START", f); break;
188 case CALLBACK_EVENT_SPEECH_STOP: c_out("CALLBACK_EVENT_SPEECH_STOP", f); break;
189 case CALLBACK_EVENT_RECOGNITION_BEGIN: c_out("CALLBACK_EVENT_RECOGNITION_BEGIN", f); break;
190 case CALLBACK_EVENT_RECOGNITION_END: c_out("CALLBACK_EVENT_RECOGNITION_END", f); break;
191 case CALLBACK_EVENT_SEGMENT_BEGIN: c_out("CALLBACK_EVENT_SEGMENT_BEGIN", f); break;
192 case CALLBACK_EVENT_SEGMENT_END: c_out("CALLBACK_EVENT_SEGMENT_END", f); break;
193 case CALLBACK_EVENT_PASS1_BEGIN: c_out("CALLBACK_EVENT_PASS1_BEGIN", f); break;
194 //case CALLBACK_EVENT_PASS1_FRAME: c_out("CALLBACK_EVENT_PASS1_FRAME", f); break;
195 case CALLBACK_EVENT_PASS1_END: c_out("CALLBACK_EVENT_PASS1_END", f); break;
196 //case CALLBACK_RESULT_PASS1_INTERIM: c_out("CALLBACK_RESULT_PASS1_INTERIM", f); break;
197 case CALLBACK_RESULT_PASS1: c_out("CALLBACK_RESULT_PASS1", f); break;
198 case CALLBACK_RESULT_PASS1_GRAPH: c_out("CALLBACK_RESULT_PASS1_GRAPH", f); break;
199 case CALLBACK_STATUS_PARAM: c_out("CALLBACK_STATUS_PARAM", f); break;
200 case CALLBACK_EVENT_PASS2_BEGIN: c_out("CALLBACK_EVENT_PASS2_BEGIN", f); break;
201 case CALLBACK_EVENT_PASS2_END: c_out("CALLBACK_EVENT_PASS2_END", f); break;
202 case CALLBACK_RESULT: c_out("CALLBACK_RESULT", f); break;
203 case CALLBACK_RESULT_GMM: c_out("CALLBACK_RESULT_GMM", f); break;
204 case CALLBACK_RESULT_GRAPH: c_out("CALLBACK_RESULT_GRAPH", f); break;
205 case CALLBACK_RESULT_CONFNET: c_out("CALLBACK_RESULT_CONFNET", f); break;
206 //case CALLBACK_ADIN_CAPTURED: c_out("CALLBACK_ADIN_CAPTURED", f); break;
207 //case CALLBACK_ADIN_TRIGGERED: c_out("CALLBACK_ADIN_TRIGGERED", f); break;
208 case CALLBACK_EVENT_PAUSE: c_out("CALLBACK_EVENT_PAUSE", f); break;
209 case CALLBACK_EVENT_RESUME: c_out("CALLBACK_EVENT_RESUME", f); break;
210 case CALLBACK_PAUSE_FUNCTION: c_out("CALLBACK_PAUSE_FUNCTION", f); break;
211 case CALLBACK_DEBUG_PASS2_POP: c_out("CALLBACK_DEBUG_PASS2_POP", f); break;
212 case CALLBACK_DEBUG_PASS2_PUSH: c_out("CALLBACK_DEBUG_PASS2_PUSH", f); break;
213 //case CALLBACK_RESULT_PASS1_DETERMINED: c_out("CALLBACK_RESULT_PASS1_DETERMINED", f); break;
214 }
215 }
216
217 /**
218 * <EN>
219 * Execute all functions assigned to a callback registory.
220 * </EN>
221 * <JA>
222 * ������Хå��쥸���ȥ����Ͽ����Ƥ���ؿ������Ƽ¹Ԥ���.
223 * </JA>
224 *
225 * @param code [in] callback code
226 * @param recog [in] engine instance.
227 *
228 * @callergraph
229 * @callgraph
230 *
231 */
232 void
callback_exec(int code,Recog * recog)233 callback_exec(int code, Recog *recog)
234 {
235 int i;
236
237 if (code < 0 || code >= SIZEOF_CALLBACK_ID) {
238 jlog("ERROR: callback_exec: failed to exec callback: invalid code number: %d\n", code);
239 return;
240 }
241 if (callback_debug_flag) callback_debug_stdout(code, recog);
242 for(i=0;i<recog->callback_function_num[code];i++) {
243 (*(recog->callback_function[code][i]))(recog, recog->callback_user_data[code][i]);
244 }
245 }
246
247 /**
248 * <EN>
249 * Execute all functions assigned to a A/D-in callback.
250 * </EN>
251 * <JA>
252 * A/D-in �����פΥ�����Хå�����Ͽ���줿�ؿ������Ƽ¹Ԥ���.
253 * </JA>
254 *
255 * @param code [in] callbcak code
256 * @param recog [in] engine instance
257 * @param buf [in] buffer that holds the current input speech which will be passed to the functions
258 * @param len [in] length of @a buf
259 *
260 * @callergraph
261 * @callgraph
262 *
263 */
264 void
callback_exec_adin(int code,Recog * recog,SP16 * buf,int len)265 callback_exec_adin(int code, Recog *recog, SP16 *buf, int len)
266 {
267 int i;
268
269 if (code < 0 || code >= SIZEOF_CALLBACK_ID) {
270 jlog("ERROR: callback_exec_adin: failed to exec callback: invalid code number: %d\n", code);
271 return;
272 }
273 if (callback_debug_flag) callback_debug_stdout(code, recog);
274 for(i=0;i<recog->callback_function_num[code];i++) {
275 (*(recog->callback_function[code][i]))(recog, buf, len, recog->callback_user_data[code][i]);
276 }
277 }
278
279 /**
280 * <EN>
281 * Check if at least one function has been registered to a callback repository.
282 * </EN>
283 * <JA>
284 * ������Хå��쥸���ȥ�ˣ��ĤǤ�ؿ�����Ͽ���줿���ɤ������֤�.
285 * </JA>
286 *
287 * @param recog [in] engine instance
288 * @param code [in] callback code
289 *
290 * @return TRUE when at least one is registered, or FALSE if none.
291 *
292 * @ingroup callback
293 * @callergraph
294 * @callgraph
295 *
296 */
297 boolean
callback_exist(Recog * recog,int code)298 callback_exist(Recog *recog, int code)
299 {
300 if (recog->callback_function_num[code] == 0) return FALSE;
301 return TRUE;
302 }
303
304 /**
305 * <EN>
306 * Delete an already registered function from callback.
307 * </EN>
308 * <JA>
309 * ������Хå�����ؿ���������.
310 * </JA>
311 *
312 * @param recog [i/o] engine instance
313 * @param id [in] global callback ID to delete
314 *
315 * @return TRUE on success, or FALSE on failure.
316 *
317 * @ingroup callback
318 * @callergraph
319 * @callgraph
320 *
321 */
322 boolean
callback_delete(Recog * recog,int id)323 callback_delete(Recog *recog, int id)
324 {
325 int code;
326 int loc;
327 int i;
328
329 if (id >= recog->callback_num || id < 0) {
330 jlog("ERROR: callback_delete: callback id #%d not exist!\n", id);
331 return FALSE;
332 }
333
334 code = recog->callback_list_code[id];
335 loc = recog->callback_list_loc[id];
336
337 if (code == -1) {
338 jlog("WARNING: callback_delete: callback #%d already deleted\n", id);
339 return TRUE;
340 }
341
342 for(i=loc;i<recog->callback_function_num[code]-1;i++) {
343 recog->callback_function[code][i] = recog->callback_function[code][i+1];
344 recog->callback_function[code][i] = recog->callback_function[code][i+1];
345 recog->callback_user_data[code][i] = recog->callback_user_data[code][i+1];
346 }
347 recog->callback_function_num[code]--;
348 recog->callback_list_code[id] = -1;
349 recog->callback_list_loc[id] = -1;
350
351 jlog("STAT: callback #%d deleted\n", id);
352 return TRUE;
353 }
354
355 /* end of file */
356