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