1 /*
2  * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 /**
17  * @file picoapi.c
18  *
19  * Copyright (C) 2008-2009 SVOX AG, Baslerstr. 30, 8048 Zuerich, Switzerland
20  * All rights reserved.
21  *
22  * History:
23  * - 2009-04-20 -- initial version
24  */
25 #include "picodefs.h"
26 #include "picoos.h"
27 #include "picodbg.h"
28 #include "picorsrc.h"
29 #include "picoctrl.h"
30 #include "picoapi.h"
31 #include "picoapid.h"
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 /* ****************************************************************************/
38 /* System-level API functions                                                 */
39 /* ****************************************************************************/
40 
41 #define MAGIC_MASK 0x5069636F  /* Pico */
42 
43 #define SET_MAGIC_NUMBER(sys) \
44     (sys)->magic = ((picoos_uint32) (uintptr_t) (sys)) ^ MAGIC_MASK
45 
46 #define CHECK_MAGIC_NUMBER(sys) \
47     ((sys)->magic == (((picoos_uint32) (uintptr_t) (sys)) ^ MAGIC_MASK))
48 
49 
50 
51 /* *** Auxiliary routines (may also be called from picoextapi.c) **************/
52 
53 
is_valid_system_handle(pico_System system)54 int is_valid_system_handle(pico_System system)
55 {
56     return (system != NULL) && CHECK_MAGIC_NUMBER(system);
57 }
58 
59 
pico_sysGetCommon(pico_System this)60 picoos_Common pico_sysGetCommon(pico_System this)
61 {
62     if (this != NULL) {
63         return this->common;
64     } else {
65         return NULL;
66     }
67 }
68 
69 
70 
71 /* *** System initialization and termination functions ************************/
pico_initialize_priv(void * memory,const pico_Uint32 size,pico_Int16 enableMemProt,pico_System * system)72 pico_Status pico_initialize_priv(
73         void *memory,
74         const pico_Uint32 size,
75         pico_Int16 enableMemProt,
76         pico_System *system
77         )
78 {
79     pico_Status status = PICO_OK;
80 
81     PICODBG_INITIALIZE(PICODBG_LOG_LEVEL_INFO);
82     PICODBG_ENABLE_COLORS(0);
83     /*PICODBG_SET_OUTPUT_FORMAT((PICODBG_SHOW_LEVEL | PICODBG_SHOW_SRCNAME));*/
84 
85     if (memory == NULL) {
86         status = PICO_ERR_NULLPTR_ACCESS;
87     } else if (size == 0) {
88         status = PICO_ERR_INVALID_ARGUMENT;
89     } else if (system == NULL) {
90         status = PICO_ERR_NULLPTR_ACCESS;
91     } else {
92         byte_ptr_t rest_mem;
93         picoos_objsize_t rest_mem_size;
94         pico_System sys;
95         picoos_MemoryManager sysMM;
96         picoos_ExceptionManager sysEM;
97 
98         sys = (pico_System) picoos_raw_malloc(memory, size, sizeof(pico_system_t),
99                 &rest_mem, &rest_mem_size);
100         if (sys != NULL) {
101             sysMM = picoos_newMemoryManager(rest_mem, rest_mem_size, enableMemProt ? TRUE : FALSE);
102             if (sysMM != NULL) {
103                 sysEM = picoos_newExceptionManager(sysMM);
104                 sys->common = picoos_newCommon(sysMM);
105                 sys->rm = picorsrc_newResourceManager(sysMM, sys->common);
106                 if ((sysEM != NULL) && (sys->common != NULL) && (sys->rm != NULL)) {
107                     sys->common->em = sysEM;
108                     sys->common->mm = sysMM;
109                     sys->engine = NULL;
110 
111                     picorsrc_createDefaultResource(sys->rm /*,&defaultResource */);
112 
113                     SET_MAGIC_NUMBER(sys);
114                     status = PICO_OK;
115                 } else {
116                     status = PICO_EXC_OUT_OF_MEM;
117                 }
118             } else {
119                 status = PICO_EXC_OUT_OF_MEM;
120             }
121         } else {
122             status = PICO_EXC_OUT_OF_MEM;
123         }
124         *system = sys;
125     }
126 
127     if (status != PICO_OK) {
128         if (system != NULL) {
129             *system = NULL;
130         }
131         PICODBG_TERMINATE();
132     }
133 
134     return status;
135 }
136 /**
137  * pico_initialize : initializes the pico system private memory
138  * @param    memory : pointer to a free and already allocated memory area
139  * @param    size : size of the memory area
140  * @param    system : pointer to a pico_System struct
141  * @return  PICO_OK : successful init, !PICO_OK : error on allocating private memory
142  * @callgraph
143  * @callergraph
144 */
pico_initialize(void * memory,const pico_Uint32 size,pico_System * system)145 PICO_FUNC pico_initialize(
146         void *memory,
147         const pico_Uint32 size,
148         pico_System *system
149         )
150 {
151     return pico_initialize_priv(memory, size, /*enableMemProt*/ FALSE, system);
152 }
153 
154 /**
155  * pico_terminate : deallocates the pico system private memory
156  * @param    system : pointer to a pico_System struct
157  * @return  PICO_OK : successful de-init, !PICO_OK : error on de-allocating private memory
158  * @callgraph
159  * @callergraph
160 */
pico_terminate(pico_System * system)161 PICO_FUNC pico_terminate(
162         pico_System *system
163         )
164 {
165     pico_Status status = PICO_OK;
166 
167     if ((system == NULL) || !is_valid_system_handle(*system)) {
168         status = PICO_ERR_INVALID_HANDLE;
169     } else {
170         pico_System sys = *system;
171 
172         /* close engine(s) */
173         picoctrl_disposeEngine(sys->common->mm, sys->rm, &sys->engine);
174 
175         /* close all resources */
176         picorsrc_disposeResourceManager(sys->common->mm, &sys->rm);
177 
178         sys->magic ^= 0xFFFEFDFC;
179         *system = NULL;
180     }
181 
182     PICODBG_TERMINATE();
183 
184     return status;
185 }
186 
187 
188 
189 /* *** System status and error/warning message retrieval function *************/
190 
191 /**
192  * pico_getSystemStatusMessage : Returns a description of the system status or errors
193  * @param    system : pointer to a pico_System struct
194  * @param    errCode : pico_System error code
195  * @param    outMessage : memory area where to return a string
196  * @return  PICO_OK : successful
197  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
198  * @callgraph
199  * @callergraph
200 */
pico_getSystemStatusMessage(pico_System system,pico_Status errCode,pico_Retstring outMessage)201 PICO_FUNC pico_getSystemStatusMessage(
202         pico_System system,
203         pico_Status errCode,
204         pico_Retstring outMessage
205         )
206 {
207     pico_Status status = PICO_OK;
208 
209     if (!is_valid_system_handle(system)) {
210         status = PICO_ERR_INVALID_HANDLE;
211         if (outMessage != NULL) {
212             picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'system' not initialized", PICO_RETSTRINGSIZE);
213         }
214     } else if (outMessage == NULL) {
215         status = PICO_ERR_NULLPTR_ACCESS;
216     } else {
217         if (picoos_emGetExceptionCode(system->common->em) == PICO_OK) {
218             if (errCode == PICO_OK) {
219                 picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "system ok", PICO_RETSTRINGSIZE);
220             } else {
221                 /* exceptionManager was not informed yet; produce default message */
222                 picoos_setErrorMsg((picoos_char *) outMessage, PICO_RETSTRINGSIZE, errCode, NULL, NULL, NULL);
223             }
224         } else {
225             picoos_emGetExceptionMessage(system->common->em, (picoos_char *) outMessage, PICO_RETSTRINGSIZE);
226         }
227     }
228 
229     return status;
230 }
231 
232 /**
233  * pico_getSystemStatusMessage : Returns the number of warnings
234  * @param    system : pointer to a pico_System struct
235  * @param    *outNrOfWarnings : pointer to location to receive number of warnings
236  * @return  PICO_OK : successful
237  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
238  * @callgraph
239  * @callergraph
240 */
pico_getNrSystemWarnings(pico_System system,pico_Int32 * outNrOfWarnings)241 PICO_FUNC pico_getNrSystemWarnings(
242         pico_System system,
243         pico_Int32 *outNrOfWarnings
244         )
245 {
246     pico_Status status = PICO_OK;
247 
248     if (!is_valid_system_handle(system)) {
249         status = PICO_ERR_INVALID_HANDLE;
250         if (outNrOfWarnings != NULL) {
251             *outNrOfWarnings = 0;
252         }
253     } else if (outNrOfWarnings == NULL) {
254         status = PICO_ERR_NULLPTR_ACCESS;
255     } else {
256         *outNrOfWarnings = picoos_emGetNumOfWarnings(system->common->em);
257     }
258 
259     return status;
260 }
261 
262 /**
263  * pico_getSystemWarning : Returns a description of a warning
264  * @param    system : pointer to a pico_System struct
265  * @param    warningIndex : warning index
266  * @param    *outCode : pointer to receive the warning code
267  * @param    outMessage : pointer to receive the output message
268  * @return  PICO_OK : successful
269  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
270  * @callgraph
271  * @callergraph
272 */
pico_getSystemWarning(pico_System system,const pico_Int32 warningIndex,pico_Status * outCode,pico_Retstring outMessage)273 PICO_FUNC pico_getSystemWarning(
274         pico_System system,
275         const pico_Int32 warningIndex,
276         pico_Status *outCode,
277         pico_Retstring outMessage
278         )
279 {
280     pico_Status status = PICO_OK;
281 
282     if (!is_valid_system_handle(system)) {
283         status = PICO_ERR_INVALID_HANDLE;
284         if (outMessage != NULL) {
285             picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'system' not initialized", PICO_RETSTRINGSIZE);
286         }
287     } else if (warningIndex < 0) {
288         status = PICO_ERR_INDEX_OUT_OF_RANGE;
289     } else if ((outCode == NULL) || (outMessage == NULL)) {
290         status = PICO_ERR_NULLPTR_ACCESS;
291     } else {
292         *outCode = picoos_emGetWarningCode(system->common->em, warningIndex);
293         picoos_emGetWarningMessage(system->common->em, warningIndex, (picoos_char *) outMessage, (picoos_uint16) PICO_RETSTRINGSIZE);
294     }
295 
296     return status;
297 }
298 
299 
300 
301 /* *** Resource loading and unloading functions *******************************/
302 
303 /**
304  * pico_loadResource : Loads a resource file into the Pico system
305  * @param    system : pointer to a pico_System struct
306  * @param    *lingwareFileName : lingware resource file name
307  * @param    *outLingware : pointer to receive the loaded lingware resource memory area address
308  * @return  PICO_OK : successful
309  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
310  * @callgraph
311  * @callergraph
312 */
pico_loadResource(pico_System system,const pico_Char * lingwareFileName,pico_Resource * outLingware)313 PICO_FUNC pico_loadResource(
314         pico_System system,
315         const pico_Char *lingwareFileName,
316         pico_Resource *outLingware
317         )
318 {
319     pico_Status status = PICO_OK;
320 
321     if (!is_valid_system_handle(system)) {
322         status = PICO_ERR_INVALID_HANDLE;
323     } else if ((lingwareFileName == NULL) || (outLingware == NULL)) {
324         status = PICO_ERR_NULLPTR_ACCESS;
325     } else {
326         PICODBG_DEBUG(("memory usage before resource loading"));
327         picoos_showMemUsage(system->common->mm, FALSE, TRUE);
328         picoos_emReset(system->common->em);
329         status = picorsrc_loadResource(system->rm, (picoos_char *) lingwareFileName, (picorsrc_Resource *) outLingware);
330         PICODBG_DEBUG(("memory used to load resource %s", lingwareFileName));
331         picoos_showMemUsage(system->common->mm, TRUE, FALSE);
332     }
333 
334     return status;
335 }
336 
337 /**
338  * pico_unloadResource : unLoads a resource file from the Pico system
339  * @param    system : pointer to a pico_System struct
340  * @param    *inoutLingware : pointer to the loaded lingware resource memory area address
341  * @return  PICO_OK : successful
342  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
343  * @callgraph
344  * @callergraph
345 */
pico_unloadResource(pico_System system,pico_Resource * inoutLingware)346 PICO_FUNC pico_unloadResource(
347         pico_System system,
348         pico_Resource *inoutLingware
349         )
350 {
351     pico_Status status = PICO_OK;
352 
353     if (!is_valid_system_handle(system)) {
354         status = PICO_ERR_INVALID_HANDLE;
355     } else if (inoutLingware == NULL) {
356         status = PICO_ERR_NULLPTR_ACCESS;
357     } else if (!picoctrl_isValidResourceHandle(*((picorsrc_Resource *) inoutLingware))) {
358         status = PICO_ERR_INVALID_HANDLE;
359     } else {
360         PICODBG_DEBUG(("memory usage before resource unloading"));
361         picoos_showMemUsage(system->common->mm, FALSE, TRUE);
362         picoos_emReset(system->common->em);
363         status = picorsrc_unloadResource(system->rm, (picorsrc_Resource *) inoutLingware);
364         PICODBG_DEBUG(("memory released by resource unloading"));
365         picoos_showMemUsage(system->common->mm, TRUE, FALSE);
366     }
367 
368     return status;
369 }
370 
371 /* *** Resource inspection functions *******************************/
372 /**
373  * pico_getResourceName : Gets a resource name
374  * @param    system : pointer to a pico_System struct
375  * @param    resource : pointer to the loaded resource memory area address
376  * @param    outName : pointer to the area to receuive the resource name
377  * @return  PICO_OK : successful
378  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
379  * @callgraph
380  * @callergraph
381 */
pico_getResourceName(pico_System system,pico_Resource resource,pico_Retstring outName)382 PICO_FUNC pico_getResourceName(
383         pico_System system,
384         pico_Resource resource,
385         pico_Retstring outName) {
386 
387     if (!is_valid_system_handle(system)) {
388         return PICO_ERR_INVALID_HANDLE;
389     } else if (NULL == outName) {
390         return PICO_ERR_NULLPTR_ACCESS;
391     }
392     return picorsrc_rsrcGetName((picorsrc_Resource)resource, (picoos_char *) outName, PICO_RETSTRINGSIZE);
393 }
394 
395 
396 /* *** Voice definition functions *********************************************/
397 
398 /**
399  * pico_createVoiceDefinition : Creates a voice definition
400  * @param    system : pointer to a pico_System struct
401  * @param    *voiceName : pointer to the area to receive the voice definition
402  * @return  PICO_OK : successful
403  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
404  * @callgraph
405  * @callergraph
406 */
pico_createVoiceDefinition(pico_System system,const pico_Char * voiceName)407 PICO_FUNC pico_createVoiceDefinition(
408         pico_System system,
409         const pico_Char *voiceName
410         )
411 {
412     pico_Status status = PICO_OK;
413 
414     if (!is_valid_system_handle(system)) {
415         status = PICO_ERR_INVALID_HANDLE;
416     } else if (voiceName == NULL) {
417         status = PICO_ERR_NULLPTR_ACCESS;
418     } else if (picoos_strlen((picoos_char *) voiceName) == 0) {
419         status = PICO_ERR_INVALID_ARGUMENT;
420     } else {
421         picoos_emReset(system->common->em);
422         status = picorsrc_createVoiceDefinition(system->rm, (picoos_char *) voiceName);
423     }
424 
425     return status;
426 }
427 
428 /**
429  * pico_addResourceToVoiceDefinition : Adds a mapping pair to a voice definition
430  * @param    system : pointer to a pico_System struct
431  * @param    *voiceName : pointer to the area containing the voice definition
432  * @param    *resourceName : pointer to the area containing the resource name
433  * @return  PICO_OK : successful
434  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
435  * @callgraph
436  * @callergraph
437 */
pico_addResourceToVoiceDefinition(pico_System system,const pico_Char * voiceName,const pico_Char * resourceName)438 PICO_FUNC pico_addResourceToVoiceDefinition(
439         pico_System system,
440         const pico_Char *voiceName,
441         const pico_Char *resourceName
442         )
443 {
444     pico_Status status = PICO_OK;
445 
446     if (!is_valid_system_handle(system)) {
447         status = PICO_ERR_INVALID_HANDLE;
448     } else if (voiceName == NULL) {
449         status = PICO_ERR_NULLPTR_ACCESS;
450     } else if (picoos_strlen((picoos_char *) voiceName) == 0) {
451         status = PICO_ERR_INVALID_ARGUMENT;
452     } else if (resourceName == NULL) {
453         status = PICO_ERR_NULLPTR_ACCESS;
454     } else if (picoos_strlen((picoos_char *) resourceName) == 0) {
455         status = PICO_ERR_INVALID_ARGUMENT;
456     } else {
457         picoos_emReset(system->common->em);
458         status = picorsrc_addResourceToVoiceDefinition(system->rm, (picoos_char *) voiceName, (picoos_char *) resourceName);
459     }
460 
461     return status;
462 }
463 
464 /**
465  * pico_releaseVoiceDefinition : Releases a voice definition
466  * @param    system : pointer to a pico_System struct
467  * @param    *voiceName : pointer to the area containing the voice definition
468  * @return  PICO_OK : successful
469  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
470  * @callgraph
471  * @callergraph
472 */
pico_releaseVoiceDefinition(pico_System system,const pico_Char * voiceName)473 PICO_FUNC pico_releaseVoiceDefinition(
474         pico_System system,
475         const pico_Char *voiceName
476         )
477 {
478     pico_Status status = PICO_OK;
479 
480     if (!is_valid_system_handle(system)) {
481         status = PICO_ERR_INVALID_HANDLE;
482     } else if (voiceName == NULL) {
483         status = PICO_ERR_NULLPTR_ACCESS;
484     } else if (picoos_strlen((picoos_char *) voiceName) == 0) {
485         status = PICO_ERR_INVALID_ARGUMENT;
486     } else {
487         picoos_emReset(system->common->em);
488         status = picorsrc_releaseVoiceDefinition(system->rm, (picoos_char *) voiceName);
489     }
490 
491     return status;
492 }
493 
494 
495 
496 /* *** Engine creation and deletion functions *********************************/
497 
498 /**
499  * pico_newEngine : Creates and initializes a new Pico engine
500  * @param    system : pointer to a pico_System struct
501  * @param    *voiceName : pointer to the area containing the voice definition
502  * @param    *outEngine : pointer to the Pico engine handle
503  * @return  PICO_OK : successful
504  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
505  * @callgraph
506  * @callergraph
507 */
pico_newEngine(pico_System system,const pico_Char * voiceName,pico_Engine * outEngine)508 PICO_FUNC pico_newEngine(
509         pico_System system,
510         const pico_Char *voiceName,
511         pico_Engine *outEngine
512         )
513 {
514     pico_Status status = PICO_OK;
515 
516     PICODBG_DEBUG(("creating engine for voice '%s'", (picoos_char *) voiceName));
517 
518     if (!is_valid_system_handle(system)) {
519         status = PICO_ERR_INVALID_HANDLE;
520     } else if (voiceName == NULL) {
521         status = PICO_ERR_NULLPTR_ACCESS;
522     } else if (picoos_strlen((picoos_char *) voiceName) == 0) {
523         status = PICO_ERR_INVALID_ARGUMENT;
524     } else if (outEngine == NULL) {
525         status = PICO_ERR_NULLPTR_ACCESS;
526     } else {
527         picoos_emReset(system->common->em);
528         if (system->engine == NULL) {
529             *outEngine = (pico_Engine) picoctrl_newEngine(system->common->mm, system->rm, voiceName);
530             if (*outEngine != NULL) {
531                 system->engine = (picoctrl_Engine) *outEngine;
532             } else {
533                 status = picoos_emRaiseException(system->common->em, PICO_EXC_OUT_OF_MEM,
534                             (picoos_char *) "out of memory creating new engine", NULL);
535             }
536         } else {
537             status = picoos_emRaiseException(system->common->em, PICO_EXC_MAX_NUM_EXCEED,
538                         NULL, (picoos_char *) "no more than %i engines", 1);
539         }
540     }
541 
542     return status;
543 }
544 
545 /**
546  * pico_disposeEngine : Disposes a Pico engine
547  * @param    system : pointer to a pico_System struct
548  * @param    *inoutEngine : pointer to the Pico engine handle
549  * @return  PICO_OK : successful
550  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
551  * @callgraph
552  * @callergraph
553 */
pico_disposeEngine(pico_System system,pico_Engine * inoutEngine)554 PICO_FUNC pico_disposeEngine(
555         pico_System system,
556         pico_Engine *inoutEngine
557         )
558 {
559     pico_Status status = PICO_OK;
560 
561     if (!is_valid_system_handle(system)) {
562         status = PICO_ERR_INVALID_HANDLE;
563     } else if (inoutEngine == NULL) {
564         status = PICO_ERR_NULLPTR_ACCESS;
565     } else if (!picoctrl_isValidEngineHandle(*((picoctrl_Engine *) inoutEngine))) {
566         status = PICO_ERR_INVALID_HANDLE;
567     } else {
568         picoos_emReset(system->common->em);
569         picoctrl_disposeEngine(system->common->mm, system->rm, (picoctrl_Engine *) inoutEngine);
570         system->engine = NULL;
571         status = picoos_emGetExceptionCode(system->common->em);
572     }
573 
574     return status;
575 }
576 
577 
578 
579 /* ****************************************************************************/
580 /* Engine-level API functions                                                 */
581 /* ****************************************************************************/
582 
583 /**
584  * pico_putTextUtf8 : Puts UTF8 text into Pico text input buffer
585  * @param    engine : pointer to a Pico engine handle
586  * @param    *text : pointer to the text buffer
587  * @param    textSize : text buffer size
588  * @param    *bytesPut : pointer to variable to receive the number of bytes put
589  * @return  PICO_OK : successful
590  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
591  * @callgraph
592  * @callergraph
593  */
pico_putTextUtf8(pico_Engine engine,const pico_Char * text,const pico_Int16 textSize,pico_Int16 * bytesPut)594 PICO_FUNC pico_putTextUtf8(
595         pico_Engine engine,
596         const pico_Char *text,
597         const pico_Int16 textSize,
598         pico_Int16 *bytesPut)
599 {
600     pico_Status status = PICO_OK;
601 
602     if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) {
603         status = PICO_ERR_INVALID_HANDLE;
604     } else if (text == NULL) {
605         status = PICO_ERR_NULLPTR_ACCESS;
606     } else if (textSize < 0) {
607         status = PICO_ERR_INVALID_ARGUMENT;
608     } else if (bytesPut == NULL) {
609         status = PICO_ERR_NULLPTR_ACCESS;
610     } else {
611         picoctrl_engResetExceptionManager((picoctrl_Engine) engine);
612         status = picoctrl_engFeedText((picoctrl_Engine) engine, (picoos_char *)text, textSize, bytesPut);
613     }
614 
615     return status;
616 }
617 
618 /**
619  * pico_getData : Gets speech data from the engine.
620  * @param    engine : pointer to a Pico engine handle
621  * @param    *buffer : pointer to output buffer
622  * @param    bufferSize : out buffer size
623  * @param    *bytesReceived : pointer to a variable to receive the number of bytes received
624  * @param    *outDataType : pointer to a variable to receive the type of buffer received
625  * @return  PICO_OK : successful
626  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
627  * @callgraph
628  * @callergraph
629 */
pico_getData(pico_Engine engine,void * buffer,const pico_Int16 bufferSize,pico_Int16 * bytesReceived,pico_Int16 * outDataType)630 PICO_FUNC pico_getData(
631         pico_Engine engine,
632         void *buffer,
633         const pico_Int16 bufferSize,
634         pico_Int16 *bytesReceived,
635         pico_Int16 *outDataType
636         )
637 {
638     pico_Status status = PICO_OK;
639 
640     if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) {
641         status = PICO_STEP_ERROR;
642     } else if (buffer == NULL) {
643         status = PICO_STEP_ERROR;
644     } else if (bufferSize < 0) {
645         status = PICO_STEP_ERROR;
646     } else if (bytesReceived == NULL) {
647         status = PICO_STEP_ERROR;
648     } else {
649         picoctrl_engResetExceptionManager((picoctrl_Engine) engine);
650         status = picoctrl_engFetchOutputItemBytes((picoctrl_Engine) engine, (picoos_char *)buffer, bufferSize, bytesReceived);
651         if ((status != PICO_STEP_IDLE) && (status != PICO_STEP_BUSY)) {
652             status = PICO_STEP_ERROR;
653         }
654     }
655 
656     *outDataType = PICO_DATA_PCM_16BIT;
657     return status;
658 }
659 
660 /**
661  * pico_resetEngine : Resets the engine
662  * @param    engine : pointer to a Pico engine handle
663  * @param resetMode : reset mode; one of PICO_RESET_FULL or PICO_RESET_SOFT
664  * @return  PICO_OK : successful
665  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
666  * @callgraph
667  * @callergraph
668 */
pico_resetEngine(pico_Engine engine,pico_Int32 resetMode)669 PICO_FUNC pico_resetEngine(
670         pico_Engine engine,
671         pico_Int32 resetMode)
672 {
673     pico_Status status = PICO_OK;
674 
675     if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) {
676         status = PICO_ERR_INVALID_HANDLE;
677     } else {
678         picoctrl_engResetExceptionManager((picoctrl_Engine) engine);
679 
680         resetMode = (PICO_RESET_SOFT == resetMode) ? PICO_RESET_SOFT : PICO_RESET_FULL;
681 
682         status = picoctrl_engReset((picoctrl_Engine) engine, (picoos_int32)resetMode);
683     }
684 
685     return status;
686 }
687 
688 /**
689  * pico_getEngineStatusMessage : Returns the engine status or error description
690  * @param    engine : pointer to a Pico engine handle
691  * @param    errCode : error code
692  * @param    outMessage : pointer to a memory area to receive the output message
693  * @return  PICO_OK : successful
694  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
695  * @callgraph
696  * @callergraph
697 */
pico_getEngineStatusMessage(pico_Engine engine,pico_Status errCode,pico_Retstring outMessage)698 PICO_FUNC pico_getEngineStatusMessage(
699         pico_Engine engine,
700         pico_Status errCode,
701         pico_Retstring outMessage
702         )
703 {
704     pico_Status status = PICO_OK;
705 
706     PICODBG_DEBUG(("got error code %i", errCode));
707 
708     if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) {
709         status = PICO_ERR_INVALID_HANDLE;
710         if (outMessage != NULL) {
711             picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'engine' not initialized", PICO_RETSTRINGSIZE);
712         }
713     } else if (outMessage == NULL) {
714         status = PICO_ERR_NULLPTR_ACCESS;
715     } else {
716         picoos_Common common = picoctrl_engGetCommon((picoctrl_Engine) engine);
717         if (picoos_emGetExceptionCode(common->em) == PICO_OK) {
718             if (errCode == PICO_OK) {
719                 picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "engine ok", PICO_RETSTRINGSIZE);
720             } else {
721                 /* exceptionManager was not informed yet; produce default message */
722                 picoos_setErrorMsg((picoos_char *) outMessage, PICO_RETSTRINGSIZE, errCode, NULL, NULL, NULL);
723             }
724         } else {
725             picoos_emGetExceptionMessage(common->em, (picoos_char *) outMessage, PICO_RETSTRINGSIZE);
726         }
727     }
728 
729     return status;
730 }
731 
732 /**
733  * pico_getNrEngineWarnings : Returns the number of warnings
734  * @param    engine : pointer to a Pico engine handle
735  * @param    *outNrOfWarnings: pointer to a variable to receive the number of warnings
736  * @return  PICO_OK : successful
737  * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
738  * @callgraph
739  * @callergraph
740 */
pico_getNrEngineWarnings(pico_Engine engine,pico_Int32 * outNrOfWarnings)741 PICO_FUNC pico_getNrEngineWarnings(
742         pico_Engine engine,
743         pico_Int32 *outNrOfWarnings
744         )
745 {
746     pico_Status status = PICO_OK;
747 
748     if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) {
749         status = PICO_ERR_INVALID_HANDLE;
750         if (outNrOfWarnings != NULL) {
751             *outNrOfWarnings = 0;
752         }
753     } else if (outNrOfWarnings == NULL) {
754         status = PICO_ERR_NULLPTR_ACCESS;
755     } else {
756         picoos_Common common = picoctrl_engGetCommon((picoctrl_Engine) engine);
757         *outNrOfWarnings = picoos_emGetNumOfWarnings(common->em);
758     }
759 
760     return status;
761 }
762 
763 /**
764      * pico_getEngineWarning : Returns a description of a warning
765      * @param    engine : pointer to a Pico engine handle
766      * @param    warningIndex : warning index
767      * @param    *outCode: pointer to a variable to receive the warning code
768      * @param    outMessage: pointer to a memory area to receive the warning description
769      * @return  PICO_OK : successful
770      * @return     PICO_ERR_INVALID_HANDLE, PICO_ERR_NULLPTR_ACCESS : errors
771      * @callgraph
772      * @callergraph
773 */
pico_getEngineWarning(pico_Engine engine,const pico_Int32 warningIndex,pico_Status * outCode,pico_Retstring outMessage)774 PICO_FUNC pico_getEngineWarning(
775         pico_Engine engine,
776         const pico_Int32 warningIndex,
777         pico_Status *outCode,
778         pico_Retstring outMessage
779         )
780 {
781     pico_Status status = PICO_OK;
782 
783     if (!picoctrl_isValidEngineHandle((picoctrl_Engine) engine)) {
784         status = PICO_ERR_INVALID_HANDLE;
785         if (outMessage != NULL) {
786             picoos_strlcpy((picoos_char *) outMessage, (picoos_char *) "'engine' not initialized", PICO_RETSTRINGSIZE);
787         }
788     } else if (warningIndex < 0) {
789         status = PICO_ERR_INDEX_OUT_OF_RANGE;
790     } else if ((outCode == NULL) || (outMessage == NULL)) {
791         status = PICO_ERR_NULLPTR_ACCESS;
792     } else {
793         picoos_Common common = picoctrl_engGetCommon((picoctrl_Engine) engine);
794         *outCode = picoos_emGetWarningCode(common->em, warningIndex);
795         picoos_emGetWarningMessage(common->em, warningIndex, (picoos_char *) outMessage, (picoos_uint16) PICO_RETSTRINGSIZE);
796     }
797 
798     return status;
799 }
800 
801 #ifdef __cplusplus
802 }
803 #endif
804 
805 
806 /* end */
807