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