[Feature] add GA346 baseline version
Change-Id: Ic62933698569507dcf98240cdf5d9931ae34348f
diff --git a/src/multimedia/audio-tuning/audio-xml-parser/audio_big_sw/AudioParamTreeView.c b/src/multimedia/audio-tuning/audio-xml-parser/audio_big_sw/AudioParamTreeView.c
new file mode 100644
index 0000000..13b9c1e
--- /dev/null
+++ b/src/multimedia/audio-tuning/audio-xml-parser/audio_big_sw/AudioParamTreeView.c
@@ -0,0 +1,399 @@
+// SPDX-License-Identifier: MediaTekProprietary
+/* MediaTek Inc. (C) 2016. All rights reserved.
+ *
+ * Copyright Statement:
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ */
+
+/*
+ * Description:
+ * Implement ParamTreeView related APIs
+ */
+
+#include "AudioParamParserPriv.h"
+
+EXPORT ParamTreeView *paramTreeViewCreate(AudioType *audioType, int verMaj, int verMin) {
+ ParamTreeView *paramTreeView = malloc(sizeof(ParamTreeView));
+ if (!paramTreeView) {
+ ERR_LOG("malloc fail!\n");
+ return NULL;
+ }
+
+ paramTreeView->audioType = audioType;
+ paramTreeView->verMaj = verMaj;
+ paramTreeView->verMin = verMin;
+ paramTreeView->treeRootHash = NULL;
+ return paramTreeView;
+}
+
+EXPORT void paramTreeViewRelease(ParamTreeView *paramTreeView) {
+ if (paramTreeView) {
+ if (paramTreeView->treeRootHash) {
+ TreeRoot *tmp = NULL, *item = NULL;
+ HASH_ITER(hh, paramTreeView->treeRootHash, item, tmp) {
+ if (paramTreeView->treeRootHash) {
+ HASH_DEL(paramTreeView->treeRootHash, item);
+ treeRootRelease(item);
+ }
+ }
+ }
+ free(paramTreeView);
+ }
+}
+
+EXPORT TreeRoot *treeRootCreate(const char *name, xmlNode *treeRootNode, ParamTreeView *paramTreeView) {
+ TreeRoot *treeRoot = malloc(sizeof(TreeRoot));
+ if (!treeRoot) {
+ ERR_LOG("malloc fail!\n");
+ return NULL;
+ }
+
+ treeRoot->name = strdup(name);
+ treeRoot->treeRootNode = treeRootNode;
+ treeRoot->paramTreeView = paramTreeView;
+ treeRoot->featureHash = NULL;
+ treeRoot->switchFieldInfo = NULL;
+ return treeRoot;
+}
+
+EXPORT void treeRootRelease(TreeRoot *treeRoot) {
+ if (treeRoot) {
+ if (treeRoot->featureHash) {
+ Feature *tmp = NULL, *item = NULL;
+ HASH_ITER(hh, treeRoot->featureHash, item, tmp) {
+ if (treeRoot->featureHash) {
+ HASH_DEL(treeRoot->featureHash, item);
+ featureRelease(item);
+ }
+ }
+ }
+
+ free(treeRoot->name);
+ free(treeRoot);
+ }
+}
+
+EXPORT Feature *featureCreate(const char *name, AudioType *audioType, FieldInfo *switchFieldInfo, const char *featureOption) {
+ Feature *feature = malloc(sizeof(Feature));
+ if (!feature) {
+ ERR_LOG("malloc fail!\n");
+ return NULL;
+ }
+
+ feature->name = strdup(name);
+ feature->audioType = audioType;
+
+ if (featureOption) {
+ feature->featureOption = strdup(featureOption);
+ } else {
+ feature->featureOption = NULL;
+ }
+
+ feature->categoryPathHash = NULL;
+ feature->featureFieldHash = NULL;
+ feature->switchFieldInfo = switchFieldInfo;
+ return feature;
+}
+
+EXPORT void featureRelease(Feature *feature) {
+ if (feature) {
+ if (feature->categoryPathHash) {
+ CategoryPath *tmp = NULL, *item = NULL;
+ HASH_ITER(hh, feature->categoryPathHash, item, tmp) {
+ if (feature->categoryPathHash) {
+ HASH_DEL(feature->categoryPathHash, item);
+ categoryPathRelease(item);
+ }
+ }
+ }
+
+ if (feature->featureFieldHash) {
+ FeatureField *tmp, *item;
+ HASH_ITER(hh, feature->featureFieldHash, item, tmp) {
+ if (feature->featureFieldHash) {
+ HASH_DEL(feature->featureFieldHash, item);
+ featureFieldRelease(item);
+ }
+ }
+ }
+
+ if (feature->name) {
+ free(feature->name);
+ }
+
+ if (feature->featureOption) {
+ free(feature->featureOption);
+ }
+
+ free(feature);
+ }
+}
+
+EXPORT APP_STATUS categoryPathValidation(CategoryPath *categoryPath) {
+ char *path = NULL;
+ char *categoryGroup = NULL;
+ char *restOfStr = NULL;
+
+ if (!strncmp(categoryPath->path, "", strlen("") + 1)) {
+ return APP_NO_ERROR;
+ }
+
+ path = strdup(categoryPath->path);
+ categoryGroup = utilStrtok(path, ARRAY_SEPERATOR, &restOfStr);
+ if (categoryGroup == NULL || audioTypeValidCategoryGroupName(categoryPath->feature->audioType, categoryGroup) == APP_ERROR) {
+ free(path);
+ return APP_ERROR;
+ }
+
+ while ((categoryGroup = utilStrtok(NULL, ARRAY_SEPERATOR, &restOfStr)) != NULL) {
+ if (audioTypeValidCategoryGroupName(categoryPath->feature->audioType, categoryGroup) == APP_ERROR) {
+ free(path);
+ return APP_ERROR;
+ }
+ }
+
+ free(path);
+ return APP_NO_ERROR;
+}
+
+EXPORT CategoryPath *categoryPathCreate(Feature *feature, const char *path) {
+ CategoryPath *categoryPath = malloc(sizeof(CategoryPath));
+ if (!categoryPath) {
+ ERR_LOG("malloc fail!\n");
+ return NULL;
+ }
+
+ categoryPath->path = strdup(path);
+ categoryPath->feature = feature;
+
+#ifdef WIN32
+ /* The category path validation only run on win32 */
+ if (categoryPathValidation(categoryPath) == APP_ERROR) {
+ ERR_LOG("The %s feature's category path is not belong to categoryGroup! (%s)\n", feature->name, categoryPath->path);
+ categoryPathRelease(categoryPath);
+ return NULL;
+ }
+#endif
+
+ return categoryPath;
+}
+
+EXPORT void categoryPathRelease(CategoryPath *categoryPath) {
+ if (categoryPath) {
+ free(categoryPath->path);
+ free(categoryPath);
+ }
+}
+
+EXPORT FeatureField *featureFieldCreate(FieldInfo *fieldInfo) {
+ FeatureField *featureField = malloc(sizeof(FeatureField));
+ if (!featureField) {
+ ERR_LOG("malloc fail!\n");
+ return NULL;
+ }
+
+ featureField->fieldInfo = fieldInfo;
+
+ return featureField;
+}
+
+EXPORT void featureFieldRelease(FeatureField *featureField) {
+ if (featureField) {
+ free(featureField);
+ }
+}
+
+EXPORT Feature *treeRootGetFeatureByName(TreeRoot *treeRoot, const char *featureName) {
+ Feature *feature = NULL;
+ HASH_FIND_STR(treeRoot->featureHash, featureName, feature);
+ return feature;
+}
+
+CategoryPath *findFeatureCategoryPath(char **arr, int *Switch, int n, Feature *feature) {
+ CategoryPath *categoryPath = NULL;
+ UT_string *path = NULL;
+ int i = 0;
+
+ /* Generate the search string */
+ utstring_new(path);
+ for (i = 0; i < n; ++i) {
+ if (i == n - 1) {
+ utstring_printf(path, "%s", arr[Switch[i]]);
+ } else {
+ utstring_printf(path, "%s,", arr[Switch[i]]);
+ }
+ }
+
+ /* Find the categoryPath */
+ HASH_FIND_STR(feature->categoryPathHash, utstring_body(path), categoryPath);
+ DEBUG_LOG("Search path = %s, paramTree = 0x%p\n", utstring_body(path), categoryPath);
+
+ utstring_free(path);
+ return categoryPath;
+}
+
+CategoryPath *fuzzySearchFeatureCategoryPath(char **arr, int totalSize, int pickSize, Feature *feature) {
+ CategoryPath *categoryPath = NULL;
+ int i = 0, j = 0, pos = pickSize - 1;
+ int *swpArray = NULL;
+
+ if (pickSize > totalSize) {
+ return categoryPath;
+ }
+
+ swpArray = (int *)malloc(sizeof(int) * totalSize);
+ if (!swpArray) {
+ ERR_LOG("malloc fail!\n");
+ return NULL;
+ }
+
+ for (i = 0; i < totalSize; ++i) {
+ swpArray[i] = i;
+ }
+
+ categoryPath = findFeatureCategoryPath(arr, swpArray, pickSize, feature);
+ if (categoryPath) {
+ free(swpArray);
+ return categoryPath;
+ }
+
+ do {
+ if (swpArray[pickSize - 1] == totalSize - 1) {
+ --pos;
+ } else {
+ pos = pickSize - 1;
+ }
+
+ ++swpArray[pos];
+
+ for (j = pos + 1; j < pickSize; ++j) {
+ swpArray[j] = swpArray[j - 1] + 1;
+ }
+
+ categoryPath = findFeatureCategoryPath(arr, swpArray, pickSize, feature);
+ if (categoryPath) {
+ free(swpArray);
+ return categoryPath;
+ }
+
+ } while (swpArray[0] < totalSize - pickSize);
+
+ free(swpArray);
+ return categoryPath;
+}
+
+CategoryPath *searchFeatureCategoryPath(Feature *feature, const char *categoryPath) {
+ CategoryPath *featureCategoryPath = NULL;
+ char **categoryArray = NULL;
+ char *category = NULL;
+ char *tmpStr = NULL;
+ char *restOfStr = NULL;
+ size_t numOfCategoryType = 0;
+ size_t numOfCategory = 0;
+ size_t i = 0;
+
+ DEBUG_LOG("+Feature = %s, categoryPath = %s\n", feature->name, categoryPath);
+
+ /* Full path search first */
+ HASH_FIND_STR(feature->categoryPathHash, categoryPath, featureCategoryPath);
+ if (featureCategoryPath) {
+ DEBUG_LOG("fuzzySearch paramTree found. (path = %s)\n", featureCategoryPath->path);
+ return featureCategoryPath;
+ } else if (!strncmp(categoryPath, "", strlen("") + 1)) {
+ return NULL;
+ }
+
+ /* Setup array for fuzzy search path enum */
+ numOfCategoryType = audioTypeGetNumOfCategoryType(feature->audioType);
+ if (numOfCategoryType > 0) {
+ categoryArray = calloc(1, sizeof(char *) * numOfCategoryType);
+ if (NULL == categoryArray) {
+ ERR_LOG("allocate working buf fail");
+ return NULL;
+ }
+ }
+
+ if (categoryArray) {
+ tmpStr = strdup(categoryPath ? categoryPath : "");
+ category = utilStrtok(tmpStr, ARRAY_SEPERATOR, &restOfStr);
+ if (!category) {
+ ERR_LOG("Cannot parse category\n");
+ free(categoryArray);
+ free(tmpStr);
+ return NULL;
+ }
+ categoryArray[i++] = category;
+
+ while ((category = utilStrtok(NULL, ARRAY_SEPERATOR, &restOfStr)) != NULL) {
+ categoryArray[i++] = category;
+ }
+ numOfCategory = i;
+
+ /* Fuzzy search */
+ for (i = 1; i < numOfCategory; i++) {
+ featureCategoryPath = fuzzySearchFeatureCategoryPath(categoryArray, numOfCategory, numOfCategory - i, feature);
+ if (featureCategoryPath) {
+ break;
+ }
+ }
+
+ if (!featureCategoryPath) {
+ /* If no paramTree found, try to get the root paramTree */
+ UT_string *path = NULL;
+ utstring_new(path);
+ utstring_printf(path, "%s", "");
+ HASH_FIND_STR(feature->categoryPathHash, utstring_body(path), featureCategoryPath);
+ utstring_free(path);
+ }
+
+ free(categoryArray);
+ free(tmpStr);
+ }
+
+ DEBUG_LOG("-fuzzySearch featureCategoryPath %s found. \n", featureCategoryPath ? "" : "not ");
+ return featureCategoryPath;
+}
+
+EXPORT int featureIsCategoryPathSupport(Feature *feature, const char *categoryPath) {
+ /* Get the category path */
+ CategoryPath *featureCategoryPath = NULL;
+ UT_string *searchPath = NULL;
+
+ if (!feature) {
+ ERR_LOG("feature is NULL\n");
+ return 0;
+ }
+
+ if (!categoryPath) {
+ ERR_LOG("categoryPath is NULL\n");
+ return 0;
+ }
+
+ /* Check if feature support all categoryPath first */
+ featureCategoryPath = searchFeatureCategoryPath(feature, "");
+ if (featureCategoryPath) {
+ return 1;
+ }
+
+ searchPath = utilNormalizeCategoryGroupPathForAudioType(categoryPath, feature->audioType);
+ if (!searchPath) {
+ ERR_LOG("Cannot normalize categoryPath for %s AudioType. (path = %s)\n", feature->audioType->name, categoryPath);
+ return 0;
+ }
+
+ /* Search the feature's category path */
+ featureCategoryPath = searchFeatureCategoryPath(feature, utstring_body(searchPath));
+ utstring_free(searchPath);
+
+ if (featureCategoryPath) {
+ return 1;
+ } else {
+ return 0;
+ }
+}