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
28 #include <media/AudioParameter.h>
29 #include "convert.h"
30
31 namespace android {
32
33 template <typename T>
34 struct DefaultTraits
35 {
36 typedef T Type;
37 typedef std::vector<Type> Collection;
addDefaultTraits38 static void add(Collection &collection, Type value)
39 {
40 collection.push_back(value);
41 }
42 };
43 template <typename T>
44 struct SetTraits
45 {
46 typedef T Type;
47 typedef std::set<Type> Collection;
addSetTraits48 static void add(Collection &collection, Type value)
49 {
50 collection.insert(value);
51 }
52 };
53
54 using SampleRateTraits = SetTraits<uint32_t>;
55 using DeviceTraits = DefaultTraits<audio_devices_t>;
56 struct OutputDeviceTraits : public DeviceTraits {};
57 struct InputDeviceTraits : public DeviceTraits {};
58 using ChannelTraits = SetTraits<audio_channel_mask_t>;
59 struct OutputChannelTraits : public ChannelTraits {};
60 struct InputChannelTraits : public ChannelTraits {};
61 struct ChannelIndexTraits : public ChannelTraits {};
62 using InputFlagTraits = DefaultTraits<audio_input_flags_t>;
63 using OutputFlagTraits = DefaultTraits<audio_output_flags_t>;
64 using FormatTraits = DefaultTraits<audio_format_t>;
65 using GainModeTraits = DefaultTraits<audio_gain_mode_t>;
66 using StreamTraits = DefaultTraits<audio_stream_type_t>;
67 using AudioModeTraits = DefaultTraits<audio_mode_t>;
68 using AudioContentTraits = DefaultTraits<audio_content_type_t>;
69 using UsageTraits = DefaultTraits<audio_usage_t>;
70 using SourceTraits = DefaultTraits<audio_source_t>;
71 struct AudioFlagTraits : public DefaultTraits<audio_flags_mask_t> {};
72
73 template <class Traits>
74 static void collectionFromString(const std::string &str, typename Traits::Collection &collection,
75 const char *del = AudioParameter::valueListSeparator)
76 {
77 char *literal = strdup(str.c_str());
78 for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
79 typename Traits::Type value;
80 if (utilities::convertTo<std::string, typename Traits::Type >(cstr, value)) {
81 Traits::add(collection, value);
82 }
83 }
84 free(literal);
85 }
86
87 template <class Traits>
88 class TypeConverter
89 {
90 public:
91 static bool toString(const typename Traits::Type &value, std::string &str);
92
93 static bool fromString(const std::string &str, typename Traits::Type &result);
94
95 static void collectionFromString(const std::string &str,
96 typename Traits::Collection &collection,
97 const char *del = AudioParameter::valueListSeparator);
98
99 static typename Traits::Type maskFromString(
100 const std::string &str, const char *del = AudioParameter::valueListSeparator);
101
102 static void maskToString(
103 typename Traits::Type mask, std::string &str,
104 const char *del = AudioParameter::valueListSeparator);
105
106 protected:
107 // Default implementations use mTable for to/from string conversions
108 // of each individual enum value.
109 // These functions may be specialized to use external converters instead.
110 static bool toStringImpl(const typename Traits::Type &value, std::string &str);
111 static bool fromStringImpl(const std::string &str, typename Traits::Type &result);
112
113 struct Table {
114 const char *literal;
115 typename Traits::Type value;
116 };
117
118 static const Table mTable[];
119 };
120
121 template <class Traits>
toStringImpl(const typename Traits::Type & value,std::string & str)122 inline bool TypeConverter<Traits>::toStringImpl(
123 const typename Traits::Type &value, std::string &str) {
124 for (size_t i = 0; mTable[i].literal; i++) {
125 if (mTable[i].value == value) {
126 str = mTable[i].literal;
127 return true;
128 }
129 }
130 return false;
131 }
132
133 template <class Traits>
fromStringImpl(const std::string & str,typename Traits::Type & result)134 inline bool TypeConverter<Traits>::fromStringImpl(
135 const std::string &str, typename Traits::Type &result) {
136 for (size_t i = 0; mTable[i].literal; i++) {
137 if (strcmp(mTable[i].literal, str.c_str()) == 0) {
138 result = mTable[i].value;
139 return true;
140 }
141 }
142 return false;
143 }
144
145 template <class Traits>
toString(const typename Traits::Type & value,std::string & str)146 inline bool TypeConverter<Traits>::toString(const typename Traits::Type &value, std::string &str)
147 {
148 const bool success = toStringImpl(value, str);
149 if (!success) {
150 char result[64];
151 snprintf(result, sizeof(result), "Unknown enum value %d", value);
152 str = result;
153 }
154 return success;
155 }
156
157 template <class Traits>
fromString(const std::string & str,typename Traits::Type & result)158 inline bool TypeConverter<Traits>::fromString(const std::string &str, typename Traits::Type &result)
159 {
160 const bool success = fromStringImpl(str, result);
161 ALOGV_IF(success, "stringToEnum() found %s", str.c_str());
162 return success;
163 }
164
165 template <class Traits>
collectionFromString(const std::string & str,typename Traits::Collection & collection,const char * del)166 inline void TypeConverter<Traits>::collectionFromString(const std::string &str,
167 typename Traits::Collection &collection,
168 const char *del)
169 {
170 char *literal = strdup(str.c_str());
171
172 for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
173 typename Traits::Type value;
174 if (fromString(cstr, value)) {
175 Traits::add(collection, value);
176 }
177 }
178 free(literal);
179 }
180
181 template <class Traits>
maskFromString(const std::string & str,const char * del)182 inline typename Traits::Type TypeConverter<Traits>::maskFromString(
183 const std::string &str, const char *del)
184 {
185 char *literal = strdup(str.c_str());
186 uint32_t value = 0;
187 for (const char *cstr = strtok(literal, del); cstr != NULL; cstr = strtok(NULL, del)) {
188 typename Traits::Type type;
189 if (fromString(cstr, type)) {
190 value |= static_cast<uint32_t>(type);
191 }
192 }
193 free(literal);
194 return static_cast<typename Traits::Type>(value);
195 }
196
197 template <class Traits>
maskToString(typename Traits::Type mask,std::string & str,const char * del)198 inline void TypeConverter<Traits>::maskToString(
199 typename Traits::Type mask, std::string &str, const char *del)
200 {
201 if (mask != 0) {
202 bool first_flag = true;
203 for (size_t bit = 0; bit < sizeof(uint32_t) * 8; ++bit) {
204 uint32_t flag = 1u << bit;
205 if ((flag & mask) == flag) {
206 std::string flag_str;
207 if (toString(static_cast<typename Traits::Type>(flag), flag_str)) {
208 if (!first_flag) str += del;
209 first_flag = false;
210 str += flag_str;
211 }
212 }
213 }
214 } else {
215 toString(static_cast<typename Traits::Type>(0), str);
216 }
217 }
218
219 typedef TypeConverter<DeviceTraits> DeviceConverter;
220 typedef TypeConverter<OutputDeviceTraits> OutputDeviceConverter;
221 typedef TypeConverter<InputDeviceTraits> InputDeviceConverter;
222 typedef TypeConverter<OutputFlagTraits> OutputFlagConverter;
223 typedef TypeConverter<InputFlagTraits> InputFlagConverter;
224 typedef TypeConverter<FormatTraits> FormatConverter;
225 typedef TypeConverter<OutputChannelTraits> OutputChannelConverter;
226 typedef TypeConverter<InputChannelTraits> InputChannelConverter;
227 typedef TypeConverter<ChannelIndexTraits> ChannelIndexConverter;
228 typedef TypeConverter<GainModeTraits> GainModeConverter;
229 typedef TypeConverter<StreamTraits> StreamTypeConverter;
230 typedef TypeConverter<AudioModeTraits> AudioModeConverter;
231 typedef TypeConverter<AudioContentTraits> AudioContentTypeConverter;
232 typedef TypeConverter<UsageTraits> UsageTypeConverter;
233 typedef TypeConverter<SourceTraits> SourceTypeConverter;
234 typedef TypeConverter<AudioFlagTraits> AudioFlagConverter;
235
236 template<> const AudioModeConverter::Table AudioModeConverter::mTable[];
237 template<> const AudioFlagConverter::Table AudioFlagConverter::mTable[];
238
239 template <>
toStringImpl(const DeviceTraits::Type & value,std::string & str)240 inline bool TypeConverter<DeviceTraits>::toStringImpl(
241 const DeviceTraits::Type &value, std::string &str) {
242 str = audio_device_to_string(value);
243 return !str.empty();
244 }
245
246 template <>
fromStringImpl(const std::string & str,DeviceTraits::Type & result)247 inline bool TypeConverter<DeviceTraits>::fromStringImpl(
248 const std::string &str, DeviceTraits::Type &result) {
249 return audio_device_from_string(str.c_str(), &result);
250 }
251
252 template <>
toStringImpl(const OutputDeviceTraits::Type & value,std::string & str)253 inline bool TypeConverter<OutputDeviceTraits>::toStringImpl(
254 const OutputDeviceTraits::Type &value, std::string &str) {
255 if (audio_is_output_device(value)) {
256 str = audio_device_to_string(value);
257 return !str.empty();
258 }
259 return false;
260 }
261
262 template <>
fromStringImpl(const std::string & str,OutputDeviceTraits::Type & result)263 inline bool TypeConverter<OutputDeviceTraits>::fromStringImpl(
264 const std::string &str, OutputDeviceTraits::Type &result) {
265 OutputDeviceTraits::Type temp;
266 if (audio_device_from_string(str.c_str(), &temp) &&
267 audio_is_output_device(temp)) {
268 result = temp;
269 return true;
270 }
271 return false;
272 }
273
274 template <>
toStringImpl(const InputDeviceTraits::Type & value,std::string & str)275 inline bool TypeConverter<InputDeviceTraits>::toStringImpl(
276 const InputDeviceTraits::Type &value, std::string &str) {
277 if (audio_is_input_device(value)) {
278 str = audio_device_to_string(value);
279 return !str.empty();
280 }
281 return false;
282 }
283
284 template <>
fromStringImpl(const std::string & str,InputDeviceTraits::Type & result)285 inline bool TypeConverter<InputDeviceTraits>::fromStringImpl(
286 const std::string &str, InputDeviceTraits::Type &result) {
287 InputDeviceTraits::Type temp;
288 if (audio_device_from_string(str.c_str(), &temp) &&
289 audio_is_input_device(temp)) {
290 result = temp;
291 return true;
292 }
293 return false;
294 }
295
296 template <>
toStringImpl(const audio_input_flags_t & value,std::string & str)297 inline bool TypeConverter<InputFlagTraits>::toStringImpl(
298 const audio_input_flags_t &value, std::string &str) {
299 str = audio_input_flag_to_string(value);
300 return !str.empty();
301 }
302
303 template <>
fromStringImpl(const std::string & str,audio_input_flags_t & result)304 inline bool TypeConverter<InputFlagTraits>::fromStringImpl(
305 const std::string &str, audio_input_flags_t &result) {
306 return audio_input_flag_from_string(str.c_str(), &result);
307 }
308
309 template <>
toStringImpl(const audio_output_flags_t & value,std::string & str)310 inline bool TypeConverter<OutputFlagTraits>::toStringImpl(
311 const audio_output_flags_t &value, std::string &str) {
312 str = audio_output_flag_to_string(value);
313 return !str.empty();
314 }
315
316 template <>
fromStringImpl(const std::string & str,audio_output_flags_t & result)317 inline bool TypeConverter<OutputFlagTraits>::fromStringImpl(
318 const std::string &str, audio_output_flags_t &result) {
319 return audio_output_flag_from_string(str.c_str(), &result);
320 }
321
322 template <>
toStringImpl(const audio_format_t & value,std::string & str)323 inline bool TypeConverter<FormatTraits>::toStringImpl(
324 const audio_format_t &value, std::string &str) {
325 str = audio_format_to_string(value);
326 return !str.empty();
327 }
328
329 template <>
fromStringImpl(const std::string & str,audio_format_t & result)330 inline bool TypeConverter<FormatTraits>::fromStringImpl(
331 const std::string &str, audio_format_t &result) {
332 return audio_format_from_string(str.c_str(), &result);
333 }
334
335 template <>
toStringImpl(const audio_channel_mask_t & value,std::string & str)336 inline bool TypeConverter<OutputChannelTraits>::toStringImpl(
337 const audio_channel_mask_t &value, std::string &str) {
338 str = audio_channel_out_mask_to_string(value);
339 return !str.empty();
340 }
341
342 template <>
fromStringImpl(const std::string & str,audio_channel_mask_t & result)343 inline bool TypeConverter<OutputChannelTraits>::fromStringImpl(
344 const std::string &str, audio_channel_mask_t &result) {
345 OutputChannelTraits::Type temp;
346 if (audio_channel_mask_from_string(str.c_str(), &temp) &&
347 audio_is_output_channel(temp)) {
348 result = temp;
349 return true;
350 }
351 return false;
352 }
353
354 template <>
toStringImpl(const audio_channel_mask_t & value,std::string & str)355 inline bool TypeConverter<InputChannelTraits>::toStringImpl(
356 const audio_channel_mask_t &value, std::string &str) {
357 str = audio_channel_in_mask_to_string(value);
358 return !str.empty();
359 }
360
361 template <>
fromStringImpl(const std::string & str,audio_channel_mask_t & result)362 inline bool TypeConverter<InputChannelTraits>::fromStringImpl(
363 const std::string &str, audio_channel_mask_t &result) {
364 InputChannelTraits::Type temp;
365 if (audio_channel_mask_from_string(str.c_str(), &temp) &&
366 audio_is_input_channel(temp)) {
367 result = temp;
368 return true;
369 }
370 return false;
371 }
372
373 template <>
toStringImpl(const audio_channel_mask_t & value,std::string & str)374 inline bool TypeConverter<ChannelIndexTraits>::toStringImpl(
375 const audio_channel_mask_t &value, std::string &str) {
376 str = audio_channel_index_mask_to_string(value);
377 return !str.empty();
378 }
379
380 template <>
fromStringImpl(const std::string & str,audio_channel_mask_t & result)381 inline bool TypeConverter<ChannelIndexTraits>::fromStringImpl(
382 const std::string &str, audio_channel_mask_t &result) {
383 ChannelIndexTraits::Type temp;
384 if (audio_channel_mask_from_string(str.c_str(), &temp) &&
385 audio_channel_mask_get_representation(temp) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
386 result = temp;
387 return true;
388 }
389 return false;
390 }
391
392 template <>
toStringImpl(const audio_stream_type_t & value,std::string & str)393 inline bool TypeConverter<StreamTraits>::toStringImpl(
394 const audio_stream_type_t &value, std::string &str) {
395 str = audio_stream_type_to_string(value);
396 return !str.empty();
397 }
398
399 template <>
fromStringImpl(const std::string & str,audio_stream_type_t & result)400 inline bool TypeConverter<StreamTraits>::fromStringImpl(
401 const std::string &str, audio_stream_type_t &result)
402 {
403 return audio_stream_type_from_string(str.c_str(), &result);
404 }
405
406 template <>
toStringImpl(const audio_gain_mode_t & value,std::string & str)407 inline bool TypeConverter<GainModeTraits>::toStringImpl(
408 const audio_gain_mode_t &value, std::string &str) {
409 str = audio_gain_mode_to_string(value);
410 return !str.empty();
411 }
412
413 template <>
fromStringImpl(const std::string & str,audio_gain_mode_t & result)414 inline bool TypeConverter<GainModeTraits>::fromStringImpl(
415 const std::string &str, audio_gain_mode_t &result) {
416 return audio_gain_mode_from_string(str.c_str(), &result);
417 }
418
419 template <>
toStringImpl(const audio_content_type_t & value,std::string & str)420 inline bool TypeConverter<AudioContentTraits>::toStringImpl(
421 const audio_content_type_t &value, std::string &str) {
422 str = audio_content_type_to_string(value);
423 return !str.empty();
424 }
425
426 template <>
fromStringImpl(const std::string & str,audio_content_type_t & result)427 inline bool TypeConverter<AudioContentTraits>::fromStringImpl(
428 const std::string &str, audio_content_type_t &result) {
429 return audio_content_type_from_string(str.c_str(), &result);
430 }
431
432 template <>
toStringImpl(const audio_usage_t & value,std::string & str)433 inline bool TypeConverter<UsageTraits>::toStringImpl(const audio_usage_t &value, std::string &str)
434 {
435 str = audio_usage_to_string(value);
436 return !str.empty();
437 }
438
439 template <>
fromStringImpl(const std::string & str,audio_usage_t & result)440 inline bool TypeConverter<UsageTraits>::fromStringImpl(
441 const std::string &str, audio_usage_t &result) {
442 return audio_usage_from_string(str.c_str(), &result);
443 }
444
445 template <>
toStringImpl(const audio_source_t & value,std::string & str)446 inline bool TypeConverter<SourceTraits>::toStringImpl(const audio_source_t &value, std::string &str)
447 {
448 str = audio_source_to_string(value);
449 return !str.empty();
450 }
451
452 template <>
fromStringImpl(const std::string & str,audio_source_t & result)453 inline bool TypeConverter<SourceTraits>::fromStringImpl(
454 const std::string &str, audio_source_t &result) {
455 return audio_source_from_string(str.c_str(), &result);
456 }
457
458 SampleRateTraits::Collection samplingRatesFromString(
459 const std::string &samplingRates, const char *del = AudioParameter::valueListSeparator);
460
461 FormatTraits::Collection formatsFromString(
462 const std::string &formats, const char *del = AudioParameter::valueListSeparator);
463
464 audio_format_t formatFromString(
465 const std::string &literalFormat, audio_format_t defaultFormat = AUDIO_FORMAT_DEFAULT);
466
467 audio_channel_mask_t channelMaskFromString(const std::string &literalChannels);
468
469 ChannelTraits::Collection channelMasksFromString(
470 const std::string &channels, const char *del = AudioParameter::valueListSeparator);
471
472 InputChannelTraits::Collection inputChannelMasksFromString(
473 const std::string &inChannels, const char *del = AudioParameter::valueListSeparator);
474
475 OutputChannelTraits::Collection outputChannelMasksFromString(
476 const std::string &outChannels, const char *del = AudioParameter::valueListSeparator);
477
478 // counting enumerations
479 template <typename T, std::enable_if_t<std::is_same<T, audio_content_type_t>::value
480 || std::is_same<T, audio_devices_t>::value
481 || std::is_same<T, audio_mode_t>::value
482 || std::is_same<T, audio_source_t>::value
483 || std::is_same<T, audio_stream_type_t>::value
484 || std::is_same<T, audio_usage_t>::value
485 || std::is_same<T, audio_format_t>::value
486 , int> = 0>
toString(const T & value)487 static inline std::string toString(const T& value)
488 {
489 std::string result;
490 return TypeConverter<DefaultTraits<T>>::toString(value, result)
491 ? result : std::to_string(static_cast<int>(value));
492
493 }
494
495 // flag enumerations
496 template <typename T, std::enable_if_t<std::is_same<T, audio_gain_mode_t>::value
497 || std::is_same<T, audio_input_flags_t>::value
498 || std::is_same<T, audio_output_flags_t>::value
499 , int> = 0>
toString(const T & value)500 static inline std::string toString(const T& value)
501 {
502 std::string result;
503 TypeConverter<DefaultTraits<T>>::maskToString(value, result);
504 return result;
505 }
506
toString(const audio_attributes_t & attributes)507 static inline std::string toString(const audio_attributes_t& attributes)
508 {
509 std::ostringstream result;
510 result << "{ Content type: " << toString(attributes.content_type)
511 << " Usage: " << toString(attributes.usage)
512 << " Source: " << toString(attributes.source)
513 << std::hex << " Flags: 0x" << attributes.flags
514 << std::dec << " Tags: " << attributes.tags
515 << " }";
516
517 return result.str();
518 }
519
520 }; // namespace android
521
522 #endif /*ANDROID_TYPE_CONVERTER_H_*/
523