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