1 /*
2  * Copyright (c) 2021-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 #include "audio_concurrency_parser.h"
16 
17 namespace OHOS {
18 namespace AudioStandard {
19 
LoadConfig(std::map<std::pair<AudioPipeType,AudioPipeType>,ConcurrencyAction> & concurrencyMap)20 int32_t AudioConcurrencyParser::LoadConfig(std::map<std::pair<AudioPipeType, AudioPipeType>,
21     ConcurrencyAction> &concurrencyMap)
22 {
23     doc_ = xmlReadFile(AUDIO_CONCURRENCY_CONFIG_FILE, nullptr, 0);
24     CHECK_AND_RETURN_RET_LOG(doc_ != nullptr, ERR_OPERATION_FAILED, "xmlRead AudioConcurrencyConfigFile failed!");
25     xmlNode *root = xmlDocGetRootElement(doc_);
26     CHECK_AND_RETURN_RET_LOG(root != nullptr, ERR_OPERATION_FAILED, "xmlDocGetRootElement failed!");
27     if (xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>("audioConcurrencyPolicy"))) {
28         AUDIO_ERR_LOG("Missing tag - audioConcurrencyPolicy");
29         xmlFreeDoc(doc_);
30         return ERR_OPERATION_FAILED;
31     }
32     ParseInternal(root, concurrencyMap);
33     return SUCCESS;
34 }
35 
ParseInternal(xmlNode * node,std::map<std::pair<AudioPipeType,AudioPipeType>,ConcurrencyAction> & concurrencyMap)36 void AudioConcurrencyParser::ParseInternal(xmlNode *node, std::map<std::pair<AudioPipeType, AudioPipeType>,
37     ConcurrencyAction> &concurrencyMap)
38 {
39     xmlNode *curNode = node;
40     for (; curNode; curNode = curNode->next) {
41         if (curNode->type == XML_ELEMENT_NODE &&
42             !xmlStrcmp(curNode->name, reinterpret_cast<const xmlChar*>("existingStream"))) {
43             char *nodeName = reinterpret_cast<char*>(xmlGetProp(curNode,
44                 reinterpret_cast<xmlChar*>(const_cast<char*>("name"))));
45             std::string existingStream = nodeName;
46             AUDIO_DEBUG_LOG("existingStream: %{public}s", existingStream.c_str());
47             ParseIncoming(existingStream, curNode->children, concurrencyMap);
48         } else {
49             ParseInternal((curNode->children), concurrencyMap);
50         }
51     }
52     return;
53 }
54 
ParseIncoming(const std::string & existing,xmlNode * node,std::map<std::pair<AudioPipeType,AudioPipeType>,ConcurrencyAction> & concurrencyMap)55 void AudioConcurrencyParser::ParseIncoming(const std::string &existing, xmlNode *node,
56     std::map<std::pair<AudioPipeType, AudioPipeType>, ConcurrencyAction> &concurrencyMap)
57 {
58     xmlNode *incomingNode = node;
59     while (incomingNode != nullptr) {
60         if (incomingNode->type == XML_ELEMENT_NODE &&
61             !xmlStrcmp(incomingNode->name, reinterpret_cast<const xmlChar*>("incomingStream"))) {
62             char *incomingName = reinterpret_cast<char*>(xmlGetProp(incomingNode,
63             reinterpret_cast<xmlChar*>(const_cast<char*>("name"))));
64             char *actionName = reinterpret_cast<char*>(xmlGetProp(incomingNode,
65             reinterpret_cast<xmlChar*>(const_cast<char*>("action"))));
66             std::string incoming = incomingName;
67             std::string action = actionName;
68             AUDIO_DEBUG_LOG("existing: %{public}s %{public}d, incoming: %{public}s %{public}d, action: %{public}s",
69                 existing.c_str(), audioPipeTypeMap_[existing], incoming.c_str(),
70                 audioPipeTypeMap_[incoming], action.c_str());
71             std::pair<AudioPipeType, AudioPipeType> concurrencyPair =
72                 std::make_pair(audioPipeTypeMap_[existing], audioPipeTypeMap_[incoming]);
73             ConcurrencyAction concurrencyAction = (action == "play both" || action == "mix") ? PLAY_BOTH :
74                 (action == "concede existing" ? CONCEDE_EXISTING : CONCEDE_INCOMING);
75             concurrencyMap.emplace(concurrencyPair, concurrencyAction);
76             xmlFree(incomingName);
77             xmlFree(actionName);
78         }
79         incomingNode = incomingNode->next;
80     }
81 }
82 } // namespace AudioStandard
83 } // namespace OHOS