1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_TYPE_CONVERTER_H_
18 #define ANDROID_TYPE_CONVERTER_H_
19 
20 #include <set>
21 #include <string>
22 #include <string.h>
23 #include <vector>
24 
25 #include <system/audio.h>
26 #include <utils/Log.h>
27 #include <utils/Vector.h>
28 #include <utils/SortedVector.h>
29 
30 #include <media/AudioParameter.h>
31 #include "convert.h"
32 
33 namespace android {
34 
35 template <typename T>
36 struct DefaultTraits
37 {
38     typedef T Type;
39     typedef std::vector<Type> Collection;
addDefaultTraits40     static void add(Collection &collection, Type value)
41     {
42         collection.push_back(value);
43     }
44 };
45 template <typename T>
46 struct SortedVectorTraits
47 {
48     typedef T Type;
49     typedef SortedVector<Type> Collection;
addSortedVectorTraits50     static void add(Collection &collection, Type value)
51     {
52         collection.add(value);
53     }
54 };
55 template <typename T>
56 struct SetTraits
57 {
58     typedef T Type;
59     typedef std::set<Type> Collection;
addSetTraits60     static void add(Collection &collection, Type value)
61     {
62         collection.insert(value);
63     }
64 };
65 
66 using SampleRateTraits = SetTraits<uint32_t>;
67 using DeviceTraits = DefaultTraits<audio_devices_t>;
68 struct OutputDeviceTraits : public DeviceTraits {};
69 struct InputDeviceTraits : public DeviceTraits {};
70 using ChannelTraits = SetTraits<audio_channel_mask_t>;
71 struct OutputChannelTraits : public ChannelTraits {};
72 struct InputChannelTraits : public ChannelTraits {};
73 struct ChannelIndexTraits : public ChannelTraits {};
74 using InputFlagTraits = DefaultTraits<audio_input_flags_t>;
75 using OutputFlagTraits = DefaultTraits<audio_output_flags_t>;
76 using FormatTraits = DefaultTraits<audio_format_t>;
77 using GainModeTraits = DefaultTraits<audio_gain_mode_t>;
78 using StreamTraits = DefaultTraits<audio_stream_type_t>;
79 using AudioModeTraits = DefaultTraits<audio_mode_t>;
80 using AudioContentTraits = DefaultTraits<audio_content_type_t>;
81 using UsageTraits = DefaultTraits<audio_usage_t>;
82 using SourceTraits = DefaultTraits<audio_source_t>;
83 struct AudioFlagTraits : public DefaultTraits<audio_flags_mask_t> {};
84 
85 template <class Traits>
86 static void collectionFromString(const std::string &str, typename Traits::Collection &collection,
87                                  const char *del = AudioParameter::valueListSeparator)
88 {
89     char *literal = strdup(str.c_str());
90     for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
91         typename Traits::Type value;
92         if (utilities::convertTo<std::string, typename Traits::Type >(cstr, value)) {
93             Traits::add(collection, value);
94         }
95     }
96     free(literal);
97 }
98 
99 template <class Traits>
100 class TypeConverter
101 {
102 public:
103     static bool toString(const typename Traits::Type &value, std::string &str);
104 
105     static bool fromString(const std::string &str, typename Traits::Type &result);
106 
107     static void collectionFromString(const std::string &str,
108                                      typename Traits::Collection &collection,
109                                      const char *del = AudioParameter::valueListSeparator);
110 
111     static uint32_t maskFromString(
112             const std::string &str, const char *del = AudioParameter::valueListSeparator);
113 
114     static void maskToString(
115             uint32_t mask, std::string &str, const char *del = AudioParameter::valueListSeparator);
116 
117 protected:
118     struct Table {
119         const char *literal;
120         typename Traits::Type value;
121     };
122 
123     static const Table mTable[];
124 };
125 
126 template <class Traits>
toString(const typename Traits::Type & value,std::string & str)127 inline bool TypeConverter<Traits>::toString(const typename Traits::Type &value, std::string &str)
128 {
129     for (size_t i = 0; mTable[i].literal; i++) {
130         if (mTable[i].value == value) {
131             str = mTable[i].literal;
132             return true;
133         }
134     }
135     char result[64];
136     snprintf(result, sizeof(result), "Unknown enum value %d", value);
137     str = result;
138     return false;
139 }
140 
141 template <class Traits>
fromString(const std::string & str,typename Traits::Type & result)142 inline bool TypeConverter<Traits>::fromString(const std::string &str, typename Traits::Type &result)
143 {
144     for (size_t i = 0; mTable[i].literal; i++) {
145         if (strcmp(mTable[i].literal, str.c_str()) == 0) {
146             ALOGV("stringToEnum() found %s", mTable[i].literal);
147             result = mTable[i].value;
148             return true;
149         }
150     }
151     return false;
152 }
153 
154 template <class Traits>
collectionFromString(const std::string & str,typename Traits::Collection & collection,const char * del)155 inline void TypeConverter<Traits>::collectionFromString(const std::string &str,
156         typename Traits::Collection &collection,
157         const char *del)
158 {
159     char *literal = strdup(str.c_str());
160 
161     for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
162         typename Traits::Type value;
163         if (fromString(cstr, value)) {
164             Traits::add(collection, value);
165         }
166     }
167     free(literal);
168 }
169 
170 template <class Traits>
maskFromString(const std::string & str,const char * del)171 inline uint32_t TypeConverter<Traits>::maskFromString(const std::string &str, const char *del)
172 {
173     char *literal = strdup(str.c_str());
174     uint32_t value = 0;
175     for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
176         typename Traits::Type type;
177         if (fromString(cstr, type)) {
178             value |= static_cast<uint32_t>(type);
179         }
180     }
181     free(literal);
182     return value;
183 }
184 
185 template <class Traits>
maskToString(uint32_t mask,std::string & str,const char * del)186 inline void TypeConverter<Traits>::maskToString(uint32_t mask, std::string &str, const char *del)
187 {
188     if (mask != 0) {
189         bool first_flag = true;
190         for (size_t i = 0; mTable[i].literal; i++) {
191             uint32_t value = static_cast<uint32_t>(mTable[i].value);
192             if (mTable[i].value != 0 && ((mask & value) == value)) {
193                 if (!first_flag) str += del;
194                 first_flag = false;
195                 str += mTable[i].literal;
196             }
197         }
198     } else {
199         toString(static_cast<typename Traits::Type>(0), str);
200     }
201 }
202 
203 typedef TypeConverter<OutputDeviceTraits> OutputDeviceConverter;
204 typedef TypeConverter<InputDeviceTraits> InputDeviceConverter;
205 typedef TypeConverter<OutputFlagTraits> OutputFlagConverter;
206 typedef TypeConverter<InputFlagTraits> InputFlagConverter;
207 typedef TypeConverter<FormatTraits> FormatConverter;
208 typedef TypeConverter<OutputChannelTraits> OutputChannelConverter;
209 typedef TypeConverter<InputChannelTraits> InputChannelConverter;
210 typedef TypeConverter<ChannelIndexTraits> ChannelIndexConverter;
211 typedef TypeConverter<GainModeTraits> GainModeConverter;
212 typedef TypeConverter<StreamTraits> StreamTypeConverter;
213 typedef TypeConverter<AudioModeTraits> AudioModeConverter;
214 typedef TypeConverter<AudioContentTraits> AudioContentTypeConverter;
215 typedef TypeConverter<UsageTraits> UsageTypeConverter;
216 typedef TypeConverter<SourceTraits> SourceTypeConverter;
217 typedef TypeConverter<AudioFlagTraits> AudioFlagConverter;
218 
219 template<> const OutputDeviceConverter::Table OutputDeviceConverter::mTable[];
220 template<> const InputDeviceConverter::Table InputDeviceConverter::mTable[];
221 template<> const OutputFlagConverter::Table OutputFlagConverter::mTable[];
222 template<> const InputFlagConverter::Table InputFlagConverter::mTable[];
223 template<> const FormatConverter::Table FormatConverter::mTable[];
224 template<> const OutputChannelConverter::Table OutputChannelConverter::mTable[];
225 template<> const InputChannelConverter::Table InputChannelConverter::mTable[];
226 template<> const ChannelIndexConverter::Table ChannelIndexConverter::mTable[];
227 template<> const GainModeConverter::Table GainModeConverter::mTable[];
228 template<> const StreamTypeConverter::Table StreamTypeConverter::mTable[];
229 template<> const AudioModeConverter::Table AudioModeConverter::mTable[];
230 template<> const AudioContentTypeConverter::Table AudioContentTypeConverter::mTable[];
231 template<> const UsageTypeConverter::Table UsageTypeConverter::mTable[];
232 template<> const SourceTypeConverter::Table SourceTypeConverter::mTable[];
233 template<> const AudioFlagConverter::Table AudioFlagConverter::mTable[];
234 
235 bool deviceFromString(const std::string& literalDevice, audio_devices_t& device);
236 
237 SampleRateTraits::Collection samplingRatesFromString(
238         const std::string &samplingRates, const char *del = AudioParameter::valueListSeparator);
239 
240 FormatTraits::Collection formatsFromString(
241         const std::string &formats, const char *del = AudioParameter::valueListSeparator);
242 
243 audio_format_t formatFromString(
244         const std::string &literalFormat, audio_format_t defaultFormat = AUDIO_FORMAT_DEFAULT);
245 
246 audio_channel_mask_t channelMaskFromString(const std::string &literalChannels);
247 
248 ChannelTraits::Collection channelMasksFromString(
249         const std::string &channels, const char *del = AudioParameter::valueListSeparator);
250 
251 InputChannelTraits::Collection inputChannelMasksFromString(
252         const std::string &inChannels, const char *del = AudioParameter::valueListSeparator);
253 
254 OutputChannelTraits::Collection outputChannelMasksFromString(
255         const std::string &outChannels, const char *del = AudioParameter::valueListSeparator);
256 
257 // counting enumerations
258 template <typename T, std::enable_if_t<std::is_same<T, audio_content_type_t>::value
259                                     || std::is_same<T, audio_mode_t>::value
260                                     || std::is_same<T, audio_source_t>::value
261                                     || std::is_same<T, audio_stream_type_t>::value
262                                     || std::is_same<T, audio_usage_t>::value
263                                     || std::is_same<T, audio_format_t>::value
264                                     , int> = 0>
toString(const T & value)265 static inline std::string toString(const T& value)
266 {
267     std::string result;
268     return TypeConverter<DefaultTraits<T>>::toString(value, result)
269             ? result : std::to_string(static_cast<int>(value));
270 
271 }
272 
273 // flag enumerations
274 template <typename T, std::enable_if_t<std::is_same<T, audio_gain_mode_t>::value
275                                     || std::is_same<T, audio_input_flags_t>::value
276                                     || std::is_same<T, audio_output_flags_t>::value
277                                     , int> = 0>
toString(const T & value)278 static inline std::string toString(const T& value)
279 {
280     std::string result;
281     TypeConverter<DefaultTraits<T>>::maskToString(value, result);
282     return result;
283 }
284 
toString(const audio_devices_t & devices)285 static inline std::string toString(const audio_devices_t& devices)
286 {
287     std::string result;
288     if ((devices & AUDIO_DEVICE_BIT_IN) != 0) {
289         InputDeviceConverter::maskToString(devices, result);
290     } else {
291         OutputDeviceConverter::maskToString(devices, result);
292     }
293     return result;
294 }
295 
toString(const audio_attributes_t & attributes)296 static inline std::string toString(const audio_attributes_t& attributes)
297 {
298     std::ostringstream result;
299     result << "{ Content type: " << toString(attributes.content_type)
300            << " Usage: " << toString(attributes.usage)
301            << " Source: " << toString(attributes.source)
302            << std::hex << " Flags: 0x" << attributes.flags
303            << std::dec << " Tags: " << attributes.tags
304            << " }";
305 
306     return result.str();
307 }
308 
309 }; // namespace android
310 
311 #endif  /*ANDROID_TYPE_CONVERTER_H_*/
312