1 /*
2 * Copyright (c) 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 #ifndef LOG_TAG
16 #define LOG_TAG "AudioToneParser"
17 #endif
18
19 #include "audio_tone_parser.h"
20
21 namespace OHOS {
22 namespace AudioStandard {
AudioToneParser()23 AudioToneParser::AudioToneParser()
24 {
25 AUDIO_INFO_LOG("AudioToneParser ctor");
26 }
27
~AudioToneParser()28 AudioToneParser::~AudioToneParser()
29 {
30 }
31
LoadConfig(std::unordered_map<int32_t,std::shared_ptr<ToneInfo>> & toneDescriptorMap)32 int32_t AudioToneParser::LoadConfig(std::unordered_map<int32_t, std::shared_ptr<ToneInfo>> &toneDescriptorMap)
33 {
34 AUDIO_INFO_LOG("Enter");
35 xmlDoc *doc = nullptr;
36 xmlNode *rootElement = nullptr;
37 AUDIO_ERR_LOG("AudioToneParser::LoadConfig");
38 doc = xmlReadFile(AUDIO_TONE_CONFIG_FILE, nullptr, 0);
39 CHECK_AND_RETURN_RET_LOG(doc != nullptr, ERROR, "error: could not parse file %s", AUDIO_TONE_CONFIG_FILE);
40 rootElement = xmlDocGetRootElement(doc);
41 xmlNode *currNode = rootElement;
42 CHECK_AND_RETURN_RET_LOG(currNode != nullptr, ERROR, "root element is null");
43 if (xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("DTMF"))) {
44 AUDIO_ERR_LOG("Missing tag - DTMF: %s", AUDIO_TONE_CONFIG_FILE);
45 xmlFreeDoc(doc);
46 return ERROR;
47 }
48 if (currNode->xmlChildrenNode) {
49 currNode = currNode->xmlChildrenNode;
50 } else {
51 AUDIO_ERR_LOG("Missing child - DTMF: %s", AUDIO_TONE_CONFIG_FILE);
52 xmlFreeDoc(doc);
53 return ERROR;
54 }
55
56 while (currNode != nullptr) {
57 if ((currNode->type == XML_ELEMENT_NODE) &&
58 (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("Tones")))) {
59 currNode = currNode->xmlChildrenNode;
60 } else if ((currNode->type == XML_ELEMENT_NODE) &&
61 (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("ToneInfo")))) {
62 ParseToneInfo(currNode, toneDescriptorMap);
63 break;
64 } else {
65 currNode = currNode->next;
66 }
67 }
68 if (currNode == nullptr) {
69 AUDIO_WARNING_LOG("Missing tag - Tones, ToneInfo: %s", AUDIO_TONE_CONFIG_FILE);
70 }
71 xmlFreeDoc(doc);
72 AUDIO_INFO_LOG("Done");
73 return SUCCESS;
74 }
75
ParseToneInfoAttribute(xmlNode * sNode,std::shared_ptr<ToneInfo> ltoneDesc)76 void AudioToneParser::ParseToneInfoAttribute(xmlNode *sNode, std::shared_ptr<ToneInfo> ltoneDesc)
77 {
78 int segCnt = 0;
79 int segInx = 0;
80 while (sNode != nullptr) {
81 if (sNode->type != XML_ELEMENT_NODE) {
82 sNode = sNode->next;
83 continue;
84 }
85 char *pValue = nullptr;
86 if (!xmlStrcmp(sNode->name, reinterpret_cast<const xmlChar*>("RepeatCount"))) {
87 AUDIO_DEBUG_LOG("RepeatCount node type: Element, name: %{public}s", sNode->name);
88 pValue = reinterpret_cast<char*>(xmlGetProp(sNode,
89 reinterpret_cast<xmlChar*>(const_cast<char*>("value"))));
90 if (!xmlStrcmp(reinterpret_cast<const xmlChar*>(pValue), reinterpret_cast<const xmlChar*>("INF"))) {
91 ltoneDesc->repeatCnt = TONEINFO_INF;
92 } else {
93 ltoneDesc->repeatCnt = static_cast<uint32_t>(atoi(pValue));
94 }
95 AUDIO_DEBUG_LOG("ParseToneInfo repeatCnt %{public}d", ltoneDesc->repeatCnt);
96 } else if (!xmlStrcmp(sNode->name, reinterpret_cast<const xmlChar*>("RepeatSegment"))) {
97 AUDIO_DEBUG_LOG("RepeatSegment node type: Element, name: %{public}s", sNode->name);
98 pValue = reinterpret_cast<char*>(xmlGetProp(sNode,
99 reinterpret_cast<xmlChar*>(const_cast<char*>("value"))));
100 ltoneDesc->repeatSegment = static_cast<uint32_t>(atoi(pValue));
101 AUDIO_DEBUG_LOG("ParseToneInfo repeatSegment %{public}d", ltoneDesc->repeatSegment);
102 } else if (!xmlStrcmp(sNode->name, reinterpret_cast<const xmlChar*>("SegmentCount"))) {
103 AUDIO_DEBUG_LOG("SegmentCount node type: Element, name: %{public}s", sNode->name);
104 pValue = reinterpret_cast<char*>(xmlGetProp(sNode,
105 reinterpret_cast<xmlChar*>(const_cast<char*>("value"))));
106 segCnt = atoi(pValue);
107 ltoneDesc->segmentCnt = static_cast<uint32_t>(segCnt);
108 AUDIO_DEBUG_LOG("ParseToneInfo segmentCnt %{public}d", ltoneDesc->segmentCnt);
109 } else if (!xmlStrcmp(sNode->name, reinterpret_cast<const xmlChar*>("Segment"))) {
110 if (segInx < segCnt) {
111 ParseSegment(sNode, segInx, ltoneDesc);
112 segInx++;
113 }
114 }
115 if (pValue != nullptr) {
116 xmlFree(pValue);
117 }
118 sNode = sNode->next;
119 }
120 }
ParseToneInfo(xmlNode * node,std::unordered_map<int32_t,std::shared_ptr<ToneInfo>> & toneDescriptorMap)121 void AudioToneParser::ParseToneInfo(xmlNode *node, std::unordered_map<int32_t,
122 std::shared_ptr<ToneInfo>> &toneDescriptorMap)
123 {
124 xmlNode *currNode = node;
125 while (currNode != nullptr) {
126 if (currNode->type != XML_ELEMENT_NODE) {
127 currNode = currNode->next;
128 continue;
129 }
130 if (!xmlStrcmp(currNode->name, reinterpret_cast<const xmlChar*>("ToneInfo"))) {
131 std::shared_ptr<ToneInfo> ltoneDesc = std::make_shared<ToneInfo>(); // new ToneInfo();
132 AUDIO_DEBUG_LOG("node type: Element, name: %s", currNode->name);
133 char *pToneType = reinterpret_cast<char*>(xmlGetProp(currNode,
134 reinterpret_cast<xmlChar*>(const_cast<char*>("toneType"))));
135 int toneType = atoi(pToneType);
136 AUDIO_DEBUG_LOG("ParseToneInfo toneType %{public}d", toneType);
137 xmlFree(pToneType);
138 if (currNode->xmlChildrenNode) {
139 xmlNode *sNode = currNode->xmlChildrenNode;
140 ParseToneInfoAttribute(sNode, ltoneDesc);
141 }
142 toneDescriptorMap[toneType] = ltoneDesc;
143 }
144 currNode = currNode->next;
145 }
146 }
147
ParseSegment(xmlNode * node,int SegInx,std::shared_ptr<ToneInfo> ltoneDesc)148 void AudioToneParser::ParseSegment(xmlNode *node, int SegInx, std::shared_ptr<ToneInfo> ltoneDesc)
149 {
150 xmlNode *currNode = node;
151 for (uint32_t i = 0; i < TONEINFO_MAX_WAVES + 1; i++) {
152 ltoneDesc->segments[SegInx].waveFreq[i]=0;
153 }
154 if ((currNode->type == XML_ELEMENT_NODE) && (!xmlStrcmp(currNode->name,
155 reinterpret_cast<const xmlChar*>("Segment")))) {
156 char *pValue = reinterpret_cast<char*>(xmlGetProp(currNode,
157 reinterpret_cast<xmlChar*>(const_cast<char*>("duration"))));
158 if (!xmlStrcmp(reinterpret_cast<const xmlChar*>(pValue), reinterpret_cast<const xmlChar*>("INF"))) {
159 ltoneDesc->segments[SegInx].duration = TONEINFO_INF;
160 } else {
161 ltoneDesc->segments[SegInx].duration = static_cast<uint32_t>(atoi(pValue));
162 }
163 AUDIO_DEBUG_LOG("duration: %{public}d", ltoneDesc->segments[SegInx].duration);
164 xmlFree(pValue);
165 pValue = reinterpret_cast<char*>(xmlGetProp(currNode,
166 reinterpret_cast<xmlChar*>(const_cast<char*>("loopCount"))));
167 ltoneDesc->segments[SegInx].loopCnt = atoi(pValue);
168 AUDIO_DEBUG_LOG("loopCnt: %{public}d", ltoneDesc->segments[SegInx].loopCnt);
169 xmlFree(pValue);
170 pValue = reinterpret_cast<char*>(xmlGetProp(currNode,
171 reinterpret_cast<xmlChar*>(const_cast<char*>("loopIndex"))));
172 ltoneDesc->segments[SegInx].loopIndx = atoi(pValue);
173 AUDIO_DEBUG_LOG("loopIndx: %{public}d", ltoneDesc->segments[SegInx].loopIndx);
174 xmlFree(pValue);
175 pValue = reinterpret_cast<char*>(xmlGetProp(currNode,
176 reinterpret_cast<xmlChar*>(const_cast<char*>("freq"))));
177 ParseFrequency(pValue, ltoneDesc->segments[SegInx]);
178 xmlFree(pValue);
179 }
180 }
181
ParseFrequency(std::string freqList,ToneSegment & ltonesegment)182 void AudioToneParser::ParseFrequency (std::string freqList, ToneSegment <onesegment)
183 {
184 std::vector<int> vect;
185 std::stringstream ss(freqList);
186
187 for (int i; ss >> i;) {
188 vect.push_back(i);
189 if (ss.peek() == ',') {
190 ss.ignore();
191 }
192 }
193
194 for (std::size_t i = 0; i < vect.size(); i++) {
195 AUDIO_DEBUG_LOG("Freq: %{public}d", vect[i]);
196 ltonesegment.waveFreq[i] = vect[i];
197 }
198 }
199 } // namespace AudioStandard
200 } // namespace OHOS
201