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