• 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             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 &ltonesegment)
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