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