1/*---------------------------------------------------------------------------*
2 *  SessionTypeImpl.c  *
3 *                                                                           *
4 *  Copyright 2007, 2008 Nuance Communciations, Inc.                               *
5 *                                                                           *
6 *  Licensed under the Apache License, Version 2.0 (the 'License');          *
7 *  you may not use this file except in compliance with the License.         *
8 *                                                                           *
9 *  You may obtain a copy of the License at                                  *
10 *      http://www.apache.org/licenses/LICENSE-2.0                           *
11 *                                                                           *
12 *  Unless required by applicable law or agreed to in writing, software      *
13 *  distributed under the License is distributed on an 'AS IS' BASIS,        *
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
15 *  See the License for the specific language governing permissions and      *
16 *  limitations under the License.                                           *
17 *                                                                           *
18 *---------------------------------------------------------------------------*/
19
20
21#include "ESR_SessionType.h"
22#include "ESR_SessionTypeImpl.h"
23#include "HashMap.h"
24#include "IntArrayList.h"
25#include "LCHAR.h"
26#include "lstring.h"
27#include "passert.h"
28#include "pendian.h"
29#include "PFile.h"
30#include "PFileSystem.h"
31#include "plog.h"
32#include "pmemory.h"
33#include "pstdio.h"
34#include "string.h"
35#include "ESR_SessionTypeListener.h"
36
37#define MTAG NULL
38
39ESR_ReturnCode ESR_SessionTypeCreate(ESR_SessionType** self)
40{
41  ESR_SessionType* Interface;
42  ESR_SessionTypeData* data;
43  ESR_ReturnCode rc;
44
45  if (self == NULL)
46  {
47    PLogError(L("ESR_OUT_OF_MEMORY"));
48    return ESR_OUT_OF_MEMORY;
49  }
50  Interface = NEW(ESR_SessionType, MTAG);
51  if (Interface == NULL)
52  {
53    PLogError(L("ESR_OUT_OF_MEMORY"));
54    return ESR_OUT_OF_MEMORY;
55  }
56  data = NEW(ESR_SessionTypeData, MTAG);
57  if (data == NULL)
58  {
59    rc = ESR_OUT_OF_MEMORY;
60    goto CLEANUP;
61  }
62
63
64  Interface->addListener = &ESR_SessionTypeAddListenerImpl;
65  Interface->contains = &ESR_SessionTypeContainsImpl;
66  Interface->convertToBool = &ESR_SessionTypeConvertToBoolImpl;
67  Interface->convertToFloat = &ESR_SessionTypeConvertToFloatImpl;
68  Interface->convertToInt = &ESR_SessionTypeConvertToIntImpl;
69  Interface->convertToUint16_t = &ESR_SessionTypeConvertToUint16_tImpl;
70  Interface->convertToSize_t = &ESR_SessionTypeConvertToSize_tImpl;
71  Interface->destroy = &ESR_SessionTypeDestroyImpl;
72  Interface->getBool = &ESR_SessionTypeGetBoolImpl;
73  Interface->getFloat = &ESR_SessionTypeGetFloatImpl;
74  Interface->getInt = &ESR_SessionTypeGetIntImpl;
75  Interface->getUint16_t = &ESR_SessionTypeGetUint16_tImpl;
76  Interface->getKeyAtIndex = &ESR_SessionTypeGetKeyAtIndexImpl;
77  Interface->getLCHAR = &ESR_SessionTypeGetLCHARImpl;
78  Interface->getProperty = &ESR_SessionTypeGetPropertyImpl;
79  Interface->getPropertyType = &ESR_SessionTypeGetPropertyTypeImpl;
80  Interface->getSize = &ESR_SessionTypeGetSizeImpl;
81  Interface->getSize_t = &ESR_SessionTypeGetSize_tImpl;
82  Interface->importCommandLine = &ESR_SessionTypeImportCommandLineImpl;
83  Interface->importParFile = &ESR_SessionTypeImportParFileImpl;
84  Interface->removeProperty = &ESR_SessionTypeRemovePropertyImpl;
85  Interface->removeAndFreeProperty = &ESR_SessionTypeRemoveAndFreePropertyImpl;
86  Interface->setBool = &ESR_SessionTypeSetBoolImpl;
87  Interface->setBoolIfEmpty = &ESR_SessionTypeSetBoolIfEmptyImpl;
88  Interface->setFloat = &ESR_SessionTypeSetFloatImpl;
89  Interface->setFloatIfEmpty = &ESR_SessionTypeSetFloatIfEmptyImpl;
90  Interface->setInt = &ESR_SessionTypeSetIntImpl;
91  Interface->setIntIfEmpty = &ESR_SessionTypeSetIntIfEmptyImpl;
92  Interface->setUint16_t = &ESR_SessionTypeSetUint16_tImpl;
93  Interface->setUint16_tIfEmpty = &ESR_SessionTypeSetUint16_tIfEmptyImpl;
94  Interface->setLCHAR = &ESR_SessionTypeSetLCHARImpl;
95  Interface->setLCHARIfEmpty = &ESR_SessionTypeSetLCHARIfEmptyImpl;
96  Interface->setProperty = &ESR_SessionTypeSetPropertyImpl;
97  Interface->setSize_t = &ESR_SessionTypeSetSize_tImpl;
98  Interface->setSize_tIfEmpty = &ESR_SessionTypeSetSize_tIfEmptyImpl;
99  Interface->removeListener = &ESR_SessionTypeRemoveListenerImpl;
100
101  Interface->data = data;
102  data->value = NULL;
103  data->listeners = NULL;
104
105  CHK(rc, HashMapCreate(&data->value));
106  CHK(rc, ArrayListCreate(&data->listeners));
107  *self = Interface;
108  return ESR_SUCCESS;
109CLEANUP:
110  Interface->destroy(Interface);
111  return rc;
112}
113
114/*
115 * Because there are no functions to set and get int size_t parameters and because most if not
116 * all int parameters should be size_t anyway, I am adding code to allow size_t and int parameters
117 * to be considered equal. Besides, this check is kind of overkill anyway. SteveR
118 */
119
120ESR_ReturnCode ESR_SessionTypeGetPropertyImpl(ESR_SessionType* self,
121    const LCHAR* name, void** value,
122    VariableTypes type)
123{
124  ESR_SessionTypeData* data = self->data;
125  ESR_SessionPair* pair;
126  ESR_ReturnCode rc;
127
128  CHK(rc, HashMapGet(data->value, name, (void **)&pair));
129  if ( ( pair->type != type) && ( ( ( pair->type != TYPES_INT ) && ( type != TYPES_SIZE_T ) ) ||
130      ( ( type != TYPES_INT ) && ( pair->type != TYPES_SIZE_T ) ) ) )
131  {
132    PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), type, pair->type);
133    return ESR_INVALID_RESULT_TYPE;
134  }
135  *value = pair->value;
136  return ESR_SUCCESS;
137CLEANUP:
138  return rc;
139}
140
141ESR_ReturnCode ESR_SessionTypeGetIntImpl(ESR_SessionType* self,
142    const LCHAR* name, int* value)
143{
144  ESR_ReturnCode rc;
145  ESR_SessionTypeData* data;
146  ESR_SessionPair* pair;
147
148  data = self->data;
149  CHK(rc, HashMapGet(data->value, name, (void **)&pair));
150  if ( ( pair->type != TYPES_INT ) && ( pair->type != TYPES_SIZE_T ) )
151  {
152    PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_INT, pair->type);
153    return ESR_INVALID_RESULT_TYPE;
154  }
155  *value = *((int*) pair->value);
156  return ESR_SUCCESS;
157CLEANUP:
158  return rc;
159}
160
161ESR_ReturnCode ESR_SessionTypeGetUint16_tImpl(ESR_SessionType* self,
162    const LCHAR* name, asr_uint16_t* value)
163{
164  ESR_ReturnCode rc;
165  ESR_SessionTypeData* data;
166  ESR_SessionPair* pair;
167
168  data = self->data;
169  CHK(rc, HashMapGet(data->value, name, (void **)&pair));
170  if (pair->type != TYPES_UINT16_T)
171  {
172    PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_UINT16_T, pair->type);
173    return ESR_INVALID_RESULT_TYPE;
174  }
175  *value = *((asr_uint16_t*) pair->value);
176  return ESR_SUCCESS;
177CLEANUP:
178  return rc;
179}
180
181ESR_ReturnCode ESR_SessionTypeGetSize_tImpl(ESR_SessionType* self,
182    const LCHAR* name,
183    size_t* value)
184{
185  ESR_ReturnCode rc;
186  ESR_SessionTypeData* data;
187  ESR_SessionPair* pair;
188
189  data = self->data;
190  CHKLOG(rc, HashMapGet(data->value, name, (void **)&pair));
191  if ( ( pair->type != TYPES_INT ) && ( pair->type != TYPES_SIZE_T ) )
192  {
193    PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_SIZE_T, pair->type);
194    return ESR_INVALID_RESULT_TYPE;
195  }
196  *value = *((size_t*) pair->value);
197  return ESR_SUCCESS;
198CLEANUP:
199  return rc;
200}
201
202ESR_ReturnCode ESR_SessionTypeGetFloatImpl(ESR_SessionType* self,
203    const LCHAR* name, float* value)
204{
205  ESR_ReturnCode rc;
206  ESR_SessionTypeData* data;
207  ESR_SessionPair* pair;
208
209  data = self->data;
210  CHK(rc, HashMapGet(data->value, name, (void **)&pair));
211  if (pair->type != TYPES_FLOAT)
212  {
213    PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_FLOAT, pair->type);
214    return ESR_INVALID_RESULT_TYPE;
215  }
216  *value = *((float*) pair->value);
217  return ESR_SUCCESS;
218CLEANUP:
219  return rc;
220}
221
222ESR_ReturnCode ESR_SessionTypeGetBoolImpl(ESR_SessionType* self,
223    const LCHAR* name, ESR_BOOL* value)
224{
225  ESR_ReturnCode rc;
226  ESR_SessionTypeData* data;
227  ESR_SessionPair* pair;
228
229  data = self->data;
230  CHK(rc, HashMapGet(data->value, name, (void **)&pair));
231  if (pair->type != TYPES_BOOL)
232  {
233    PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_BOOL, pair->type);
234    return ESR_INVALID_RESULT_TYPE;
235  }
236  *value = *((ESR_BOOL*) pair->value);
237  return ESR_SUCCESS;
238CLEANUP:
239  return rc;
240}
241
242ESR_ReturnCode ESR_SessionTypeGetLCHARImpl(ESR_SessionType* self,
243    const LCHAR* name,
244    LCHAR* value, size_t* len)
245{
246  LCHAR* lValue;
247  ESR_ReturnCode rc;
248  ESR_SessionTypeData* data;
249  ESR_SessionPair* pair;
250
251  if (name == NULL || value == NULL || len == NULL)
252    return ESR_INVALID_ARGUMENT;
253  data = self->data;
254
255  CHK(rc, HashMapGet(data->value, name, (void **)&pair));
256  if (pair->type != TYPES_PLCHAR)
257  {
258    PLogError(L("ESR_INVALID_RESULT_TYPE: [got=%d, expected=%d]"), TYPES_PLCHAR, pair->type);
259    return ESR_INVALID_RESULT_TYPE;
260  }
261  lValue = (LCHAR*) pair->value;
262  if (LSTRLEN(pair->value) + 1 > *len)
263  {
264    *len = LSTRLEN(lValue) + 1;
265    return ESR_BUFFER_OVERFLOW;
266  }
267  LSTRCPY(value, lValue);
268  return ESR_SUCCESS;
269CLEANUP:
270  return rc;
271}
272
273ESR_ReturnCode ESR_SessionTypeContainsImpl(ESR_SessionType* self,
274    const LCHAR* name, ESR_BOOL* exists)
275{
276  ESR_SessionTypeData* data = self->data;
277
278  return HashMapContainsKey(data->value, name, exists);
279}
280
281static ESR_ReturnCode firePropertyChanged(ESR_SessionType* self, const LCHAR* name,
282    const void* oldValue, const void* newValue,
283    enum VariableTypes_t type)
284{
285  ESR_SessionTypeData* data = self->data;
286  ArrayList* list = data->listeners;
287  size_t size, i;
288  ESR_SessionTypeListenerPair* listener;
289  ESR_ReturnCode rc;
290
291  CHKLOG(rc, list->getSize(list, &size));
292  for (i = 0; i < size; ++i)
293  {
294    CHKLOG(rc, list->get(list, i, (void **)&listener));
295    CHKLOG(rc, listener->listener->propertyChanged(listener->listener, name, oldValue, newValue, type, listener->data));
296  }
297  return ESR_SUCCESS;
298CLEANUP:
299  return rc;
300}
301
302ESR_ReturnCode ESR_SessionTypeSetPropertyImpl(ESR_SessionType* self,
303    const LCHAR* name, void* value,
304    VariableTypes type)
305{
306  ESR_SessionTypeData* data = self->data;
307  ESR_SessionPair* pair = NULL;
308  ESR_BOOL exists;
309  ESR_ReturnCode rc;
310
311  CHKLOG(rc, HashMapContainsKey(data->value, name, &exists));
312  if ( exists )
313  {
314/* We allow change of parameters through the recognizer and we rely on the recognizer to do
315 * all of the needed validation. SteveR
316 */
317/* Deleting the old entry seems stupid, but it's the only way to prevent a memory leak,
318 * since the old data is not returned when you add the new data. SteveR
319 */
320    CHKLOG ( rc, ESR_SessionTypeRemoveAndFreePropertyImpl ( self, name ) );
321  }
322  pair = NEW(ESR_SessionPair, MTAG);
323  if (pair == NULL)
324  {
325    PLogError(L("ESR_OUT_OF_MEMORY"));
326    return ESR_OUT_OF_MEMORY;
327  }
328  pair->value = value;
329  pair->type = type;
330
331  CHKLOG(rc, firePropertyChanged(self, name, NULL, value, type));
332  CHKLOG(rc, HashMapPut(data->value, name, pair));
333  return ESR_SUCCESS;
334CLEANUP:
335/* The cleanup potentially leaks memory which could be cleard up with  FREE ( pair->value );
336 * but you can't guarantee that the value was allocated. A leak is better than a crash. SteveR
337 */
338  FREE(pair);
339  return rc;
340}
341
342ESR_ReturnCode ESR_SessionTypeSetIntImpl(ESR_SessionType* self,
343    const LCHAR* name, int value)
344{
345  ESR_SessionTypeData* data;
346  int* clone;
347
348  data = self->data;
349  clone = MALLOC(sizeof(int), MTAG);
350  if (clone == NULL)
351  {
352    PLogError(L("ESR_OUT_OF_MEMORY"));
353    return ESR_OUT_OF_MEMORY;
354  }
355
356  *clone = value;
357  return self->setProperty(self, name, clone, TYPES_INT);
358}
359
360ESR_ReturnCode ESR_SessionTypeSetUint16_tImpl(ESR_SessionType* self,
361    const LCHAR* name, asr_uint16_t value)
362{
363  ESR_SessionTypeData* data;
364  asr_uint16_t* clone;
365
366  data = self->data;
367  clone = MALLOC(sizeof(asr_uint16_t), MTAG);
368  if (clone == NULL)
369  {
370    PLogError(L("ESR_OUT_OF_MEMORY"));
371    return ESR_OUT_OF_MEMORY;
372  }
373
374  *clone = value;
375  return self->setProperty(self, name, clone, TYPES_UINT16_T);
376}
377
378ESR_ReturnCode ESR_SessionTypeSetSize_tImpl(ESR_SessionType* self,
379    const LCHAR* name, size_t value)
380{
381  ESR_SessionTypeData* data;
382  int* clone;
383
384  data = self->data;
385  clone = MALLOC(sizeof(size_t), MTAG);
386  if (clone == NULL)
387  {
388    PLogError(L("ESR_OUT_OF_MEMORY"));
389    return ESR_OUT_OF_MEMORY;
390  }
391
392  *clone = value;
393  return self->setProperty(self, name, clone, TYPES_SIZE_T);
394}
395
396ESR_ReturnCode ESR_SessionTypeSetFloatImpl(ESR_SessionType* self,
397    const LCHAR* name, float value)
398{
399  ESR_SessionTypeData* data;
400  float* clone;
401
402  data = self->data;
403  clone = MALLOC(sizeof(float), MTAG);
404  if (clone == NULL)
405  {
406    PLogError(L("ESR_OUT_OF_MEMORY"));
407    return ESR_OUT_OF_MEMORY;
408  }
409
410  *clone = value;
411  return self->setProperty(self, name, clone, TYPES_FLOAT);
412}
413
414ESR_ReturnCode ESR_SessionTypeSetBoolImpl(ESR_SessionType* self,
415    const LCHAR* name, ESR_BOOL value)
416{
417  ESR_SessionTypeData* data;
418  ESR_BOOL* clone;
419
420  data = self->data;
421  clone = MALLOC(sizeof(ESR_BOOL), MTAG);
422  if (clone == NULL)
423  {
424    PLogError(L("ESR_OUT_OF_MEMORY"));
425    return ESR_OUT_OF_MEMORY;
426  }
427
428  *clone = value;
429  return self->setProperty(self, name, clone, TYPES_BOOL);
430}
431
432ESR_ReturnCode ESR_SessionTypeSetLCHARImpl(ESR_SessionType* self,
433    const LCHAR* name, LCHAR* value)
434{
435  ESR_SessionTypeData* data;
436  LCHAR* clone;
437
438  data = self->data;
439  clone = MALLOC(sizeof(LCHAR) * (LSTRLEN(value) + 1), MTAG);
440  if (clone == NULL)
441  {
442    PLogError(L("ESR_OUT_OF_MEMORY"));
443    return ESR_OUT_OF_MEMORY;
444  }
445
446  LSTRCPY(clone, value);
447  return self->setProperty(self, name, clone, TYPES_PLCHAR);
448}
449
450ESR_ReturnCode ESR_SessionTypeSetIntIfEmptyImpl(ESR_SessionType* self,
451    const LCHAR* name, int value)
452{
453  ESR_BOOL exists;
454  ESR_ReturnCode rc;
455
456  CHK(rc, self->contains(self, name, &exists));
457  if (exists)
458    return ESR_SUCCESS;
459  return self->setInt(self, name, value);
460CLEANUP:
461  return rc;
462}
463
464ESR_ReturnCode ESR_SessionTypeSetUint16_tIfEmptyImpl(ESR_SessionType* self,
465    const LCHAR* name, asr_uint16_t value)
466{
467  ESR_BOOL exists;
468  ESR_ReturnCode rc;
469
470  CHK(rc, self->contains(self, name, &exists));
471  if (exists)
472    return ESR_SUCCESS;
473  return self->setInt(self, name, value);
474CLEANUP:
475  return rc;
476}
477
478ESR_ReturnCode ESR_SessionTypeSetSize_tIfEmptyImpl(ESR_SessionType* self,
479    const LCHAR* name, size_t value)
480{
481  ESR_BOOL exists;
482  ESR_ReturnCode rc;
483
484  CHK(rc, self->contains(self, name, &exists));
485  if (exists)
486    return ESR_SUCCESS;
487  return self->setSize_t(self, name, value);
488CLEANUP:
489  return rc;
490}
491
492ESR_ReturnCode ESR_SessionTypeSetFloatIfEmptyImpl(ESR_SessionType* self,
493    const LCHAR* name, float value)
494{
495  ESR_BOOL exists;
496  ESR_ReturnCode rc;
497
498  CHK(rc, self->contains(self, name, &exists));
499  if (exists)
500    return ESR_SUCCESS;
501  return self->setFloat(self, name, value);
502CLEANUP:
503  return rc;
504}
505
506ESR_ReturnCode ESR_SessionTypeSetBoolIfEmptyImpl(ESR_SessionType* self,
507    const LCHAR* name, ESR_BOOL value)
508{
509  ESR_BOOL exists;
510  ESR_ReturnCode rc;
511
512  CHK(rc, self->contains(self, name, &exists));
513  if (exists)
514    return ESR_SUCCESS;
515  return self->setBool(self, name, value);
516CLEANUP:
517  return rc;
518}
519
520ESR_ReturnCode ESR_SessionTypeSetLCHARIfEmptyImpl(ESR_SessionType* self,
521    const LCHAR* name, LCHAR* value)
522{
523  ESR_BOOL exists;
524  ESR_ReturnCode rc;
525
526  CHK(rc, self->contains(self, name, &exists));
527  if (exists)
528    return ESR_SUCCESS;
529  return self->setLCHAR(self, name, value);
530CLEANUP:
531  return rc;
532}
533
534ESR_ReturnCode ESR_SessionTypeRemovePropertyImpl(ESR_SessionType* self,
535    const LCHAR* name)
536{
537  ESR_ReturnCode rc;
538  ESR_SessionTypeData* data = self->data;
539  ESR_SessionPair* pair;
540
541  CHK(rc, HashMapGet(data->value, name, (void **)&pair));
542  CHKLOG(rc, firePropertyChanged(self, name, pair->value, NULL, pair->type));
543  CHK(rc, HashMapRemove(data->value, name));
544  FREE(pair);
545  return ESR_SUCCESS;
546CLEANUP:
547  return rc;
548}
549
550ESR_ReturnCode ESR_SessionTypeRemoveAndFreePropertyImpl(ESR_SessionType* self,
551    const LCHAR* name)
552{
553  ESR_ReturnCode rc;
554  ESR_SessionTypeData* data = self->data;
555  ESR_SessionPair* pair;
556  ESR_SessionPair temp;
557  IntArrayList* intList;
558
559  CHK(rc, data->value->get(data->value, name, (void **)&pair));
560  temp = *pair;
561  CHK(rc, self->removeProperty(self, name));
562  if (temp.value)
563  {
564    if (temp.type == TYPES_INTARRAYLIST)
565    {
566      intList = temp.value;
567      intList->destroy(intList);
568    }
569    else
570      FREE(temp.value);
571  }
572  return ESR_SUCCESS;
573CLEANUP:
574  return rc;
575}
576
577ESR_ReturnCode ESR_SessionTypeImportCommandLineImpl(ESR_SessionType* self,
578    int argc, LCHAR* argv[])
579{
580  char* key = NULL;
581  char* value = NULL;
582  VariableTypes type;
583  ESR_ReturnCode rc;
584
585  while (--argc > 0 && **++argv)
586  {
587    if (**argv != '-')
588    {
589      /* got value */
590      if (key == NULL)
591      {
592        /* but we don't have any key to associate it with */
593        pfprintf(PSTDERR, "Options must be prefixed by '-'%s\n", *argv);
594      }
595      else
596      {
597        rc = self->getPropertyType(self, key, &type);
598        if (rc == ESR_SUCCESS)
599        {
600          CHKLOG(rc, self->getProperty(self, key, (void **)&value, type));
601          CHKLOG(rc, self->removeProperty(self, key));
602          FREE(value);
603          value = NULL;
604        }
605        else if (rc != ESR_NO_MATCH_ERROR)
606        {
607          PLogError(ESR_rc2str(rc));
608          goto CLEANUP;
609        }
610        value = MALLOC(sizeof(LCHAR) * (strlen(*argv) + 1), MTAG);
611        if (value == NULL)
612        {
613          rc = ESR_OUT_OF_MEMORY;
614          PLogError(L("ESR_OUT_OF_MEMORY"));
615          goto CLEANUP;
616        }
617        LSTRCPY(value, *argv);
618        CHKLOG(rc, self->setProperty(self, key, value, TYPES_PLCHAR));
619        FREE(key);
620        key = NULL;
621        value = NULL;
622      }
623    }
624    else
625    {
626      /* got key */
627      if (key != NULL)
628      {
629        /* But we already have a key without a value, so set the old key's value to "" */
630        rc = self->getPropertyType(self, key, &type);
631        if (rc == ESR_SUCCESS)
632        {
633          CHKLOG(rc, self->getProperty(self, key, (void **)&value, type));
634          CHKLOG(rc, self->removeProperty(self, key));
635          FREE(value);
636          value = NULL;
637        }
638        else if (rc != ESR_NO_MATCH_ERROR)
639        {
640          PLogError(ESR_rc2str(rc));
641          goto CLEANUP;
642        }
643        value = MALLOC(sizeof(LCHAR) + 1, MTAG);
644        strcpy(value, "");
645        CHKLOG(rc, self->setProperty(self, key, value, TYPES_PLCHAR));
646        FREE(key);
647        value = NULL;
648      }
649      key = MALLOC(sizeof(LCHAR) * (LSTRLEN("cmdline.") + LSTRLEN(*argv) + 1), MTAG);
650      if (key == NULL)
651      {
652        rc = ESR_OUT_OF_MEMORY;
653        PLogError(L("ESR_OUT_OF_MEMORY"));
654        goto CLEANUP;
655      }
656      LSTRCPY(key, "cmdline.");
657      LSTRCAT(key, *argv + 1);
658    }
659  }
660  return ESR_SUCCESS;
661CLEANUP:
662  if (key != NULL)
663    FREE(key);
664  if (value != NULL)
665    FREE(value);
666  return rc;
667}
668
669ESR_ReturnCode ESR_SessionTypeGetSizeImpl(ESR_SessionType* self, size_t* size)
670{
671  ESR_SessionTypeData* data = self->data;
672  ESR_ReturnCode rc;
673
674  CHK(rc, HashMapGetSize(data->value, size));
675  return ESR_SUCCESS;
676CLEANUP:
677  return rc;
678}
679
680ESR_ReturnCode ESR_SessionTypeGetKeyAtIndexImpl(ESR_SessionType* self,
681    size_t index, LCHAR** key)
682{
683  ESR_SessionTypeData* data = self->data;
684  ESR_ReturnCode rc;
685
686  CHK(rc, HashMapGetKeyAtIndex(data->value, index, key));
687  return ESR_SUCCESS;
688CLEANUP:
689  return rc;
690}
691
692ESR_ReturnCode ESR_SessionTypeConvertToIntImpl(ESR_SessionType* self,
693    const LCHAR* key)
694{
695  LCHAR* value;
696  int *newValue = NULL;
697  ESR_ReturnCode rc;
698
699  CHK(rc, self->getProperty(self, key, (void **)&value, TYPES_PLCHAR));
700  if (value == NULL)
701    return ESR_SUCCESS;
702  newValue = MALLOC(sizeof(long), MTAG);
703  if (newValue == NULL)
704  {
705    rc = ESR_OUT_OF_MEMORY;
706    goto CLEANUP;
707  }
708  CHKLOG(rc, lstrtoi(value, newValue, 10));
709  CHKLOG(rc, self->setProperty(self, key, newValue, TYPES_INT));
710  FREE(value);
711  return ESR_SUCCESS;
712CLEANUP:
713  if (newValue != NULL)
714    FREE(newValue);
715  return rc;
716}
717
718ESR_ReturnCode ESR_SessionTypeConvertToUint16_tImpl(ESR_SessionType* self,
719    const LCHAR* key)
720{
721  LCHAR* value;
722  int *newValue = NULL;
723  ESR_ReturnCode rc;
724
725  CHK(rc, self->getProperty(self, key, (void **)&value, TYPES_PLCHAR));
726  if (value == NULL)
727    return ESR_SUCCESS;
728  newValue = MALLOC(sizeof(long), MTAG);
729  if (newValue == NULL)
730  {
731    rc = ESR_OUT_OF_MEMORY;
732    goto CLEANUP;
733  }
734  CHKLOG(rc, lstrtoi(value, newValue, 10));
735  CHKLOG(rc, self->setProperty(self, key, newValue, TYPES_UINT16_T));
736  FREE(value);
737  return ESR_SUCCESS;
738CLEANUP:
739  if (newValue != NULL)
740    FREE(newValue);
741  return rc;
742}
743
744ESR_ReturnCode ESR_SessionTypeConvertToSize_tImpl(ESR_SessionType* self,
745    const LCHAR* key)
746{
747  LCHAR* value;
748  size_t* newValue = NULL;
749  ESR_ReturnCode rc;
750
751  CHK(rc, self->getProperty(self, key, (void **)&value, TYPES_PLCHAR));
752  if (value == NULL)
753    return ESR_SUCCESS;
754  newValue = MALLOC(sizeof(size_t), MTAG);
755  if (newValue == NULL)
756  {
757    rc = ESR_OUT_OF_MEMORY;
758    goto CLEANUP;
759  }
760  CHKLOG(rc, lstrtosize_t(value, newValue, 10));
761  CHKLOG(rc, self->setProperty(self, key, newValue, TYPES_SIZE_T));
762  FREE(value);
763  return ESR_SUCCESS;
764CLEANUP:
765  if (newValue != NULL)
766    FREE(newValue);
767  return rc;
768}
769
770ESR_ReturnCode ESR_SessionTypeConvertToFloatImpl(ESR_SessionType* self,
771    const LCHAR* key)
772{
773  LCHAR* value;
774  float *newValue = NULL;
775  ESR_ReturnCode rc;
776
777  CHK(rc, self->getProperty(self, key, (void **)&value, TYPES_PLCHAR));
778  if (value == NULL)
779    return ESR_SUCCESS;
780  newValue = MALLOC(sizeof(double), MTAG);
781  if (newValue == NULL)
782  {
783    rc = ESR_OUT_OF_MEMORY;
784    goto CLEANUP;
785  }
786  CHKLOG(rc, lstrtof(value, newValue));
787  CHKLOG(rc, self->setProperty(self, key, newValue, TYPES_FLOAT));
788  FREE(value);
789  return ESR_SUCCESS;
790CLEANUP:
791  if (newValue != NULL)
792    FREE(newValue);
793  return rc;
794}
795
796ESR_ReturnCode ESR_SessionTypeConvertToBoolImpl(ESR_SessionType* self,
797    const LCHAR* key)
798{
799  LCHAR* value;
800  ESR_BOOL *newValue = NULL;
801  ESR_ReturnCode rc;
802
803  CHK(rc, self->getProperty(self, key, (void **)&value, TYPES_PLCHAR));
804  if (value == NULL)
805    return ESR_SUCCESS;
806  newValue = MALLOC(sizeof(ESR_BOOL), MTAG);
807  if (newValue == NULL)
808  {
809    rc = ESR_OUT_OF_MEMORY;
810    goto CLEANUP;
811  }
812  rc = lstrtob(value, newValue);
813  if (rc != ESR_SUCCESS)
814  {
815    FREE(newValue);
816    return rc;
817  }
818  rc = self->setProperty(self, key, newValue, TYPES_BOOL);
819  if (rc != ESR_SUCCESS)
820  {
821    FREE(newValue);
822    return rc;
823  }
824  FREE(value);
825  return ESR_SUCCESS;
826CLEANUP:
827  if (newValue != NULL)
828    FREE(newValue);
829  return rc;
830}
831
832/**
833 * Imports file containing [key, value] pairs into session.
834 *
835 * @param self ESR_SessionType handle
836 * @param filename File to read session from
837 * @param addMapping Function used to map keys to their type and add them to the session
838 * @param data Data used by the mapping function
839 */
840static ESR_ReturnCode importKeyValueFile(ESR_SessionType* self,
841    const LCHAR* filename,
842    ESR_ReturnCode(*addMapping)(ESR_SessionType* self, const LCHAR* key, LCHAR* value, void* data),
843    void* data)
844{
845  const size_t LINE_SIZE = 512;
846  LCHAR key[512];
847  LCHAR buffer[512];
848  LCHAR* value;
849  LCHAR* ending;
850  LCHAR* line;
851  PFile* file = NULL;
852  ESR_BOOL lineSpan = ESR_FALSE;
853  LString* valueBuffer = NULL;
854  ESR_ReturnCode rc = ESR_SUCCESS;
855
856  if (filename == NULL)
857    return ESR_INVALID_ARGUMENT;
858
859  file = pfopen ( filename, L("r") );
860/*  CHKLOG(rc, PFileSystemCreatePFile(filename, ESR_TRUE, &file));
861  CHKLOG(rc, PFileOpen(file, L("r")));*/
862
863  if (file == NULL)
864  {
865    LCHAR msg[P_PATH_MAX + 30];
866    LCHAR cwd[P_PATH_MAX];
867    size_t len;
868
869    len = P_PATH_MAX;
870    CHKLOG(rc, pf_get_cwd (cwd, &len));
871    psprintf(msg, L("ESR_OPEN_FILE_ERROR(filename=%s, cwd=%s)"), filename, cwd);
872    rc = ESR_OPEN_ERROR;
873    PLogError(msg);
874    goto CLEANUP;
875  }
876
877  rc = LStringCreate(&valueBuffer);
878  if (rc != ESR_SUCCESS)
879    goto CLEANUP;
880
881  line = buffer;
882  while (ESR_TRUE)
883  {
884    line = pfgets(line, LINE_SIZE, file);
885    if (line == NULL)
886    {
887      if (pfeof(file))
888        break;
889      rc = ESR_READ_ERROR;
890      PLogError(ESR_rc2str(rc));
891      goto CLEANUP;
892    }
893    if (LSTRLEN(line) == LINE_SIZE)
894    {
895      PLogError(L("%s: line surpasses %d character limit: '%s'"), filename, line);
896      continue;
897    }
898    lstrtrim(line);
899    if (LSTRLEN(line) == 0 || line[0] == '#')
900      continue;
901
902    if (!lineSpan)
903    {
904      if (rc != ESR_SUCCESS) goto CLEANUP;
905
906      /* locate the key and value pair */
907      ending = LSTRCHR(line, '=');
908      if (ending == NULL)
909      {
910        fprintf(stderr, "Missing equal sign on line '%s'\n", line);
911        continue;
912      }
913      *ending = L('\0');
914      value = ending + 1;
915    }
916    else
917      value = line;
918
919    /* Optionally use ';' to denote end of value */
920    ending = LSTRCHR(value, L(';'));
921    if (ending != NULL)
922      *ending = L('\0');
923    else
924    {
925      ending = LSTRCHR(value, L('\n'));
926      if (ending != NULL)
927        *ending = L('\0');
928    }
929    if (!lineSpan)
930    {
931      LSTRCPY(key, line);
932      lstrtrim(key);
933    }
934    if (LSTRLEN(value) == 0)
935    {
936      pfprintf(PSTDERR, L("Missing value for '%s'\n"), key);
937      continue;
938    }
939    lstrtrim(value);
940    if ((ending = LSTRCHR(value, '\\')) == (value + LSTRLEN(value) - 1))
941    {
942      /* found '\\' at end of line which means data will span to the next line */
943      lineSpan = ESR_TRUE;
944      *ending = L('\0');
945    }
946    else
947      lineSpan = ESR_FALSE;
948    rc = LStringAppend(valueBuffer, value);
949    if (rc != ESR_SUCCESS)
950    {
951      PLogError(ESR_rc2str(rc));
952      goto CLEANUP;
953    }
954    if (!lineSpan)
955    {
956      rc = LStringToLCHAR(valueBuffer, &value);
957      valueBuffer = NULL;
958      if (rc != ESR_SUCCESS)
959      {
960        PLogError(ESR_rc2str(rc));
961        goto CLEANUP;
962      }
963      rc = addMapping(self, key, value, data);
964      if (value != NULL)
965      {
966        FREE(value);
967        value = NULL;
968      }
969      if (rc != ESR_SUCCESS)
970      {
971        PLogError(ESR_rc2str(rc));
972        goto CLEANUP;
973      }
974      rc = LStringCreate(&valueBuffer);
975      if (rc != ESR_SUCCESS)
976      {
977        PLogError(ESR_rc2str(rc));
978        goto CLEANUP;
979      }
980    }
981  }
982
983  if (pferror(file))
984  {
985    rc = ESR_READ_ERROR;
986    PLogError(ESR_rc2str(rc));
987    goto CLEANUP;
988  }
989  if (pfclose(file) != 0)
990  {
991    rc = ESR_CLOSE_ERROR;
992    PLogError(ESR_rc2str(rc));
993    goto CLEANUP;
994  }
995  if (valueBuffer != NULL)
996    LStringDestroy(valueBuffer);
997  return ESR_SUCCESS;
998CLEANUP:
999  if (file != NULL)
1000    pfclose(file);
1001  if (valueBuffer != NULL)
1002    LStringDestroy(valueBuffer);
1003  return rc;
1004}
1005
1006/**
1007 * Appends a collection of integers stored in string format to an IntArrayList.
1008 *
1009 * @param self ESR_SessionType handle
1010 * @param text Text containing integers
1011 * @param list List to be populated
1012 */
1013static ESR_ReturnCode parseIntList(ESR_SessionType* self,
1014                                   LCHAR* text, IntArrayList* list)
1015{
1016  size_t size, pos, beginning;
1017  int value;
1018  ESR_ReturnCode rc;
1019
1020  size = LSTRLEN(text);
1021  pos = 0;
1022  while (ESR_TRUE)
1023  {
1024    /* Scan for beginning of next token */
1025    for (; pos < size && LISSPACE(text[pos]); ++pos);
1026
1027    if (pos >= size)
1028    {
1029      /* Reached end of string while looking for beginning of next token */
1030      break;
1031    }
1032    beginning = pos;
1033
1034    /* Scan for ending of current token */
1035    for (; pos < size && !LISSPACE(text[pos]); ++pos);
1036    text[pos] = L('\0');
1037    CHKLOG(rc, lstrtoi(text + beginning, &value, 10));
1038    CHKLOG(rc, IntArrayListAdd(list, value));
1039    ++pos;
1040  }
1041  return ESR_SUCCESS;
1042CLEANUP:
1043  return rc;
1044}
1045
1046ESR_ReturnCode ESR_SessionTypeGetPropertyTypeImpl(ESR_SessionType* self,
1047    const LCHAR* name, VariableTypes* type)
1048{
1049  ESR_SessionTypeData* data = self->data;
1050  ESR_SessionPair* pair;
1051  ESR_ReturnCode rc;
1052
1053  CHK(rc, HashMapGet(data->value, name, (void **)&pair));
1054  *type = pair->type;
1055  return ESR_SUCCESS;
1056CLEANUP:
1057  return rc;
1058}
1059
1060/**
1061 * Maps key -> type for PAR files.
1062 *
1063 * @param self ESR_Session handle
1064 * @param key Key name
1065 * @param value The value
1066 */
1067static ESR_ReturnCode addParMapping(ESR_SessionType* self,
1068                                    const LCHAR* key, LCHAR* value, void* data)
1069{
1070  IntArrayList* iList;
1071  ESR_ReturnCode rc;
1072  HashMap* map;
1073  VariableTypes* type;
1074  int iValue;
1075  size_t size_tValue;
1076  float fValue;
1077  ESR_BOOL bValue;
1078  ESR_BOOL exists;
1079
1080  map = (HashMap*) data;
1081  rc = HashMapGet(data, key, (void **)&type);
1082  if (rc == ESR_NO_MATCH_ERROR)
1083  {
1084    /* If type is unknown, assume LCHAR* */
1085    PLogMessage(L("Unknown parfile key '%s'"), key);
1086    CHKLOG(rc, self->setLCHAR(self, key, value));
1087  }
1088  else if (rc == ESR_SUCCESS)
1089  {
1090    switch (*type)
1091    {
1092      case TYPES_INT:
1093        CHKLOG(rc, lstrtoi(value, &iValue, 10));
1094        CHKLOG(rc, self->contains(self, key, &exists));
1095        if (exists)
1096          CHKLOG(rc, self->removeAndFreeProperty(self, key));
1097        CHKLOG(rc, self->setInt(self, key, iValue));
1098        break;
1099      case TYPES_UINT16_T:
1100        CHKLOG(rc, lstrtosize_t(value, &size_tValue, 10));
1101        passert(size_tValue >= UINT16_TMIN && size_tValue <= UINT16_TMAX);
1102        CHKLOG(rc, self->contains(self, key, &exists));
1103        if (exists)
1104          CHKLOG(rc, self->removeAndFreeProperty(self, key));
1105        CHKLOG(rc, self->setUint16_t(self, key, (asr_uint16_t) size_tValue));
1106        break;
1107      case TYPES_SIZE_T:
1108        CHKLOG(rc, lstrtosize_t(value, &size_tValue, 10));
1109        CHKLOG(rc, self->contains(self, key, &exists));
1110        if (exists)
1111          CHKLOG(rc, self->removeAndFreeProperty(self, key));
1112        CHKLOG(rc, self->setSize_t(self, key, size_tValue));
1113        break;
1114      case TYPES_FLOAT:
1115        CHKLOG(rc, lstrtof(value, &fValue));
1116        CHKLOG(rc, self->contains(self, key, &exists));
1117        if (exists)
1118          CHKLOG(rc, self->removeAndFreeProperty(self, key));
1119        CHKLOG(rc, self->setFloat(self, key, fValue));
1120        break;
1121      case TYPES_BOOL:
1122        CHKLOG(rc, lstrtob(value, &bValue));
1123        CHKLOG(rc, self->contains(self, key, &exists));
1124        if (exists)
1125          CHKLOG(rc, self->removeAndFreeProperty(self, key));
1126        CHKLOG(rc, self->setBool(self, key, bValue));
1127        break;
1128      case TYPES_INTARRAYLIST:
1129        CHKLOG(rc, self->contains(self, key, &exists));
1130        if (exists)
1131        {
1132          CHKLOG(rc, self->getProperty(self, key, (void **)&iList, TYPES_INTARRAYLIST));
1133          CHKLOG(rc, self->removeProperty(self, key));
1134          CHKLOG(rc, iList->destroy(iList));
1135        }
1136        CHKLOG(rc, IntArrayListCreate(&iList));
1137        CHKLOG(rc, parseIntList(self, value, iList));
1138        CHKLOG(rc, self->setProperty(self, key, iList, TYPES_INTARRAYLIST));
1139        break;
1140      default:
1141        passert(0); /* Unknown variable type. Assuming LCHAR* */
1142      case TYPES_PLCHAR:
1143        CHKLOG(rc, self->contains(self, key, &exists));
1144        if (exists)
1145          CHKLOG(rc, self->removeAndFreeProperty(self, key));
1146        CHKLOG(rc, self->setLCHAR(self, key, value));
1147        break;
1148    }
1149  }
1150  return rc;
1151CLEANUP:
1152  return rc;
1153}
1154
1155ESR_ReturnCode ESR_SessionTypeImportParFileImpl(ESR_SessionType* self,
1156    const LCHAR* filename)
1157{
1158  ESR_ReturnCode rc;
1159  HashMap* parameterList;
1160  VariableTypes Int = TYPES_INT;
1161  VariableTypes UInt16_t = TYPES_UINT16_T;
1162  VariableTypes Float = TYPES_FLOAT;
1163  VariableTypes Bool = TYPES_BOOL;
1164  VariableTypes IntArrayList = TYPES_INTARRAYLIST;
1165  VariableTypes PLChar = TYPES_PLCHAR;
1166  VariableTypes Size_t = TYPES_SIZE_T;
1167
1168  /* Create [key, type] lookup table */
1169  CHKLOG(rc, HashMapCreate(&parameterList));
1170
1171  CHKLOG(rc, parameterList->put(parameterList, "cmdline.arbfile", &PLChar));
1172  CHKLOG(rc, parameterList->put(parameterList, "cmdline.bgsniff", &Size_t));
1173  CHKLOG(rc, parameterList->put(parameterList, "cmdline.channel", &PLChar));
1174  CHKLOG(rc, parameterList->put(parameterList, "cmdline.datapath", &PLChar));
1175  CHKLOG(rc, parameterList->put(parameterList, "cmdline.DataCaptureDirectory", &PLChar));
1176  CHKLOG(rc, parameterList->put(parameterList, "cmdline.detail_res", &PLChar));
1177  CHKLOG(rc, parameterList->put(parameterList, "cmdline.lda", &PLChar));
1178  CHKLOG(rc, parameterList->put(parameterList, "cmdline.modelfiles", &PLChar));
1179  CHKLOG(rc, parameterList->put(parameterList, "cmdline.modelfiles11", &PLChar));
1180  CHKLOG(rc, parameterList->put(parameterList, "cmdline.modelfiles8", &PLChar));
1181  CHKLOG(rc, parameterList->put(parameterList, "cmdline.lda11", &PLChar));
1182  CHKLOG(rc, parameterList->put(parameterList, "cmdline.lda8", &PLChar));
1183  CHKLOG(rc, parameterList->put(parameterList, "cmdline.results", &PLChar));
1184  CHKLOG(rc, parameterList->put(parameterList, "cmdline.rules", &PLChar));
1185  CHKLOG(rc, parameterList->put(parameterList, "cmdline.tcp", &PLChar));
1186  CHKLOG(rc, parameterList->put(parameterList, "cmdline.multable", &PLChar));
1187  CHKLOG(rc, parameterList->put(parameterList, "cmdline.parfile", &PLChar));
1188  CHKLOG(rc, parameterList->put(parameterList, "cmdline.vocabulary", &PLChar));
1189  CHKLOG(rc, parameterList->put(parameterList, "cmdline.use_image", &Int));
1190  CHKLOG(rc, parameterList->put(parameterList, "cmdline.semproc_verbose", &Bool));
1191  CHKLOG(rc, parameterList->put(parameterList, "cmdline.nametagPath", &PLChar));
1192
1193  /* Beginning of speech detection stuff */
1194  CHKLOG(rc, parameterList->put(parameterList, "cmdline.bgsniff_min", &Size_t));
1195  CHKLOG(rc, parameterList->put(parameterList, "cmdline.silence_duration_in_frames", &Size_t));
1196  CHKLOG(rc, parameterList->put(parameterList, "cmdline.end_of_utterance_hold_off_in_frames", &Size_t));
1197  CHKLOG(rc, parameterList->put(parameterList, "cmdline.gatedmode", &Bool));
1198
1199  /* new param from SREC that did not exist in CREC */
1200  CHKLOG(rc, parameterList->put(parameterList, "SREC.Recognizer.utterance_timeout", &Size_t));
1201  CHKLOG(rc, parameterList->put(parameterList, "SREC.Recognizer.osi_log_level", &Size_t));
1202  CHKLOG(rc, parameterList->put(parameterList, "SREC.voice_enroll.bufsz_kB", &Size_t));
1203  CHKLOG(rc, parameterList->put(parameterList, "SREC.voice_enroll.eos_comfort_frames", &Size_t));
1204  CHKLOG(rc, parameterList->put(parameterList, "SREC.voice_enroll.bos_comfort_frames", &Size_t));
1205
1206  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.gdiff.one_nbest", &PLChar));
1207  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.gdiff.many_nbest", &PLChar));
1208  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.sd.one_nbest", &PLChar));
1209  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.sd.many_nbest", &PLChar));
1210  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.sd13.one_nbest", &PLChar));
1211  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.sd13.many_nbest", &PLChar));
1212  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.spf.one_nbest", &PLChar));
1213  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.spf.many_nbest", &PLChar));
1214  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.abs.one_nbest", &PLChar));
1215  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.abs.many_nbest", &PLChar));
1216  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.gdiffpf.one_nbest", &PLChar));
1217  CHKLOG(rc, parameterList->put(parameterList, "SREC.Confidence.sigmoid_param.gdiffpf.many_nbest", &PLChar));
1218
1219  CHKLOG(rc, parameterList->put(parameterList, "CREC.ParVersion", &Float));
1220  CHKLOG(rc, parameterList->put(parameterList, "CREC.useCREClogger", &Int));
1221  CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.dimen", &Int));
1222  CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.skip", &Int));
1223  CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.stay", &Int));
1224  CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.durscale", &Int));
1225  CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.minvar", &Int));
1226  CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.maxvar", &Int));
1227  CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.frame_period", &Int));
1228  CHKLOG(rc, parameterList->put(parameterList, "CREC.Acoustic.load_models", &PLChar));
1229  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.mel_dim", &Int));
1230  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.samplerate", &Size_t));
1231  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.premel", &Float));
1232  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.lowcut", &Int));
1233  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.highcut", &Int));
1234  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.window_factor", &Float));
1235  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.offset", &Float));
1236  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.ddmel", &Bool));
1237  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.peakdecayup", &Float));
1238  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.peakdecaydown", &Float));
1239  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.do_skip_even_frames", &Bool));
1240  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.do_smooth_c0", &Bool));
1241  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.melA", &IntArrayList));
1242  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.melB", &IntArrayList));
1243  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.dmelA", &IntArrayList));
1244  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.dmelB", &IntArrayList));
1245  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.ddmelA", &IntArrayList));
1246  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.ddmelB", &IntArrayList));
1247
1248  /* new for S2G 3 (read from parfile instead of hardcoding) */
1249  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.cmn", &IntArrayList));
1250  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.cmn8", &IntArrayList));
1251  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.cmn11", &IntArrayList));
1252  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.tmn", &IntArrayList));
1253  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.adjust", &IntArrayList));
1254  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.debug", &Bool));
1255  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.sbindex", &IntArrayList));
1256  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.forget_factor", &IntArrayList));
1257  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.cache_resolution", &IntArrayList));
1258  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.inutt.forget_factor2", &IntArrayList));
1259  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.inutt.disable_after", &IntArrayList));
1260  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.inutt.enable_after", &IntArrayList));
1261
1262
1263  /* zwz */
1264  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.swicms.do_VN", &Bool));
1265
1266  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.speech_detect", &Int));
1267  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.ambient_within", &Int));
1268  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.speech_above", &Int));
1269  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.start_windback", &Int));
1270  CHKLOG(rc, parameterList->put(parameterList, "CREC.Frontend.utterance_allowance", &Int));
1271
1272
1273  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.dimen", &Int));
1274  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.whole_dimen", &Int));
1275  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.mix_score_scale", &Float));
1276  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.start", &Int));
1277  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.chelt_imelda", &Bool));
1278  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.vfrlimit", &Bool));
1279  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.vfrthresh", &Bool));
1280  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.mix_score_scale", &Float));
1281  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.imelda_scale", &Float));
1282  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.uni_score_scale", &Float));
1283  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.uni_score_offset", &Float));
1284  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.forget_speech", &Int));
1285  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.forget_background", &Int));
1286  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.rel_low", &Int));
1287  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.rel_high", &Int));
1288  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.gap_period", &Int));
1289  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.click_period", &Int));
1290  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.breath_period", &Int));
1291  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.extend_annotation", &Int));
1292  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.min_initial_quiet_frames", &Int));
1293  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.min_annotation_frames", &Int));
1294  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.min_initial_quiet_frames", &Int));
1295  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.max_annotation_frames", &Int));
1296  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.delete_leading_segments", &Int));
1297  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.leading_segment_min_frames", &Int));
1298  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.leading_segment_max_frames", &Int));
1299  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.leading_segment_min_silence_gap_frames", &Int));
1300  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.leading_segment_accept_if_not_found", &Int));
1301  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.snr_holdoff", &Int));
1302  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.min_acceptable_snr", &Int));
1303  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.param", &Int));
1304  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.beep_size", &Int));
1305  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.beep_threshold", &Int));
1306  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.partial_distance_dim", &Int));
1307  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.partial_distance_threshold", &Int));
1308  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.partial_distance_offset", &Int));
1309  CHKLOG(rc, parameterList->put(parameterList, "CREC.Pattern.global_model_means", &IntArrayList));
1310
1311  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.NBest", &Int));
1312  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.reject", &Int));
1313  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.often", &Int));
1314  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.partial_results", &Bool));
1315  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.wordpen", &Int));
1316  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.viterbi_prune_thresh", &Int));
1317  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_hmm_tokens", &Int));
1318  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_fsmnode_tokens", &Int));
1319  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_word_tokens", &Int));
1320  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_altword_tokens", &Int));
1321  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.num_wordends_per_frame", &Int));
1322  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_fsm_nodes", &Int));
1323  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_fsm_arcs", &Int));
1324  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_searches", &Int));
1325  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.terminal_timeout", &Int));
1326  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.optional_terminal_timeout", &Int));
1327  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.non_terminal_timeout", &Int));
1328  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.eou_threshold", &Int));
1329  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_frames", &Int));
1330  CHKLOG(rc, parameterList->put(parameterList, "CREC.Recognizer.max_model_states", &Int));
1331  CHKLOG(rc, parameterList->put(parameterList, "thread.priority", &UInt16_t));
1332  /* for G2P */
1333  CHKLOG(rc, parameterList->put(parameterList, "G2P.Available", &Bool));
1334  CHKLOG(rc, parameterList->put(parameterList, "G2P.Data", &PLChar));
1335  CHKLOG(rc, parameterList->put(parameterList, "G2P.Dictionary", &PLChar));
1336  /* Enable Get Waveform */
1337  CHKLOG(rc, parameterList->put(parameterList, "enableGetWaveform", &Bool));
1338
1339  rc = importKeyValueFile(self, filename, addParMapping, parameterList);
1340  if (rc != ESR_SUCCESS)
1341    goto CLEANUP;
1342  CHKLOG(rc, HashMapDestroy(parameterList));
1343  return ESR_SUCCESS;
1344CLEANUP:
1345  HashMapDestroy(parameterList);
1346  return rc;
1347}
1348
1349ESR_ReturnCode ESR_SessionTypeAddListenerImpl(ESR_SessionType* self, ESR_SessionTypeListenerPair* listener)
1350{
1351  ESR_SessionTypeData* data = self->data;
1352  ArrayList* listeners = data->listeners;
1353  ESR_ReturnCode rc;
1354
1355  CHKLOG(rc, listeners->add(listeners, listener));
1356  return ESR_SUCCESS;
1357CLEANUP:
1358  return rc;
1359}
1360
1361ESR_ReturnCode ESR_SessionTypeRemoveListenerImpl(ESR_SessionType* self, ESR_SessionTypeListenerPair* listener)
1362{
1363  ESR_SessionTypeData* data = self->data;
1364  ArrayList* listeners = data->listeners;
1365  ESR_ReturnCode rc;
1366
1367  CHKLOG(rc, listeners->remove(listeners, listener));
1368  return ESR_SUCCESS;
1369CLEANUP:
1370  return rc;
1371}
1372
1373ESR_ReturnCode ESR_SessionTypeDestroyImpl(ESR_SessionType* self)
1374{
1375  ESR_SessionTypeData* data = self->data;
1376  size_t hashSize;
1377  ESR_SessionPair* pair;
1378  ESR_ReturnCode rc;
1379
1380  if (data != NULL)
1381  {
1382    if (data->value != NULL)
1383    {
1384      CHKLOG(rc, HashMapGetSize(data->value, &hashSize));
1385      while (hashSize > 0)
1386      {
1387        CHKLOG(rc, HashMapGetValueAtIndex(data->value, 0, (void **)&pair));
1388
1389        if (pair->value)
1390        {
1391          if (pair->type == TYPES_INTARRAYLIST)
1392            CHKLOG(rc, IntArrayListDestroy((IntArrayList*) pair->value));
1393          else
1394            FREE(pair->value);
1395        }
1396        CHKLOG(rc, HashMapRemoveAtIndex(data->value, 0));
1397        --hashSize;
1398        FREE(pair);
1399      }
1400
1401      CHKLOG(rc, HashMapDestroy(data->value));
1402      data->value = NULL;
1403    }
1404    if (data->listeners != NULL)
1405    {
1406      CHKLOG(rc, data->listeners->destroy(data->listeners));
1407      data->listeners = NULL;
1408    }
1409    FREE(data);
1410  }
1411
1412  FREE(self);
1413  return ESR_SUCCESS;
1414CLEANUP:
1415  return rc;
1416}
1417