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 #include "audio_utils.h"
21
22 namespace OHOS {
23 namespace AudioStandard {
AudioToneParser()24 AudioToneParser::AudioToneParser()
25 {
26 AUDIO_INFO_LOG("AudioToneParser ctor");
27 }
28
~AudioToneParser()29 AudioToneParser::~AudioToneParser()
30 {
31 }
32
Trim(const std::string & str)33 std::string Trim(const std::string& str)
34 {
35 size_t start = str.find_first_not_of(" \t\n\r");
36 size_t end = str.find_last_not_of(" \t\n\r");
37 if (start == std::string::npos || end == std::string::npos || start > end) {
38 AUDIO_ERR_LOG("Failed to trim the string: %{public}s", str.c_str());
39 return "";
40 }
41
42 std::string trimStr = str.substr(start, end - start + 1);
43 for (char &c : trimStr) {
44 c = std::tolower(c);
45 }
46 return trimStr;
47 }
48
SplitAndTrim(const std::string & str)49 std::vector<std::string> SplitAndTrim(const std::string& str)
50 {
51 std::stringstream ss(str);
52 std::string token;
53 std::vector<std::string> result;
54
55 while (std::getline(ss, token, ',')) {
56 std::string trimmedToken = Trim(token);
57 if (!trimmedToken.empty()) {
58 result.push_back(trimmedToken);
59 }
60 }
61
62 if (result.empty()) {
63 AUDIO_ERR_LOG("Failed to split and trim the string: %{public}s", str.c_str());
64 }
65
66 return result;
67 }
68
LoadNewConfig(const std::string & configPath,ToneInfoMap & toneDescriptorMap,std::unordered_map<std::string,ToneInfoMap> & customToneDescriptorMap)69 int32_t AudioToneParser::LoadNewConfig(const std::string &configPath, ToneInfoMap &toneDescriptorMap,
70 std::unordered_map<std::string, ToneInfoMap> &customToneDescriptorMap)
71 {
72 AUDIO_INFO_LOG("Enter");
73 std::shared_ptr<AudioXmlNode> curNode = AudioXmlNode::Create();
74 CHECK_AND_RETURN_RET_LOG(curNode->Config(configPath.c_str(), nullptr, 0) == SUCCESS, ERROR,
75 "error: could not parse file %{public}s", configPath.c_str());
76
77 if (!curNode->CompareName("DTMF")) {
78 AUDIO_ERR_LOG("Missing tag - DTMF: %{public}s", configPath.c_str());
79 curNode = nullptr;
80 return ERROR;
81 }
82 curNode->MoveToChildren();
83 if (!curNode->IsNodeValid()) {
84 AUDIO_ERR_LOG("Missing child - DTMF: %{public}s", configPath.c_str());
85 curNode = nullptr;
86 return ERROR;
87 }
88
89 while (curNode->IsNodeValid()) {
90 if (!curNode->IsNodeValid()) {
91 curNode->MoveToNext();
92 continue;
93 }
94 if (curNode->CompareName("Default") || curNode->CompareName("Tones")) {
95 std::vector<ToneInfoMap*> toneDescriptorMaps;
96 toneDescriptorMaps.push_back(&toneDescriptorMap);
97 ParseToneInfo(curNode->GetChildrenNode(), toneDescriptorMaps);
98 } else if (curNode->CompareName("Custom")) {
99 ParseCustom(curNode->GetChildrenNode(), customToneDescriptorMap);
100 }
101 curNode->MoveToNext();
102 }
103 curNode = nullptr;
104 AUDIO_INFO_LOG("Done");
105 return SUCCESS;
106 }
107
ParseCustom(std::shared_ptr<AudioXmlNode> curNode,std::unordered_map<std::string,ToneInfoMap> & customToneDescriptorMap)108 void AudioToneParser::ParseCustom(std::shared_ptr<AudioXmlNode> curNode,
109 std::unordered_map<std::string, ToneInfoMap> &customToneDescriptorMap)
110 {
111 AUDIO_DEBUG_LOG("Enter");
112 while (curNode->IsNodeValid()) {
113 if (!curNode->IsElementNode()) {
114 curNode->MoveToNext();
115 continue;
116 }
117 if (curNode->CompareName("CountryInfo")) {
118 std::string pCountryName;
119 int32_t ret = curNode->GetProp("names", pCountryName);
120 if (ret != SUCCESS) {
121 curNode->MoveToNext();
122 continue;
123 }
124 AUDIO_DEBUG_LOG("ParseCustom names %{public}s", pCountryName.c_str());
125 std::vector<ToneInfoMap*> toneDescriptorMaps;
126 std::vector<std::string> cuntryNames = SplitAndTrim(pCountryName);
127 for (auto &countryName : cuntryNames) {
128 toneDescriptorMaps.push_back(&customToneDescriptorMap[countryName]);
129 }
130 ParseToneInfo(curNode->GetChildrenNode(), toneDescriptorMaps);
131 }
132 curNode->MoveToNext();
133 }
134 }
135
LoadConfig(std::unordered_map<int32_t,std::shared_ptr<ToneInfo>> & toneDescriptorMap)136 int32_t AudioToneParser::LoadConfig(std::unordered_map<int32_t, std::shared_ptr<ToneInfo>> &toneDescriptorMap)
137 {
138 AUDIO_INFO_LOG("Enter");
139 std::shared_ptr<AudioXmlNode> curNode = AudioXmlNode::Create();
140 AUDIO_ERR_LOG("AudioToneParser::LoadConfig");
141
142 CHECK_AND_RETURN_RET_LOG(curNode->Config(AUDIO_TONE_CONFIG_FILE, nullptr, 0) == SUCCESS, ERROR,
143 "error: could not parse file %s", AUDIO_TONE_CONFIG_FILE);
144
145 if (!curNode->CompareName("DTMF")) {
146 AUDIO_ERR_LOG("Missing tag - DTMF: %s", AUDIO_TONE_CONFIG_FILE);
147 curNode = nullptr;
148 return ERROR;
149 }
150 curNode->MoveToChildren();
151 if (!curNode->IsNodeValid()) {
152 AUDIO_ERR_LOG("Missing child - DTMF: %s", AUDIO_TONE_CONFIG_FILE);
153 curNode = nullptr;
154 return ERROR;
155 }
156 while (curNode->IsNodeValid()) {
157 if (curNode->CompareName("Tones")) {
158 curNode->MoveToChildren();
159 } else if (curNode->CompareName("ToneInfo")) {
160 std::vector<ToneInfoMap*> toneDescriptorMaps;
161 toneDescriptorMaps.push_back(&toneDescriptorMap);
162 ParseToneInfo(curNode->GetCopyNode(), toneDescriptorMaps);
163 break;
164 } else {
165 curNode->MoveToNext();
166 }
167 }
168 curNode = nullptr;
169 AUDIO_INFO_LOG("Done");
170 return SUCCESS;
171 }
172
ParseToneInfoAttribute(std::shared_ptr<AudioXmlNode> curNode,std::shared_ptr<ToneInfo> ltoneDesc)173 void AudioToneParser::ParseToneInfoAttribute(std::shared_ptr<AudioXmlNode> curNode,
174 std::shared_ptr<ToneInfo> ltoneDesc)
175 {
176 int segCnt = 0;
177 int segInx = 0;
178 while (curNode->IsNodeValid()) {
179 if (!curNode->IsElementNode()) {
180 curNode->MoveToNext();
181 continue;
182 }
183 std::string pValueStr;
184 if (curNode->CompareName("RepeatCount")) {
185 AUDIO_DEBUG_LOG("RepeatCount node type: Element, name: RepeatCount");
186 curNode->GetProp("value", pValueStr);
187
188 if (pValueStr == "INF") {
189 ltoneDesc->repeatCnt = TONEINFO_INF;
190 } else {
191 CHECK_AND_RETURN_LOG(StringConverter(pValueStr, ltoneDesc->repeatCnt),
192 "convert ltoneDesc->repeatCnt fail!");
193 }
194 AUDIO_DEBUG_LOG("ParseToneInfo repeatCnt %{public}d", ltoneDesc->repeatCnt);
195 } else if (curNode->CompareName("RepeatSegment")) {
196 AUDIO_DEBUG_LOG("RepeatSegment node type: Element, name: RepeatSegment");
197 curNode->GetProp("value", pValueStr);
198 CHECK_AND_RETURN_LOG(StringConverter(pValueStr, ltoneDesc->repeatSegment),
199 "convert ltoneDesc->repeatSegment fail!");
200 AUDIO_DEBUG_LOG("ParseToneInfo repeatSegment %{public}d", ltoneDesc->repeatSegment);
201 } else if (curNode->CompareName("SegmentCount")) {
202 AUDIO_DEBUG_LOG("SegmentCount node type: Element, name: SegmentCount");
203 curNode->GetProp("value", pValueStr);
204 CHECK_AND_RETURN_LOG(StringConverter(pValueStr, segCnt),
205 "convert segCnt fail!");
206 ltoneDesc->segmentCnt = static_cast<uint32_t>(segCnt);
207 AUDIO_DEBUG_LOG("ParseToneInfo segmentCnt %{public}d", ltoneDesc->segmentCnt);
208 } else if (curNode->CompareName("Segment")) {
209 if (segInx < segCnt) {
210 ParseSegment(curNode->GetCopyNode(), segInx, ltoneDesc);
211 segInx++;
212 }
213 }
214 curNode->MoveToNext();
215 }
216 }
217
ParseToneInfo(std::shared_ptr<AudioXmlNode> curNode,std::vector<ToneInfoMap * > & toneDescriptorMaps)218 void AudioToneParser::ParseToneInfo(std::shared_ptr<AudioXmlNode> curNode,
219 std::vector<ToneInfoMap*> &toneDescriptorMaps)
220 {
221 while (curNode->IsNodeValid()) {
222 if (!curNode->IsElementNode()) {
223 curNode->MoveToNext();
224 continue;
225 }
226 if (!curNode->CompareName("ToneInfo")) {
227 curNode->MoveToNext();
228 continue;
229 }
230 std::shared_ptr<ToneInfo> ltoneDesc = std::make_shared<ToneInfo>();
231 std::string pToneType;
232 if (curNode->GetProp("toneType", pToneType) != SUCCESS) {
233 AUDIO_DEBUG_LOG("getprop toneType fail");
234 curNode->MoveToNext();
235 continue;
236 }
237 int32_t toneType = 0;
238 CHECK_AND_RETURN_LOG(StringConverter(pToneType, toneType),
239 "convert pToneType: %{public}s Fail!", pToneType.c_str());
240 AUDIO_DEBUG_LOG("toneType value: %{public}d", toneType);
241
242 ParseToneInfoAttribute(curNode->GetChildrenNode(), ltoneDesc);
243
244 for (auto toneDescriptorMap : toneDescriptorMaps) {
245 if (toneDescriptorMap) {
246 (*toneDescriptorMap)[toneType] = ltoneDesc;
247 }
248 }
249 curNode->MoveToNext();
250 }
251 }
252
ParseSegment(std::shared_ptr<AudioXmlNode> curNode,int SegInx,std::shared_ptr<ToneInfo> ltoneDesc)253 void AudioToneParser::ParseSegment(std::shared_ptr<AudioXmlNode> curNode,
254 int SegInx, std::shared_ptr<ToneInfo> ltoneDesc)
255 {
256 for (uint32_t i = 0; i < TONEINFO_MAX_WAVES + 1; i++) {
257 ltoneDesc->segments[SegInx].waveFreq[i]=0;
258 }
259 if (curNode->CompareName("Segment")) {
260 std::string pValueStr;
261 curNode->GetProp("duration", pValueStr);
262 if (pValueStr == "INF") {
263 ltoneDesc->segments[SegInx].duration = TONEINFO_INF;
264 } else {
265 CHECK_AND_RETURN_LOG(StringConverter(pValueStr, ltoneDesc->segments[SegInx].duration),
266 "convert ltoneDesc->segments[SegInx].duration fail!");
267 }
268 AUDIO_DEBUG_LOG("duration: %{public}d", ltoneDesc->segments[SegInx].duration);
269
270 curNode->GetProp("loopCount", pValueStr);
271 CHECK_AND_RETURN_LOG(StringConverter(pValueStr, ltoneDesc->segments[SegInx].loopCnt),
272 "convert ltoneDesc->segments[SegInx].loopCnt fail!");
273 AUDIO_DEBUG_LOG("loopCnt: %{public}d", ltoneDesc->segments[SegInx].loopCnt);
274
275 curNode->GetProp("loopIndex", pValueStr);
276 CHECK_AND_RETURN_LOG(StringConverter(pValueStr, ltoneDesc->segments[SegInx].loopIndx),
277 "convert ltoneDesc->segments[SegInx].loopIndx fail!");
278 AUDIO_DEBUG_LOG("loopIndx: %{public}d", ltoneDesc->segments[SegInx].loopIndx);
279
280 curNode->GetProp("freq", pValueStr);
281 ParseFrequency(pValueStr, ltoneDesc->segments[SegInx]);
282 }
283 }
284
ParseFrequency(std::string freqList,ToneSegment & ltonesegment)285 void AudioToneParser::ParseFrequency(std::string freqList, ToneSegment <onesegment)
286 {
287 std::vector<int> vect;
288 std::stringstream ss(freqList);
289
290 for (int i; ss >> i;) {
291 vect.push_back(i);
292 if (ss.peek() == ',') {
293 ss.ignore();
294 }
295 }
296
297 for (std::size_t i = 0; i < vect.size(); i++) {
298 AUDIO_DEBUG_LOG("Freq: %{public}d", vect[i]);
299 ltonesegment.waveFreq[i] = vect[i];
300 }
301 }
302 } // namespace AudioStandard
303 } // namespace OHOS
304