• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 
16 #include "media_log.h"
17 
18 #include "xml_parser.h"
19 
20 namespace OHOS {
21 namespace AudioStandard {
LoadConfiguration()22 bool XMLParser::LoadConfiguration()
23 {
24     mDoc = xmlReadFile(CONFIG_FILE, nullptr, 0);
25     if (mDoc == nullptr) {
26         MEDIA_ERR_LOG("xmlReadFile Failed");
27         return false;
28     }
29 
30     return true;
31 }
32 
Parse()33 bool XMLParser::Parse()
34 {
35     xmlNode *root = xmlDocGetRootElement(mDoc);
36     if (root == nullptr) {
37         MEDIA_ERR_LOG("xmlDocGetRootElement Failed");
38         return false;
39     }
40 
41     if (!ParseInternal(*root)) {
42         return false;
43     }
44 
45     return true;
46 }
47 
Destroy()48 void XMLParser::Destroy()
49 {
50     if (mDoc != nullptr) {
51         xmlFreeDoc(mDoc);
52     }
53 }
54 
ParseInternal(xmlNode & node)55 bool XMLParser::ParseInternal(xmlNode &node)
56 {
57     xmlNode *currNode = &node;
58     for (; currNode; currNode = currNode->next) {
59         if (XML_ELEMENT_NODE == currNode->type) {
60             switch (GetNodeNameAsInt(*currNode)) {
61                 case DEVICE_CLASS:
62                     ParseDeviceClass(*currNode);
63                     break;
64                 case AUDIO_INTERRUPT_ENABLE:
65                     ParseAudioInterrupt(*currNode);
66                     break;
67                 default:
68                     ParseInternal(*(currNode->children));
69                     break;
70             }
71         }
72     }
73 
74     mPortObserver.OnXmlParsingCompleted(xmlParsedDataMap_);
75     return true;
76 }
77 
ParseDeviceClass(xmlNode & node)78 void XMLParser::ParseDeviceClass(xmlNode &node)
79 {
80     xmlNode *modulesNode = nullptr;
81     modulesNode = node.xmlChildrenNode;
82 
83     std::string className = ExtractPropertyValue("name", node);
84     if (className.empty()) {
85         MEDIA_ERR_LOG("No name provided for the device class %{public}s", node.name);
86         return;
87     }
88 
89     deviceClassType_ = GetDeviceClassType(className);
90     xmlParsedDataMap_[deviceClassType_] = {};
91 
92     while (modulesNode != nullptr) {
93         if (modulesNode->type == XML_ELEMENT_NODE) {
94             ParseModules(*modulesNode, className);
95         }
96         modulesNode = modulesNode->next;
97     }
98 }
99 
ParseModules(xmlNode & node,std::string & className)100 void XMLParser::ParseModules(xmlNode &node, std::string &className)
101 {
102     xmlNode *moduleNode = nullptr;
103     std::list<AudioModuleInfo> moduleList = {};
104     moduleNode = node.xmlChildrenNode;
105 
106     while (moduleNode != nullptr) {
107         if (moduleNode->type == XML_ELEMENT_NODE) {
108             AudioModuleInfo moduleInfo = {};
109             moduleInfo.className = className;
110             moduleInfo.name = ExtractPropertyValue("name", *moduleNode);
111             moduleInfo.lib = ExtractPropertyValue("lib", *moduleNode);
112             moduleInfo.role = ExtractPropertyValue("role", *moduleNode);
113             moduleInfo.rate = ExtractPropertyValue("rate", *moduleNode);
114             moduleInfo.format = ExtractPropertyValue("format", *moduleNode);
115             moduleInfo.channels = ExtractPropertyValue("channels", *moduleNode);
116             moduleInfo.bufferSize = ExtractPropertyValue("buffer_size", *moduleNode);
117             moduleInfo.fileName = ExtractPropertyValue("file", *moduleNode);
118             moduleInfo.ports = {};
119 
120             ParsePorts(*moduleNode, moduleInfo);
121             moduleList.push_back(moduleInfo);
122         }
123         moduleNode = moduleNode->next;
124     }
125 
126     xmlParsedDataMap_[deviceClassType_] = moduleList;
127 }
128 
ParsePorts(xmlNode & node,AudioModuleInfo & moduleInfo)129 void XMLParser::ParsePorts(xmlNode &node, AudioModuleInfo &moduleInfo)
130 {
131     xmlNode *portsNode = nullptr;
132     portsNode = node.xmlChildrenNode;
133 
134     while (portsNode != nullptr) {
135         if (portsNode->type == XML_ELEMENT_NODE) {
136             ParsePort(*portsNode, moduleInfo);
137         }
138         portsNode = portsNode->next;
139     }
140 }
141 
ParsePort(xmlNode & node,AudioModuleInfo & moduleInfo)142 void XMLParser::ParsePort(xmlNode &node, AudioModuleInfo &moduleInfo)
143 {
144     xmlNode *portNode = nullptr;
145     std::list<AudioModuleInfo> portInfoList = {};
146     portNode = node.xmlChildrenNode;
147 
148     while (portNode != nullptr) {
149         if (portNode->type == XML_ELEMENT_NODE) {
150             moduleInfo.adapterName = ExtractPropertyValue("adapter_name", *portNode);
151             moduleInfo.id = ExtractPropertyValue("id", *portNode);
152 
153             // if some parameter is not configured inside <Port>, take data from moduleinfo
154             std::string value = ExtractPropertyValue("rate", *portNode);
155             if (!value.empty()) {
156                 moduleInfo.rate = value;
157             }
158 
159             value = ExtractPropertyValue("format", *portNode);
160             if (!value.empty()) {
161                 moduleInfo.format = value;
162             }
163 
164             value = ExtractPropertyValue("channels", *portNode);
165             if (!value.empty()) {
166                 moduleInfo.channels = value;
167             }
168 
169             value = ExtractPropertyValue("buffer_size", *portNode);
170             if (!value.empty()) {
171                 moduleInfo.bufferSize = value;
172             }
173 
174             value = ExtractPropertyValue("file", *portNode);
175             if (!value.empty()) {
176                 moduleInfo.fileName = value;
177             }
178 
179             portInfoList.push_back(moduleInfo);
180         }
181         portNode = portNode->next;
182     }
183 
184     moduleInfo.ports.assign(portInfoList.begin(), portInfoList.end());
185 }
186 
GetNodeNameAsInt(xmlNode & node)187 NodeName XMLParser::GetNodeNameAsInt(xmlNode &node)
188 {
189     if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("deviceclass"))) {
190         return DEVICE_CLASS;
191     } else  if (!xmlStrcmp(node.name, reinterpret_cast<const xmlChar*>("AudioInterruptEnable"))) {
192         return AUDIO_INTERRUPT_ENABLE;
193     } else {
194         return UNKNOWN;
195     }
196 }
197 
ParseAudioInterrupt(xmlNode & node)198 void XMLParser::ParseAudioInterrupt(xmlNode &node)
199 {
200     xmlNode *child = node.children;
201     xmlChar *enableFlag = xmlNodeGetContent(child);
202 
203     if (!xmlStrcmp(enableFlag, reinterpret_cast<const xmlChar*>("true"))) {
204         mPortObserver.OnAudioInterruptEnable(true);
205     } else {
206         mPortObserver.OnAudioInterruptEnable(false);
207     }
208 
209     xmlFree(enableFlag);
210 }
211 
GetDeviceClassType(const std::string & deviceClass)212 ClassType XMLParser::GetDeviceClassType(const std::string &deviceClass)
213 {
214     if (deviceClass == PRIMARY_CLASS)
215         return ClassType::TYPE_PRIMARY;
216     else if (deviceClass == A2DP_CLASS)
217         return ClassType::TYPE_A2DP;
218     else if (deviceClass == USB_CLASS)
219         return ClassType::TYPE_USB;
220     else
221         return ClassType::TYPE_INVALID;
222 }
223 
ExtractPropertyValue(const std::string & propName,xmlNode & node)224 std::string XMLParser::ExtractPropertyValue(const std::string &propName, xmlNode &node)
225 {
226     std::string propValue = "";
227     xmlChar *tempValue = nullptr;
228 
229     if (xmlHasProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()))) {
230         tempValue = xmlGetProp(&node, reinterpret_cast<const xmlChar*>(propName.c_str()));
231     }
232 
233     if (tempValue != nullptr) {
234         propValue = reinterpret_cast<const char*>(tempValue);
235         xmlFree(tempValue);
236     }
237 
238     return propValue;
239 }
240 } // namespace AudioStandard
241 } // namespace OHOS
242