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