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