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