• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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