• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &ltonesegment)
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