blob: 91268e59b3f84b6b81a307e7c1ade2d8da1acced [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/* MediaTek Inc. (C) 2016. All rights reserved.
2 *
3 * Copyright Statement:
4 * This software/firmware and related documentation ("MediaTek Software") are
5 * protected under relevant copyright laws. The information contained herein is
6 * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
7 * the prior written permission of MediaTek inc. and/or its licensors, any
8 * reproduction, modification, use or disclosure of MediaTek Software, and
9 * information contained herein, in whole or in part, shall be strictly
10 * prohibited.
11 */
12
13/*
14 * Description:
15 * Implement ParamTreeView related APIs
16 */
17
18#include "AudioParamParserPriv.h"
19
20EXPORT ParamTreeView *paramTreeViewCreate(AudioType *audioType, int verMaj, int verMin) {
21 ParamTreeView *paramTreeView = malloc(sizeof(ParamTreeView));
22 paramTreeView->audioType = audioType;
23 paramTreeView->verMaj = verMaj;
24 paramTreeView->verMin = verMin;
25 paramTreeView->treeRootHash = NULL;
26 return paramTreeView;
27}
28
29EXPORT void paramTreeViewRelease(ParamTreeView *paramTreeView) {
30 if (paramTreeView) {
31 if (paramTreeView->treeRootHash) {
32 TreeRoot *tmp, *item;
33 HASH_ITER(hh, paramTreeView->treeRootHash, item, tmp) {
34 HASH_DEL(paramTreeView->treeRootHash, item);
35 treeRootRelease(item);
36 }
37 }
38 free(paramTreeView);
39 }
40}
41
42EXPORT TreeRoot *treeRootCreate(const char *name, xmlNode *treeRootNode, ParamTreeView *paramTreeView) {
43 TreeRoot *treeRoot = malloc(sizeof(TreeRoot));
44 treeRoot->name = strdup(name);
45 treeRoot->treeRootNode = treeRootNode;
46 treeRoot->paramTreeView = paramTreeView;
47 treeRoot->featureHash = NULL;
48 treeRoot->switchFieldInfo = NULL;
49 return treeRoot;
50}
51
52EXPORT void treeRootRelease(TreeRoot *treeRoot) {
53 if (treeRoot) {
54 if (treeRoot->featureHash) {
55 Feature *tmp, *item;
56 HASH_ITER(hh, treeRoot->featureHash, item, tmp) {
57 HASH_DEL(treeRoot->featureHash, item);
58 featureRelease(item);
59 }
60 }
61
62 free(treeRoot->name);
63 free(treeRoot);
64 }
65}
66
67EXPORT Feature *featureCreate(const char *name, AudioType *audioType, FieldInfo *switchFieldInfo, const char *featureOption) {
68 Feature *feature = malloc(sizeof(Feature));
69 feature->name = strdup(name);
70 feature->audioType = audioType;
71
72 if (featureOption) {
73 feature->featureOption = strdup(featureOption);
74 } else {
75 feature->featureOption = NULL;
76 }
77
78 feature->categoryPathHash = NULL;
79 feature->featureFieldHash = NULL;
80 feature->switchFieldInfo = switchFieldInfo;
81 return feature;
82}
83
84EXPORT void featureRelease(Feature *feature) {
85 if (feature) {
86 if (feature->categoryPathHash) {
87 CategoryPath *tmp, *item;
88 HASH_ITER(hh, feature->categoryPathHash, item, tmp) {
89 HASH_DEL(feature->categoryPathHash, item);
90 categoryPathRelease(item);
91 }
92 }
93
94 if (feature->featureFieldHash) {
95 FeatureField *tmp, *item;
96 HASH_ITER(hh, feature->featureFieldHash, item, tmp) {
97 HASH_DEL(feature->featureFieldHash, item);
98 featureFieldRelease(item);
99 }
100 }
101
102 if (feature->name) {
103 free(feature->name);
104 }
105
106 if (feature->featureOption) {
107 free(feature->featureOption);
108 }
109
110 free(feature);
111 }
112}
113
114EXPORT APP_STATUS categoryPathValidation(CategoryPath *categoryPath) {
115 char *path;
116 char *categoryGroup;
117 char *restOfStr = NULL;
118
119 if (!strncmp(categoryPath->path, "", strlen("") + 1)) {
120 return APP_NO_ERROR;
121 }
122
123 path = strdup(categoryPath->path);
124 categoryGroup = utilStrtok(path, ARRAY_SEPERATOR, &restOfStr);
125 if (categoryGroup == NULL || audioTypeValidCategoryGroupName(categoryPath->feature->audioType, categoryGroup) == APP_ERROR) {
126 free(path);
127 return APP_ERROR;
128 }
129
130 while ((categoryGroup = utilStrtok(NULL, ARRAY_SEPERATOR, &restOfStr)) != NULL) {
131 if (audioTypeValidCategoryGroupName(categoryPath->feature->audioType, categoryGroup) == APP_ERROR) {
132 free(path);
133 return APP_ERROR;
134 }
135 }
136
137 free(path);
138 return APP_NO_ERROR;
139}
140
141EXPORT CategoryPath *categoryPathCreate(Feature *feature, const char *path) {
142 CategoryPath *categoryPath = malloc(sizeof(CategoryPath));
143 categoryPath->path = strdup(path);
144 categoryPath->feature = feature;
145
146#ifdef WIN32
147 /* The category path validation only run on win32 */
148 if (categoryPathValidation(categoryPath) == APP_ERROR) {
149 ERR_LOG("The %s feature's category path is not belong to categoryGroup! (%s)\n", feature->name, categoryPath->path);
150 categoryPathRelease(categoryPath);
151 return NULL;
152 }
153#endif
154
155 return categoryPath;
156}
157
158EXPORT void categoryPathRelease(CategoryPath *categoryPath) {
159 if (categoryPath) {
160 free(categoryPath->path);
161 free(categoryPath);
162 }
163}
164
165EXPORT FeatureField *featureFieldCreate(FieldInfo *fieldInfo) {
166 FeatureField *featureField = malloc(sizeof(FeatureField));
167 featureField->fieldInfo = fieldInfo;
168
169 return featureField;
170}
171
172EXPORT void featureFieldRelease(FeatureField *featureField) {
173 if (featureField) {
174 free(featureField);
175 }
176}
177
178EXPORT Feature *treeRootGetFeatureByName(TreeRoot *treeRoot, const char *featureName) {
179 Feature *feature;
180 HASH_FIND_STR(treeRoot->featureHash, featureName, feature);
181 return feature;
182}
183
184CategoryPath *findFeatureCategoryPath(char **arr, int *Switch, int n, Feature *feature) {
185 CategoryPath *categoryPath = NULL;
186 UT_string *path = NULL;
187 int i;
188
189 /* Generate the search string */
190 utstring_new(path);
191 for (i = 0; i < n; ++i) {
192 if (i == n - 1) {
193 utstring_printf(path, "%s", arr[Switch[i]]);
194 } else {
195 utstring_printf(path, "%s,", arr[Switch[i]]);
196 }
197 }
198
199 /* Find the categoryPath */
200 HASH_FIND_STR(feature->categoryPathHash, utstring_body(path), categoryPath);
201 DEBUG_LOG("Search path = %s, paramTree = 0x%p\n", utstring_body(path), categoryPath);
202
203 utstring_free(path);
204 return categoryPath;
205}
206
207CategoryPath *fuzzySearchFeatureCategoryPath(char **arr, int totalSize, int pickSize, Feature *feature) {
208 CategoryPath *categoryPath = NULL;
209 int i, j, pos = pickSize - 1;
210 int *swpArray;
211
212 if (pickSize > totalSize) {
213 return categoryPath;
214 }
215
216 swpArray = (int *)malloc(sizeof(int) * totalSize);
217
218 for (i = 0; i < totalSize; ++i) {
219 swpArray[i] = i;
220 }
221
222 categoryPath = findFeatureCategoryPath(arr, swpArray, pickSize, feature);
223 if (categoryPath) {
224 free(swpArray);
225 return categoryPath;
226 }
227
228 do {
229 if (swpArray[pickSize - 1] == totalSize - 1) {
230 --pos;
231 } else {
232 pos = pickSize - 1;
233 }
234
235 ++swpArray[pos];
236
237 for (j = pos + 1; j < pickSize; ++j) {
238 swpArray[j] = swpArray[j - 1] + 1;
239 }
240
241 categoryPath = findFeatureCategoryPath(arr, swpArray, pickSize, feature);
242 if (categoryPath) {
243 free(swpArray);
244 return categoryPath;
245 }
246
247 } while (swpArray[0] < totalSize - pickSize);
248
249 free(swpArray);
250 return categoryPath;
251}
252
253CategoryPath *searchFeatureCategoryPath(Feature *feature, const char *categoryPath) {
254 CategoryPath *featureCategoryPath;
255 char **categoryArray;
256 char *category;
257 char *tmpStr;
258 char *restOfStr = NULL;
259 size_t numOfCategoryType;
260 size_t numOfCategory;
261 size_t i = 0;
262
263 DEBUG_LOG("+Feature = %s, categoryPath = %s\n", feature->name, categoryPath);
264
265 /* Full path search first */
266 HASH_FIND_STR(feature->categoryPathHash, categoryPath, featureCategoryPath);
267 if (featureCategoryPath) {
268 DEBUG_LOG("fuzzySearch paramTree found. (path = %s)\n", featureCategoryPath->path);
269 return featureCategoryPath;
270 } else if (!strncmp(categoryPath, "", strlen("") + 1)) {
271 return NULL;
272 }
273
274 /* Setup array for fuzzy search path enum */
275 numOfCategoryType = audioTypeGetNumOfCategoryType(feature->audioType);
276 if (numOfCategoryType > 0) {
277 categoryArray = malloc(sizeof(char *) * numOfCategoryType);
278 if (NULL == categoryArray) {
279 ERR_LOG("allocate working buf fail");
280 return NULL;
281 }
282 }
283 tmpStr = strdup(categoryPath ? categoryPath : "");
284 category = utilStrtok(tmpStr, ARRAY_SEPERATOR, &restOfStr);
285 if (!category) {
286 ERR_LOG("Cannot parse category\n");
287 free(categoryArray);
288 free(tmpStr);
289 return NULL;
290 }
291 categoryArray[i++] = category;
292
293 while ((category = utilStrtok(NULL, ARRAY_SEPERATOR, &restOfStr)) != NULL) {
294 categoryArray[i++] = category;
295 }
296 numOfCategory = i;
297
298 /* Fuzzy search */
299 for (i = 1; i < numOfCategory; i++) {
300 featureCategoryPath = fuzzySearchFeatureCategoryPath(categoryArray, numOfCategory, numOfCategory - i, feature);
301 if (featureCategoryPath) {
302 break;
303 }
304 }
305
306 if (!featureCategoryPath) {
307 /* If no paramTree found, try to get the root paramTree */
308 UT_string *path = NULL;
309 utstring_new(path);
310 utstring_printf(path, "%s", "");
311 HASH_FIND_STR(feature->categoryPathHash, utstring_body(path), featureCategoryPath);
312 utstring_free(path);
313 }
314
315 free(categoryArray);
316 free(tmpStr);
317
318 DEBUG_LOG("-fuzzySearch featureCategoryPath %s found. \n", featureCategoryPath ? "" : "not ");
319 return featureCategoryPath;
320}
321
322EXPORT int featureIsCategoryPathSupport(Feature *feature, const char *categoryPath) {
323 /* Get the category path */
324 CategoryPath *featureCategoryPath = NULL;
325 UT_string *searchPath;
326
327 if (!feature) {
328 ERR_LOG("feature is NULL\n");
329 return 0;
330 }
331
332 if (!categoryPath) {
333 ERR_LOG("categoryPath is NULL\n");
334 return 0;
335 }
336
337 /* Check if feature support all categoryPath first */
338 featureCategoryPath = searchFeatureCategoryPath(feature, "");
339 if (featureCategoryPath) {
340 return 1;
341 }
342
343 searchPath = utilNormalizeCategoryGroupPathForAudioType(categoryPath, feature->audioType);
344 if (!searchPath) {
345 ERR_LOG("Cannot normalize categoryPath for %s AudioType. (path = %s)\n", feature->audioType->name, categoryPath);
346 return 0;
347 }
348
349 /* Search the feature's category path */
350 featureCategoryPath = searchFeatureCategoryPath(feature, utstring_body(searchPath));
351 utstring_free(searchPath);
352
353 if (featureCategoryPath) {
354 return 1;
355 } else {
356 return 0;
357 }
358}