1 // Copyright (C) 2022 The Android Open Source Project
2 //
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 "ServiceConfig.h"
16 
17 #include <android-base/parseint.h>
18 #include <android-base/strings.h>
19 #include <getopt.h>
20 
21 #include <utility>
22 #include <vector>
23 
24 namespace audio_proxy::service {
25 namespace {
parseStreamConfig(const char * optarg)26 std::pair<std::string, StreamConfig> parseStreamConfig(const char* optarg) {
27   std::vector<std::string> tokens = android::base::Split(optarg, ":");
28   if (tokens.size() != 3) {
29     return {};
30   }
31 
32   StreamConfig config;
33   if (!android::base::ParseUint(tokens[1].c_str(), &config.bufferSizeMs)) {
34     return {};
35   }
36 
37   if (!android::base::ParseUint(tokens[2].c_str(), &config.latencyMs)) {
38     return {};
39   }
40 
41   return {tokens[0], config};
42 }
43 }  // namespace
44 
parseServiceConfigFromCommandLine(int argc,char ** argv)45 std::optional<ServiceConfig> parseServiceConfigFromCommandLine(int argc,
46                                                                char** argv) {
47   // $command --name service_name
48   //   --stream address1:buffer_size:latency
49   //   --stream address2:buffer_size:latency
50   static option options[] = {
51       {"name", required_argument, nullptr, 'n'},
52       {"stream", required_argument, nullptr, 's'},
53       {nullptr, 0, nullptr, 0},
54   };
55 
56   // Reset, this is useful in unittest.
57   optind = 0;
58 
59   ServiceConfig config;
60   int val = 0;
61   while ((val = getopt_long(argc, argv, "n:s:", options, nullptr)) != -1) {
62     switch (val) {
63       case 'n':
64         config.name = optarg;
65         break;
66 
67       case 's': {
68         std::pair<std::string, StreamConfig> streamConfig =
69             parseStreamConfig(optarg);
70         if (streamConfig.first.empty()) {
71           return std::nullopt;
72         }
73 
74         auto it = config.streams.emplace(std::move(streamConfig));
75         if (!it.second) {
76           return std::nullopt;
77         }
78 
79         break;
80       }
81 
82       default:
83         break;
84     }
85   }
86 
87   if (config.name.empty() || config.streams.empty()) {
88     return std::nullopt;
89   }
90 
91   return config;
92 }
93 
94 }  // namespace audio_proxy::service