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