• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "audio_effect_config_parser.h"
16 #include <libxml/parser.h>
17 #include <libxml/tree.h>
18 
19 namespace OHOS {
20 namespace AudioStandard {
21 static constexpr char AUDIO_EFFECT_CONFIG_FILE[] = "system/etc/audio/audio_effect_config.xml";
22 static const std::string EFFECT_CONFIG_NAME[5] = {"libraries", "effects", "effectChains", "preProcess", "postProcess"};
23 static constexpr int32_t FILE_CONTENT_ERROR = -2;
24 static constexpr int32_t FILE_PARSE_ERROR = -3;
25 static constexpr int32_t INDEX_LIBRARIES = 0;
26 static constexpr int32_t INDEX_EFFECS = 1;
27 static constexpr int32_t INDEX_EFFECTCHAINE = 2;
28 static constexpr int32_t INDEX_PREPROCESS = 3;
29 static constexpr int32_t INDEX_POSTPROCESS = 4;
30 static constexpr int32_t INDEX_EXCEPTION = 5;
31 static constexpr int32_t NODE_SIZE = 6;
32 static constexpr int32_t MODULE_SIZE = 5;
33 
AudioEffectConfigParser()34 AudioEffectConfigParser::AudioEffectConfigParser()
35 {
36     AUDIO_INFO_LOG("AudioEffectConfigParser created");
37 }
38 
~AudioEffectConfigParser()39 AudioEffectConfigParser::~AudioEffectConfigParser()
40 {
41 }
42 
LoadConfigCheck(xmlDoc * doc,xmlNode * currNode)43 static int32_t LoadConfigCheck(xmlDoc* doc, xmlNode* currNode)
44 {
45     if (currNode == nullptr) {
46         AUDIO_ERR_LOG("error: could not parse file %{public}s", AUDIO_EFFECT_CONFIG_FILE);
47         return FILE_PARSE_ERROR;
48     }
49     if (xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("audio_effects_conf"))) {
50         AUDIO_ERR_LOG("Missing tag - audio_effects_conf: %{public}s", AUDIO_EFFECT_CONFIG_FILE);
51         xmlFreeDoc(doc);
52         xmlCleanupParser();
53         return FILE_CONTENT_ERROR;
54     }
55 
56     if (currNode->xmlChildrenNode) {
57         return 0;
58     } else {
59         AUDIO_ERR_LOG("Missing node - audio_effects_conf: %s", AUDIO_EFFECT_CONFIG_FILE);
60         xmlFreeDoc(doc);
61         xmlCleanupParser();
62         return FILE_CONTENT_ERROR;
63     }
64 }
65 
LoadConfigVersion(OriginalEffectConfig & result,xmlNode * currNode)66 static void LoadConfigVersion(OriginalEffectConfig &result, xmlNode* currNode)
67 {
68     if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("version"))) {
69         AUDIO_ERR_LOG("missing information: audio_effects_conf node has no version attribute");
70         return;
71     }
72 
73     float pVersion = atof(reinterpret_cast<char*>
74     (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("version"))));
75     result.version = pVersion;
76 }
77 
LoadLibrary(OriginalEffectConfig & result,xmlNode * secondNode)78 static void LoadLibrary(OriginalEffectConfig &result, xmlNode* secondNode)
79 {
80     xmlNode *currNode = secondNode;
81     int32_t countLibrary = 0;
82     while (currNode != nullptr) {
83         if (countLibrary >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
84             AUDIO_ERR_LOG("the number of library nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
85             return;
86         }
87         if (currNode->type != XML_ELEMENT_NODE) {
88             currNode = currNode->next;
89             continue;
90         }
91         if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("library"))) {
92             if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("name"))) {
93                 AUDIO_ERR_LOG("missing information: library has no name attribute");
94             } else if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("path"))) {
95                 AUDIO_ERR_LOG("missing information: library has no path attribute");
96             } else {
97                 std::string pLibName = reinterpret_cast<char*>
98                                       (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("name")));
99                 std::string pLibPath = reinterpret_cast<char*>
100                                       (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("path")));
101                 Library tmp = {pLibName, pLibPath};
102                 result.libraries.push_back(tmp);
103             }
104         } else {
105             AUDIO_ERR_LOG("wrong name: %{public}s, should be library", currNode->name);
106         }
107         countLibrary++;
108         currNode = currNode->next;
109     }
110     if (countLibrary == 0) {
111         AUDIO_ERR_LOG("missing information: libraries have no child library");
112     }
113 }
114 
LoadEffectConfigLibraries(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])115 static void LoadEffectConfigLibraries(OriginalEffectConfig &result, const xmlNode* currNode,
116                                       int32_t (&countFirstNode)[NODE_SIZE])
117 {
118     if (countFirstNode[INDEX_LIBRARIES] >= AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
119         if (countFirstNode[INDEX_LIBRARIES] == AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
120             countFirstNode[INDEX_LIBRARIES]++;
121             AUDIO_ERR_LOG("the number of libraries nodes exceeds limit: %{public}d",
122                 AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT);
123         }
124     } else if (currNode->xmlChildrenNode) {
125         LoadLibrary(result, currNode->xmlChildrenNode);
126         countFirstNode[INDEX_LIBRARIES]++;
127     } else {
128         AUDIO_ERR_LOG("missing information: libraries have no child library");
129         countFirstNode[INDEX_LIBRARIES]++;
130     }
131 }
132 
LoadEffect(OriginalEffectConfig & result,xmlNode * secondNode)133 static void LoadEffect(OriginalEffectConfig &result, xmlNode* secondNode)
134 {
135     xmlNode *currNode = secondNode;
136     int32_t countEffect = 0;
137     while (currNode != nullptr) {
138         if (countEffect >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
139             AUDIO_ERR_LOG("the number of effect nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
140             return;
141         }
142         if (currNode->type != XML_ELEMENT_NODE) {
143             currNode = currNode->next;
144             continue;
145         }
146         if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("effect"))) {
147             if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("name"))) {
148                 AUDIO_ERR_LOG("missing information: effect has no name attribute");
149             } else if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("library"))) {
150                 AUDIO_ERR_LOG("missing information: effect has no library attribute");
151             } else {
152                 std::string pEffectName = reinterpret_cast<char*>
153                               (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("name")));
154                 std::string pEffectLib = reinterpret_cast<char*>
155                              (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("library")));
156                 Effect tmp = {pEffectName, pEffectLib};
157                 result.effects.push_back(tmp);
158             }
159         } else {
160             AUDIO_ERR_LOG("wrong name: %{public}s, should be effect", currNode->name);
161         }
162         countEffect++;
163         currNode = currNode->next;
164     }
165     if (countEffect == 0) {
166         AUDIO_ERR_LOG("missing information: effects have no child effect");
167     }
168 }
169 
LoadEffectConfigEffects(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])170 static void LoadEffectConfigEffects(OriginalEffectConfig &result, const xmlNode* currNode,
171                                     int32_t (&countFirstNode)[NODE_SIZE])
172 {
173     if (countFirstNode[INDEX_EFFECS] >= AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
174         if (countFirstNode[INDEX_EFFECS] == AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
175             countFirstNode[INDEX_EFFECS]++;
176             AUDIO_ERR_LOG("the number of effects nodes exceeds limit: %{public}d",
177                 AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT);
178         }
179     } else if (currNode->xmlChildrenNode) {
180         LoadEffect(result, currNode->xmlChildrenNode);
181         countFirstNode[INDEX_EFFECS]++;
182     } else {
183         AUDIO_ERR_LOG("missing information: effects have no child effect");
184         countFirstNode[INDEX_EFFECS]++;
185     }
186 }
187 
LoadApply(OriginalEffectConfig & result,const xmlNode * thirdNode,const int32_t segInx)188 static void LoadApply(OriginalEffectConfig &result, const xmlNode* thirdNode, const int32_t segInx)
189 {
190     if (!thirdNode->xmlChildrenNode) {
191         AUDIO_ERR_LOG("missing information: effectChain has no child apply");
192         return;
193     }
194     int32_t countApply = 0;
195     xmlNode *currNode = thirdNode->xmlChildrenNode;
196     while (currNode != nullptr) {
197         if (countApply >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
198             AUDIO_ERR_LOG("the number of apply nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
199             return;
200         }
201         if (currNode->type != XML_ELEMENT_NODE) {
202             currNode = currNode->next;
203             continue;
204         }
205         if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("apply"))) {
206             if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("effect"))) {
207                 AUDIO_ERR_LOG("missing information: apply has no effect attribute");
208             } else {
209                 std::string ppValue = reinterpret_cast<char*>
210                                      (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("effect")));
211                 result.effectChains[segInx].apply.push_back(ppValue);
212             }
213         } else {
214             AUDIO_ERR_LOG("wrong name: %{public}s, should be apply", currNode->name);
215         }
216         countApply++;
217         currNode = currNode->next;
218     }
219     if (countApply == 0) {
220         AUDIO_ERR_LOG("missing information: effectChain has no child apply");
221     }
222 }
223 
LoadEffectChain(OriginalEffectConfig & result,xmlNode * secondNode)224 static void LoadEffectChain(OriginalEffectConfig &result, xmlNode* secondNode)
225 {
226     xmlNode *currNode = secondNode;
227     int32_t countEffectChain = 0;
228     int32_t segInx = 0;
229     std::vector<std::string> apply;
230     while (currNode != nullptr) {
231         if (countEffectChain >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
232             AUDIO_ERR_LOG("the number of effectChain nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
233             return;
234         }
235         if (currNode->type != XML_ELEMENT_NODE) {
236             currNode = currNode->next;
237             continue;
238         }
239         if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("effectChain"))) {
240             if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("name"))) {
241                 AUDIO_ERR_LOG("missing information: effectChain has no name attribute");
242             } else {
243                 std::string peffectChainName = reinterpret_cast<char*>
244                                    (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("name")));
245                 EffectChain tmp = {peffectChainName, apply};
246                 result.effectChains.push_back(tmp);
247                 LoadApply(result, currNode, segInx);
248                 segInx++;
249             }
250         } else {
251             AUDIO_ERR_LOG("wrong name: %{public}s, should be effectChain", currNode->name);
252         }
253         countEffectChain++;
254         currNode = currNode->next;
255     }
256     if (countEffectChain == 0) {
257         AUDIO_ERR_LOG("missing information: effectChains have no child effectChain");
258     }
259 }
260 
LoadEffectConfigEffectChains(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])261 static void LoadEffectConfigEffectChains(OriginalEffectConfig &result, const xmlNode* currNode,
262                                          int32_t (&countFirstNode)[NODE_SIZE])
263 {
264     if (countFirstNode[INDEX_EFFECTCHAINE] >= AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
265         if (countFirstNode[INDEX_EFFECTCHAINE] == AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
266             countFirstNode[INDEX_EFFECTCHAINE]++;
267             AUDIO_ERR_LOG("the number of effectChains nodes exceeds limit: %{public}d",
268                 AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT);
269         }
270     } else if (currNode->xmlChildrenNode) {
271         LoadEffectChain(result, currNode->xmlChildrenNode);
272         countFirstNode[INDEX_EFFECTCHAINE]++;
273     } else {
274         AUDIO_ERR_LOG("missing information: effectChains have no child effectChain");
275         countFirstNode[INDEX_EFFECTCHAINE]++;
276     }
277 }
278 
LoadPreDevice(OriginalEffectConfig & result,const xmlNode * fourthNode,const int32_t modeNum,const int32_t streamNum)279 static void LoadPreDevice(OriginalEffectConfig &result, const xmlNode* fourthNode,
280                           const int32_t modeNum, const int32_t streamNum)
281 {
282     if (!fourthNode->xmlChildrenNode) {
283         AUDIO_ERR_LOG("missing information: streamEffectMode has no child devicePort");
284         return;
285     }
286     int32_t countDevice = 0;
287     xmlNode *currNode = fourthNode->xmlChildrenNode;
288     while (currNode != nullptr) {
289         if (countDevice >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
290             AUDIO_ERR_LOG("the number of devicePort nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
291             return;
292         }
293         if (currNode->type != XML_ELEMENT_NODE) {
294             currNode = currNode->next;
295             continue;
296         }
297         if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("devicePort"))) {
298             if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("type"))) {
299                 AUDIO_ERR_LOG("missing information: devicePort has no type attribute");
300             } else if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("effectChain"))) {
301                 AUDIO_ERR_LOG("missing information: devicePort has no effectChain attribute");
302             } else {
303                 std::string pDevType = reinterpret_cast<char*>
304                            (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("type")));
305                 std::string pChain = reinterpret_cast<char*>
306                          (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("effectChain")));
307                 Device tmpdev = {pDevType, pChain};
308                 result.preProcess[streamNum].device[modeNum].push_back(tmpdev);
309             }
310         } else {
311             AUDIO_ERR_LOG("wrong name: %{public}s, should be devicePort", currNode->name);
312         }
313         countDevice++;
314         currNode = currNode->next;
315     }
316     if (countDevice == 0) {
317         AUDIO_ERR_LOG("missing information: streamEffectMode has no child devicePort");
318     }
319 }
320 
LoadPreMode(OriginalEffectConfig & result,const xmlNode * thirdNode,const int32_t streamNum)321 static void LoadPreMode(OriginalEffectConfig &result, const xmlNode* thirdNode, const int32_t streamNum)
322 {
323     if (!thirdNode->xmlChildrenNode) {
324         AUDIO_ERR_LOG("missing information: stream has no child streamEffectMode");
325         return;
326     }
327     int32_t countMode = 0;
328     int32_t modeNum = 0;
329     xmlNode *currNode = thirdNode->xmlChildrenNode;
330     while (currNode != nullptr) {
331         if (countMode >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
332             AUDIO_ERR_LOG("the number of streamEffectMode nodes exceeds limit: %{public}d",
333                 AUDIO_EFFECT_COUNT_UPPER_LIMIT);
334             return;
335         }
336         if (currNode->type != XML_ELEMENT_NODE) {
337             currNode = currNode->next;
338             continue;
339         }
340         if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("streamEffectMode"))) {
341             if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("mode"))) {
342                 AUDIO_ERR_LOG("missing information: streamEffectMode has no mode attribute");
343             } else {
344                 std::string pStreamAEMode = reinterpret_cast<char*>
345                                 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("mode")));
346                 result.preProcess[streamNum].mode.push_back(pStreamAEMode);
347                 result.preProcess[streamNum].device.push_back({});
348                 LoadPreDevice(result, currNode, modeNum, streamNum);
349                 modeNum++;
350             }
351         } else {
352             AUDIO_ERR_LOG("wrong name: %{public}s, should be streamEffectMode", currNode->name);
353         }
354         countMode++;
355         currNode = currNode->next;
356     }
357     if (countMode == 0) {
358         AUDIO_ERR_LOG("missing information: stream has no child streamEffectMode");
359     }
360 }
361 
LoadPreProcess(OriginalEffectConfig & result,xmlNode * secondNode)362 static void LoadPreProcess(OriginalEffectConfig &result, xmlNode* secondNode)
363 {
364     std::string stream;
365     std::vector<std::string> mode;
366     std::vector<std::vector<Device>> device;
367     Preprocess tmp = {stream, mode, device};
368     xmlNode *currNode = secondNode;
369     int32_t countPreprocess = 0;
370     int32_t streamNum = 0;
371     while (currNode != nullptr) {
372         if (countPreprocess >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
373             AUDIO_ERR_LOG("the number of stream nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
374             return;
375         }
376         if (currNode->type != XML_ELEMENT_NODE) {
377             currNode = currNode->next;
378             continue;
379         }
380         if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("stream"))) {
381             if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("scene"))) {
382                 AUDIO_ERR_LOG("missing information: stream has no scene attribute");
383             } else {
384                 std::string pStreamType = reinterpret_cast<char*>
385                                          (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("scene")));
386                 tmp.stream = pStreamType;
387                 result.preProcess.push_back(tmp);
388                 LoadPreMode(result, currNode, streamNum);
389                 streamNum++;
390             }
391         } else {
392             AUDIO_ERR_LOG("wrong name: %{public}s, should be stream", currNode->name);
393         }
394         countPreprocess++;
395         currNode = currNode->next;
396     }
397     if (countPreprocess == 0) {
398         AUDIO_ERR_LOG("missing information: preProcess has no child stream");
399     }
400 }
401 
LoadEffectConfigPreProcess(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])402 static void LoadEffectConfigPreProcess(OriginalEffectConfig &result, const xmlNode* currNode,
403                                        int32_t (&countFirstNode)[NODE_SIZE])
404 {
405     if (countFirstNode[INDEX_PREPROCESS] >= AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
406         if (countFirstNode[INDEX_PREPROCESS] == AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
407             countFirstNode[INDEX_PREPROCESS]++;
408             AUDIO_ERR_LOG("the number of preProcess nodes exceeds limit: %{public}d",
409                 AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT);
410         }
411     } else if (currNode->xmlChildrenNode) {
412         LoadPreProcess(result, currNode->xmlChildrenNode);
413         countFirstNode[INDEX_PREPROCESS]++;
414     } else {
415         AUDIO_ERR_LOG("missing information: preProcess has no child stream");
416         countFirstNode[INDEX_PREPROCESS]++;
417     }
418 }
419 
LoadPostDevice(OriginalEffectConfig & result,const xmlNode * fourthNode,const int32_t modeNum,const int32_t streamNum)420 static void LoadPostDevice(OriginalEffectConfig &result, const xmlNode* fourthNode,
421                            const int32_t modeNum, const int32_t streamNum)
422 {
423     if (!fourthNode->xmlChildrenNode) {
424         AUDIO_ERR_LOG("missing information: streamEffectMode has no child devicePort");
425         return;
426     }
427     int32_t countDevice = 0;
428     xmlNode *currNode = fourthNode->xmlChildrenNode;
429     while (currNode != nullptr) {
430         if (countDevice >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
431             AUDIO_ERR_LOG("the number of devicePort nodes exceeds limit: %{public}d", AUDIO_EFFECT_COUNT_UPPER_LIMIT);
432             return;
433         }
434         if (currNode->type != XML_ELEMENT_NODE) {
435             currNode = currNode->next;
436             continue;
437         }
438         if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("devicePort"))) {
439             if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("type"))) {
440                 AUDIO_ERR_LOG("missing information: devicePort has no type attribute");
441             } else if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("effectChain"))) {
442                 AUDIO_ERR_LOG("missing information: devicePort has no effectChain attribute");
443             } else {
444                 std::string pDevType = reinterpret_cast<char*>
445                            (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("type")));
446                 std::string pChain = reinterpret_cast<char*>
447                          (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("effectChain")));
448                 Device tmpdev = {pDevType, pChain};
449                 result.postProcess[streamNum].device[modeNum].push_back(tmpdev);
450             }
451         } else {
452             AUDIO_ERR_LOG("wrong name: %{public}s, should be devicePort", currNode->name);
453         }
454         countDevice++;
455         currNode = currNode->next;
456     }
457     if (countDevice == 0) {
458         AUDIO_ERR_LOG("missing information: streamEffectMode has no child devicePort");
459     }
460 }
461 
LoadPostMode(OriginalEffectConfig & result,const xmlNode * thirdNode,const int32_t streamNum)462 static void LoadPostMode(OriginalEffectConfig &result, const xmlNode* thirdNode, const int32_t streamNum)
463 {
464     if (!thirdNode->xmlChildrenNode) {
465         AUDIO_ERR_LOG("missing information: stream has no child streamEffectMode");
466         return;
467     }
468     int32_t countMode = 0;
469     int32_t modeNum = 0;
470     xmlNode *currNode = thirdNode->xmlChildrenNode;
471     while (currNode != nullptr) {
472         if (countMode >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
473             AUDIO_ERR_LOG("the number of streamEffectMode nodes exceeds limit: %{public}d",
474                 AUDIO_EFFECT_COUNT_UPPER_LIMIT);
475             return;
476         }
477         if (currNode->type != XML_ELEMENT_NODE) {
478             currNode = currNode->next;
479             continue;
480         }
481         if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("streamEffectMode"))) {
482             if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("mode"))) {
483                 AUDIO_ERR_LOG("missing information: streamEffectMode has no mode attribute");
484             } else {
485                 std::string pStreamAEMode = reinterpret_cast<char*>
486                                 (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("mode")));
487                 result.postProcess[streamNum].mode.push_back(pStreamAEMode);
488                 result.postProcess[streamNum].device.push_back({});
489                 LoadPostDevice(result, currNode, modeNum, streamNum);
490                 modeNum++;
491             }
492         } else {
493             AUDIO_ERR_LOG("wrong name: %{public}s, should be streamEffectMode", currNode->name);
494         }
495         countMode++;
496         currNode = currNode->next;
497     }
498     if (countMode == 0) {
499         AUDIO_ERR_LOG("missing information: stream has no child streamEffectMode");
500     }
501 }
502 
LoadPostProcess(OriginalEffectConfig & result,xmlNode * secondNode)503 static void LoadPostProcess(OriginalEffectConfig &result, xmlNode* secondNode)
504 {
505     std::string stream;
506     std::vector<std::string> mode;
507     std::vector<std::vector<Device>> device;
508     Postprocess tmp = {stream, mode, device};
509     xmlNode *currNode = secondNode;
510     int32_t countPostprocess = 0;
511     int32_t streamNum = 0;
512     while (currNode != nullptr) {
513         if (countPostprocess >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
514             AUDIO_ERR_LOG("the number of stream nodes exceeds limit: %{public}d",
515                 AUDIO_EFFECT_COUNT_UPPER_LIMIT);
516             return;
517         }
518         if (currNode->type != XML_ELEMENT_NODE) {
519             currNode = currNode->next;
520             continue;
521         }
522         if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("stream"))) {
523             if (!xmlHasProp(currNode, reinterpret_cast<const xmlChar*>("scene"))) {
524                 AUDIO_ERR_LOG("missing information: stream has no scene attribute");
525             } else {
526                 std::string pStreamType = reinterpret_cast<char*>
527                                          (xmlGetProp(currNode, reinterpret_cast<const xmlChar*>("scene")));
528                 tmp.stream = pStreamType;
529                 result.postProcess.push_back(tmp);
530                 LoadPostMode(result, currNode, streamNum);
531                 streamNum++;
532             }
533         } else {
534             AUDIO_ERR_LOG("wrong name: %{public}s, should be stream", currNode->name);
535         }
536         countPostprocess++;
537         currNode = currNode->next;
538     }
539     if (countPostprocess == 0) {
540         AUDIO_ERR_LOG("missing information: postProcess has no child stream");
541     }
542 }
543 
LoadEffectConfigPostProcess(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])544 static void LoadEffectConfigPostProcess(OriginalEffectConfig &result, const xmlNode* currNode,
545                                         int32_t (&countFirstNode)[NODE_SIZE])
546 {
547     if (countFirstNode[INDEX_POSTPROCESS] >= AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
548         if (countFirstNode[INDEX_POSTPROCESS] == AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT) {
549             countFirstNode[INDEX_POSTPROCESS]++;
550             AUDIO_ERR_LOG("the number of postProcess nodes exceeds limit: %{public}d",
551                 AUDIO_EFFECT_COUNT_FIRST_NODE_UPPER_LIMIT);
552         }
553     } else if (currNode->xmlChildrenNode) {
554         LoadPostProcess(result, currNode->xmlChildrenNode);
555         countFirstNode[INDEX_POSTPROCESS]++;
556     } else {
557         AUDIO_ERR_LOG("missing information: postProcess has no child stream");
558         countFirstNode[INDEX_POSTPROCESS]++;
559     }
560 }
561 
LoadEffectConfigException(OriginalEffectConfig & result,const xmlNode * currNode,int32_t (& countFirstNode)[NODE_SIZE])562 static void LoadEffectConfigException(OriginalEffectConfig &result, const xmlNode* currNode,
563                                       int32_t (&countFirstNode)[NODE_SIZE])
564 {
565     if (countFirstNode[INDEX_EXCEPTION] >= AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
566         if (countFirstNode[INDEX_EXCEPTION] == AUDIO_EFFECT_COUNT_UPPER_LIMIT) {
567             countFirstNode[INDEX_EXCEPTION]++;
568             AUDIO_ERR_LOG("the number of nodes with wrong name exceeds limit: %{public}d",
569                 AUDIO_EFFECT_COUNT_UPPER_LIMIT);
570         }
571     } else {
572         AUDIO_ERR_LOG("wrong name: %{public}s", currNode->name);
573         countFirstNode[INDEX_EXCEPTION]++;
574     }
575 }
576 
LoadEffectConfig(OriginalEffectConfig & result)577 int32_t AudioEffectConfigParser::LoadEffectConfig(OriginalEffectConfig &result)
578 {
579     int32_t countFirstNode[NODE_SIZE] = {0};
580     int32_t i = 0;
581     xmlDoc *doc = nullptr;
582     xmlNode *rootElement = nullptr;
583     AUDIO_INFO_LOG("AudioEffectParser::LoadConfig");
584     if ((doc = xmlReadFile(AUDIO_EFFECT_CONFIG_FILE, nullptr, (1 << 5) | (1 << 6))) == nullptr) { // 5, 6: arguments
585         AUDIO_ERR_LOG("error: could not parse file %{public}s", AUDIO_EFFECT_CONFIG_FILE);
586         return FILE_PARSE_ERROR;
587     }
588 
589     rootElement = xmlDocGetRootElement(doc);
590     xmlNode *currNode = rootElement;
591 
592     if (LoadConfigCheck(doc, currNode) == 0) {
593         LoadConfigVersion(result, currNode);
594         currNode = currNode->xmlChildrenNode;
595     } else {
596         return FILE_CONTENT_ERROR;
597     }
598 
599     while (currNode != nullptr) {
600         if (currNode->type != XML_ELEMENT_NODE) {
601             currNode = currNode->next;
602             continue;
603         }
604 
605         if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("libraries"))) {
606             LoadEffectConfigLibraries(result, currNode, countFirstNode);
607         } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("effects"))) {
608             LoadEffectConfigEffects(result, currNode, countFirstNode);
609         } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("effectChains"))) {
610             LoadEffectConfigEffectChains(result, currNode, countFirstNode);
611         } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("preProcess"))) {
612             LoadEffectConfigPreProcess(result, currNode, countFirstNode);
613         } else if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("postProcess"))) {
614             LoadEffectConfigPostProcess(result, currNode, countFirstNode);
615         } else {
616             LoadEffectConfigException(result, currNode, countFirstNode);
617         }
618 
619         currNode = currNode->next;
620     }
621 
622     for (i = 0; i < MODULE_SIZE; i++) {
623         if (countFirstNode[i] == 0) {
624             AUDIO_ERR_LOG("missing information: %{public}s", EFFECT_CONFIG_NAME[i].c_str());
625         }
626     }
627 
628     if (doc) {
629         xmlFreeDoc(doc);
630         xmlCleanupParser();
631     }
632 
633     return 0;
634 }
635 } // namespace AudioStandard
636 } // namespace OHOS